There are several tools to create a tags file. The two dominant tools are [[etags?]] and ExuberantCtags. Etags comes with Emacs and ExuberantCtags is separate but available on most systems. ExuberantCtags is the better choice as it supports more languages and is more robust.
To use ctags with emacs, you must supply the
‘-e’ parameter to instruct ctags to generate an emacs tag file. The commands below are often sourced into a Makefile and then run with a CompileCommand.
cd /path/to/my/project ctags -e myfile.cpp
Ctags also has a recursive option,
‘-R’. This is the most common (and simple) usage. To generate tags for all files that ctags recognizes, simply execute this from the terminal:
cd /path/to/my/project ctags -e -R .
You can filter it to specific extensions if needed:
cd /path/to/my/project ctags -e -R *.cpp *.hpp *.h
EDIT: It seems that with recent version of ctags, there is no “-e” option.
‘ctags’ makes an alias to
‘etags’, and when using this alias, it creates an emacs tag file. The way I generate the tags for my project is (not the best, but it works!):
cd /path/to/my/project find . | grep ".*\.\(hh\|hxx\|cc\)" | xargs etags -f TAGS
Put this in your init file:
(setq path-to-ctags "/opt/local/bin/ctags") ;; <- your ctags path here
(defun create-tags (dir-name) "Create tags file." (interactive "DDirectory: ") (shell-command (format "%s -f %s/TAGS -e -R %s" path-to-ctags dir-name (directory-file-name dir-name))) )
Then, once it has been evaluated, you can invoke it via `m-x create-tags’
First, see a list of languages supported by etags by running `etags --help’.
To generate tags for certain source files (like *.el files), invoke this:
cd /path/to/my/project etags *.el
To recurse through directories, run something like this:
cd /path/to/my/project find . -type f -iname "*.[ch]" | etags -
FYI: If you want to use
‘etags’, you have to use the --append flag (e.g.
find . -type f -iname "*.[ch]" | xargs etags --append). Otherwise, etags will overwrite the tags file for each file it gets from xargs.
Put this in your init file:
(defun create-tags (dir-name) "Create tags file." (interactive "DDirectory: ") (eshell-command (format "find %s -type f -name \"*.[ch]\" | etags -" dir-name)))
;;; Jonas.Jarnestrom<at>ki.ericsson.se A smarter ;;; find-tag that automagically reruns etags when it cant find a ;;; requested item and then makes a new try to locate it. ;;; Fri Mar 15 09:52:14 2002
(defadvice find-tag (around refresh-etags activate) "Rerun etags and reload tags if tag not found and redo find-tag. If buffer is modified, ask about save before running etags." (let ((extension (file-name-extension (buffer-file-name)))) (condition-case err ad-do-it (error (and (buffer-modified-p) (not (ding)) (y-or-n-p "Buffer is modified, save it? ") (save-buffer)) (er-refresh-etags extension) ad-do-it))))
(defun er-refresh-etags (&optional extension) "Run etags on all peer files in current dir and reload them silently." (interactive) (shell-command (format "etags *.%s" (or extension "el"))) (let ((tags-revert-without-query t)) ; don't query, revert silently (visit-tags-table default-directory nil)))
It just works with ExuberantCtags and etags, as both recognize the language based on extension.
If you happen to need to use two separate tags programs (like rtags and ctags) to parse all languages used in a project, just append one to the other.