2010-09-11 19:53:20 +00:00
|
|
|
vberthoux@users.sourceforge.netFrequently Asked Questions
|
2001-11-02 04:53:43 +00:00
|
|
|
==========================
|
|
|
|
|
|
|
|
* 1. Why do you call it "Exuberant Ctags"?
|
|
|
|
* 2. Why doesn't my editor work with these tag files?
|
|
|
|
* 3. What are these strange bits of text beginning with ;"?
|
|
|
|
* 4. Why doesn't XEmacs' Speedbar module work with Exuberant Ctags?
|
|
|
|
* 5. Why doesn't Xemacs correctly locate the tag in the source file?
|
|
|
|
* 6. Why doesn't NEdit correctly locate the tag in the source file?
|
|
|
|
* 7. Why can't I jump to "class::member"?
|
|
|
|
* 8. How can I avoid having to specify my favorite option every time?
|
|
|
|
* 9. Why do I end up on the wrong line when I jump to a tag?
|
|
|
|
* 10. How do I jump to the tag I want instead of the wrong one by the
|
|
|
|
same name?
|
|
|
|
* 11. What is "Vim"?
|
|
|
|
* 12. How can I locate all references to a specific function or variable?
|
|
|
|
* 13. Why does appending tags to a tag file tag so long?
|
|
|
|
* 14. How do I get regex support for Win32?
|
|
|
|
* 15. How should I set up tag files for a multi-level directory hierarchy?
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
1. Why do you call it "Exuberant Ctags"?
|
|
|
|
|
|
|
|
Because one of the meanings of the word "exuberant" is:
|
|
|
|
|
|
|
|
exuberant : produced in extreme abundance : PLENTIFUL syn see PROFUSE
|
|
|
|
|
|
|
|
Compare the tag file produced by Exuberant Ctags with that produced by any
|
|
|
|
other ctags and you will see how appropriate the name is.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
2. Why doesn't my editor work with these tag files?
|
|
|
|
|
|
|
|
3. What are these strange bits of text beginning with ;" which follow
|
|
|
|
many of the lines in the tag file?
|
|
|
|
|
|
|
|
These are "extension flags". They are added in order to provide extra
|
|
|
|
information about the tag that may be utilized by the editor in order to
|
|
|
|
more intelligently handle tags. They are appended to the EX command part of
|
|
|
|
the tag line in a manner that provides backwards compatibility with existing
|
|
|
|
implementations of the Vi editor. The semicolon is an EX command separator
|
|
|
|
and the double quote begins an EX comment. Thus, the extension flags appear
|
|
|
|
as an EX comment and should be ignored by the editor when it processes the
|
|
|
|
EX command.
|
|
|
|
|
|
|
|
Some non-vi editors, however, implement only the bare minimum of EX commands
|
|
|
|
in order to process the search command or line number in the third field of
|
|
|
|
the tag file. If you encounter this problem, use the option "--format=1" to
|
|
|
|
generate a tag file without these extensions (remember that you can set the
|
|
|
|
CTAGS environment variable to any default arguments you wish to supply). Then
|
|
|
|
ask the supplier of your editor to implement handling of this feature of EX
|
|
|
|
commands.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
4. Why doesn't XEmacs' Speedbar module work with Exuberant Ctags?
|
|
|
|
|
|
|
|
The default command line switches used by XEmacs for "etags" are not
|
|
|
|
compatible with Exuberant Ctags options. By default, Exuberant Ctags installs
|
|
|
|
a symbolic link, "etags", pointing to the ctags executable. When Exuberant
|
|
|
|
Ctags is started with the name "etags", it produces Emacs-style tag files by
|
|
|
|
default.
|
|
|
|
|
|
|
|
To fix this, add the following lines to your .emacs file, replacing the path
|
|
|
|
to "etags" with the path where the symbolic link was installed.
|
|
|
|
|
|
|
|
(autoload 'speedbar "speedbar")
|
|
|
|
(setq speedbar-fetch-etags-command "/usr/local/bin/etags"
|
|
|
|
speedbar-fetch-etags-arguments '("-f" "-"))
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
5. Why doesn't Xemacs correctly locate the tag in the source file?
|
|
|
|
|
|
|
|
This has been observed with version 20.3. It seems that when Xemacs searches
|
|
|
|
for a tag, it searches using the tag name instead of the search string located
|
|
|
|
in the TAGS file. This is a bug in Xemacs and does not occur in the GNU
|
|
|
|
version of Emacs.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
6. Why doesn't NEdit correctly locate the tag in the source file?
|
|
|
|
|
|
|
|
Versions of NEdit prior to 5.1 did not support the extended tag file format
|
|
|
|
generated by Exuberant Ctags by default. Either upgrade to version 5.1 or
|
|
|
|
specify the option "--format=1" when running ctags to output the old tag file
|
|
|
|
format.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
7. Why can't I jump to "class::member"?
|
|
|
|
|
|
|
|
Because, by default, ctags only generates tags for the separate identifiers
|
|
|
|
found in the source files. If you specify the --extra=+q option, then
|
|
|
|
ctags will also generate a second, class-qualified tag for each class member
|
|
|
|
(data and function/method) in the form class::member for C++, and in the form
|
|
|
|
class.method for Eiffel and Java.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
8. How can I avoid having to specify my favorite option every time?
|
|
|
|
|
|
|
|
Either by setting the environment variable CTAGS to your custom
|
|
|
|
options, or putting them into a .ctags file in your home directory.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
9. Why do I end up on the wrong line when I jump to a tag?
|
|
|
|
|
|
|
|
By default, ctags encodes the line number in the file where macro (#define)
|
|
|
|
tags are found. This was done to remain compatible with the original UNIX
|
|
|
|
version of ctags. If you change the file containing the tag without
|
|
|
|
rebuilding the tag file, the location of tag in the tag file may no longer
|
|
|
|
match the current location.
|
|
|
|
|
|
|
|
In order to avoid this problem, you can specify the option "--excmd=p",
|
|
|
|
which causes ctags to use a search pattern to locate macro tags. I have
|
|
|
|
never uncovered the reason why the original UNIX ctags used line numbers
|
|
|
|
exclusively for macro tags, but have so far resisted changing the default
|
|
|
|
behaviour of Exuberant Ctags to behave differently.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
10. How do I jump to the tag I want instead of the wrong one by the
|
|
|
|
same name?
|
|
|
|
|
|
|
|
A tag file is simple a list of tag names and where to find them. If there
|
|
|
|
are duplicate entries, you often end up going to the wrong one because the
|
|
|
|
tag file is sorted and your editor locates the first one in the tag file.
|
|
|
|
|
|
|
|
Standard Vi provides no facilities to alter this behavior. However, Vim
|
|
|
|
has some nice features to minimize this problem, primarly by examining all
|
|
|
|
matches and choosing the best one under the circumstances. Vim also provides
|
|
|
|
commands which allow for selection of the desired matching tag.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
11. What is "Vim"?
|
|
|
|
|
|
|
|
Vim is a vi-compatible editor available as source and compilable for any
|
|
|
|
platform. Yeah, I know the first reaction is to shy away from this. But you
|
|
|
|
will never regret getting it, and you will become greatly attached to its
|
|
|
|
features, which you can learn gradually. I would be willing to say that it
|
|
|
|
is the best vi-clone available within 4 light-years of Alpha Centauri. It
|
|
|
|
works (nearly) exactly like standard vi, but provides some incredibly useful
|
|
|
|
extensions (some of which I have participated in designing with the author).
|
2002-07-11 02:44:14 +00:00
|
|
|
Most Linux distributions have adopted Vim as its standard vi.
|
2001-11-02 04:53:43 +00:00
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
12. How can I locate all references to a specific function or variable?
|
|
|
|
|
|
|
|
There are several packages already available which provide this capability.
|
|
|
|
Namely, these are: GLOBAL source code tag system, GNU id-utils, cscope,
|
|
|
|
and cflow. As of this writing, they can be found in the following locations:
|
|
|
|
|
2003-07-03 06:08:21 +00:00
|
|
|
GLOBAL: http://www.gnu.org/software/global
|
2001-11-02 04:53:43 +00:00
|
|
|
id-utils: http://www.gnu.org/software/idutils/idutils.html
|
|
|
|
cscope: http://cscope.sourceforge.net
|
|
|
|
cflow: ftp://www.ibiblio.org/pub/Linux/devel/lang/c
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
13. Why does appending tags to a tag file tag so long?
|
|
|
|
|
|
|
|
Sometimes, in an attempt to build a global tag file for all source files in
|
|
|
|
a large source tree of many directories, someone will make an attempt to run
|
|
|
|
ctags in append (-a) mode on every directory in the hierarchy. Each time
|
|
|
|
ctags is invoked, its default behavior is to sort the tag file once the tags
|
|
|
|
for that execution have been added. As the cumulative tag file grows, the sort
|
|
|
|
time increases arithmetically.
|
|
|
|
|
|
|
|
The best way to avoid this problem (and the most efficient) is to make
|
|
|
|
use of the --recurse (or -R) option of ctags by executing the following
|
|
|
|
command in the root of the directory hierarchy (thus running ctags only once):
|
|
|
|
|
|
|
|
ctags -R
|
|
|
|
|
|
|
|
If you really insist on running ctags separately on each directory, you can
|
|
|
|
avoid the sort pass each time by specifying the option "--sort=no". Once the
|
|
|
|
tag file is completely built, use the sort command to manually sort the
|
|
|
|
final tag file, or let the final invocation of ctags sort the file.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
14. How do I get regex support for Win32?
|
|
|
|
|
|
|
|
You need to download the GNU regex package for Win32 from the following
|
|
|
|
location:
|
|
|
|
|
2002-07-11 02:44:14 +00:00
|
|
|
http://people.delphiforums.com/gjc/gnu_regex.html
|
2001-11-02 04:53:43 +00:00
|
|
|
|
|
|
|
Then point the makefile macro, REGEX_DIR, found in mk_mvc.mak and mk_bc5.mak,
|
|
|
|
to the directory created by extracting this archive.
|
|
|
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
15. How should I set up tag files for a multi-level directory hierarchy?
|
|
|
|
|
|
|
|
There are a few ways of approaching this:
|
|
|
|
|
|
|
|
1. A local tag file in each directory containing only the tags for source
|
|
|
|
files in that directory.
|
|
|
|
|
|
|
|
2. One single big, global tag file present in the root directory of your
|
|
|
|
hierarchy, containing all tags present in all source files in the
|
|
|
|
hierarchy.
|
|
|
|
|
|
|
|
3. A local tag file in each directory containing only the tags for source
|
|
|
|
files in that directory, in addition to one single global tag file
|
|
|
|
present in the root directory of your hierarchy, containing all
|
|
|
|
non-static tags present in all source files in the hierarchy.
|
|
|
|
|
|
|
|
4. A local tag file in each directory of the hierarchy, each one
|
|
|
|
containing all tags present in source files in that directory and all
|
|
|
|
non-static tags in every directory below it (note that this implies
|
|
|
|
also having one big tag file in the root directory of the hierarchy).
|
|
|
|
|
|
|
|
Each of these approaches has its own set of advantages and disadvantages,
|
|
|
|
depending upon your particular conditions. Which approach is deemed best
|
|
|
|
depends upon the following factors:
|
|
|
|
|
|
|
|
A. The ability of your editor to use multiple tag files.
|
|
|
|
|
|
|
|
If your editor cannot make use of multiple tag files (original vi
|
|
|
|
implementations could not), then one large tag file is the only way to
|
|
|
|
go if you ever desire to jump to tags located in other directories. If
|
|
|
|
you never need to jump to tags in another directory (i.e. the source
|
|
|
|
in each directory is entirely self-contained), then a local tag file
|
|
|
|
in each directory will fit your needs.
|
|
|
|
|
|
|
|
B. The time is takes for your editor to look up a tag in the tag file.
|
|
|
|
|
|
|
|
The significance of this factor depends upon the size of your source
|
|
|
|
tree and on whether the source files are located on a local or remote
|
|
|
|
file system. For source and tag files located on a local file system,
|
|
|
|
looking up a tag is not as big a hit as one might first imagine, since
|
|
|
|
vi implementations typically perform a binary search on a sorted tag
|
|
|
|
file. This may or may not be true for the editor you use. For files
|
|
|
|
located on a remote file system, reading a large file is an expensive
|
|
|
|
operation.
|
|
|
|
|
|
|
|
C. Whether or not you expect the source code to change and the time it
|
|
|
|
takes to rebuild a tag file to account for changes to the source code.
|
|
|
|
|
|
|
|
While Exuberant Ctags is particularly fast in scanning source code
|
|
|
|
(around 1-2 MB/sec), a large project may still result in objectionable
|
|
|
|
delays if one wishes to keep their tag file(s) up to date on a
|
|
|
|
frequent basis, or if the files are located on a remote file system.
|
|
|
|
|
|
|
|
D. The presence of duplicate tags in the source code and the ability to
|
|
|
|
handle them.
|
|
|
|
|
|
|
|
The impact of this factor is influenced by the following three issues:
|
|
|
|
|
|
|
|
1. How common are duplicate tags in your project?
|
|
|
|
|
|
|
|
2. Does your editor provide any facilities for dealing with duplicate
|
|
|
|
tags?
|
|
|
|
|
|
|
|
While standard vi does not, many modern vi implementations, such
|
|
|
|
as Vim have good facilities for selecting the desired match from
|
|
|
|
the list of duplicates. If your editor does not support duplicate
|
|
|
|
tags, then it will typically send you to only one of them, whether
|
|
|
|
or not that is the one you wanted (and not even notifying you that
|
|
|
|
there are other potential matches).
|
|
|
|
|
|
|
|
3. What is the significance of duplicate tags?
|
|
|
|
|
|
|
|
For example, if you have two tags of the same name from entirely
|
|
|
|
isolated software components, jumping first to the match found
|
|
|
|
in component B while working in component A may be entirely
|
|
|
|
misleading, distracting or inconvenient (to keep having to choose
|
|
|
|
which one if your editor provides you with a list of matches).
|
|
|
|
However, if you have two tags of the same name for parallel builds
|
|
|
|
(say two initialization routines for different hosts), you may
|
|
|
|
always want to specify which one you want.
|
|
|
|
|
|
|
|
Of the approaches listed above, I tend to favor Approach 3. My editor of
|
|
|
|
choice is Vim, which provides a rich set of features for handling multiple
|
|
|
|
tag files, which partly influences my choice. If you are working with
|
|
|
|
source files on a remote file system, then I would recommend either
|
|
|
|
Approach 3 or Approach 4, depending upon the hit when reading the global
|
|
|
|
tag file.
|
|
|
|
|
|
|
|
The advantages of Approach 3 are many (assuming that your editor has
|
|
|
|
the ability to support both multiple tag files and duplicate tags). All
|
|
|
|
lookups of tag located in the currect directory are fast and the local
|
|
|
|
tag file can be quickly and easily regenerated in one second or less
|
|
|
|
(I have even mapped a keystroke to do this easily). A lookup of a
|
|
|
|
(necessarily non-static) tag found in another directory fails a lookup in
|
|
|
|
the local tag file, but is found in the global tag file, which satisfies
|
|
|
|
all cross-directory lookups. The global tag file can be automatically
|
|
|
|
regenerated periodically with a cron job (and perhaps the local tag files
|
|
|
|
also).
|
|
|
|
|
|
|
|
Now I give an example of how you would implement Approach 3. Means of
|
|
|
|
implementing the other approaches can be performed in a similar manner.
|
|
|
|
|
|
|
|
Here is a visual representation of an example directory hierarchy:
|
|
|
|
|
|
|
|
project
|
|
|
|
`-----misccomp
|
|
|
|
| `...
|
|
|
|
`-----sysint
|
|
|
|
`-----client
|
|
|
|
| `-----hdrs
|
|
|
|
| `-----lib
|
|
|
|
| `-----src
|
|
|
|
| `-----test
|
|
|
|
`-----common
|
|
|
|
| `-----hdrs
|
|
|
|
| `-----lib
|
|
|
|
| `-----src
|
|
|
|
| `-----test
|
|
|
|
`-----server
|
|
|
|
`-----hdrs
|
|
|
|
`-----lib
|
|
|
|
`-----src
|
|
|
|
`-----test
|
|
|
|
|
|
|
|
Here is a recommended solution (conceptually) to build the tag files:
|
|
|
|
|
|
|
|
1. Within each of the leaf nodes (i.e. hdrs, lib, src, test) build a tag
|
|
|
|
file using "ctags *.[ch]". This can be easily be done for the whole
|
|
|
|
hierarchy by making a shell script, call it "dirtags", containing the
|
|
|
|
following lines:
|
|
|
|
|
|
|
|
#!/bin/sh
|
|
|
|
cd $1
|
|
|
|
ctags *
|
|
|
|
|
|
|
|
Now execute the following command:
|
|
|
|
|
|
|
|
find * -type d -exec dirtags {} \;
|
|
|
|
|
|
|
|
These tag files are trivial (and extremely quick) to rebuild while
|
|
|
|
making changes within a directory. The following Vim key mapping is
|
|
|
|
quite useful to rebuild the tag file in the directory of the current
|
|
|
|
source file:
|
|
|
|
|
|
|
|
:nmap ,t :!(cd %:p:h;ctags *.[ch])&<CR><CR>
|
|
|
|
|
|
|
|
2. Build the global tag file:
|
|
|
|
|
|
|
|
cd ~/project
|
|
|
|
ctags --file-scope=no -R
|
|
|
|
|
|
|
|
thus constructing a tag file containing only non-static tags for all
|
|
|
|
source files in all descendent directories.
|
|
|
|
|
|
|
|
3. Configure your editor to read the local tag file first, then consult
|
|
|
|
the global tag file when not found in the local tag file. In Vim,
|
|
|
|
this is done as follows:
|
|
|
|
|
|
|
|
:set tags=./tags,tags,~/project/tags
|
|
|
|
|
|
|
|
If you wish to implement Approach 4, you would need to replace the
|
|
|
|
"dirtags" script of step 1 with the following:
|
|
|
|
|
|
|
|
#!/bin/sh
|
|
|
|
cd $1
|
|
|
|
ctags *
|
|
|
|
# Now append the non-static tags from descendent directories
|
|
|
|
find * -type d -prune -print | ctags -aR --file-scope=no -L-
|
|
|
|
|
|
|
|
And replace the configuration of step 3 with this:
|
|
|
|
|
2010-09-11 19:53:20 +00:00
|
|
|
:set tags=./tags;$HOME,tags
|
2001-11-02 04:53:43 +00:00
|
|
|
|
|
|
|
As a caveat, it should be noted that step 2 builds a global tag file whose
|
|
|
|
file names will be relative to the directory in which the global tag file
|
|
|
|
is being built. This takes advantage of the Vim 'tagrelative' option,
|
|
|
|
which causes the path to be interpreted a relative to the location of the
|
|
|
|
tag file instead of the current directory. For standard vi, which always
|
|
|
|
interprets the paths as relative to the current directory, we need to
|
|
|
|
build the global tag file with absolute path names. This can be
|
|
|
|
accomplished by replacing step 2 with the following:
|
|
|
|
|
|
|
|
cd ~/project
|
|
|
|
ctags --file-scope=no -R `pwd`
|
|
|
|
|
|
|
|
--
|