January 31, 2007

Using tags to browse through source code

Author: Aleksey 'LXj' Alekseyev

When you read source code, often you need to look for definitions of functions, classes, or other objects. Editors such as Emacs and Vim help you browse the code by supporting the concept of tags. You can think of tags as labels that can be jumped to.

Each such label is actually a filename and a position in a file (stated via a line number or a regular expression), stored in a tags table file. Just what names from the described files are recorded in the tags table depends on the programming language and the tool you use to generate the tags table. They normally include all file names, functions, and subroutines, and may also include global variables, data types, and anything else convenient. Each name recorded is called a tag.

Emacs and Vim support different formats of tags tables. Emacs users use the etags utility (part of Emacs package), which creates a file called TAGS. Vim users use the Exuberant Ctags utility (in modern distributions it is usually preinstalled with Vim), which creates the tags file. Both files are created in the current working directory.

Using tags involves three steps: generating a tags table, telling your editor to look for tags in this generated file or files, and actually searching for definitions of tags.

To generate the the tags table file, run the appropriate utility, giving the input file name(s) as parameters (e.g. etags *.c). Exuberant Ctags has the option to generate one big tags table for all relevant files in a whole directory tree:

  cd ~/proj
  exuberant-ctags -R .

If you want to get the same effect from etags, you need to use the find utility:

  find . -name "*.[chCH]" -print | etags -

In this example we're finding all C files in the current directory and its subdirectories. etags - means to get file names from standard input.

In Emacs you use the command M-x visit-tags-table to select a tags table or add one to the list of selected ones.

Vim will automatically use the tags file from the current working directory. If you want to manually select the tags table(s), you can set the tags option:

  :set tags=~/proj/tags

You can use several filenames, separated by commas.

Tags tables format differences

Etags actually uses both line numbers and search patterns to define the file position. So if the position recorded in the tags table becomes a little bit wrong (due to other editing), the only consequence is a slight delay in finding the tag. The ctags format allows you to state either line number or search pattern, but not both.

That means that with both Exuberant Ctags and etags you should update a tags table when you define new tags that you want to have listed, or when you move tag definitions from one file to another, or when changes become substantial. Normally there is no need to update this kind of tags table after each edit, or even every day.

The drawback of the etags format is that tags are not sorted by name. This means that Emacs has to use a slow linear search algorithm when looking up in the tags table.

Searching for tags

When you are in Vim and you want to go to a tag definition, you can jump to it by using the command :tag <tag>, or simply press CTRL-] to jump to the tag of the word that is under the cursor. In Emacs use the command M-. <tag> RET (if the <tag> is empty, the word under the cursor will be used). After several jumps made by continuously invoking these commands, you may want to pop back: use the M-* command in Emacs and Ctrl-T in Vim.

If you want to split the view and see the tag definition in another window (so the contents of the current window are still shown), you can use a special command: in Emacs it is C-x 4 . <tag> RET and in Vim, :stag <tag>. If you want to look for the tag of the word that is under the cursor, leave <tag> as blank in Emacs and use the key combination Ctrl-W ] in Vim.

If there is more then one match for a tag, use C-u M-. and C-u - M-. in Emacs and :tnext and :tprevious in Vim to go to
the next/previous match.

You can use autocompletion by typing the first characters of the tag and pressing Tab in both editors. If you want to search for the tag by pattern, use C-M-. <pattern> RET in Emacs and browse through matches with C-u C-M-.. In Vim, start searching by typing :tag /<pattern> and end by pressing Tab. Press Tab again to cycle through matches.

Click Here!