How tags work

by Eli the Bearded

(based on RTFSing Vim 4.5)

This is intended for people who have already read the help file text for ":help tags_and_searches" (all of section 8 in vim_ref.txt). It will primarily be of use to people creating tags files by hand or creating programs to create tags files. One ambiguity in that help is the bit about specifing multiple tags files (":help tags_option"). In vim, you can use either a comma or space seperated list, but in the plain vi's I have tried, only the space seperated list works. Vim also makes a distinction between "./tags" and "tags". The former looks for a tags file in the same directory as the currently edited file, the later in the current directory of the vim process.

The format of a line in a tags file takes one of two general forms. Here I use angle brackets to denote the entities of the two forms.

  1. <tag-name><whitespace><file><whitespace><command>
  2. <file><:><tag-name><whitespace><file><whitespace><command>

The first is a global tag, the second is a static tag. Note that the two occurances of file must be the same for a static tag. Wildcards may be for the <file>, but the comparison between the two names of a static tag is done before shell expansion. Also note that it is an error for the expansion to match more than one file.

<tag-name> is the string by which tag is activated. Normally it is some text which will be found on a line that the tag jumps to, but that need not be the case.

<file> is the file that <command> will be applied to.

<command> is interesting. There are three possible forms.

  1. </><search-text>
  2. <?><search-text>
  3. <ex-command>

In the first two forms things are quite restrictive. "/" vs "?" will determine the direction to search. Searching begins on the current line in the current file, or on the first line of a new file. <search-text> is not a regular expression. The only magic characters in it are the "^" and "$" anchors. A ending "/" or "?" may be appended, but trailing movements are not allowed. Thus while "/^text/+2" is legal normally, it is not allowed here. Note that you must backslash escape all backslashes in <search-text>. This seems to be there for backwards compatibility.

The third form of <command>, <ex-command> offers you the full power of the ":" commands availible in vim. The trivial case is just a number, which will jump you to that line. But there is much more to be had. Since a leading ":" will be ignored on any ":" command, prepending one is a good way to force a search to be executed normally. For example:

tag1	file1	/string[match]/
tag2	file1	:/string[match]/

tag1 and tag2 will behave very differently if you have "magic" searching enabled (ie regular expression searching), which you probably do because it is the default. The first will search for the RE "/search\[match\]/", while the second will search for the RE "/search[match]/".

Here are some interesting tags I tried and had success with:

six		tags	6
seven		tags	$-15
eight		tags	:$d|/^bar/+6
expl:map	expl	:map ` GA

Here's a really nasty one that almost works:

expl:mpp	expl	:$|normal A

The only problem with it is that the screen does not refresh and keys are not echoed until after you hit escape and return. This is true when "jumped" to from expl or another file. If we are lucky this will be fixed in the next version of vim. :^) (Actually further investigation has shown this to be a general limitation of the ":normal" command and not something specific to tags.)

It would be nice if you could use wildcards such as "*" in the filename feild of a tags file, so as to create a library of commands in a tags file and then use ":ta tagname" to execute the command sequence on the current file. But the wildcard can only match a single file. You can however use a trick like this:

command	/non/existant/file	:e #|s/ome/comands/

Vim will jump to the non-existant file and then execute the command field which will first jump the user back to the last file and then execute some commands on it. This is probably a lot better than cluttering up memory with scores of little used ":map" macros. For one thing there is much less chance of a name conflict, if you choose tagnames carefully. So when you by habit try to use it on another system, you will get an error and not actually run some weird command.

As a side note, this opens a new door for security holes in vim. A malicious user able to write to a tags file could create some very dangerous tags. The versions of vi I have played with don't go for fancy ex commands in tags files.



Last modified (05/02/97 11:36:08) by Benjamin Elijah Griffin.