Navigating code with Vim and ctags

Vim’s builtin tag integration is an incredibly easy way to jump from one source location to the definition of a function or class using Ctrl+]1 and Ctrl+t. To generate the tags file, I used to map the following command to <Leader>gt

:!ctags -R -f .tags --sort=yes --exclude=build --exclude=_build

As you probably can imagine, such command line will never cover all corner cases of files that need to be ex- or included. However, Git already knows about which files I’d like to ignore, so I now just feed the list of files already versioned to ctags which I map like this:

:!git ls-tree -r --name-only $(git rev-parse --abbrev-ref HEAD) <bar> ctags -f .tags --sort=yes -L -

To open and close the whole folds of target destinations prior and after the jumps, I use the following functions and maps:

function TagJumpForward()
    execute "tag " . expand("<cword>")
    try | foldopen! | catch | | endtry

function TagJumpBack()
    try | foldclose! | catch | | endtry

nnoremap <silent> <C-i> :call TagJumpForward()<CR>
nnoremap <silent> <C-t> :call TagJumpBack()<CR>

Finally, if you use CtrlP for buffer and file navigation, you should enable the tag support and map the launcher, for example to Ctrl+B

let g:ctrlp_extensions = ['tag']
nnoremap <C-b> :CtrlPTag<CR>

That reduces navigations like <C-p>foo_file_c<CR>/bar_func n n n to <C-b>bar_func.

  1. Ctrl+] is pretty hard to reach on a German keyboard layout, so I mapped that to Ctrl+i.