Vim Tips Wiki
(→‎Highlighting with the match command: alternate pattern made more useful with an autocmd, use BufWinEnter rather than WinEnter in existing autocmd so it doesn't fire when switching windows)
(Undo revision 40474 by 35.3.13.64 (talk))
(36 intermediate revisions by 23 users not shown)
Line 3: Line 3:
 
|previous=395
 
|previous=395
 
|next=397
 
|next=397
|created=January 9, 2003
+
|created=2003
 
|complexity=basic
 
|complexity=basic
|author=Anon
+
|author=
 
|version=6.0
 
|version=6.0
 
|rating=147/80
 
|rating=147/80
|category1=
+
|category1=Syntax
 
|category2=
 
|category2=
 
}}
 
}}
 
It can be hard to maintain consistent use of whitespace characters (space and tab). You may not want spaces before tabs, or trailing whitespace at the end of a line. Sometimes you may want to avoid tabs, or just see where tabs occur.
 
It can be hard to maintain consistent use of whitespace characters (space and tab). You may not want spaces before tabs, or trailing whitespace at the end of a line. Sometimes you may want to avoid tabs, or just see where tabs occur.
   
This tip shows several ways to highlight unwanted whitespace.
+
This tip shows several ways to highlight unwanted whitespace. In addition, the tip explains how to use the <code>listchars</code> option (abbreviated to <code>lcs</code>) to indicate when characters are not displayed on long lines.
   
 
==Highlighting with a search==
 
==Highlighting with a search==
For occasional use, you can simply search using a suitable pattern to highlight what you want. The following examples assume you have used <tt>:set&nbsp;hlsearch</tt>. {{help|'hlsearch'}}
+
For occasional use, you can simply search using a suitable pattern to highlight what you want. The following examples assume you use [[VimTip14|search highlighting]] (<code>:set&nbsp;hlsearch</code>).
 
 
<pre>
 
<pre>
 
" Show all tabs:
 
" Show all tabs:
Line 24: Line 23:
 
" Show trailing whitespace:
 
" Show trailing whitespace:
 
/\s\+$
 
/\s\+$
  +
  +
" Show trailing whitespace only after some text (ignores blank lines):
  +
/\S\zs\s\+$
   
 
" Show spaces before a tab:
 
" Show spaces before a tab:
Line 30: Line 32:
   
 
==Highlighting with the match command==
 
==Highlighting with the match command==
The <tt>:match</tt> command specifies the name of a highlight group and a pattern. Any text matching the pattern will be displayed in the foreground and background colors defined by the highlight group. {{help|:match}} {{help|:2match}}
+
The <code>:match</code> command specifies the name of a highlight group and a pattern. Any text matching the pattern will be displayed in the foreground and background colors defined by the highlight group. {{help|:match}} {{help|:2match}}
   
Some examples follow. These use a highlight group named <tt>ExtraWhitespace</tt> which could be defined with one of the following in your&nbsp;[[vimrc]] file. {{help|:highlight}}
+
Some examples follow. These use a highlight group named <code>ExtraWhitespace</code> which could be defined with one of the following in your&nbsp;[[vimrc]]. {{help|:highlight}}
 
<pre>
 
<pre>
 
:highlight ExtraWhitespace ctermbg=red guibg=red
 
:highlight ExtraWhitespace ctermbg=red guibg=red
Line 41: Line 43:
 
</pre>
 
</pre>
   
  +
However, be aware that future colorscheme commands may clear all user-defined highlight groups. Using,
  +
<pre>
  +
:autocmd ColorScheme * highlight ExtraWhitespace ctermbg=red guibg=red
  +
</pre>
  +
'''before''' the first colorscheme command will ensure that the highlight group gets created and is not cleared by future colorscheme commands. {{help|:colorscheme}}
  +
  +
Once this highlight group is created, it can be associated with matching text as in the following examples.
 
<pre>
 
<pre>
 
" Show trailing whitespace:
 
" Show trailing whitespace:
 
:match ExtraWhitespace /\s\+$/
 
:match ExtraWhitespace /\s\+$/
   
" Show trailing whitepace and spaces before a tab:
+
" Show trailing whitespace and spaces before a tab:
 
:match ExtraWhitespace /\s\+$\| \+\ze\t/
 
:match ExtraWhitespace /\s\+$\| \+\ze\t/
   
Line 58: Line 67:
 
</pre>
 
</pre>
   
Following is an alternative to show trailing whitespace. This does not match when you type in a trailing whitespace (it won't highlight while you are typing at the end of a line).
+
Alternatively, the following pattern will match trailing whitespace, except when typing at the end of a line.
 
<pre>
 
<pre>
 
:match ExtraWhitespace /\s\+\%#\@<!$/
 
:match ExtraWhitespace /\s\+\%#\@<!$/
Line 64: Line 73:
   
 
If you use this alternate pattern, you may want to consider using the following autocmd to let the highlighting show up as soon as you leave insert mode after entering trailing whitespace:
 
If you use this alternate pattern, you may want to consider using the following autocmd to let the highlighting show up as soon as you leave insert mode after entering trailing whitespace:
 
 
<pre>
 
<pre>
 
:autocmd InsertLeave * redraw!
 
:autocmd InsertLeave * redraw!
 
</pre>
 
</pre>
  +
Or alternatively, the following can be used:
  +
<pre>
  +
:au InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
  +
:au InsertLeave * match ExtraWhitespace /\s\+$/
  +
</pre>
  +
which does not "flash" the screen.
   
Any <tt>:match</tt> highlighting applies only to the current window. With the following in your vimrc, the command will be applied to the first window, and to any subsequent windows. The pattern <tt>*</tt> applies the highlight to all files.
+
Any <code>:match</code> highlighting applies only to the current window. With the following in your vimrc, the command will be applied to the first window, and to any subsequent windows. The pattern <code>*</code> applies the highlight to all files.
 
<pre>
 
<pre>
 
" Show leading whitespace that includes spaces, and trailing whitespace.
 
" Show leading whitespace that includes spaces, and trailing whitespace.
Line 75: Line 89:
 
</pre>
 
</pre>
   
Rather than an autocmd, you may prefer a mapping. With the following, and the default backslash Leader key, you can press <tt>\wn</tt> to switch highlighting on, and <tt>\wf</tt> to switch it off.
+
Rather than an autocmd, you may prefer a mapping. With the following, and the default backslash Leader key, you can type <code>\wn</code> to switch highlighting on, and <code>\wf</code> to switch it off.
 
<pre>
 
<pre>
 
:nnoremap <Leader>wn :match ExtraWhitespace /^\s* \s*\<Bar>\s\+$/<CR>
 
:nnoremap <Leader>wn :match ExtraWhitespace /^\s* \s*\<Bar>\s\+$/<CR>
 
:nnoremap <Leader>wf :match<CR>
 
:nnoremap <Leader>wf :match<CR>
  +
</pre>
  +
  +
With Vim 7.1.40 and later, you can use the <code>matchadd()</code> function to define matches (making the <code>:match</code> command available for other purposes). See [[VimTip810|Highlight long lines]] for examples.
  +
  +
If your goal is to:
  +
# highlight trailing whitespace in red
  +
# have this highlighting not appear whilst you are typing in insert mode
  +
# have the highlighting of whitespace apply when you open new buffers
  +
then the following 6 commands are what you should put into your .vimrc. They are all listed on this page in separate sections, but this is a consolidated list of precisely what you need.
  +
<pre>
  +
highlight ExtraWhitespace ctermbg=red guibg=red
  +
match ExtraWhitespace /\s\+$/
  +
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
  +
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
  +
autocmd InsertLeave * match ExtraWhitespace /\s\+$/
  +
autocmd BufWinLeave * call clearmatches()
 
</pre>
 
</pre>
   
 
==Highlighting with the syntax command==
 
==Highlighting with the syntax command==
Using the <tt>:match</tt> command is easy, but you may want to keep it for another purpose. An alternative is to use syntax highlighting. {{help|syntax}}
+
Using the <code>:match</code> command is easy, but you may want to keep it for another purpose. An alternative is to use syntax highlighting. {{help|syntax}}
   
Here is an example using one of the patterns shown earlier. Put this in your [[vimrc]], ''after'' the command <tt>:syntax&nbsp;on</tt> (which you may already have). Of course you would also need to define <tt>ExtraWhitespace</tt> with a <tt>:highlight</tt> command, as shown earlier.
+
Here is an example using one of the patterns shown earlier. Put this in your [[vimrc]], ''after'' the command <code>:syntax&nbsp;on</code> (which you may already have). Of course you would also need to define <code>ExtraWhitespace</code> with a <code>:highlight</code> command, as shown earlier.
 
<pre>
 
<pre>
 
" Show trailing whitepace and spaces before a tab:
 
" Show trailing whitepace and spaces before a tab:
Line 90: Line 120:
 
</pre>
 
</pre>
   
  +
If you want the above command to also work if the match is nested in some other syntax group, append <code>containedin=ALL</code> to the end.
==Using the list and listchars options==
 
In Vim, <tt>'list'</tt> is a boolean option that defaults to off. If <tt>'list'</tt> is on, whitespace characters are made visible. The <tt>'listchars'</tt> option can be used to customize the way whitespace characters are shown. The default displays "^I" for each tab, and "$" at each EOL (end of line, so trailing whitespace can be seen). {{help|'list'}}
 
   
 
==Using the list and listchars options==
The command <tt>:set list</tt> displays whitespace, while <tt>:set nolist</tt> displays normally. It is convenient to use <tt>:set list!</tt> to toggle the option on, so that you can later press <tt>:</tt> followed by Up arrow to repeat the previous command, to toggle <tt>'list'</tt> off.
 
 
In Vim, <code>'list'</code> is a boolean option that defaults to off. If <code>'list'</code> is on, whitespace characters are made visible. The <code>'listchars'</code> option can be used to customize the way whitespace characters are shown. The default displays "<code>^I</code>" for each tab, and "<code>$</code>" at each EOL (end of line, so trailing whitespace can be seen). {{help|'list'}}
   
 
The command <code>:set list</code> displays whitespace, while <code>:set nolist</code> displays normally. It is convenient to use <code>:set list!</code> to toggle the option on, so that you can later press <code>:</code> followed by the up arrow to repeat the previous command, to toggle <code>'list'</code> off.
The following example toggles <tt>list</tt>, then sets <tt>listchars</tt> to ''not'' display an end-of-line character, and to display <tt>></tt> for the first character occupied by a tab, and <tt>-</tt> for any subsequent characters that the tab may occupy.
 
   
 
The following example toggles <code>list</code>, then sets <code>listchars</code> to ''not'' display an end-of-line character, and to display <code>></code> for the first character occupied by a tab, and <code>-</code> for any subsequent characters that the tab may occupy.
 
<pre>
 
<pre>
 
:set list!
 
:set list!
Line 102: Line 133:
 
</pre>
 
</pre>
   
Here are some alternatives that you can try (each sets list and listchars in one command):
+
Here are some alternatives that you can try (each sets <code>list</code> and <code>listchars</code> in one command):
 
<pre>
 
<pre>
 
:set list listchars=tab:>-,trail:.,extends:>
 
:set list listchars=tab:>-,trail:.,extends:>
Line 113: Line 144:
 
" The command :dig displays other digraphs you can use.
 
" The command :dig displays other digraphs you can use.
 
</pre>
 
</pre>
 
----
 
   
 
The listchars option uses the "NonText" highlighting group for "eol", "extends" and "precedes", and the "SpecialKey" highlighting group for "nbsp", "tab" and "trail". {{help|'listchars'}}
 
The listchars option uses the "NonText" highlighting group for "eol", "extends" and "precedes", and the "SpecialKey" highlighting group for "nbsp", "tab" and "trail". {{help|'listchars'}}
   
 
==Using syntax space errors==
 
==Using syntax space errors==
Vim has several syntax files that support the display of "space errors". For example, for the C programming language (<tt>:set&nbsp;filetype=c</tt>), you could put the following in your&nbsp;[[vimrc]]:
+
Vim has several syntax files that support the display of "space errors". For example, for the C programming language (<code>:set&nbsp;filetype=c</code>), you could put the following in your&nbsp;[[vimrc]]:
 
<pre>
 
<pre>
let c_space_errors=1
+
let c_space_errors = 1
 
</pre>
 
</pre>
   
Line 128: Line 157:
 
To highlight space errors in java files, you would use:
 
To highlight space errors in java files, you would use:
 
<pre>
 
<pre>
let java_space_errors=1
+
let java_space_errors = 1
 
</pre>
 
</pre>
   
 
For C, if you don't want to see trailing space errors at end-of-line set:
 
For C, if you don't want to see trailing space errors at end-of-line set:
 
<pre>
 
<pre>
let c_no_trail_space_error=1
+
let c_no_trail_space_error = 1
 
</pre>
 
</pre>
   
 
If you only use spaces to indent, and don't want to see space errors in front of tabs:
 
If you only use spaces to indent, and don't want to see space errors in front of tabs:
 
<pre>
 
<pre>
let c_no_tab_space_error=1
+
let c_no_tab_space_error = 1
 
</pre>
 
</pre>
   
If you are interested in learning more, open the syntax file for C (in Vim, put the cursor on the path $VIMRUNTIME/syntax/c.vim and press <tt>gf</tt>). Then look for the definition of the highlight group <tt>cSpaceError</tt> (near the end of the file). That group specifies the color used to display space errors in C files. The command <tt>:hi&nbsp;cSpaceError</tt> will show "xxx" in that color.
+
If you are interested in learning more, open the syntax file for C (in Vim, put the cursor on the path <code>$VIMRUNTIME/syntax/c.vim</code> and type <code>gf</code>). Then look for the definition of the highlight group <code>cSpaceError</code> (near the end of the file). That group specifies the color used to display space errors in C files. The command <code>:hi&nbsp;cSpaceError</code> will show "xxx" in that color.
  +
  +
{{anchor|HighlightLongLines}}
  +
==Showing long lines==
  +
By default, lines longer than the screen width are not wrapped, and you can horizontally scroll the text, for example by moving the cursor to the end of a long line. Therefore there may be characters preceding the visible text (non-displayed characters on the left), and there may be characters that extend after the visible text (non-displayed characters on the right). The <code>listchars</code> option can be used to show a highlighted symbol when characters are not displayed, for example:
  +
<pre>
  +
" Show < or > when characters are not displayed on the left or right.
  +
:set list listchars=precedes:<,extends:>
  +
" Same, but also show tabs and trailing spaces.
  +
:set list listchars=tab:>-,trail:.,precedes:<,extends:>
  +
</pre>
  +
  +
==Resolving performance problems==
  +
It seems that vim does not handle sucessive calls of the match command gracefully. Since BufWinEnter commands are executed every time a buffer is displayed (i.e., switching to another file), the match command is executed many times during a vim session. This seems to lead to a memory leak which slowly impacts performance (for example scrolling and writing become unbearably slow). Include the following line to fix the issue:
  +
<pre>
  +
autocmd BufWinLeave * call clearmatches()
  +
</pre>
  +
  +
NOTE: Versions < 7.2
  +
  +
While I would suggest you keep your VIM up to date, there are reasons why maybe you cannot. To avoid errors you could modify part of the settings above to make sure clearmatches() is an available function (apparently available in 7.2+).
  +
  +
<pre>
  +
if version >= 702
  +
autocmd BufWinLeave * call clearmatches()
  +
endif
  +
</pre>
   
 
==See also==
 
==See also==
  +
*[[VimTip1274|Highlight some whitespace characters]] a script to toggle specified highlighting
 
*[[VimTip12|Converting tabs to spaces]] to convert tabs to spaces or vice versa
 
*[[VimTip12|Converting tabs to spaces]] to convert tabs to spaces or vice versa
 
*[[VimTip878|Remove unwanted spaces]] to display or remove unwanted spaces
 
*[[VimTip878|Remove unwanted spaces]] to display or remove unwanted spaces
Line 149: Line 205:
 
*{{script|id=363|text=cream-showinvisibles}} plugin for attractive display of tabs, returns and trailing spaces
 
*{{script|id=363|text=cream-showinvisibles}} plugin for attractive display of tabs, returns and trailing spaces
   
==Comments==
+
==Related scripts==
  +
*The {{script|id=3966|text=ShowTrailingWhitespace}} plugin highlights without affecting syntax or :match command, and comes with exceptions for certain filetypes.
{{Todo}}
 
  +
*The {{script|id=3968|text=JumpToTrailingWhitespace}} plugin provides corresponding movement commands to quickly locate trailing whitespace.
*Recheck that the commands work.
 
  +
*The {{script|id=2635|text=smartmatcheol.vim}} plugin highlights based on file extension or name.
*Rename tip, perhaps to "Highlight unwanted spaces".
 
  +
*The {{script|id=3201|text=trailing-whitespace}} plugin uses :match.
*Mention <tt>matchadd()</tt> as an alternative to :match
 
  +
*The {{script|id=3735|text=bad-whitespace}} plugin uses :match, allows on/off/toggling via commands.
*Check script in [[VimTip1274]]. If it is useful, keep 1274 and add it to see-also here. If not, delete 1274.
 
  +
*The {{script|id=3938|text=Trailer Trash}} plugin uses :match.
  +
*The {{script|id=3965|text=DynamicSigns}} plugin can show whitespace errors (also mixed indent) in the sign column.
   
  +
==Comments==
----
 
  +
If you want to leave <code>:match</code> available for other uses and still have the match change when you enter or leave Insert mode, then you can use the following snippet.
{{Todo}}
 
*Is following comment worthwhile, or should we just delete it?
 
*Investigate its regex: Isn't <tt>\_^\|\_^\t\+</tt> just <tt>\_^\t*</tt>
 
*An alternative pattern was used above: <tt>/[^\t]\zs\t\+/</tt>
 
 
I added the following to my syntax file. See {{help|mysyntaxfile-add}} for how to add your own syntax options.
 
 
<pre>
 
<pre>
  +
highlight ExtraWhitespace ctermbg=red guibg=red
" Show tabs that are not at the start of a line:
 
  +
augroup WhitespaceMatch
syn match cTodo display "\(\_^\|\_^\t\+\)\@<!\t"
 
  +
" Remove ALL autocommands for the WhitespaceMatch group.
  +
autocmd!
  +
autocmd BufWinEnter * let w:whitespace_match_number =
  +
\ matchadd('ExtraWhitespace', '\s\+$')
  +
autocmd InsertEnter * call s:ToggleWhitespaceMatch('i')
  +
autocmd InsertLeave * call s:ToggleWhitespaceMatch('n')
  +
augroup END
  +
function! s:ToggleWhitespaceMatch(mode)
  +
let pattern = (a:mode == 'i') ? '\s\+\%#\@<!$' : '\s\+$'
  +
if exists('w:whitespace_match_number')
  +
call matchdelete(w:whitespace_match_number)
  +
call matchadd('ExtraWhitespace', pattern, 10, w:whitespace_match_number)
  +
else
  +
" Something went wrong, try to be graceful.
  +
let w:whitespace_match_number = matchadd('ExtraWhitespace', pattern)
  +
endif
  +
endfunction
 
</pre>
 
</pre>
 
 
----
 
----

Revision as of 06:42, 21 February 2019

Tip 396 Printable Monobook Previous Next

created 2003 · complexity basic · version 6.0


It can be hard to maintain consistent use of whitespace characters (space and tab). You may not want spaces before tabs, or trailing whitespace at the end of a line. Sometimes you may want to avoid tabs, or just see where tabs occur.

This tip shows several ways to highlight unwanted whitespace. In addition, the tip explains how to use the listchars option (abbreviated to lcs) to indicate when characters are not displayed on long lines.

Highlighting with a search

For occasional use, you can simply search using a suitable pattern to highlight what you want. The following examples assume you use search highlighting (:set hlsearch).

" Show all tabs:
/\t

" Show trailing whitespace:
/\s\+$

" Show trailing whitespace only after some text (ignores blank lines):
/\S\zs\s\+$

" Show spaces before a tab:
/ \+\ze\t

Highlighting with the match command

The :match command specifies the name of a highlight group and a pattern. Any text matching the pattern will be displayed in the foreground and background colors defined by the highlight group. :help :match :help :2match

Some examples follow. These use a highlight group named ExtraWhitespace which could be defined with one of the following in your vimrc. :help :highlight

:highlight ExtraWhitespace ctermbg=red guibg=red
" The following alternative may be less obtrusive.
:highlight ExtraWhitespace ctermbg=darkgreen guibg=lightgreen
" Try the following if your GUI uses a dark background.
:highlight ExtraWhitespace ctermbg=darkgreen guibg=darkgreen

However, be aware that future colorscheme commands may clear all user-defined highlight groups. Using,

:autocmd ColorScheme * highlight ExtraWhitespace ctermbg=red guibg=red

before the first colorscheme command will ensure that the highlight group gets created and is not cleared by future colorscheme commands. :help :colorscheme

Once this highlight group is created, it can be associated with matching text as in the following examples.

" Show trailing whitespace:
:match ExtraWhitespace /\s\+$/

" Show trailing whitespace and spaces before a tab:
:match ExtraWhitespace /\s\+$\| \+\ze\t/

" Show tabs that are not at the start of a line:
:match ExtraWhitespace /[^\t]\zs\t\+/

" Show spaces used for indenting (so you use only tabs for indenting).
:match ExtraWhitespace /^\t*\zs \+/

" Switch off :match highlighting.
:match

Alternatively, the following pattern will match trailing whitespace, except when typing at the end of a line.

:match ExtraWhitespace /\s\+\%#\@<!$/

If you use this alternate pattern, you may want to consider using the following autocmd to let the highlighting show up as soon as you leave insert mode after entering trailing whitespace:

:autocmd InsertLeave * redraw!

Or alternatively, the following can be used:

:au InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
:au InsertLeave * match ExtraWhitespace /\s\+$/

which does not "flash" the screen.

Any :match highlighting applies only to the current window. With the following in your vimrc, the command will be applied to the first window, and to any subsequent windows. The pattern * applies the highlight to all files.

" Show leading whitespace that includes spaces, and trailing whitespace.
:autocmd BufWinEnter * match ExtraWhitespace /^\s* \s*\|\s\+$/

Rather than an autocmd, you may prefer a mapping. With the following, and the default backslash Leader key, you can type \wn to switch highlighting on, and \wf to switch it off.

:nnoremap <Leader>wn :match ExtraWhitespace /^\s* \s*\<Bar>\s\+$/<CR>
:nnoremap <Leader>wf :match<CR>

With Vim 7.1.40 and later, you can use the matchadd() function to define matches (making the :match command available for other purposes). See Highlight long lines for examples.

If your goal is to:

  1. highlight trailing whitespace in red
  2. have this highlighting not appear whilst you are typing in insert mode
  3. have the highlighting of whitespace apply when you open new buffers

then the following 6 commands are what you should put into your .vimrc. They are all listed on this page in separate sections, but this is a consolidated list of precisely what you need.

highlight ExtraWhitespace ctermbg=red guibg=red
match ExtraWhitespace /\s\+$/
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
autocmd InsertLeave * match ExtraWhitespace /\s\+$/
autocmd BufWinLeave * call clearmatches()

Highlighting with the syntax command

Using the :match command is easy, but you may want to keep it for another purpose. An alternative is to use syntax highlighting. :help syntax

Here is an example using one of the patterns shown earlier. Put this in your vimrc, after the command :syntax on (which you may already have). Of course you would also need to define ExtraWhitespace with a :highlight command, as shown earlier.

" Show trailing whitepace and spaces before a tab:
:autocmd Syntax * syn match ExtraWhitespace /\s\+$\| \+\ze\t/

If you want the above command to also work if the match is nested in some other syntax group, append containedin=ALL to the end.

Using the list and listchars options

In Vim, 'list' is a boolean option that defaults to off. If 'list' is on, whitespace characters are made visible. The 'listchars' option can be used to customize the way whitespace characters are shown. The default displays "^I" for each tab, and "$" at each EOL (end of line, so trailing whitespace can be seen). :help 'list'

The command :set list displays whitespace, while :set nolist displays normally. It is convenient to use :set list! to toggle the option on, so that you can later press : followed by the up arrow to repeat the previous command, to toggle 'list' off.

The following example toggles list, then sets listchars to not display an end-of-line character, and to display > for the first character occupied by a tab, and - for any subsequent characters that the tab may occupy.

:set list!
:set listchars=tab:>-

Here are some alternatives that you can try (each sets list and listchars in one command):

:set list listchars=tab:>-,trail:.,extends:>
" Enter the middle-dot by pressing Ctrl-k then .M
:set list listchars=tab:\|_,trail:·
" Enter the right-angle-quote by pressing Ctrl-k then >>
:set list listchars=tab:»·,trail:·
" Enter the Pilcrow mark by pressing Ctrl-k then PI
:set list listchars=tab:>-,eol:¶
" The command :dig displays other digraphs you can use.

The listchars option uses the "NonText" highlighting group for "eol", "extends" and "precedes", and the "SpecialKey" highlighting group for "nbsp", "tab" and "trail". :help 'listchars'

Using syntax space errors

Vim has several syntax files that support the display of "space errors". For example, for the C programming language (:set filetype=c), you could put the following in your vimrc:

let c_space_errors = 1

Supported languages are: ada, c, chill, csc, forth, groovy, icon, java, lpc, mel, nqc, nroff, ora, pascal, plm, plsql, python and ruby. The c settings also apply to cpp.

To highlight space errors in java files, you would use:

let java_space_errors = 1

For C, if you don't want to see trailing space errors at end-of-line set:

let c_no_trail_space_error = 1

If you only use spaces to indent, and don't want to see space errors in front of tabs:

let c_no_tab_space_error = 1

If you are interested in learning more, open the syntax file for C (in Vim, put the cursor on the path $VIMRUNTIME/syntax/c.vim and type gf). Then look for the definition of the highlight group cSpaceError (near the end of the file). That group specifies the color used to display space errors in C files. The command :hi cSpaceError will show "xxx" in that color.

Showing long lines

By default, lines longer than the screen width are not wrapped, and you can horizontally scroll the text, for example by moving the cursor to the end of a long line. Therefore there may be characters preceding the visible text (non-displayed characters on the left), and there may be characters that extend after the visible text (non-displayed characters on the right). The listchars option can be used to show a highlighted symbol when characters are not displayed, for example:

" Show < or > when characters are not displayed on the left or right.
:set list listchars=precedes:<,extends:>
" Same, but also show tabs and trailing spaces.
:set list listchars=tab:>-,trail:.,precedes:<,extends:>

Resolving performance problems

It seems that vim does not handle sucessive calls of the match command gracefully. Since BufWinEnter commands are executed every time a buffer is displayed (i.e., switching to another file), the match command is executed many times during a vim session. This seems to lead to a memory leak which slowly impacts performance (for example scrolling and writing become unbearably slow). Include the following line to fix the issue:

autocmd BufWinLeave * call clearmatches()

NOTE: Versions < 7.2

While I would suggest you keep your VIM up to date, there are reasons why maybe you cannot. To avoid errors you could modify part of the settings above to make sure clearmatches() is an available function (apparently available in 7.2+).

if version >= 702
  autocmd BufWinLeave * call clearmatches()
endif

See also

Related scripts

Comments

If you want to leave :match available for other uses and still have the match change when you enter or leave Insert mode, then you can use the following snippet.

highlight ExtraWhitespace ctermbg=red guibg=red
augroup WhitespaceMatch
  " Remove ALL autocommands for the WhitespaceMatch group.
  autocmd!
  autocmd BufWinEnter * let w:whitespace_match_number =
        \ matchadd('ExtraWhitespace', '\s\+$')
  autocmd InsertEnter * call s:ToggleWhitespaceMatch('i')
  autocmd InsertLeave * call s:ToggleWhitespaceMatch('n')
augroup END
function! s:ToggleWhitespaceMatch(mode)
  let pattern = (a:mode == 'i') ? '\s\+\%#\@<!$' : '\s\+$'
  if exists('w:whitespace_match_number')
    call matchdelete(w:whitespace_match_number)
    call matchadd('ExtraWhitespace', pattern, 10, w:whitespace_match_number)
  else
    " Something went wrong, try to be graceful.
    let w:whitespace_match_number =  matchadd('ExtraWhitespace', pattern)
  endif
endfunction