Ctags is a source code indexing tool. With ctags, we can easily find the definitions of the classes, functions, and variables. According to my experiences, ctags can significantly reduce the time to browse the source code. In this post, I would like to give a brief introduction to ctags and vim.
First, we have to install
exuberant-ctags package for ctags. On
Ubuntu or Debian, we can install
$ sudo apt-get install exuberant-ctags
Second, I would suggest to tweak the
.vimrc as well. By default,
vim will only load the tags file from:
- the current working directory, or
- the directory containing the opened source file.
For example, if you have opened the file
foo/bar.c, then vim will
only check the tags file named after
foo/TAGS. However, the tags file in the
parent directories, such as
../../tags won't be considered.
To ask vim to search for tags file in the parent directories, we should
add an extra semicolon
Third, if you wish to put the generated tags file in the
directory so that the tags file won't be added to git repository, then you
may wish to add the following snippets to the
.vimrc as well:
" Check .git/tags for ctags file. fun! FindTagsFileInGitDir(file) let path = fnamemodify(a:file, ':p:h') while path != '/' let fname = path . '/.git/tags' if filereadable(fname) silent! exec 'set tags+=' . fname endif let path = fnamemodify(path, ':h') endwhile endfun augroup CtagsGroup autocmd! autocmd BufRead * call FindTagsFileInGitDir(expand("<afile>")) augroup END
This snippet allows vim to search for the tags file in the
directory of the parent directories of the source file, such as
After installation, we have to generate the tags file as the index. We can generate the tags file with the following commands:
$ ctags -R [dir] $ ctags -R -f [tags-file] [dir] $ ctags --tag-relative=yes -R -f [tags-file] [dir]
Usually, I prefer to run this command in the git repository:
$ ctags --tag-relative=yes -R -f .git/tags .
It is highly recommended to add
--tag-relative=yes to the
command. Without this option, vim won't be able to open the correct source
file under certain circumstances.
Sometimes, there might be some special naming convention in your project. To
index those files, we can change the programming language map with
--langmap option. For example, to treat the
extension as C++ source code:
$ ctags --langmap=c++:+*.inc ...
This options adds
.inc to the C++ file extensions (in addition to the
default file extensions such as
.cpp, and etc.)
After generating the tags file, we can browse the source code with vim and ctags. Vim has excellent built-in support for ctags. We can simply jump to or preview the definition with a little key stroke. Here are some combinations for your reference.
First, we can jump to the matching patterns with the
If we are not satisfied by the first match, we can jump to the next match
:tn. Conversely, we can jump to the previous match with
:tN. We can also list all matches with
|:ta [pattern]||Jump to the best matching tag|
|:ta /[regex]||Jump to the best matching tag|
|:ts [pattern]||List the tags and jump to the selected one|
|:ts /[regex]||List the tags and jump to the selected one|
|:tn||Jump to next matching tag|
|:tN||Jump to previous matching tag|
Here are some tips to search for the keyword pointed by the cursor:
- To show the best matching in the new window, press
]. (This is my favorite!)
- To list all matchings and show the selected one in the new window, press
- To jump to the best matching directly, press
- To list all matchings and jump to selected one, press
- To search a pattern by selection, press
vto enter visual mode, select the text, and press either
The preview window is a separated window that will pop up on the top for
quick reference. Unlike the "
]" command mentioned
above, the cursor won't be moved to the preview window.
To preview the keywords pointed by the cursor, press
}. Alternatively, we can open the preview window by the
command. To close the preview window, use the
|:pt [pattern]||Preview the best matching tag|
|:ptn||Preview the next matching tag|
|:ptN||Preview the previous matching tag|
|:pc||Close the preview window|
If we jump to a matching tag with
g], we may wish to go
back and forth. When we jump to a new tag, the current position will be pushed
to the tag stack. To go back to previous position (i.e. pop the tag
stack), we can use the
:po command. To go forward, we can use the
|:tags||List the tag stack|
|:po||Pop the tag stack (go up)|
|:ta||Push the tag stack (go down)|
In this post, we gave a brief introduction to the basic usages of ctags. We
have mentioned some handy
.vimrc tweaks and some important ctags
option. Besides, we have walked through several useful vim commands for
code browsing and navigation. This should would be sufficient for most
use cases. You can find more materials from the references.
Last, but not the least, I would like to say that ctags is an amazing source code indexing tool. I found my programming productivity has been significantly improved by ctags. Hope you enjoy it too. Happy coding!