When I open some bash script files with vim it sometimes identifies them as conf
files, that's okay, I can just correct that by setting the filetype to sh
with :setf sh
.
That great, except I've noticed that this doesn't fix things entirely:
Notice that shopt
is properly highlighted on the left, but not on the right, where I manually set the filetype to sh
.
This means that when a file is identified as bash
or sh
by vim, it sets the filetype to sh
but then does some extra steps that I'm not doing when I set the filetype manually.
Any one know what that might be, and how I could fix it?
vim already recognizes many file types by default. Most of them work by file extensions, but in a case like this, vim will also analyze the content of the file to guess the correct type.
vim sets the filetype for specific file names like .bashrc
, .tcshrc
, etc. automatically. But a file with a .sh
extension will be recognized as either csh, ksh or bash script. To determine what kind of script this is exactly, vim reads the first line of the file to look at the #! line.
If the first line contains the word bash
, the file is identified as a bash script. Usually you see #!/bin/bash
if the script is meant to be executed directly, for some other shell configuration file you should use the file extensions .bash
.
The help in vim explains this as well at :help ft-bash-syntax
. You can also use let g:is_bash=1
in your .vimrc to make bash syntax highlighting the default for all files with filetype=sh
. If you want to look at the details, this is implemented in $VIMRUNTIME/filetype.vim
.
It turns out that syntax/sh.vim
includes specific highlighting for Korn, Bash and sh, you just have to tell it which you're using. This is done with b:is_kornshell
, b:is_bash
and b:is_sh
respectively.
Depending on the situation I figure I'll use the following:
au BufRead,BufNewFile *bash* let g:is_bash=1
au BufRead,BufNewFile *bash* setf sh
# vim:let g:is_bash=1:set filetype=sh:
nmap <silent> <leader>b :let g:is_bash=1<cr> :setf sh<cr>
Similar to Peter Coulton's solution and documented as well as an alternative in the section "new-filetype" of the "filetype" Vim help the ~/.vim/filetype.vim
file could contain the following code:
if exists("did_load_filetypes")
finish
endif
augroup filetypedetect
au! BufRead,BufNewFile *bash* let b:is_bash = 1 | setfiletype sh
augroup END
This approach has the following implications:
~/.vim/filetype.vim
file instead of one for each file type under the ~/.vim/ftdetect
directory.b:is_bash
variable is set local to the buffer as opposed to global by referring to it as g:is_bash
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With