Explosion Pills
Explosion Pills

Reputation: 191809

Run a command each time a file opens, or general syntax

I have a syntax rule that highlights trailing whitespace:

highlight Badspace ctermfg=red ctermbg=red
match Badspace /\s\+$/

This is in my .vimrc. It works fine, but the problem is I use splits a lot, and it seems that the match is only run on the first file you open, as well it should because the .vimrc should only run once.

Anyway, how can I get the above syntax to match any file that is opened? Is there a "general" syntax file? Is there any other way to run match each time a file opens rather than just once? I'd like to know both because I could end up using either one in the future.

Upvotes: 3

Views: 297

Answers (4)

Quinn Strahl
Quinn Strahl

Reputation: 1818

The correct approach to this problem is actually to use :syntax to define a custom syn-match.

Try putting this in your vimrc:

augroup BadWhitespace
    au!
    au Syntax * syn match customBadWhitespace /\s\+$/ containedin=ALL | hi link customBadWhitespace Error
augroup END

Edit: It should also be noted that there is built-in support for highlighting trailing whitespace with the 'list' option; see :help 'listchars' and :h hl-SpecialKey (SpecialKey is the highlight group used to highlight trailing whitespace characters when 'list' is on).

Upvotes: 1

Quinn Strahl
Quinn Strahl

Reputation: 1818

This is accomplished using autocmd. The events you're looking for are BufWinEnter and VimEnter. From the Vim manual:

BufWinEnter

After a buffer is displayed in a window.  This
can be when the buffer is loaded (after
processing the modelines) or when a hidden
buffer is displayed in a window (and is no
longer hidden).
Does not happen for |:split| without
arguments, since you keep editing the same
buffer, or ":split" with a file that's already
open in a window, because it re-uses an
existing buffer.  But it does happen for a
":split" with the name of the current buffer,
since it reloads that buffer.

VimEnter

After doing all the startup stuff, including
loading .vimrc files, executing the "-c cmd"
arguments, creating all windows and loading
the buffers in them.

Try putting this in your vimrc:

augroup BadWhitespace
    au!
    au VimEnter,BufWinEnter * match Badspace /\s\+$/
augroup END

Do :help autocmd for more info.

This is completely wrong because :match is window-local, not buffer-local. Ingo Karkat has the right idea. Unfortunately, there is no good way to avoid triggering the autocmd every time you enter the window.

More to the point, though, this is a job for a custom syntax, not match.

Upvotes: 0

Ingo Karkat
Ingo Karkat

Reputation: 172758

The :match command applies the highlighting to a window, so you can use the WinEnter event to define an :autocmd.

:autocmd WinEnter * match Badspace /\s\+$/

Note that there are already a number of plugins for this purpose, most based on this VimTip: http://vim.wikia.com/wiki/Highlight_unwanted_spaces

They handle all that for you, and turn off the highlighting in insert mode; some can also automatically delete the whitespace. In fact, I have written a set of plugins for that, too: ShowTrailingWhitespace plugin.

Upvotes: 3

Jim Stewart
Jim Stewart

Reputation: 17343

You could accomplish this by using an autocmd:

highlight Badspace ctermfg=red ctermbg=red
autocmd BufEnter * match Badspace /\s\+$/

However, there's another way to accomplish your specific goal of marking trailing whitespace. Vim has a built-in feature for highlighting "special" whitespace, which includes tabs (to differentiate from spaces), trailing whitespace, and non-breaking spaces (character 160, which looks like a normal space but isn't).

See :help list and :help listchars. Here's what I use:

set list listchars=tab:>·,trail:·,nbsp:·,extends:>

listchars has the benefit of working with any file type, and marking up multiple whitespace types that are of interest. It is also a lot faster (match will be noticeably slow on giant files) and built-in already.

(Note that those are funky non-ASCII dot characters, which should work fine for you if you cut-and-paste into a UTF8-capable Vim. If they don't work for you, you can use any characters you like there, such as periods or underscores).

Here's what it looks like for me:

enter image description here

Upvotes: 2

Related Questions