2009-01-05

[Updated] I was always amazed by the way emacs gurus navigated through source code. It almost seemed like magic. They see some function call, and then with some short keyboard combo jump to another file, on the exact place where the function was defined.

The 'magic' in this case is a tag file. A tag file is a file that maintains an index of all the symbols in source code, where they are used and where they are defined. If you use grep and the like to look for things, you'll find tag files very useful.

There are different programs to create and deal with tag files; emacs ships with etags and there's also ctags. I'm not too familiar with those systems, but instead rely on GNU-Global for my tagging needs; it's available for Unix-like systems. The instructions below assume that you have installed GNU-Global.

tags from the command line

First, let's see how to create and update a tag file from the command line. GNU-Global works recursively on a directory tree; that is, you can run it in the top of your source directory, and it will then index all the files found, traversing through subdirectories. To create a tag file, go to the top of your source tree and run:

$ gtags

This will create a bunch of files (GPATH, GRTAGS, GSYMS and GTAGS) that together form your tagfile.
If you have run gtags before, and only want to update for changes in your source files, run:

$ global -u

This is usually much faster than running gtags. Also note that you can run this from anywhere in your source tree. The program will locate the G*-files by itself.

After that, you can search for symbols etc from the command line; please refer to the global man page for details. However, let's see how we can do all that from within emacs.

Using GNU-Global from emacs

GNU-Global comes with support for emacs, which makes it very convenient to use. It still relies on the command line to use create / update the tagfiles though; but we can do something about that with a bit of elisp. First, we define the following function djcb-gtags-create-or-update in our .emacs:

I've found GNU-Global fast enough to run djcb-gtags-create-or-update automatically. However, if you work with really huge code bases (for example, the linux kernel sources) it's better to use a tag file for some not-too-big sub-tree, or turn tagging off. To turn off automatic updating/creating tagging for some particular directory, you could do something like:
[Update: fix elisp error, thanks Anatoly]

instead of the above add-hook. You can then still run djcb-gtags-create-or-update by hand for some particular subdirectory.

usage

Now, having done all this, tagging is quite easy - and quickly through your source code is even easier. To find the definition of a function (or symbol), type M-. (Alt + dot). If your cursor is on a function name (or on other symbol), it will be the default target. Otherwise, you type the name; autocompletion is available with the Tab-key.

If you want to do the reverse, ie. finding all the uses of a certain symbol, use M-, (Alt + comma) and we get a list of locations. There are some more functions available, all starting with gtags-; see the built-in documentation for details.

Hi,I started emacs with 'emacs -q' to exclude any problems with my emacs init file. Then I evaluate:(autoload 'gtags-mode "gtags" "" t)

and I get the response in the mini-buffer:(autoload "gtags" "" t nil)

I next open a C++ file and run:M-x gtags-modebut I get the error in the mini-buffer:Cannot open load file: gtags

I had previously run gtags in the parent directory of where the C++ file is located, and I confirmed that the GRTAGS, GPATH and GTAGS files were created and that running 'global func' is able to find func.