Tips on using Ctags with Emacs
Ctags is critical to my web projects. I use it for code navigation by M-x find-tag
and code auto-completion by using company-ctags plus company-mode.
The first tip is to use global variable tags-table-list
instead of tags-file-name
. The Emacs documentation says you should NOT set both. tags-table-list
is better because it's a list, where you can store multiple tag files.
Here is the value of tags-table-list
for one project:
("/Users/cb/projs/their-project/test/cdn/test/assets/test/js/TAGS" "/Users/cb/projs/their-project/test/app/TAGS")
The purpose to use multiple tag files in sub-folders instead of one tag file in root folder is to scan less code files.
The second tip is we can avoid feeding big js files to ctags. Currently one of my client's project is not managed well. They place the concatenated js files, third party js libraries, and normal code file into one folder. The naming of files is a mess. So I can not tell which is which from file name or file path. The tag file created from those big concatenated js files will crash my Emacs.
Changing the ctags command line will solve the problem. Here is the actual liner to create a tag file:
find proj-dir -type f -not -iwholename '*TAGS' -not -size +16k | ctags -f ~/proj/output/TAGS -e -L -
The point is the option -not -size +16k
. It means only handle files less thank 16k.
Here is the Emacs lisp function to wrap above shell command:
(defun my-create-tags-if-needed (SRC-DIR CTAGS-OPTS &optional FORCE)
"return the full path of tags file"
;; TODO save the CTAGS-OPTS into hash
(let ((dir (file-name-as-directory (file-truename SRC-DIR)) )
file
cmd)
(setq file (concat dir "TAGS"))
(when (or FORCE (not (file-exists-p file)))
(setq cmd (format "find %s -type f -not -iwholename '*TAGS' -not -size +24k | ctags -f %s -e %s -L -" dir file CTAGS-OPTS))
(shell-command cmd))
file))
BTW, here is my ~/.ctags.
UPDATE:
- My tags file management strategy is described at How to use ctags in Emacs effectively. It's effective to me. But it may be not generic enough to apply to others' use cases.
- I do use Gnu Global for C/C++/Java code. I use it exactly in the same way as ctags. Please
man global
for the details. Hint, all you need care is the environment variable GTAGSLIBPATH.