ctags etags gtags: How to Find Where a Function is Defined or Called?
if you work with a project new to you, that has tens of files or more in nested directories, you'll need this.
How do you quickly find where a function is called, or where a function is defined?
the classic tool for this is ctags. Basically, ctags
is a shell command. Run it to create a index file, then you can use command to quickly jump to a identifier (function)'s definition.
(using grep is much slower, because everytime it needs to search all the files. That's why ctags creates a index files first, which is basically the one-shot search result of all function names.)
ctags index file is named tags
.
The index file has a simple format, like this:
{‹tagname›}␉{‹tagfile›}␉{‹tagaddress›}
The fields are specified as follows:
{tagname}
- Any identifier, not containing white space
- ␉
- One tab character, although many versions of vi can handle any amount of white space. ␉
{tagfile}
-
The name of the file where
{tagname}
is defined, relative to the current directory {tagaddress}
- Ex mode command that will take the editor to the location of the tag. For POSIX implementations of vi this may only be a search or a line number.
Variations: ctags, etags, gtags (GNU Global)
There are many improvements of the ctags tool. They include:
- etags
- From emacs.
- gtags
-
GNU GLOBAL from GNU, with command name
gtags
andglobal
The index file format are similar or compatible with ctags.
GNU Global home page is at: http://www.gnu.org/software/global/
Install gtags on Ubuntu Linux
# install gnu global sudo apt-get install global
After intall, you have 2 commands:
gtags
- Generate index file.
global
- Locate identifiers.
See man gtags
and man global
See the official gtags tutorial at http://www.gnu.org/software/global/globaldoc_toc.html
how to make etags Index Clojure Files?
there's this regex from http://nakkaya.com/2009/12/13/getting-etags-to-index-clojure-files/ and http://stackoverflow.com/questions/1481842/clojure-emacs-etags
find . \! -name '.*' -name '*.clj' | xargs etags --regex='/[ \t\(]*def[a-zA-Z!$%&*+\-.\/:<=>?@^_~]*[ \n\t]+\(\^{[^}]*}[ \n\t]+\|\)\([a-zA-Z!$%&*+\-.\/:<=>?@^_~]+\)/\2/s' --regex='/[ \t\(]*ns \([a-z.]+\)/\1/'
but it doesn't work for me
for now, just use emacs rgrep. [see Emacs: Searching for Text in Files (grep, find)]
or use this emacs command, which calls git grep.
(defvar gitgrep-history nil) (defun gitgrep (@search-string) "call git grep to search symbols in a project. 2014-11-19 by “Left Right” https://plus.google.com/113859563190964307534/posts/CyEsoyhkTVe " (interactive (let (($sym (thing-at-point 'symbol))) (list (completing-read "String to search for: " (list $sym (buffer-name) (buffer-file-name)) 'identity nil $sym gitgrep-history $sym)))) (grep (format "git --no-pager grep -P -n '%s'" @search-string)))