CTAGS Quick Reference

Introduction

ctags is a program that generates a file containing a dictionary matching C identifiers (and other things, e.g. macros) to source files/lines. It's very useful for browsing source code and support for it is integrated into editors like vi, Vim and emacs. See man ctags etc. for a more thorough explanation.

Generating the tags

You do this with an external program (i.e. not with your editor).

On my system there are at least five different programs for generating tags files:

  1. ctags
  2. etags
  3. gctags
  4. gnuctags
  5. ootags

They all seem to be different binaries. They differ in the support they provide for languages other than C, some are intended for emacs rather than vi and so on.

I haven't tried all combinations, but on my system (SUSE 9.1) ctags works well with C and Vim, and etags works well with C and XEmacs. ctags -e usually works OK for C and XEmacs.

Generating a tags file with ctags

There are lots of different ways to do this. The one I usually use is this (for C and Vim):


$ cd my_project
$ ctags -R --tag-relative -f ~/tags *
$ cd /usr/local/some_package
$ ctags -R -a --tag-relative -f ~/tags *

			

This keeps all the tags in one file ~/tags, which works regardless of the editor's current working directory. This avoids a lot of confusion, and works well for me because the way I use Vim involves changing directory often. First we're building the tags for the project we're working on, and then using the -a option to append tags for some package we may be using and wish to browse the source code of. Obviously we can add a few more packages with a few more invocations of ctags still using -a (append) until we've built up a tags file with everything in it we want. It's often worth encapsulating all this in a script somewhere so it's easy to rebuild the tags when the sources have changed a lot and it's getting out of date.

-R means recursive (go into subdirs), and --tag-relative is what makes the tags file work regardless of the current working directory of the editor's environment. By using -e as well as those other options, you can make a tags file suitable for XEmacs.

Non-GNU versions of ctags (e.g. on Solaris systems) may not have -R or --tag-relative options. In that case, use find in place of -R to retrieve all the files, and pass them to ctags as absolute paths:


$ find `pwd` -type f | xargs ctags -f ~/tags

		

By using `pwd` instead of . to mean the current directory we list filenames with absolute paths to go in the ~/tags file. This has the same effect as --tag-relative-- the tags file will work regardless of the editor's working directory.

Generating a tags file with etags

ctags might not always work as well for XEmacs as etags. Unfortunately etags has a completely different syntax from ctags… On my system, the etags equivalent of the above sequence of ctags commands is:


$ cd my_project
$ rm -f ~/tags
$ find `pwd` -type f -name '*.[hc]' | xargs etags -a -o ~/tags
$ cd /usr/local/some_package
$ find `pwd` -type f -name '*.[hc]' | xargs etags -a -o ~/tags

		

Note also that because we are invoking etags with xargs, we use etags in append mode always. This is because if the argument list is very long (which in this case it is quite likely to be), xargs may invoke etags more than once with different sections of the argument list. We want the subsequent invocations to append, or we'll only end up with tags for last section.

Telling Vim which tags file to use


:set tags+=~/tags

		

Type :help tags for more information.

Telling XEmacs which tags file to use

Add this line to ~/.xemacs/custom.el:


(setq tag-table-alist '(("" . "~/tags")))

		

Type C-h v tag-table-alist for more information.

Using tags

These are the most important tag commands:

Command XEmacs/GNU Emacs Vim
Jump to tag M-. CTRL-]
Jump back M-* CTRL-T
Next matching tag M-, :tn
Previous matching tag ? :tp
Find by name M-x find-tag :tag