ctags
Exuberant Ctags中文手册
原文:http://easwy.com/blog/archives/exuberant-ctags-chinese-manual/
ctags很强大,甚至可以自己定义一种语言由 ctags 为它生成标签文件: http://ctags.sourceforge.net/EXTENDING.html
NAME
ctags – 为源代码产生标签文件
SYNOPSIS
ctags [options] [file(s)] etags [options] [file(s)]
DESCRIPTION
ctags 和 etags 程序 (下文中统称为 ctags,除非特别指明) 为文件中的各种语言对象生成一个索引 (或称为标签) 文件。标签文件允许这些项目能够被一个文本编辑器或其它工具简捷迅速的定位。一个 「标签」是指一个语言对象,它对应着一个有效的索引项 (或者换言之,这个索引项为这个对象而创建)。
可选的,ctags 能够为多种程序语言文件的语言对象信息生成可读格式的交叉索引列表。
标签索引文件被多种编辑器支持。这些编辑器允许用户通过出现在源文件中的名字定位对象,并且跳转到 定义这个名字的文件和行。在这个版本发布时,我们所知的编辑器包括:
Vi(1)及其变种(例如,Elvis, Vim, Vile, Lemmy), CRiSP, Emacs, FTE (Folding Text Editor), JED, jEdit, Mined, NEdit (Nirvana Edit), TSE (The SemWare Editor), UltraEdit, WorkSpace, X2, Zeus
Ctags可以为许多种不同的程序语言产生不同类型的标签。要获得完整的程序语言支持列表、它们被识别
的名字、为它们所产生的标签的的类型,请见–list-languages
和–list-kinds
选项。
SOURCE FILES
除非定义了–language-force
选项,每个源文件的语言类型将根据文件名到程序语言名的映射自动选择。
每种程序语言的映射可以通过–list-maps
选项查看,并且可以通过–langmap
选项修改。在支持的平
台上,如果文件的名字没有映射到一种程序语言并且这个文件是可执行的,将检查文件的第一行,看该文
件是不是一种可识别编程语言的#!
脚本。
缺省的,所有其它文件都被忽略。这允许在一个目录的所有文件上执行 ctags (例如,ctags *
),或
在整个源代码目录树的所有文件上执行 ctags (例如,ctags -R
)。因为只有那些文件名被映射到一种
程序语言的文件才会被扫描。
[.h
扩展名的文件被映射为 C++ 文件而不是 C 文件的原因是.h
扩展名也应用于 C++ 语言,并且把它
当做 C++ 文件对待并没有害处]
OPTIONS
尽管拥有大量的选项,ctags 设置了缺省值 (适合多数情况),因此通常不带任何选项来执行 ctags (例
如,ctags *
,或ctags -R
),这将为当前目录下所有可识别的源文件生成一个标签文件。下面提供的选项
仅仅为了在有特殊需要时允许用户自定义。
需注意,用来分隔单字母选项和它们参数的空格是可选的。
同样需注意,长格式选项的布尔型参数 (那些以 –
开头并且带 [=yes|no]
参数的选项) 可以被省
略,在这种情况下隐含为 =yes
,而 =0
和 =off
被认为是 =no
。
某些选项在以 etags 模式运行时或被忽略,或会起作用 (见-e
选项)。这样的选项会特殊注明。
绝大多数选项可以出现在命令行的任意位置,只影响在该选项后面的文件。然而,少数选项必须出现在第 一个文件名之前,这样的选项也会特殊注明。
带程序语言名字的选项允许名字是大写或小写。见–list-languages
选项,以获得内建程序语言名的完
整列表。
-a
等同于–append
-B
使用向上查找的模式 (例如?pattern?
)。 [在 etags 模式中忽略]
-e
使能 etags 模式,这将创建 Emacs 编辑器使用的标签文件。可选的,如果包含 etags
调用
ctags 时 (通过重命名,或者创建符号链接到可执行文件的方式),会使能 etags 模式。这个选项
必须出现在第一个文件名之前。
-f tagfile
使用所指定的 tagfile 做为标签文件的名字 (缺省是 tags
,或 TAGS
当以etags模式运行时)。
如果 tagfile 被定义成 -
,那么标签文件被输出到标准输出。如果 tagfile 存在并且它的第一
行不是有效的标签行时,ctags 将拒绝执行。如果你错误的输入了 ctags -f *.c
,这会救你一命,
不然它会把其它文件所产生的标签覆盖到你的第一个 C 文件!
ctags 也会拒绝接受以一个 -
(减号)开头的文件名,因为这很可能是你忘记输入标签
文件的名字,而本选项试图把它后面的选项做为文件名。
如果你真的想把你的输出标签文件名命名为 -ugly
,把它定义成 ./-ugly
。这个选项
必须出现在第一个文件名之前。如果这个选项出现多次,只有最后一个生效。
-F
使用向下查找的模式 (例如/pattern/
) (缺省)。 [在 etags 模式中忽略]
-h list
定义一个文件扩展名列表,以句号分隔,这些文件将做为包含文件(或头文件)被解析。要指定没有
扩展名的文件,用一个句号,后面不跟句号以外的字符 (例如,.
,..x
,.x.
)。这个选项只
影响如何解析一种特定类型的标签的作用域 (也就是说,这些标签是全局可见,还是这些标签只在
定义它们的文件中可见);它并不把这些扩展名映射到任何特定的程序语言。任何位于非头文件中的
标签,如果不能被另外一个文件可见 (例如,链接到另外一个文件),那么它的作用域被认为局限于
该文件 (例如,static)。在头文件中的所有类型的标签,它的作用域都不会被认为局限于该文件。
如果列表中的第一个字符是加号,那么该列表中的扩展名将被加到现有列表之后;否则,该列表将
替换现有列表。另外,参见 –file-scope 选项。缺省的列表是 ".h.H.hh.hpp.hxx.h++.inc.def"。
要恢复缺省列表,使用 -h default。注意,如果此选项指定的一个扩展名还没有被映射到一种特定
的程序语言 (见上面的 SOURCE FILES),你也需要使用 –langmap 或 –language-force 选项。
-I identifier-list
定义一个标识符列表,在解析 C 和 C++ 源文件时会对这些标识符进行特殊的处理。这个选项主要 用来处理由于编译预处理宏的使用而引发的特殊情况。当列出的标识符是简单的标识符时,这些标 识符在解析源文件时会被忽略。如果一个标识符以 "+" 字符做为结尾,ctags 将忽略源文件中紧跟 在此标识符后的被括号括起来的参数列表。如果两个标识符以 "=" 字符分隔,在解析时,第一个标 识符将被第二个标识符所替代。标识符列表可以直接在命令行上提供,也可以从一个单独的文件中 读出。如果 identifier-list 的第一个字符是 "@",".",或目录分隔符 ("/" 或 ""), 或前两个 字符是驱动器的盘符 (例如,"C:"),identifier-list 参数将被解释为一个文件名,从这个文件中 读取标识符列表,每行一个标识符。否则,identifier-list 是需要被特殊处理的标识符的列表 (或一组标识符对的列表),每一个标识符被逗号或空格分开,(如果以空格分隔,需要用引号把整个 列表括起来,以使整个列表做为一个命令行参数)。可以使用多个 -I 选项。要清除已定义的标识符 列表,以 "-" 做为 identifier-list 参数。
这个特性在编译预处理宏的出现会导致句法混淆的时候非常有用。实际上,这是解决源文件中干扰 语法的宏所引发的问题的最好办法 (见下面的 CAVEATS)。下面的例子详细描述这点。
int foo ARGDECL4(void *, ptr, long int, nbytes)
在上面的例子中,宏 "ARGDECL4" 将被错误的解释为函数的名字,而不是正确的名字 "foo"。定义 -I ARGDECL4 会获得正确的结果。
/* creates an RCS version string in module */ MODULE_VERSION("$Revision: 1.41 $")
在上面的例子,宏定义看起来非常像一个函数的定义,因为它没有以分号结尾 (实际上,它后面甚 至还可以跟一个全局变量定义,这样看起来更像一个 K&R 风格的函数参数定义)。实际上,在试图 完成这个看起来像函数的定义时,可能会导致文件的其它部分被跳过。定义 -I MODULE_VERSION+ 可以避免这样的问题。
CLASS Example { // your content here };
上面的例子使用了 "CLASS" 做为预处理宏,它在不同的平台上被扩展为不同的东西。例如,在 Win32 平台上它可能被定义为 "class __declspec(dllexport)",而在 UNIX 上简单的被定义为 "class"。通常,没有 C++ 的 "class" 关键字将导致源文件被错误的解析。定义 -I CLASS=class 能够得到正确的结果。
-L file 在文件 file 中读取需要产生标签文件的文件列表。如果 file 被指定为 "-",那么文件列表由标 准输入上读取。通过这个选项读到的文件将在命令行上给出的文件之后被处理。输入中的选项也会 被接受 (*1)。如果此选项被定义多次,只使用最后一个。注意:file 以行的方式被读取,只以换 行符做为分隔符,空格被认为是有意义的,这是为了支持文件名中包含空格的情况;如果输入中包 含选项,这会影响选项如何被解析 (*2)。
-n 同 –excmd=number。
-N 同 –excmd=pattern。
-o tagfile 同 -f tagfile。
-R 同 –recurse。
-u 同 –sort=no (也就是 "unsorted",不排序)。
-V 同 –verbose。
-w 此选项被悄悄忽略。仅为兼容 SVR4 Unix 的 ctags。
-x 打印一个表格形式的、可读的交叉索引 (xref) 文件到标准输出,而不是产生一个标签文件。输出 的信息包括:标签名字;标签类型;行号,文件名和标签所定义行的内容 (多余的空格被压缩)。不 会写标签文件,并且所有影响标签文件输出的选项都被忽略。这个特性的一个应用实例是为源文件 中定义的函数生成一个列表 (例如,ctags -x –c-kinds=f file),或为源文件中所有外部可见全 局变量生成一个列表 (例如,ctags -x –c-kinds=v –file-scope=no file)。这个选项必须出现 在第一个文件名之前。
–append[=yes|no]
指明为指定文件生成的标签是增加到标签文件已存在内容的后面,还是替换它们。此选项缺省关闭。 这个选项必须出现在第一个文件名之前。
–etags-include=file
在标签文件中包含一个到 file 的引用。此选项可以被指定任意多次。这个选项支持 Emacs 在一个 标签文件中包含另外一个标签文件的功能。[只在 etags 模式中有效]
–exclude=[pattern]
将 pattern 加到排除文件/目录列表中。这个选项可以被指定任意多次。对每一个 ctags 处理的文 件名,都会把该文件的完整路径 (例如,some/path/base.ext) 以及文件名 (例如,base.ext) 与 此选项定义的每个 pattern 进行比较,这允许 pattern 只匹配一个给定的文件名而不管其路径, 或者只匹配一个指定的路径。如果你所用的 C 编译器的运行库支持,那么 pattern 中可以包含 Unix 上通用的 shell 通配符 (不是正则表达式) (确保把这个选项的参数用引号括起来,以保证通 配符在传给 ctags 之前不会被 shell 扩展;另外,要知道通配符可以匹配 "/" 字符)。 你可以通 过检查 –version 选项的输出来确定在你的平台上 shell 通配符是否可用,(如果可用,) 在编译 的特性表中将包含 "+wildcards";否则将通过简单的文本比较来检查 pattern 与文件名的匹配。
如果 pattern 以字符 "@" 开始,那么剩余的字符串将被解释成一个文件的名字,由此文件中读取 排除模式字串,每行一个。如果 pattern 为空,排除列表将被清空。注意,在程序启动时,缺省的 排除列表包含"EIFGEN","SCCS","RCS",和"CVS",这些是在处理 –recurse 选项时不想意外进入 的目录名。
–excmd=type
定义在源文件中定位标签时所用的 EX 命令的类型。[在 etags 模式中忽略]
type 的有效值为 (用整个单词或用第一个字母都可以):
number 在标签文件中只使用行号来定位标签。这有4个优点:
- 明显减小最终标签文件的大小。
- 消除因为定义标签的行被修改而导致使用 pattern 查找标签失败的情况,导致模式 匹配失败 (注意,有些编辑器,例如vim, 够在很多这样的情况中恢复)。
- 消除在查找雷同的匹配时,找到不正确的源码行的情况 (见下面的 BUGS)。
- 在标签文件中为内容相同的行保留多个不同的表项。在 pattern 模式,重复的表项 被丢弃,因为它们产生的查找字串是相同的,保存重复的表项没有意义。
但是,这个选项有一个显著的缺点:对源文件的更改会导致标签文件中的行号记录不再对 应源文件的行号,导致跳转到某些标签时偏离标签定义位置一行或多行。大体上讲,这个 选项最好用在那些不打算更改的源文件上。选择这个选项导致下面的选项被忽略:-BF。
pattern 对所有标签只使用搜索字串,与行号不同,行号通常用于宏定义。优点是标签文件产生后, 增加或删除行不会引用 到旧的行号。
mixed 在这个模式,除少数例外,通常都使用搜索字串。对 C 语言,行号用于宏定义标签。这 是原始的 ctags 生成的缺省格式,因此,保留这个选项的缺省值。对 Fortran,common 块使用行号,因为它们的源码行通常都相同,使搜索模式在查找所有匹配时没有用处。
–extra=[+|-]flags
指定是否为特定类型的信息增加额外的标签条目。flags 参数是一组单字母标记,每个代表标签文 件中的一种额外的标签条目。如果 flags 前带 "+" 或 "-" 字符,会向当前生效的标记中加入,或 删除这些标记。否则 flags 替代当前的设置。每个标记的含义如下:
f 为每个源文件的文件名包含一个条目 (例如,"example.c"),它定位到文件的第一行。
q 为每个类成员包含一个额外的类修饰符条目 (为那些支持这类信息的编程语言;当前包括 C++, Eiffel 和 Java)。修饰符标签的实际格式取决于定义该标签的语言 (使用这种语言中 修饰符被定义的那种格式)。对 C++来说,格式为 "class::member";对 Eiffel 和 Java, 格式为 "class.member"。当标签文件中一个标签的名字出现多次时,这将更容易的定位到 特定的标签。然而需注意,这有可能使标签文件的大小不止增加一倍。
–fields=[+|-]flags
定义标签文件表项中的有效扩展字段 (见下面的 TAG FILE FORMAT,以获得更多信息)。flags 参数 是一组单个字母标记, 每一个代表一种类型的扩展字段,具有如下含义 (缺省为禁用,除非下面有 注明):
-
a
:类成员的访问控制信息 -
f
:作用域局部于文件 [使能] -
i
:(关于)继承的信息 -
k
:使用一个字符表示的标签类型 [使能] -
K
:标签类型的完整名称 -
l
:包含该标签的源文件的编程语言类型 -
m
:(关于)实现的信息 -
n
:标签出现的行号 -
s
:标签的范围 [使能] -
S
:函数的指纹 (例如,原型或参数列表) -
z
:在 kind 字段中包含 "kind:" 关键字 -
t
:把变量或 typedef 的类型和名字做为 "typeref:" 字段 [使能] (*3)
每个字母或字母组合的前面可以为 "+" ,表示将它加到缺省集合,或者为 "-",表示排除它。如果 既没有 "+" 前缀也没有 "-"前缀,只有在 flags 中明确列出的类型被包含在输出中 (也就是说, 覆盖缺省集合)。如果 –format=1 选项定义了,此选项被忽略。此选项缺省值为 "fkst"。
–file-scope[=yes|no]
指明作用域只在一个文件的标签 (即只在定义它们的文件中可见,不能被其它文件见到的标签,例 如 "static" 的标签) 是否被包含在输出中。又见 -h 选项。这个选项缺省使能。
–filter[=yes|no]
使 ctags 表现的像一个过滤器,由标准输入读取文件的名字,并一个文件接一个文件的输出它们的 标签。如果 –sorted 选项使能,只对文件内定义的标签排序。文件由标准输入上按行读入 (见 -L 选项的备注 ),并且这些文件在命令行及 -L 选项指定的文件之后处理。本选项使能时, -f,-o 和 –totals 选项被忽略。这个选项太过高深,缺省为禁用。这个选项必须出现在第一个文件名之前。
–filter-terminator=string
在 –filter 选项使能时,定义一个字符串,在一个文件的标签解析完后,会打印这个字符串到标 准输出。这允许读取 ctags 输出的应用程序能够确定一个文件的输出在什么时候结束。注意,如果 读入文件名是一个目录,并且 –recurse 选项使能,这个字符串只在该目录中的所有标签之后输出 一次。这个字符串总是被文件的最后一个标签的换行符隔开。这个选项太过高深,缺省为空。这个 选项必须出现在第一个文件名之前。
–format=level
改变输出标签文件的格式。当前有效的 level 只有 1 或 2。级别1指定原始的标签文件格式,级别2 指定一种新的扩展格式,里面包含扩展字段 (但使用了一种手段,使之仍后向兼容原始的 vi(1) 实 现)。缺省的级别为 2。这个选项必须出现在第一个文件名之前。 [在 etags 模式中忽略]
–help
向标准输出打印一个详细用法描述,然后退出。
–if0[=yes|no]
指定是否对于 "#if 0" 编译预处理分支中的非宏标签进行检查 (宏标签总被包含)。因为这种构造 是为了禁用代码,所以此选项的缺省值为 no。注意,这只是指明一种偏好,并不能保证在 "#if 0" 分支中的代码真的被跳过,因为产生标签的算法会在编译预处理条件太复杂时会解析条件编译的每 一个分支。
–<LANG>-kinds=[+|-]kinds
为特定的编程语言指定一个与语言相关的标签种类 (或类型) 的列表,这些内容会被包含在输出文 件中,在这里 <LANG> 不区分大小写,并且是内建语言名的一种 (见 –list-languages 选项以获 得完整列表)。kinds 参数是一组单字母标记,用来指明 (特定于这种语言的) 标签类型是包含在输 出中,还是不包含。这些特定标记集基于每种程序语言被识别,它们的含义以及缺省值可以由 –list-kinds 选项列出。每个字母或组合可以以 "+" 做前缀,表示在缺省值中加入它,或者以 "-" 做前缀,表示在缺省值中排除它。如果不以 "+" 或 "-" 为前缀,只有在 kinds 中明确列出的类型 被包含在输出中 (就是说,覆盖这种编程语言的缺省值)。
做为 C 语言的一个例子,要想在缺省标签类型中加入函数原型和外部变量定义,但是排除宏定义, 使用 –c-kinds=+px-d;要想只包含函数的标签,使用 –c-kinds=f。
–langdef=name 定义一种新的用户自定义语言,name,使用正则表达式进行解析。一旦被定义,name 可以在其它使 用程序语言名字的选项中被使用。这个选项的典型用法是,先定义这种语言,然后使用 –langmap 把文件名映射到它,最后使用 –regex-<LANG> 定义它的标签如何被解析。
–langmap=map[,map[...]]
控制文件名如何被映射到程序语言 (见 –list-maps 选项)。每个以逗号分隔的映射中,包含语言 的名字 (内建语言或用户自定义语言),一个冒号,以及一个文件扩展名和/或文件名模式的列表。 要定义一个文件扩展名,在此扩展名前加上句号 (例如,".c")。要定义一个文件名模式,把这个模 式用括号括起来 (例如,"([Mm]ake-file)")。如果你的 C 编译器的运行库支持,那么文件名模式 中可以包含 Unix 中通用的 shell 通配符 (确保用引号把参数括起来,以保护通配符在传给 ctags 之前不会被 shell 扩展)。 你可以通过检查 –version 选项的输出来确定在你的平台上 shell 通 配符是否可用,(如果可用,) 在编译的特性表中将包含 "+wildcards";否则将通过简单的文本比 较来检查文件名模式与文件名的匹配。要映射一个 (已经使用的) 文件扩展名,首先要取消它与其 它语言的映射关系。
如果映射的第一个字符是一个 "+",那么这个映射中的扩展名和文件名模式将加到这种语言的当前 映射中;否则,这个映射将替换当前映射。例如,为了指定只有扩展名为 .c 和 .x 的文件被当做 C 语言文件,使用 "–langmap=c:.c.x";想同时把扩展名为 .j 的文件加到 Java 语言文件,定义 "–langmap=c:.c.x,java:+.j"。为了把 makefiles (例如,文件名为 "Makefile","makefile", 或具有扩展名 ".mak") 映射到一种称为 "make" 的语言,定义 "–langmap=make:([Mm]akefile).mak"。 想映射没有扩展名的文件,定义一个句号,后面不包含句号以外字符 (例如,".","..x",".x.")。 想要为一种特定的语言清除映射 (这会防止自动为这个语言生成标签),定义一个空的扩展名列表 (例如, "–langmap=fortran:")。想为特定的语言恢复缺省的映射,将映射定义为default。想为 所有的语言恢复缺省的映射,定义 "–langmap=default"。 注意,在判别文件的程序语言时,文件扩展名先于文件名模式被判断。
–language-force=language
缺省的,ctags 自动为一个源文件选择语言,忽略那些不能确定程序语言的文件 (见上面的 SOURCE FILES)。这个选项强制把每个文件做为指定程序语言 (不区分大小写;内建或用户自定义) 的文件, 而不是根据它们的扩展名自动为其选择语言类型。另外,特殊值 auto 表示语言类型应该被自动选 择 (这否决的本选项的有效方法)。
–languages=[+|-]list
定义一个语言列表,将为这些语言产生标签,list 包含一个逗号分隔的语言名列表 (不区分大小写; 内建或用户自定义)。如果列表的第一个语言前面不是 "+" 或 "-" 字符,在向列表增加或从列表删 除语言前,会先清空当前列表。列表的每个语言都将加入列表,直到遇到一个 "-"。因为 "+" 或 "-" 都可以在列表中出现,在这两个符号后面的语言就相应被加到列表,或从列表中去掉。这样, 使用一个新的列表替换当前列表,或者从当前列表中增加或删除语言都变得很简单。实际会生成标 签的文件列表取决于生效的语言扩展名映射 (见 –langmap 选项)。注意,所有的语言,包括用户 自定义的语言,(缺省)都是使能的,除非使用本选项禁止。列表中的语言名可以是任何内建语言或 一个先前被 –langdef 选项定义的语言。缺省值为 "all",这也是一个可被接受的参数。见 –list-languages 选项以获得一个完整的内建语言名称。
–license
向标准输出打印软件许可证信息,然后退出。
–line-directives[=yes|no]
定义 "#line" 操作符是否应该被识别。它们存在于预处理器的输出中,包括行号,可能还包括生成 这个预处理输出的源文件的名字。当选项使能时,ctags 会生成标签项目,将使用源文件的文件名 和行号,而不是它们在预处理器输出中的位置。标签文件中的实际文件名将和预处理器输出文件具 有同样的路径,这是因为它假设原始文件的位置相对于预处理器输出文件 (当然,除非 #line 操作 符定义的是绝对路径)。这个选项缺省关闭。注意:这个选项通常在和 –excmd-number (-n) 选项 一起使用才比较有用。你也需要使用 –langmap 或 –language-force 选项,如果 ctags 不能识 别预处理器输出文件的扩展名的话。
–links[=yes|no]
指示是否跟踪符号链接 (如果系统支持符号链接的话)。在禁止时,符号链接被忽略。这个选项缺省 打开。
–list-kinds[=language|all]
列出指定语言或全部语言所能够识别的标签种类,然后退出。在标签文件中,每个种类的标签都用 一个单字母的标记来表示,它也用于 –<LANG>-kinds 选项,用以过滤在输出中所包含的标签种类。 注意,有些语言和/或标签种类可能用正则表达式来实现,如果正则表达式支持没有编译到 ctags 中,可能无法支持 (见 –regex-<LANG> 选项)。列出的每个种类都是使能的,除非后面跟有 "[off]"。
–list-maps[=language|all]
列出指定的语言或全部语言的文件扩展名和文件名模式,然后退出。这些扩展名以及文件名模式把 一个文件与特定程序语言相关联。见上面的 –langmap 选项,以及 SOURCE FILES。
–list-languages
列出 ctags 能够识别的程序语言名,然后退出。这些程序语言名称不区分大小写,可以用在 –language-force,–languages,–<LANG>-kinds 和–regex-<LANG> 选项。
–options=file
从 file 中读取附加选项。做为一种特殊情形,如果 –options=NONE 做为命令行的第一个选项, 它将禁止自动从文件或环境变量 (见 FILES) 中读取任何配置选项。
–recurse[=yes|no]
递归进入文件列表中所遇到的目录。如果给出的文件列表为空,并且没有使用 -L 指定文件列表, 那么当前目录被使用 (也就是 ".")。符号链接将被跟踪。如果你不喜欢这样的处理,或者显式的指 定文件列表,或者通过管道将 find(1) 的输出传给 "ctags -L-"。注意,这个选项当前并不能支持 所有的平台。如果 –help 选项的输出中包含本选项,说明它可用。又见 –exclude 选项,以限制 递归行为。
–regex-<LANG>=/regexp/replacement/[kind-spec/][flags]
/regexp/replacement/ 定义一个正则表达式的替换串,与 sed 的 substitution 命令风格类似, 使用它为映射到 <LANG> 语言 (不区分大小写;内建程序语言,或用户自定义程序语言) 的源文件 产生标签。正则表达式 regexp 定义一个扩展正则表达式 (主要为 egrep(1) 所用),它用来定位包 含标签的一个源码行,使用 t 来定义 tab 字符。当一个匹配行被发现,将会生成一个名为 replacement 的标签,replacement 通常会包含特殊的前向引用 1 到 9,以引用 regexp 中的子 表达式。选项参数中的 "/" 分隔字符实际上可以换成任何字符。注意,不管使用哪个分隔符,如果 它在参数中不做分隔用,必须使用 "" 字符对其进行转义。
本选项定义的正则表达式会被添加到这种语言当前的正则表达式列表中,除非省略选项参数,这种 情况当前列表会被清空。
除非由 flags 做出更改,否则 regexp 被作为 Posix 扩展正则表达式解析。对于每个匹配行, replacement 应该被扩展为一个非空字符串,不然的话会产生一条告警信息。一个可选的标签类型 定义可以跟在 replacement 后面,它用来指定在标签的 "kind" 扩展字段里写入的类型 (见下面的 TAG FILE FORMAT)。kind-spec 的完整格式是一个单个字母,一个逗号,一个名字 (不包含空格), 一个逗号,一个描述,后面跟分隔符,这个格式定义了类型及其文本描述的长、短形式 (使用 –list-kinds 可以显示出来)。类型的名字和/或类型的描述可以被省略。如果 kind-spec 被省略, 它的缺省值为 "r,regex"。最后,flags 是一个或多个单字母字符,对 regexp 的解析有下列影响:
b 此模式被解析为 Posix 的基本正则表达式
e 此模式被解析为 Posix 的扩展正则表达式 (缺省)
i 此模式以忽略大小写的方式被应用
注意,这个选项只在 ctags 编译时加入正则表达式支持时才有效,这取决于你所用的平台。你可通 过检查 –version 选项的输出,以确定编译时是否加入正则表达式支持,(如果支持),输出的编译 特性列表中将包含 "+regex"。
欲获得 ctags 使用的正则表达式的详细信息,见 regex(5,7) 的手册页,或见 regex 的 GUU info 文档 (例如,"info regex")。
–sort[=yes|no|foldcase]
指明标签文件是否按标签名排序 (缺省为排序)。注意,原始的 vi(1) 要求排序标签。foldcase 指 定不区分大小写排序 (或大小写合并排序)。
对大小写合并排序进行快速二叉树查找需要由使用标签文件的工具提供特殊支持,例如 ctags 的 readtags 库,或 Vim 6.2 以上版本 (使用 "set ignorecase")。这个选项必须出现在第一个文件 名之前。[在 etags 模式中忽略]
–tag-relative[=yes|no]
指明标签文件中记录的名字路径应该相对于标签文件所在的目录,而不是相对于当前目录,除非命 令行所指定的文件名使用绝对路径。这个选项必须出现在第一个文件名之前。当运行在 etags 模式 时,缺省为 yes (见 -e 选项),否则缺省值为 no。
–totals[=yes|no]
打印在本次 ctags 运行期间所读入源文件以及所写标签的统计信息。这个选项缺省关闭。这个选项 必须出现在第一个文件名之前。
–verbose[=yes|no]
使能详细模式。打印处理选项的信息,以及在 ctags 处理每个文件时打印一条简洁的消息,描述采 取什么样的动作。通常,ctags 在配置文件中的选项 (见下面的 FILES) 以及 CTAGS 环境变量被读 入前,不会读取命令行参数。然而,如果本选项是命令行的第一个选项,它将在配置文件、CTAGS 环境变量,以及命令行上的每个选项被读入前生效。缺省值为 no。
–version
打印 ctags 的版本信息,然后退出。信息中始终包含字符串 "Exuberant Ctags"。
OPERATIONAL DETAILS
在 ctags 依次处理每个文件时,它试图挨顺序进行以下三步测试来确定文件的程序语言类型:是否文件 的扩展名被映射到一种程序语言,是否文件名匹配一个映射到程序语言的 shell 模式,最后判断是否该 文件可执行并且它的第一行使用 Unix 风格的 "#!" 定义了一个解释器 (如果平台支持的话)。如果程序 语言确定了,这个文件会被打开,接下来相应的语言解析器被调用,以解析当前打开的文件。解析器解析 整个文件,并且在标签文件中为每个语言对象增加一个条目。见下面的 TAG FILE FORMAT,以获得这些条 目的详细信息。
这个 ctags 实现不像旧有的实现那样,对 C 代码的格式有要求。旧的实现往往依赖特殊的预定格式来帮 助它解决编译预处理条件引发的困难。
通常,ctags 试图更巧妙的处理翻译预处理操作符。如果在一条定义了标签的语句中遇到一个编译预处理 条件,ctags 只跟随此条件的第一个分支 (除非第一分支是 "#if 0" ,在这种情况下,只跟随剩下的唯 一一条分支)。这样做的原因是 (如果) 跟随不只一条分支会导致语法不明确,就像下面例子:
#ifdef TWO_ALTERNATIVES struct { #else union { #endif short a; long b; }
不能同时跟随两个分支,否则括号会不匹配,ctags 将不能识别语法。
由于这些条件很复杂,并且 (分支) 相互排斥,如果这种办法不能正确的解析一个文件,ctags 将重新尝 试另一种不同的方法,这种方法不并选择性的跟随条件预处理分支,而是在 #if 条件分支导致大括号不 匹配时,通过位于第 1 列的大括号 ("}") 来做为一个代码块结束的指示。
Ctags 也尝试对括在两个圆括号中的参数列表进行特殊处理,以接受下面这样的条件结构:
extern void foo __ARGS((int one, char two));
任何紧挨着 "((" 的名字都被自动忽略,而使用在它之前的名字。
C++ 的运算符定义会被特殊处理。为了对所有种类的运算符 (重载或转换) 保持一致,在标签文件中,所 有运算符的名字总是以 "operator " 为前缀 (也就是说,即使实际的运算符定义被写成 "operator<<")。
在创建标签文件,或向标签文件中添加标签后,将根据标签的名字进行排序,删除相同的标签行。
TAG FILE FORMAT
在不以 etags 模式运行时,标签文件中的每个表项占单独的一行,通常每个看起来都如同这样:
tag_name<TAB>file_name<TAB>ex_cmd;"<TAB>extension_fields
字段以及分隔符定义如下:
- 标签名
- 单个 tab 字符
- 文件名,这个标签对应的对象在此文件中定义
- 单个 tab 字符
- 在文件中定位此标签的 EX 命令;通常是一个搜索模式 (/pattern/ 或 ?pattern?) 或行号 (见 –excmd)。标签文件格式 2 (见 –format)在某些情况下扩展了这个 EX 命令, 在紧挨着此 EX 命令后面的 EX 命令注释里嵌入了一套扩展字段 (在下面描述),这样 使它仍能向下兼容原始的 vi(1) 实现。
基于内部使用的目的,会向标签文件中写入一些特殊的标签。这些标签的构成使它们始终被排序到文件的 最前面。因此,这些标签的前两个字符被用做标签文件的幻数,以确定正在写入的是一个有效的标签文件, 而不是一个源文件。
注意,记录在标签文件的每个源文件名,和命令行上定义的完全相同。因此,如果你在命令行上指定的是 相对于当前目录的路径的话,它们在标签文件中以同样的方式被记录。然而,见 –tag-relative 选项, 以更改此设置。
如上所说,扩展字段作为注释增加在 EX 命令之后,是以 tab 字符分隔的 "关键字-值" 组合。这些 "关 键字-值" 组合一般为 "key:value" 的格式。它们是否在标签文件中出现,由 –fields 选项控制。可能 的关键字以及它们值的含义见下:
access 指明类成员的可见范围,它的值特定于程序语言。
file 指明此标签只在文件中可见。这个关键字没有相应的值。
kind 指明标签的类型,或种类。它的值要么是上面 –<LANG>-kinds 选项所描述的相应单字母标 志,要么是全名。此字段的关键字部分允许被省略 (实际上,这是缺省设置)。由 –fields 选项控制它的表现。
implementation
如果存在,它指明一个函数或类具有实现的限制 (抽象与具体),它的值特定于程序语言 (对 C++ 而言是 "virtual" 或 "pure virtual";对 Java 而言是 "abstract").
inherits 如果存在,值为一个逗号分隔的类列表,这个类源于列表中的类 (也就是说,它由列表中的 类继承而来)。
signature 如果存在,它的值是函数指纹,表示方法与程序语言相关。完整的函数指纹定义了此函数的 返回类型及它的参数列表格式。这个扩展字段当前只支持基于 C 的程序语言,并且不包括 返回类型。
另外,标签作用域有关的信息也 (在标签文件中) 可用,它的关键字部分是程序语言中的构造名称,它的 值是程序中此构造的名字。作用域表项指明定义此标签的范围。例如,C 语言的结构成员所生成的标签, 会包含一个作用域,看起来像这样 "struct:myStruct"。
HOW TO USE WITH VI
Vi 缺省的期望当前工作目录中有一个名为 "tags" 的标签文件。一旦生成了标签文件,下面的命令执行 按标签索引的特性:
vi -t tag 启动 vi 并且把光标定位在 "tag" 定义所在的文件和行上。
:ta tag 查找一个标签。
Ctrl-] 查找光标下的标签
Ctrl-T 返回跳转到标签前的前一次位置 (不是所有实现都支持)。
HOW TO USE WITH GNU EMACS
Emacs 缺省的期望当前工作目录中有一个名为 "TAGS" 的标签文件。一旦生成了标签文件,下面的命令执 行按标签索引的特性:
M-x visit-tags-table <RET> FILE <RET>
选择所使用的标签文件 "FILE"。
M-. [TAG] <RET>
查找第一个 TAG 定义。缺省的标签是光标下的标识符。
M-* 跳回你先前调用 "M-." 的位置
C-u M-. 查找前一次所查找的标签的下一个定义
阅读 Emacs info 文档的 Tags 主题,以了解更多命令。
HOW TO USE WITH NEDIT
NEdit 的 5.1 及以后版本可以处理新的扩展标签文件格式 (见 –format)。要使 NEdit 使用标签文件, 选择 "File->Load Tags File"。要跳转到一个标签的定义,高亮这个标签,然后按 Ctrl-D。NEdit 5.1 可以从不同的目录读取多个标签文件。设置 X 资源中的 nedit.tagFile 为标签文件的名字,可以使 NEdit 在启动时自动加载这个标签文件。
CAVEATS
由于 ctags 既不是一个预处理器也不是一个编译器,使用预处理宏会使 ctags 漏掉标签或者错误的生成 不正确的标签。虽然 ctags 已经被设计成处理一些的通用情况,但这依旧是提交最多的问题。特别是使 用预处理构造改变 C 的语法结构时,会欺骗 ctags。你可以通过使用 -I 选项避开很多这样的问题。
(*4) White space is treated as a separator for file names and options read from list files, specified using the -L option, and in filter mode (specified using the –filter option). Therefore, it is not currently possible to supply file names or other options contain-ing embedded white space (spaces, etc.) through these options.
注意,当 ctags 使用模式字串来定位标签时 (见 –excmd 选项),如果另外一个源码行和包含这个标签 的行完全相同,你的编辑器完全有可以跳到错误的行上。下面的例子说明这种情况:
int variable; /* … */ void foo(variable) int variable; { /* … */ }
取决于你所使用的编辑器,以及你在代码中位置,搜索模式可能会在查找到真正的全局变量定义之前,查 找到 foo() 的局部参数声明,因为这两行完全相同 (因此它们的搜索模式也相同)。这可以通过使用 –excmd=n 来避免。
BUGS
Ctags 具有比 ls(1) 更多的选项.
当解析一个 C++ 成员函数定义时 (例如,"className::function"),ctags 不能确定域分隔符是一个类 名分隔符还是一个 namespace 分隔符,总是把它做一个类名放在扩展字段的作用域部分。另外,如果一 个 C++ 函数定义在类定义外面 (通常都是这样),函数定义中包含的访问限定符 (即 public,protected 或 private) 以及实现信息 (例如 virtual,pure virtual) 在为这个函数生成标签时无法知道。然而, 对于原型,这些信息可用 (例如,–c++-kinds+=p)。
没有为继承自一个类的语言对象产生标签。
ENVIRONMENT VARIABLES
CTAGS 如果这个环境变量存在,在 ctags 启动时会从此环境变量中读取缺省选项,读取发生在下面 FILES 一节中列出的配置文件之后,但在命令行选项之前。命令行中出现的选项会覆盖此环境变 量中的选项。只从这个环境变量中读取选项值。注意,环境变量中的所有空格都被认为是分隔符, 这样传递一个包含空格的选项参数是不可能的。如果这会导致问题,改用配置文件。
ETAGS 与上面的 CTAGS 类似,如果存在,它会在 etags 启动时读取。如果这个环境变量未找到,etags 将尝试改用 CTAGS 环境变量。
TMPDIR 在支持 mkstemp() 的类 Unix 主机上,这个环境变量的值定义了存放临时文件的目录。这在临 时文件太大导致缺省临时文件目录所在的分区无法装下它时比较有用。ctags 只在下列情况时创 建临时文件:
- 生成一个 emacs 格式的标签文件,
- 标签文件被输出到标准输出,
- 它被编译成使用内部的排序算法来排序标签文件,而不是使用操作系统的 sort 工具。如果 使用系统的 sort 工具,它通常也会使用这个变量。如果 ctags 是 setuid 的,TMPDIR 的值将 被忽略。
FILES
- /ctags.cnf (只在 MSDOS,MSWindows)
- /etc/ctags.conf
- /usr/local/etc/ctags.conf
- \(HOME/.ctags (在 MSDOS, MSWindows 上是 \)HOME/ctags.cnf)
- .ctags (在 MSDOS,MSWindows上是 ctags.cnf)
如果这些配置文件中任一个存在,每个都应该包含一个缺省的选项集合,在 ctags 启动时会按列 出的顺序读入这些选项,读入的时刻发生在读取 CTAGS 环境变量以及命令行选项之前。这使得设 置适用于整个系统、每个人或基于项目的缺省选项值成为可能。在编译 ctags 时为它指定一个额 外的配置文件是可能的,它会在上面列出文件被读入之前读取,在 –version 选项输出中的 "custom-conf" 指示这个特性可用。CTAGS 环境变量及命令行中选项会覆盖这些文件中定义的选 项。只从这些文件中读入选项值。注意,选项文件按行读入,行内的空格有效 (因为不能像 shell 那样使用引号)。文件的每行被当做一个命令行参数 (就像它们被单引号括起来一样)。因此,使 用换行符做为命令行参数的分隔标志。
tags ctags 生成的缺省标签文件。
TAGS etags 生成的缺省标签文件。
SEE ALSO
Exuberant Ctags 的官方网站在:
参阅 ex(1),vi(1),elvis,或更好的,vim,ctags 的正式编辑器。欲获得 vim 的更多信息,请到 VIM 的 web 网站:
AUTHOR
Darren Hiebert <dhiebert at users.sourceforge.net> http://DarrenHiebert.com/
MOTIVATION
"Think ye at all times of rendering some service to every member of the human race."
"All effort and exertion put forth by man from the fullness of his heart is worship, if it is prompted by the highest motives and the will to do service to humanity."
— From the Baha’i Writings
CREDITS
这个版本的 ctags 最初继承了 Steve Kirkendall <kirkenda@cs.pdx.edu> 的 ctags 并从中获取灵感, 他的 ctags 伴随 Elvis vi 变种发行 (虽然事实上没有使用一行原来的代码)。
荣誉也要归于 Bram Moolenaar <Bram@vim.org>,vim 的作者,他花费如此多的时间和精力开发这个编辑 器 (服务于他人) 以及帮助乌干达的孤儿。
名为 "HOW TO USE WITH GNU EMACS" 的一节是从 GNU etags 的 info 文档中 "偷来" 的。
Darren Hiebert Version 5.6 CTAGS(1)
译者注:
(*1) 原文为 "Options all also accepted in this input" 。经过与作者沟通,本句应为 "Options also accepted in this input"。意思是「在输入中的选项也会被接受」,也就是说,可以在 file 中加入选项, 这些选项将会应用在其后出现的文件上。这提供了一种非常便捷的方式,允许用户为不同的文件指定不同的 选项。
(*2) 这句话意思是,因为行内的空格被视为有意义的,所以不能再以空格来分隔各个选项,而应该以换行符来分 隔多个选项。
(*3) 按译者的理解,在使用类如 struct,union 这样的复杂数据类型进行类型定义 (typedef) 或直接定义变量 时,会为之增加 "typeref:" 字段。下面两个例子中的代码生成的标签文件就包含此字段:
/* 定义类型 */ typedef struct abc { int a; char b; } abc; /* 直接定义变量 */ union { TEST1, TEST2 } test;
(*4) 这段话与前面的选项解释相抵触,正在与作者沟通。