However after adding these lines into the .vimrc, it didn't work.
The reason for this is that Vim clears existing syntax items when setting the 'syntax'
option. This is done because keeping the old syntax items would lead to some strange situations; if you have a buffer which has syntax=foo
and use set syntax=bar
then you'll end up with a buffer which has syntax highlighting for both foo
and bar
.
When Vim starts it loads your vimrc
once (on startup), but it loads the filetype and syntax files every time the filetype
or syntax
options are set, which will reset the values you've set in your vimrc.
Even if it wouldn't reset it, it wouldn't be a good idea to just add it to your vimrc, since it would apply to all buffers, and not just buffers with syntax=c
.
The below text assumes Vim on a Unix-y system, but it will work for Neovim and Windows users as well:
- Neovim users should replace
~/.vim/
with ~/.config/nvim/
.
- Windows users should replace
~/.vim/
with %USERPROFILE%\vimfiles\
.
Overriding an entire file
The easiest way to change something is to just override it. To do so create a file in ~/.vim/<file>.vim
.
<file.vim>
is the path relative to $VIMRUNTIME
(including subdirectories). In your example, it should be syntax/c.vim
. It will be loaded instead of the file in $VIMRUNTIME
.
The upshot of this is that it's easier to make changes – amending exiting syntax files can be a bit tricky sometimes. The downside is that you won't get any future updates made to the system-wide file.
I often use this as a starting point to experiment with syntax files, and then later extract my local changes to a local addition using one of the methods described below.
Local additions
There are two ways to add local additions to syntax files, they are functionally identical, and you can use the method you prefer.
Syntax
autocmd
Use the Syntax
autocmd:
augroup ft_c
autocmd!
autocmd Syntax c syn match cFunction "\<[a-zA-Z_][a-zA-Z_0-9]*\>[^()]*)("me=e-2
autocmd Syntax c syn match cFunction "\<[a-zA-Z_][a-zA-Z_0-9]*\>\s*("me=e-1
autocmd Syntax c hi cFunction gui=NONE guifg=#B5A1FF
augroup end
Note that chaining several commands with |
is problematic here, since they tend to get interpreted as part of the :syn
command, which is why I've repeated the autocmd Syntax c
several times. An alternative would be to use a function:
fun s:c()
syn match cFunction "\<[a-zA-Z_][a-zA-Z_0-9]*\>[^()]*)("me=e-2
syn match cFunction "\<[a-zA-Z_][a-zA-Z_0-9]*\>\s*("me=e-1
hi cFunction gui=NONE guifg=#B5A1FF
endfun
augroup ft_c
autocmd!
autocmd Syntax c call s:c()
augroup end
The advantage is that all changes can be contained to a single file. The disadvantage is that it's a bit ugly, especially if you have a lot of changes.
after directory
Use the after-directory: ~/.vim/after/<file>.vim
.
This will be loaded after <file>.vim
has, where <file.vim>
is the path relative to $VIMRUNTIME
(including subdirectories). In your example, it should be syntax/c.vim
.
Also see :help after-directory
.
The advantage is that it's a bit more readable than the autocmd, especially if you have many changes. The disadvantage is that you'll need to copy over an additional file if you want to mirror your Vim setup to different machines (this is an important reason many people keep their Vim files in a GitHub repo, so it can be easily mirrored across machines).
~/.vim/after/syntax/c.vim
instead..vimrc
?autocmd BufEnter *.c hl ...
, but you should keep it inafter/syntax/c.vim
. Any modern version of Vim will understand the.vim/after/
directory. On Windows, the path would bevimfiles/after/...
, so portability shouldn't be much of an issue (especially if you use any plugins).