I didn't realise that matchadd()
was piling up the same highlight pattern (just with a different, incremented id), the more I was opening new buffers or simply switching between windows. Here was the output of echo getmatches()
after just a few opened buffers and switching between windows:
[{'group': 'Error', 'pattern': '\v\s+$', 'priority': -1, 'id': 4}, {'group': 'Error', 'pattern': '\v\s+$', 'priority': -1, 'id': 5}, {'group': 'Error', 'pattern': '\v\s+$', 'priority': -1, 'id': 6}, ..., {'group': 'Error', 'pattern': '\v\s+$', 'priority': -1, 'id': 24}]
I suspect the only thing that my modified autocmd was doing is preventing a new match to be added when entering a help buffer. But it didn't remove all the previous ones, so maybe that's why a trailing whitespace was still colored in red even in a help buffer. Or maybe not. Maybe the highlighting is local to the window, so the previous ones were not affecting a help buffer displayed in a new window. I don't know. (*)
Besides, I wonder if the piling of the same matches would have an effect performance-wise in the long run...
Anyway, I've found a workaround using the Ex command :2match
instead of the function matchadd()
. Here's the code:
augroup trailing_whitespace
autocmd!
autocmd BufEnter,WinEnter * 2match Error /\s\+$/ |
\ if &filetype ==# 'help' |
\ call matchdelete(2) |
\ endif
augroup END
The advantage of :2match
compared to matchadd()
is that it doesn't pile up new matches, it just recreates the same one with the same id, 2
, every time a buffer/window is entered.
To prevent the match to be created in a help buffer, the autocmd also executes call matchdelete(2)
to delete the match whose id is 2 when the filetype is 'help'
(thank you VanLaser for giving me the idea).
So far it seems to work as intended. Trailing whitespace in red everywhere except in a help buffer.
As a side note, there are actually 3 similar commands: :match
, :2match
, :3match
which create a match whose id is respectively 1, 2 and 3.
I didn't use :match
because it's more convenient to keep it untouched in case you want to create a quick match temporarily.
And I couldn't use :3match
because it was already used by the script-local function Highlight_Matching_Pair()
defined in /usr/share/vim/vim74/plugin/matchparen.vim
.
(*) I'm not sure, but I think the matches created by matchadd()
in previous windows did have an effect on a help buffer even when displayed in a new window. Otherwise the following code would work:
augroup trailing_whitespace
autocmd!
autocmd BufEnter,WinEnter * let m = matchadd('Error', '\v\s+$', -1) |
\ if &filetype ==# 'help' |
\ call matchdelete(m) |
\ endif
augroup END
But it doesn't work. A trailing whitespace is still colored in red even in a help buffer displayed in a new window.
Edit: I've just realised I could pass a fourth optional argument to matchadd()
to specify the id I want, which would prevent the piling up of identical matches. So I could write something like:
augroup trailing_whitespace
autocmd!
autocmd BufEnter,WinEnter * call matchadd('Error', '\v\s+$', -1, 9999) |
\ if &filetype ==# 'help' |
\ call matchdelete(9999) |
\ endif
augroup END
But it doesn't work as intended. Besides, every time I would open a buffer or switch to another window, I would have the following error:
Error detected while processing BufEnter Auto commands for "*":
E801: ID already taken: 9999
matchadd()
doesn't want to create a match whose id is already used while :2match
doesn't care. So all in all, it seems :2match
is a better solution for this particular autocmd.