Vim Tips Wiki
(Change to TipImported template + severe manual clean)
(→‎Comments: OptionSet autocmd useful for textwidth-based matching)
Tags: rollback sourceedit
(40 intermediate revisions by 12 users not shown)
Line 1: Line 1:
{{review}}
 
 
{{TipImported
 
{{TipImported
 
|id=810
 
|id=810
 
|previous=809
 
|previous=809
|next=811
+
|next=812
|created=October 25, 2004
+
|created=2004
 
|complexity=intermediate
 
|complexity=intermediate
 
|author=Nitin Raut
 
|author=Nitin Raut
|version=5.7
+
|version=6.0
|rating=63/31
+
|rating=
  +
|category1=Syntax
  +
|category2=Temporary
 
}}
 
}}
  +
{{deprecated|Vim 7.3 adds the 'colorcolumn' option which allows you to highlight a specific column. The methods herein may be useful for some users however.}}
Due to oversightedness we are often left with lines of text longer than 80 columns or the set textwidth. One way to spot such lines is to highlight the text beyond textwidth.
 
  +
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. Unlike some editors, Vim cannot show a line at this width.
   
  +
You can also [[VimTip38|wrap long lines]], or show <code><</code> <code>></code> flags when [[VimTip396#HighlightLongLines|characters are not displayed]] on long lines.
I found that lines beyond textwidth in .c and .h files can be highlighted using the below line in vimrc.
 
  +
  +
==Searching==
  +
A quick method to find long lines is a search like the following. If you use [[VimTip14|search highlighting]] (<code>:set hlsearch</code>), this will highlight all text after virtual column 80 (after tabs are expanded).
 
<pre>
 
<pre>
  +
/\%>80v.\+
au BufNewFile,BufRead *.c,*.h exec 'match Todo /\%&gt;' . &amp;textwidth . 'v.\+/'
 
 
</pre>
 
</pre>
   
  +
==Matching==
You may add different file extensions for which you may wish to highlight text after textwidth.
 
  +
A simple command will highlight any text after virtual column 80:
  +
<pre>
  +
:match ErrorMsg '\%>80v.\+'
  +
</pre>
   
  +
Of course, you can [[VimTip24|define your own highlight groups]] if ErrorMsg is not to your taste. Enter <code>:match</code> to clear matching.
==Comments==
 
Just set the linebreak character/string to mark wrapped lines, e.g.
 
:set showbreak=NEWLINE:
 
or
 
:set showbreak=&gt;
 
   
  +
Alternatively, you can just highlight any character in column 81. This is less visually aggressive if you have lines that extend past 80 characters, and thus is more suited to being placed in your .vimrc and left on all the time.
You may need to set other flags like linebreak, textwidth, etc.
 
  +
<pre>
 
  +
:2mat ErrorMsg '\%81v.'
----
 
  +
</pre>
Those who find that every line is highlighted probably have textwidth set to 0. See {{help|'textwidth'}}.
 
   
  +
==Replacing==
My own mod was to add a conditional check and only highlight if textwidth was &gt; 0
 
  +
Command to replace line text >80 chars from the previous word boundary to '...':
 
<pre>
 
<pre>
  +
:g/\%>79v/norm 77|gElC...
au BufEnter * if &amp;textwidth &gt; 0 | exec 'match Todo /\%&gt;' . &amp;textwidth . 'v.\+/' | endif
 
 
</pre>
 
</pre>
   
  +
Credit to Accolade from #vim on Freenode.
Note this runs on BufEnter for all files.
 
   
  +
==Automatic matching==
----
 
  +
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 <code>-1</code> means any search highlighting will override the match highlighting):
This will force Vim to execute the autocommand manually:
 
  +
<pre>
  +
:let w:m1=matchadd('Search', '\%<81v.\%>77v', -1)
  +
:let w:m2=matchadd('ErrorMsg', '\%>80v.\+', -1)
  +
</pre>
   
  +
You can apply this highlighting automatically for all files with something like this in your [[vimrc]]:
 
<pre>
 
<pre>
  +
:au BufWinEnter * let w:m1=matchadd('Search', '\%<81v.\%>77v', -1)
:set tw=80 | do BufEnter
 
  +
:au BufWinEnter * let w:m2=matchadd('ErrorMsg', '\%>80v.\+', -1)
 
</pre>
 
</pre>
   
  +
You can change the <code>*</code> to a different pattern, or a comma-separated list, to make it work only for certain file types like <code>*.c,*.h</code> for example.
See {{help|:autocmd-execute}}.
 
   
  +
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 [[Detect window creation with WinEnter|whenever you detect a window creation]].
----
 
If you want to highlight only the 80th column with a search for example, you can do:
 
   
  +
Clear the highlighting with:
 
<pre>
 
<pre>
  +
:call matchdelete(w:m1)
/.\{79}\zs.
 
  +
:call matchdelete(w:m2)
 
</pre>
 
</pre>
   
  +
Alternatively, the following command will clear ''all'' matches that have been defined for this window:
This will 'draw' a vertical line on the 80th caracter on all the lines which have 80 caracters or more. You can map this one for a fast highlighting.
 
  +
<pre>
  +
:call clearmatches()
  +
</pre>
  +
  +
==Automatic matching (for Vim before version 7.1.40)==
  +
For earlier versions of Vim, the following is a close approximation:
  +
<pre>
  +
:syntax match Search /\%<81v.\%>77v/
  +
:syntax match ErrorMsg /\%>80v.\+/
  +
</pre>
  +
<pre>
  +
:au BufRead,BufNewFile * syntax match Search /\%<81v.\%>77v/
  +
:au BufRead,BufNewFile * syntax match ErrorMsg /\%>80v.\+/
  +
</pre>
   
  +
Note the use of BufRead and BufNewFile instead of BufWinEnter. Unlike matches, syntax is local to the ''buffer'' instead of the ''window''.
----
 
Don't get over complex, there is a search designed to do exactly this. Highlight all characters at column #81 (all longer than 80 characters)
 
   
  +
Clear the highlighting (after saving any changes) with:
 
<pre>
 
<pre>
  +
:e
\%81c
 
 
</pre>
 
</pre>
   
  +
This assumes you are editing a file using syntax rules contained in a syntax file (which usually do a <code>syntax clear</code> 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:
Highlight all characters from column #81 to the end of the line.
 
  +
<pre>
  +
:syntax clear
  +
</pre>
  +
  +
==Toggle matching based on textwidth==
  +
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 <code>'textwidth'</code> option. The mapping could look like this:
   
 
<pre>
 
<pre>
  +
nnoremap <silent> <Leader>l
\%&gt;81c
 
  +
\ :if exists('w:long_line_match') <Bar>
  +
\ silent! 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.'v.\+', -1) <Bar>
  +
\ else <Bar>
  +
\ let w:long_line_match = matchadd('ErrorMsg', '\%>80v.\+', -1) <Bar>
  +
\ endif<CR>
 
</pre>
 
</pre>
   
  +
==Explanation==
I have those searches mapped to keys, but you could just as easily add them to a syntax file or a highlight/match pattern.
 
  +
The search pattern <code>\%>80v.\+</code> checks for a match at each position. If the position being tested is at a virtual column above 80, the text at that position is checked to see if it matches what follows (<code>.\+</code>). That matches one or more characters, up to but not including the end-of-line.
   
  +
A simpler pattern such as <code>\%81v.*</code> fails to highlight text past the limit if there is no character in virtual column 81, for example if a tab starts just before that column. Furthermore, <code>\%81v.*</code> can give an erroneous highlight of column 81 on lines of exactly 80 characters.
----
 
Note that the 'c' after \%80 means that the 80th character gets matched and that tabs are characters also. So if you for example write a program and use tabs to indent your code, this is probably not what you want, especially if you are going to print the code later. Use 'v' instead in this case.
 
   
  +
The pattern <code>\%<81v.\%>77v</code> matches any character at virtual column 77 to 80 inclusive. The pattern checks for a match at each position: <code>\%<81v.</code> matches any character at a virtual column below 81; <code>\%>77v</code> causes the match to fail unless the virtual column of the next character is above 77.
----
 
  +
[[Category:Syntax]]
 
  +
==References==
  +
*{{help|matchadd()}}
  +
*{{help|:match}}
  +
*{{help|/\%v}}
  +
 
==Comments==
  +
Textwidth-based matching can be made automatic using the OptionSet autocmd event introduced in [https://github.com/vim/vim/releases/tag/v7.4.786 Vim 7.4.786]. I'm not spending time to figure out an exact script at the moment since I've personally switched over to the 'colorcolumn' option. --[[User:Fritzophrenic|Fritzophrenic]] ([[User talk:Fritzophrenic|talk]]) 16:10, September 2, 2015 (UTC)

Revision as of 16:10, 2 September 2015

Tip 810 Printable Monobook Previous Next

created 2004 · complexity intermediate · author Nitin Raut · version 6.0


This tip is deprecated for the following reasons:

Vim 7.3 adds the 'colorcolumn' option which allows you to highlight a specific column. The methods herein may be useful for some users however.

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. Unlike some editors, Vim cannot show a line at this width.

You can also wrap long lines, or show < > flags when characters are not displayed on long lines.

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 after virtual column 80 (after tabs are expanded).

/\%>80v.\+

Matching

A simple command will highlight any text after virtual column 80:

:match ErrorMsg '\%>80v.\+'

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

Alternatively, you can just highlight any character in column 81. This is less visually aggressive if you have lines that extend past 80 characters, and thus is more suited to being placed in your .vimrc and left on all the time.

:2mat ErrorMsg '\%81v.'

Replacing

Command to replace line text >80 chars from the previous word boundary to '...':

:g/\%>79v/norm 77|gElC...

Credit to Accolade from #vim on Freenode.

Automatic matching

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.\%>77v', -1)
:let w:m2=matchadd('ErrorMsg', '\%>80v.\+', -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.\%>77v', -1)
:au BufWinEnter * let w:m2=matchadd('ErrorMsg', '\%>80v.\+', -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, the following command will clear all matches that have been defined for this window:

:call clearmatches()

Automatic matching (for Vim before version 7.1.40)

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

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

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

Toggle matching based on textwidth

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>
      \   silent! 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.'v.\+', -1) <Bar>
      \ else <Bar>
      \   let w:long_line_match = matchadd('ErrorMsg', '\%>80v.\+', -1) <Bar>
      \ endif<CR>

Explanation

The search pattern \%>80v.\+ checks for a match at each position. If the position being tested is at a virtual column above 80, the text at that position is checked to see if it matches what follows (.\+). That matches one or more characters, up to but not including the end-of-line.

A simpler pattern such as \%81v.* fails to highlight text past the limit if there is no character in virtual column 81, for example if a tab starts just before that column. Furthermore, \%81v.* can give an erroneous highlight of column 81 on lines of exactly 80 characters.

The pattern \%<81v.\%>77v matches any character at virtual column 77 to 80 inclusive. The pattern checks for a match at each position: \%<81v. matches any character at a virtual column below 81; \%>77v causes the match to fail unless the virtual column of the next character is above 77.

References

Comments

Textwidth-based matching can be made automatic using the OptionSet autocmd event introduced in Vim 7.4.786. I'm not spending time to figure out an exact script at the moment since I've personally switched over to the 'colorcolumn' option. --Fritzophrenic (talk) 16:10, September 2, 2015 (UTC)