给go项目生成TAGS文件

本文的go项目特指包含go开发工具和程序库的代码,获取方式参见这里

go项目包含多种编程语言写成的代码,如C,汇编,go等等,甚至包括C和go的混合体(文件后缀名为goc)。其中的C也不是标准的C,而是被称为Plan 9 C,其中会影响到etags的就是它使用unicode中的middle dot作为symbol名字的一部分,如runtime·makechan_c。它实际是一个函数名,感觉上runtime像是一个名字空间。

让etags认识middle dot的方法很简单,只需修改emacs/lib-src/etags.c,在mitk指向的字符串最后加上它就可以了。如下:

*midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789·";

在Emacs里输入middle dot的方法是:C-x 8 RET MIDDLE DOT RET。或者直接从某个源文件里面复制。

然后重新编译

$ cd emacs/lib-src/
$ make etags

现在,就可以使用如下脚本给go项目生成TAGS文件了。

#!/usr/bin/env bash

SRC_DIR=$1

if [ ! -e "$SRC_DIR/src/all.bash" ]
then
    echo "\`$SRC_DIR' is not top directory of go source code"
    exit 1
fi

pushd "$SRC_DIR"

find src -name "*.go" | \
etags --language=none \
    --regex='/type[ \t]+[^ \t]+[ \t]/' \
    --regex='/func[ \t]+[^( \t]+[( \t]/' \
    --regex='/func[ \t]+([ \t]*[^( \t]*[ \t]+\*?\([^) \t]+\)[ \t]*)[ \t]*\([^( \t]+\)[( \t]/\1.\2/' -
find src -name "*.[hc]" | etags -a -
find src -name "*.goc" | etags --language=c -a -
find src -name "*.s" | etags -a --language=none \
    --regex='/TEXT [^(]+/' -
find include -name "*.h" | etags -a -
popd

LLVM源码定位查找工具

开始学习一个新项目的时候,我都会为其创建一个TAGS文件,便于源代码定位,LLVM也不例外。

find . -iname "*.h" -or -iname "*.cpp" | etags -
find . -iname "*.td" | grep -v '^\./\(test/\|lib/Target/[^A]\)' | \
  etags --language=none \
        --regex='/\(defm?\|\(multi\)?class\)[ \t]+\([^ \t:<]+\)/\3/' \
        -a -

除了C++程序之外,我还给LLVM TableGen的td文件也建立了索引,这样在学习td时也可以方便快捷地在classdef之间跳转,对defmmulticlass也做了有限的支持。

但是etags也有不方便的时候,比如定位Function这个class,我跳转了多次,仍然没有定位到它的定义位置。无奈,只好使用搜索。LLVM提供了一个搜索脚本utils/llvmgrep,可以在命令行下直接使用,但是我更喜欢在Emacs里面调用,这样可以直接从搜索结果跳转到源文件的相应位置。配置如下:

(defvar wl-llvm-root-dir "~/src/llvm/trunk")
(defvar wl-llvm-grep-command (concat wl-llvm-root-dir "/utils/llvmgrep"))

(defun wl-llvmgrep ()
  (interactive)
  (let ((regexp (grep-read-regexp))
	(default-directory wl-llvm-root-dir))
    (compilation-start (concat wl-llvm-grep-command
			       " -topdir " wl-llvm-root-dir
			       " "
			       (shell-quote-argument regexp)) 'grep-mode)))

我个人还给llvmgrep贡献了一个小小的patch,使其在Mac OS X上也能正常使用。