Today I setup my Vim to use ctags.

I want to use it in the situation where I am deep in a project checking the backtrace of a bug and are wondering what exactly a method call does. With ctags I can just hover the call and press CTR + ] to jump to the method definition which lies anywhere in your repository.

If you are interested in such a setup, read on.

Installing ctags

Install ctags with your package manager. On Mac OS X the best way is to use brew:

brew install ctags

Configuring the git hooks

As I didn’t want to run ctags manually after every file change, I configured some Git hooks (check tpope’s blog for more background informations).

First, setup Git to use a templatedir when creating a repository or running git init.

git config --global init.templatedir '~/.git_template'
mkdir -p ~/.git_template/hooks

Then create a script (.git_template/hooks/ctags) which calls ctags to reindex the current repository. The content of this script looks like this:

#!/bin/sh
set -e
PATH="/usr/local/bin:$PATH"
trap "rm -f .git/tags.$$" EXIT
ctags --tag-relative -Rf.git/tags.$$ --exclude=.git --exclude=tmp --exclude=coverage --languages=-javascript,sql
mv .git/tags.$$ .git/tags

I already included the exclude directive for tmp and coverage which I don’t want to have indexed by ctags. Feel free to remove these or add any other.

Now, create all the Git hooks scripts (.git_template/hooks/post-checkout, .git_template/hooks/post-merge, .git_template/hooks/post-commit) with the following content:

#!/bin/sh
.git/hooks/ctags >/dev/null 2>&1 &

There is one special script (.git_template/hooks/post-rewrite) in which we have to catch the rebase hook only:

#!/bin/sh
case "$1" in
  rebase) exec .git/hooks/post-merge ;;
esac

As these scripts save your tags file in .git (= .git/tags), you don’t have to worry about adding it to .gitignore and its a project specific file. I wanted a project specific index as I don’t often search for methods which are saved in another Git repository. Another plus is, that the Vim plugin fugitive (which I strongly suggest to install) will automatically configure Vim for this file location.

Setup the repos

If you want to install these hooks in an existing repository, just use git init and it will copy them in. For new repositories, they will be created automatically.

Setup Vim

Vim has builtin support for ctags via its tags function, so none of the following plugins are really needed.

fugitive

Install fugitive which helps you a lot when writing stuff in a Git repository.

Tagbar

Consider using tagbar to have a sidebar with the ctags of your current buffer. In case you want to use tagbar, also think about opening it automatically. Put the following configuration in your vimrc:

autocmd VimEnter * TagbarToggle

Easytags

Maybe use easytags. It supports reindexing the ctags upon saving the buffer. If you want to use easytags, ensure that the configuration corresponds with the setup above:

" ensure it checks the project specific tags file
let g:easytags_dynamic_files = 1
" configure easytags to run ctags after saving the buffer
let g:easytags_events = ['BufWritePost']

Happy debugging!