Question

In response to this question on SuperUser, I wrote a small vimscript that will detect the filetype of a symbolic link and change the syntax highlighting:

au BufNewFile,BufRead * if &syntax == '' | silent! execute (':set filetype='.matchstr(resolve(@%),'.[^.]*$')[1:]) | endif

So if I open a symbolic link with no extension, it will look at the extension of the file it points to.

It works, but an unintended consequence is that now the syntax highlighting of my .vimrc file is gone. By default, my .vimrc file has vim syntax highlighting (:echo &syntax returns vim).

But when I add the above line, :echo &syntax returns vimrc (an invalid type).

I don't know why this is happening. Shouldn't &syntax=='' evaluate to false, and thus keep &syntax==vim? I suspect that my code is executing before the syntax highlighting is set to vim. But how (and when) exactly is the syntax highlighting set to vim for .vimrc? Additionally, how can I make my script behave the way it should?

Was it helpful?

Solution

Look in Vim's runtime area for filetype.vim. You can bring it up in vim with:

:e $VIMRUNTIME/filetype.vim

In my version, it looks like this line does the trick:

" Vim script
au BufNewFile,BufRead *vimrc*           call s:StarSetf('vim')

Perhaps you want to put your autocmd in ~/.vim/after/filetype.vim. I believe this will cause it to be registered after the system ones, and then &syntax should be set up correctly.

OTHER TIPS

jszakmeister's answer diagnoses the problem accurately: filetype.vim sets the filetype for vimrc.

An alternative solution though, to keep everything contained in in your .vimrc file, is to use:

au BufNewFile,BufReadPre * if &syntax == '' | silent! execute (':set filetype='.matchstr(resolve(@%),'.[^.]*$')[1:]) | endif

Note the change from BufRead to BufReadPre. The change causes this line to execute before filetype.vim. The syntax will be changed to vimrc, but then subsequently changed to vim. The upshot is that the script works as it should, but syntax highlighting for vimrc is preserved.

When the current file is ~/.vimrc, this part of your code

matchstr(resolve(@%),'.[^.]*$')

returns your file name: .vimrc.

I have no idea how you could imagine that /home/username/.vimrc would produce vim.

This is rather obviously a bad approach for the problem you tried to solve but there's no bug: you get exactly what you ask for. Using the filename/extension for filetype can't work reliably (js vs javascript, py vs python…).

You will probably need a filename/filetype list or many if/elseif if you want your code to do what you want.

See :h syntax-loading.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top