Blog Archives

C++ AutoComplete feature in VIM

I really needed a context-sensitive C++ autocomplete feature for Vim, which would allow me to do crazy things like autocompleting class member names.  As it turns out, there is a way to do that, and it works pretty well.  I decided to write up how I set things up myself, in hopes that this will help others as well.

Here is what you need in order to set things up:

So, you need to install Vim and Ctags (which is platform dependent, and I leave it to you to figure out how to do that in your own platform).  Once you get those set up, grab the OmniCppComplete plugin, and extract it to the .vim directory under your home directory (create it if it doesn’t exist).  After that, you want to put the following inside your ~/.vimrc:

" omnicppcomplete options
map  :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q -f ~/.vim/commontags /usr/include /usr/local/include ~/moz/obj-ff-dbg/dist/include
set tags+=~/.vim/commontags

" --- OmniCppComplete ---
" -- required --
set nocp " non vi compatible mode
filetype plugin on " enable plugins

" -- optional --
" auto close options when exiting insert mode or moving away
autocmd CursorMovedI * if pumvisible() == 0|pclose|endif
autocmd InsertLeave * if pumvisible() == 0|pclose|endif
set completeopt=menu,menuone

" -- configs --
let OmniCpp_MayCompleteDot = 1 " autocomplete with .
let OmniCpp_MayCompleteArrow = 1 " autocomplete with ->
let OmniCpp_MayCompleteScope = 1 " autocomplete with ::
let OmniCpp_SelectFirstItem = 2 " select first item (but don't insert)
let OmniCpp_NamespaceSearch = 2 " search namespaces in this and included files
let OmniCpp_ShowPrototypeInAbbr = 1 " show function prototype (i.e. parameters) in popup window
let OmniCpp_LocalSearchDecl = 1 " don't require special style of function opening braces

" -- ctags --
" map +F12 to generate ctags for current folder:
map  :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
" add current directory's generated tags file to available tags
set tags+=./tags

" Setup the tab key to do autocompletion
function! CompleteTab()
  let prec = strpart( getline('.'), 0, col('.')-1 )
  if prec =~ '^\s*$' || prec =~ '\s$'
    return "\"
  else
    return "\\"
  endif
endfunction

inoremap  =CompleteTab()

You can of course customize this however you like, but the only part that you really need to customize is the second line.  You would probably want to leave /usr/include and /usr/local/include there, but you can replace ~/moz/obj-ff-dbg/dist/include to whatever project specific directory which contains header files which contain definitions which you want to include in the C++ autocompletion.  ~/moz/obj-ff-dbg/dist/include is a path on my system which contains all header files we use in Mozilla.

The autocompletion functionality is based on the ctags database.  This is a list of all symbols found in header files.  With this setup, you have two separate ctags databases, one is for your system-wide headers (which should change rarely), and the other is for your project-specific symbols.  The former is stored in ~/.vim/commontags, and the latter is stored as a file named tags in your current directory.  To update the system-wide ctags database, you can use Ctrl+X, Ctrl+X, Ctrl+T.  To update the local ctags database (which is created from the contents of the current directory, recursively), you can use Ctrl+X Ctrl+T.  You would usually update the local ctags database from time to time to make sure that the latest changes in your source files are reflected in the ctags database.

Now, open a C++ file inside Vim.  Let’s say you type the beginning of a symbol, and then press Tab.  A list of symbols matching what you have types appear on the screen, like this:

Autocompletion using tab

Also, if you type ., -> or ::, you will be presented with a list of autocomplete options as well.

Autocompletion after .Autocompletion after ->Autocompletion after ::

And that’s it! If you feel adventurous, you can type :help omnicpp in Vim and start exploring what else you can do, but this setup is working perfectly fine for me.

Posted in Blog Tagged with: ,