22

I installed gvim on both Fedora and Win7. I found that both vim and gvim on Fedora didn't highlight the function name in c code while gvim on win7 did highlight it.

I found that on win7, vim73/syntax/c.vim has the additional lines at the end:

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

If I add these lines into the c.vim on Fedora, gvim can highlight the function name, too.

To maintain the portability, I want to just modify the .vimrc to highlight the function name. However after adding these lines into the .vimrc, it didn't work.

So, can anyone help me? I did a search and there are many solutions to highlight the function names in vim. But I am just curious about how to make these lines work in .vimrc. Thanks very much!

3
  • 7
    Try adding it to ~/.vim/after/syntax/c.vim instead.
    – muru
    Oct 4, 2015 at 14:55
  • 1
    @muru Yes, it works. But how about adding it to .vimrc?
    – tamlok
    Oct 6, 2015 at 3:54
  • You'd probably have to use something like autocmd BufEnter *.c hl ..., but you should keep it in after/syntax/c.vim. Any modern version of Vim will understand the .vim/after/ directory. On Windows, the path would be vimfiles/after/..., so portability shouldn't be much of an issue (especially if you use any plugins).
    – muru
    Oct 6, 2015 at 8:54

1 Answer 1

24

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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.