vi
and tags
The vi
editor, and the significant vi-clones, as well as Emacs and
other editors, support a thing called a "tags file". It's essentially
a set of bookmarks or a book's "Index" section fore text files.
The intended use is you run a program that indexes your source code
and creates the tag entries for you. For example, with ctags
you
can run it and have it scan source code in dozens of languages (not
just C-like ones, such as Java and Go, but also Postscript, Fortran,
and others) and produce a file that tells the editor how to find
function and variable declarations. (For Emacs, use the etags
program to similar effect.)
The tags functionality is very useful when editing code. I keep tags
files in source directories for all of my multi-year projects. You can
begin and edit session by running vi -t pickle
to open the editor
to the file and line that pickle()
is defined. Say inside pickle()
you find a call to spices()
and want to know what it does, position
your cursor in the word and hit <ctrl-]>, you jump there. Return
to where you were with a :pop
. Without the keyword handy to
<ctrl-]> upon, you can instead :tag spices
as well.
For people using vim
as their vi
of choice, it might help to know
that the entirety of the :help
system is built using tags, just
slightly tweaked for where to look for the tags file. If you know how
to use help in Vim, you know how to use tags. And :help tags
can
probably teach you something you didn't already know about them.
The tags files are a little more mysterious. Normally people don't create or edit them by hand, but you can or you can create programs to create them for your own special needs.
The basic format, and all I'll cover here, is a text file with three
tab separated columns. The first column is the tag name, eg pickle
.
The second column is the file name, relative to where the tags file
is located. The third column is a ex
-mode movement within the file.
Usually the movement is a search, something like /^int pickle(recipe_t rec)$/
that will unambigously find a single line in the file. But line
numbers also work just fine. And search with line number offset works
for niche needs, eg /^int pickle(.*)$/+2
to start out on
the variable declarations if your syntax looks like the following
sample. With :set scrolloff=3
to put some space above the cursor,
it may be more useful for you.
#include "brine.h" int pickle(recipe_t rec) { long cuke; int salt; spices_t spicing = spices(rec); /* ... */ }
In traditional vi
any command you could put on a :
line would
work in the movement column, including things like :! rm *
. I know
Vim has tightened that, and I believe the other vi-clones have as
well. If Vim doesn't like any movement in a tags file, it will ignore
the whole file.
One trick I have found useful is programmatically generated tags files
created with a wrapper program. Rather than have a giant file with all
tags, I have a database that I can query and then it generates a tags
file (with a single entry) and invokes vim -t main
to jump to the
exact file and line for me. This can make my query easier to form than
remembering a specific tag keyword and does not involve a large flat
file with huge redundancy.