I was told when add a line like # vim: filetype=r in a file, vim can recognizes the file type. It seems that for some files like *.cpp,*.java, vim can recognize the file while for files like *.CPP, *.JAVA, it needs the first line information.

I have two questions. The first is that what should I type in the first line of a *.sh shell script file? The second is that is there any list for the extension names or the extension name to be typed in the first line is simply the extension name of the original file with all letters in small case?

BTW, I've read this link, but didn't find my answer.


2 Answers 2


The reason Vim detects the filetype for *.cpp and not for *.CPP files is that Vim has auto-commands for *.cpp setting the filetype, but nothing for *.CPP:

:au BufRead *.cpp
--- Auto-Commands ---
filetypedetect  BufRead
    *.cpp     if exists("cynlib_syntax_for_cpp")|setf cynlib|else|setf cpp|endif

:au BufRead *.java
--- Auto-Commands ---
filetypedetect  BufRead
    *.java    setf java

:au BufRead *.CPP
--- Auto-Commands ---

What you need is a similar autocmd for *.CPP and *.JAVA files:

au BufRead *.CPP setf cpp
au BufRead *.JAVA setf java

You can add these to your .vimrc, or more appropriately from an organizational view, to a .vim file in ~/.vim/ftdetect/.

For .sh files, Vim should already be detecting the filetype correctly, and the filetype would be sh.

# vim: filetype=r is a modeline:

There are two forms of modelines.  The first form:
   vi:noai:sw=3 ts=6 
   vim: tw=77 

The second form (this is compatible with some versions of Vi):

        [text]{white}{vi:|vim:|Vim:|ex:}[white]se[t] {options}:[text]
   /* vim: set ai tw=75: */ 
   /* Vim: set ai tw=75: */

If you absolutely must use a modeline, try something like the following after the shebang:

# vim: ft=sh

The filetypes are not necessarily the extensions. For example, .conf files can have a filetype of apache, .sh files can have a filetype of zsh if the shebang is #! /bin/zsh, and so on. Open a file for which you know the filetype is correctly detected and run set ft?:

:set ft?

The default rules for setting the filetype are in $VIMRUNTIME/filetype.vim:

vim +'e $VIMRUNTIME/filetype.vim'

Look for setf in that file.


I have a file that was installed as part of neovim


That file lists all the default filetypes defined in vim.

So for example I wanted to know what files vim considers to be of cpp type.

" Cynlib
" .cc and .cpp files can be C++ or Cynlib.
au BufNewFile,BufRead *.cc
    \ if exists("cynlib_syntax_for_cc")|setf cynlib|else|setf cpp|endif
au BufNewFile,BufRead *.cpp
    \ if exists("cynlib_syntax_for_cpp")|setf cynlib|else|setf cpp|endif

" C++
au BufNewFile,BufRead *.cxx,*.c++,*.hh,*.hxx,*.hpp,*.ipp,*.moc,*.tcc,*.inl setf cpp
if has("fname_case")
  au BufNewFile,BufRead *.C,*.H setf cpp

" .h files can be C, Ch C++, ObjC or ObjC++.
" Set c_syntax_for_h if you want C, ch_syntax_for_h if you want Ch. ObjC is
" detected automatically.
au BufNewFile,BufRead *.h           call dist#ft#FTheader()

FTheader is defined in /usr/share/nvim/runtime/autoload/dist/ft.vim

func dist#ft#FTheader()
  if match(getline(1, min([line("$"), 200])), '^@\(interface\|end\|class\)') > -1
    if exists("g:c_syntax_for_h")
      setf objc
      setf objcpp
  elseif exists("g:c_syntax_for_h")
    setf c
  elseif exists("g:ch_syntax_for_h")
    setf ch
    setf cpp

Your Answer

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

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