This document configures Vim or GVim for auto-completion using Vim OmniComplete (built-in) and exuberant-ctags.
It should be noted that the exuberant-ctags project seems a bit dated, and potentially Universal Ctags is a better choice ctags.io.
-
Install exuberant-ctags:
This document configurs
apt-get install exuberant-ctags
- Install vim-pathogen
This makes installing vim plugins cleaner by placing plugins in .vim/bundle/
$ cd ~/.vim
$ mkdir autoload bundle
$ cd autoload
$ wget https://raw.githubusercontent.com/tpope/vim-pathogen/master/autoload/pathogen.vim
- Configure vim for pathogen
Add the pathogen configuration to .vimrc
" pathogen
call pathogen#infect()
call pathogen#helptags()
" vim settings:
filetype plugin indent on
syntax on
- Install the Scala plugin
The plugin should downloaded and placed in .vim/bundle/.
vim-scala can be found here: https://github.com/derekwyatt/vim-scala
- Configure ctags
Ctags works by indexing all include paths and supports most languages. At the time of this document, this does not include Scala, but thanks to this https://leonard.io/blog/2013/04/editing-scala-with-vim/ we have settings to support scala by adding the following to ~/.ctags
-langdef=scala
--langmap=scala:.scala
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|pro
tected)?[ \t]*class[ \t]+([a-zA-Z0-9_]+)/\4/c,classes/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|pro
tected)?[ \t]*object[ \t]+([a-zA-Z0-9_]+)/\4/c,objects/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|pro
tected)?[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*case class[ \t]+([a-zA-Z0
-9_]+)/\6/c,case classes/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|pro
tected)?[ \t]*case object[ \t]+([a-zA-Z0-9_]+)/\4/c,case objects/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|pro
tected)?[ \t]*trait[ \t]+([a-zA-Z0-9_]+)/\4/t,traits/
--regex-scala=/^[ \t]*type[ \t]+([a-zA-Z0-9_]+)/\1/T,types/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy|private[^ ]*(\[[a-z]*\])*
|protected)[ \t]*)*def[ \t]+([a-zA-Z0-9_]+)/\4/m,methods/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy|private[^ ]*|protected)[
\t]*)*val[ \t]+([a-zA-Z0-9_]+)/\3/l,constants/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy|private[^ ]*|protected)[
\t]*)*var[ \t]+([a-zA-Z0-9_]+)/\3/l,variables/
--regex-scala=/^[ \t]*package[ \t]+([a-zA-Z0-9_.]+)/\1/p,packages/
We also add our excludes for ctags via this file to simplify our ctag commands a bit:
--exclude=target
--exclude=examples
--exclude=.git
--exclude=.svn
--exclude=.hg
--exclude=node_modules
--exclude=bundle.js
--exclude=*.js.map
--exclude=*.min.*
--exclude=*.swp
--exclude=*.bak
--exclude=*.tar.*
You can validate this entry by running ctags --list-maps both before and after editing .ctags file.
-
Create the directory ~/.vim/tags to store the ctag files we generate next.
-
Create the ctags build script
First we define a list of include projects that we would want to index. In this example, there are a few C++ libraries that I use extensively in other projects. I want to index these for auto-complete. There are also external projects that I want to index, which often require having the -dev version of packages installed.
ctags-build.sh
#!/bin/bash
#
TAGPATH="${HOME}/.vim/tags"
cd $TAGPATH
echo "Building ctags in ${TAGPATH}"
# --------------------
# system libs
# c++
$(ctags-exuberant -R --sort=1 --c++-kinds=+p --fields=+iaS --extra=+q \
--language-force=C++ -f cpp /path/to/cpp_src)
# wxWidgets
$(ctags-exuberant -R --sort=yes --c++-kinds=+p --fields=+iaS --extra=+q \
--language-force=C++ -f wx /usr/include/wx-3.0/)
# libxml2
$(ctags-exuberant -R --sort=yes --c++-kinds=+p --fields=+iaS --extra=+q \
--language-force=C++ -f libxml2 /usr/include/libxml2/)
# --------------------
# local projects
$(ctags-exuberant -R --sort=yes --c++-kinds=+p --fields=+iaS --extra=+q \
--language-force=C++ -f tcanetpp /home/tca/src/github/tcanetpp/)
$(ctags-exuberant -R --sort=yes --c++-kinds=+p --fields=+iaS --extra=+q \
--language-force=C++ -f tcaxmlpp /home/tca/src/github/tcaxmlpp/)
$(ctags-exuberant -R --sort=yes --c++-kinds=+p --fields=+iaS --extra=+q \
--language-force=C++ -f tcajson /home/tca/src/github/tcajson/)
Technically, if --language-force= is not set, ctags will automatically discover, so this is generally not needed.
So, as another example, we use a Apache Spark based library spark-hbase-client. In this case, we will index the project and Apache Spark, both scala projects, by adding the following to our script.
# spark 2.3.0
$(ctags-exuberant -R --sort=yes --exclude=*.js -f spark-2.3.0 /opt/hadoop/src/spark-2.3.0/)
# spark-hbase-client
$(ctags-exuberant -R --sort=yes -f spark-hbase-client /home/tca/src/github/spark-hbase-client/)
Running this script should now generate ctag files in ~/.vim/tags/. Each of this directories should be added to your .vimrc using set tags+=~/.vim/tags/tagname. The .vimrc example below demonstrates this.
- Configure .vimrc
Lastly, we configure Vim for omnicomplete. There are other, newer vim plugins, such as neocomplete, but...this is not it. For clarity, the following is a complete .vimrc:
set tags+=~/.vim/tags/cpp
set tags+=~/.vim/tags/wx
set tags+=~/.vim/tags/libxml2
set tags+=~/.vim/tags/tcanetpp
set tags+=~/.vim/tags/tcaxmlpp
set tags+=~/.vim/tags/tcajson
set tags+=~/.vim/tags/spark-hbase-client
set tags+=~/.vim/tags/spark-2.3.0
" build .tags for current project via Ctrl-F12
map <C-F12> :!ctags-exuberant -R --sort=yes -f ./.tags<CR>
" OmniCppComplete
let OmniCpp_NamespaceSearch = 1
let OmniCpp_GlobalScopeSearch = 1
let OmniCpp_ShowAccess = 1
let OmniCpp_ShowPrototypeInAbbr = 1 " show function parameters
let OmniCpp_MayCompleteDot = 1 " autocomplete after .
let OmniCpp_MayCompleteArrow = 1 " autocomplete after ->
let OmniCpp_MayCompleteScope = 1 " autocomplete after ::
let OmniCpp_DefaultNamespaces = ["std", "_GLIBCXX_STD", "tcanetpp"]
" automatically open and close the popup menu / preview window
au CursorMovedI,InsertLeave * if pumvisible() == 0|silent! pclose|endif
set completeopt=menuone,menu,longest,preview
" pathogen
call pathogen#infect()
call pathogen#helptags()
" settings
set ofu=syntaxcomplete#Complete
set nocompatible
set expandtab
set sw=4
set vb
set sb
set si
set nocp
set history=50
set ruler
set showcmd
set cmdheight=2
set guifont=Inconsolata-g\ Medium\ 8
colors desert
filetype plugin on
Now completion targets should be offered <C-n>
and <C-p>
(next or previous match)
and open declaration via <Ctrl-]>
and <Ctrl-T>
to get back.
Another cool plugin https://majutsushi.github.io/tagbar/. Just download the package and extract to ~/.vim/bundle (I rename it to tagbar). Add the following to .vimrc to enable:
nmap <F8> :TagbarToggle<CR>