Vim Tips Wiki
(Add simple ':match' + help; this merges in 1523)
Line 100: Line 100:
   
 
==Comments==
 
==Comments==
  +
  +
I think the general matching pattern should be akin to:
  +
:match ErrorMsg '\%81v.\+'
  +
Note the use of ".\+" instead of ".*". The issue with the ".*" that I am observing is that it erroneously causes a one-character highlight if the text of the line extends to, but not past column 80. The problem is that "\%81v.*" is a zero-width match, and thus triggers in such cases, whereas the proposed pattern does not have this issue.

Revision as of 05:40, 1 October 2008

Tip 810 Printable Monobook Previous Next

created October 25, 2004 · complexity intermediate · author Nitin Raut · version 6.0


There are a number of situations where it can be helpful to know when you are near or have exceeded a certain column width (say 80 columns). Vim's highlighting features can be used to easily identify when this occurs. Some editors show a line at this width; Vim cannot do this.

Searching

A quick method to find long lines is a search like the following. If you use search highlighting (:set hlsearch), this will highlight all text in and after virtual column 80 (after tabs are expanded).

/\%80v.*

Matching

A simple command will highlight any text past column 80:

:match ErrorMsg '\%81v.*'

Of course, you can define your own highlight groups if ErrorMsg is not to your taste. Enter :match to clear matching.

Automatic

If you want to be warned whenever text exceeds 80 columns you can use matching. In Vim 7.2 this is easy to achieve with the following commands (the -1 means any search highlighting will override the match highlighting):

:let w:m1=matchadd('Search','\%<81v.\%>71v',-1)
:let w:m2=matchadd('ErrorMsg','\%81v.*',-1)

You can apply this highlighting automatically for all files with something like this in your vimrc:

:au BufWinEnter * let w:m1=matchadd('Search','\%<81v.\%>71v',-1)
:au BufWinEnter * let w:m2=matchadd('ErrorMsg','\%81v.*',-1)

You can change the * to a different pattern, or a comma-separated list, to make it work only for certain file types like *.c,*.h for example.

Since matches are local to a window and are not inherited when a new window is created, this method will not necessarily apply to all new windows you create. It will be pretty close, but if you really want to highlight in all windows, you will need to apply the highlighting whenever you detect a window creation.

Clear the highlighting with:

:call matchdelete(w:m1)
:call matchdelete(w:m2)

Alternatively, use the following command if you are want to clear all matches that have been defined for this window:

:call clearmatches()

Automatic (for Vim before version 7.1.40)

For earlier versions of Vim, the following is a close approximation:

:syntax match Search /\%<81v.\%>71v/
:syntax match ErrorMsg /\%81v.*/
:au BufRead,BufNewFile * syntax match Search /\%<81v.\%>71v/
:au BufRead,BufNewFile * syntax match ErrorMsg /\%81v.*/

Note the use of BufRead and BufNewFile instead of BufWinEnter. Unlike matches, syntax is local to the buffer instead of the window.

Clear the highlighting (after saving any changes) with:

:e

This assumes you are editing a file using syntax rules contained in a syntax file (which usually do a syntax clear before applying their rules). If you are editing a file with no pre-existing syntax rules, you can get rid of all syntax highlighting with:

:syntax clear

Manual

If you don't like to always highlight long lines, but you want a fast way to check your line length, you can define a mapping to toggle highlighting on/off. This also allows you to easily define the highlight in terms of the 'textwidth' option. The mapping could look like this:

nnoremap <Silent> <Leader>l
      \ :if exists('w:long_line_match') <Bar>
      \   call matchdelete(w:long_line_match) <Bar>
      \   unlet w:long_line_match <Bar>
      \ elseif &textwidth > 0 <Bar>
      \   let w:long_line_match = matchadd('ErrorMsg','\%'.&tw+1.'v.*',-1) <Bar>
      \ else <Bar>
      \   let w:long_line_match = matchadd('ErrorMsg','\%81v.*',-1) <Bar>
      \ endif<CR>

References

Comments

I think the general matching pattern should be akin to:

 :match ErrorMsg '\%81v.\+'

Note the use of ".\+" instead of ".*". The issue with the ".*" that I am observing is that it erroneously causes a one-character highlight if the text of the line extends to, but not past column 80. The problem is that "\%81v.*" is a zero-width match, and thus triggers in such cases, whereas the proposed pattern does not have this issue.