Book HomeLearning the vi EditorSearch this book

8.5. Enhanced Tags

The "Exuberant ctags" program is a ctags clone that is considerably more capable than UNIX ctags. It produces an extended tags file format that makes tag searching and matching a more flexible and capable process. We describe it first, since it is supported by several of the vi clones.

This section also describes tag stacks: the ability to save multiple locations visited with the :tag or ^] commands. All of the clones provide tag stacking.

8.5.1. Exuberant ctags

The "Exuberant ctags" program was written by Darren Hiebert. Its home page is http://home.hiwaay.net/~darren/ctags/. As of this writing, the current version is 2.0.3. The following list of the program's features is adapted from the README file in the ctags distribution:

Exuberant ctags produces tags files in the form described in the next subsection.

8.5.2. The New tags Format

Traditionally, a tags file has three tab-separated fields: the tag name (typically an identifier), the source file containing the tag, and an indication of where to find the identifier. This indication is either a simple line number, or a nomagic search pattern enclosed either in slashes or question marks. Furthermore, the tags file is always sorted.

This is the format generated by the UNIX ctags program. In fact, many versions of vi allowed any command in the search pattern field (a rather gaping security hole). Furthermore, due to an undocumented implementation quirk, if the line ended with a semicolon and then a double-quote (;"), anything following those two characters would be ignored. (The double-quote starts a comment, as it does in .exrc files.)

The new format is backwards-compatible with the traditional one. The first three fields are the same: tag, filename, and search pattern. Exuberant ctags only generates search patterns, not arbitrary commands. Extended attributes are placed after a separating ;". Each attribute is separated from the next by a tab character, and consists of two colon-separated subfields. The first subfield is a keyword describing the attribute, the second is the actual value. Table 8.2 lists the supported keywords.

Table 8.2. Extended ctags Keywords

Keyword Meaning
kind

The value is a single letter that indicates the lexical type of the tag. It can be f for a function, v for a variable, and so on. Since the default attribute name is kind, a solitary letter can denote the tag's type (e.g., f for a function).

file

For tags that are "static", i.e., local to the file. The value should be the name of the file.

If the value is given as an empty string (just file:), it is understood to be the same as the filename field; this special case was added partly for the sake of compactness, and partly to provide an easy way to handle tags files that aren't in the current directory. The value of the filename field is always relative to the directory in which the tags file itself resides.

function

For local tags. The value is the name of function in which they're defined.

struct

For fields in a struct. The value is the name of the structure.

enum

For values in an enum data type. The value is the name of the enum type.

class

For C++ member functions and variables. The value is the name of the class.

scope

Intended mostly for C++ class member functions. It will usually be private for private members or omitted for public members, so users can restrict tag searches to only public members.

arity

For functions. The number of arguments.

If the field does not contain a colon, it is assumed to be of type kind. Here are some examples:

ARRAYMAXED      awk.h    427;"   d
AVG_CHAIN_MAX   array.c   38;"   d     file:
array.c         array.c    1;"   F

ARRAYMAXED is a C #define macro defined in awk.h. AVG_CHAIN_MAX is also a C macro but it is used only in array.c. The third line is a bit different: it is a tag for the actual source file! This is generated with the -i F option to Exuberant ctags, and allows you to give the command :tag array.c. More usefully, you can put the cursor over a filename and use the ^] command to go to that file.

Within the value part of each attribute, the characters backslash, tab, carriage return and newline should be encoded as \\, \t, \r, and \n, respectively.

Extended tags files may have some number of initial tags that begin with !_TAG_. These tags usually sort to the front of the file, and are useful for identifying which program created the file. Here is what Exuberant ctags generates:

!_TAG_FILE_FORMAT      2                /extended format; ..../
!_TAG_FILE_SORTED      1                /0=unsorted, 1=sorted/
!_TAG_PROGRAM_AUTHOR   Darren Hiebert   /darren@hiebert.com/
!_TAG_PROGRAM_NAME     Exuberant Ctags  //
!_TAG_PROGRAM_URL      http://home.hiwaay.net/~darren/ctags   /.../
!_TAG_PROGRAM_VERSION  2.0.3            /with C++ support/

Editors may take advantage of these special tags to implement special features. For example, vim pays attention to the !_TAG_FILE_SORTED tag and will use a binary search to search the tags file instead of a linear search if the file is indeed sorted.

If you use tags files, we recommend that you get and install Exuberant ctags.

8.5.3. Tag Stacks

The :tag ex command and the ^] vi mode command provide a limited means of finding identifiers, based on the information provided in a tags file. Each of the clones extends this ability by maintaining a stack of tag locations. Each time you issue the :tag ex command, or use the ^] vi mode command, the editor saves the current location before searching for the specified tag. You may then return to a saved location using (usually) the ^T command or an ex command.

Solaris vi tag stacking and an example are presented below. The way each clone handles tag stacking is described in each editor's respective chapter.

8.5.3.1. Solaris vi

Surprisingly enough, the Solaris 2.6 version of vi supports tag stacking. Perhaps not so surprisingly, this feature is completely undocumented in the Solaris ex(1) and vi(1) manual pages. For completeness, we summarize Solaris vi tag stacking in Table 8.3, Table 8.4, and Table 8.5. Tag stacking in Solaris vi is quite simple.[43]

[43]This information was discovered based on experimentation. YMMV (your mileage may vary).

Table 8.3. Solaris vi Tag Commands

Command Function
ta[g][!] tagstring

Edit the file containing tagstring as defined in the tags file. The ! forces vi to switch to the new file if the current buffer has been modified but not saved.

po[p][!]

Pop the tag stack by one element.

Table 8.4. Solaris vi Command Mode Tag Commands

Command Function
^]

Look up the location of the identifier under the cursor in the tags file, and move to that location. If tag stacking is enabled, the current location is automatically pushed onto the tag stack.

^T

Return to the previous location in the tag stack, i.e., pop off one element.

Table 8.5. Solaris vi Options for Tag Management

Option Function
taglength, tl

Controls the number of significant characters in a tag that is to be looked up. The default value of zero indicates that all characters are significant.

tags, tagpath

The value is a list of filenames in which to look for tags. The default value is "tags /usr/lib/tags".

tagstack

When set to true, vi stacks each location on the tag stack. Use :set notagstack to disable tag stacking.

To give you a feel for using tag stacks, we present a short example, using Exuberant ctags and vim.

Suppose you are working with a program that uses the GNU getopt_long function, and that you need to understand more about it.

GNU getopt consists of three files, getopt.h, getopt.c, and getopt1.c.

First, you create the tags file, then you start by editing the main program, found in main.c:

$ ctags *.[ch]
$ ls
Makefile   getopt.c   getopt.h   getopt1.c   main.c   tags
$ vim main.c
Keystrokes Results
/getopt Figure

Edit main.c and move to the call to getopt_long.

^] Figure

Do a tag lookup on getopt_long. vim moves to getopt1.c, placing the cursor on the definition of getopt_long.

It turns out that getopt_long is a "wrapper" function for _getopt_internal. You place the cursor on _getopt_internal and do another tag search.

Keystrokes Results
8jf_ ^] Figure

You have now moved to getopt.c. To find out more about struct option, move the cursor to option and do another tag search.

5jfo; ^] Figure

The editor moves to the definition of struct option in getopt.h. You may now look over the comments explaining how it's used.

:tags Figure

The :tags command in vim displays the tag stack.

Typing ^T three times would move you back to main.c, where you started. The tag facilities make it easy to move around as you edit source code.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.