Exuberant Ctags中文手册

[译序]

(Easwy) First of all, I would like to thank the author of Exuberate Ctags, Darren Hiebert,
without his help, I cannot finish the work.

翻译这个手册的想法,最初源于我在写“使用VIM开发软件项目”系列文章(现在改名为”vim使用进阶“时。当时看到大家在使用 ctags 时,
基本都是用 "ctags -R"。其实 ctags 所拥有的能力并不止这些。它的众多选项可以让你方便的控制标签文件的
内容,甚至你可以自己定义一种语言,由 ctags 为它生成标签文件 (这方面的例子,可见下面的链接:
http://ctags.sourceforge.net/EXTENDING.html)

你可以在我的BLOG上找到最新版本的译文: http://easwy.com/blog/
译文可自由使用,转载请保留译序部分。
======

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个优点:
1. 明显减小最终标签文件的大小。
2. 消除因为定义标签的行被修改而导致使用 pattern 查找标签失败的情况,导致模式
匹配失败 (注意,有些编辑器,例如vim, 够在很多这样的情况中恢复)。
3. 消除在查找雷同的匹配时,找到不正确的源码行的情况 (见下面的 BUGS)。
4. 在标签文件中为内容相同的行保留多个不同的表项。在 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

字段以及分隔符定义如下:

1. 标签名
2. 单个 tab 字符
3. 文件名,这个标签对应的对象在此文件中定义
4. 单个 tab 字符
5. 在文件中定位此标签的 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 只在下列情况时创
建临时文件: (1) 生成一个 emacs 格式的标签文件, (2) 标签文件被输出到标准输出,
(3) 它被编译成使用内部的排序算法来排序标签文件,而不是使用操作系统的 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 的官方网站在:

http://ctags.sourceforge.net

参阅 ex(1),vi(1),elvis,或更好的,vim,ctags 的正式编辑器。欲获得 vim 的更多信息,请到
VIM 的 web 网站:

http://www.vim.org/

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) 这段话与前面的选项解释相抵触,正在与作者沟通。

[译文版本]
27Apr07, easwy, initial version
28Apr07, easwy, reformat it

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/exuberant-ctags-chinese-manual/

文章的脚注信息由WordPress的wp-posturl插件自动生成

vi/vim使用进阶: 保存项目相关配置

<< 返回vim使用进阶: 目录

本节所用命令的帮助入口:

:help 'path'
:help mksession
:help find
:help gf
:help CTRL-W_f 

我们在前面介绍了vimrc,vimrc定义了vim通常的行为。然而,每个项目都有其特殊的定义,虽然我们也可以在vimrc中对每个项目进行定制,但这样一来,vimrc会变得很大,使vim启动速度变慢;另外也会使vimrc变得难以维护。

因此,我们使用其它的方法来保存项目相关的信息,这就是本文的主要内容。我们将以path选项的设置为例进行讲解。

path选项定义了一个目录列表,在使用gf,find,以及CTRL-W f等vim命令时,如果使用的是相对路径,那么就会在path选项定义的目录列表中查找相应的文件。path选项以逗号分隔各目录名。我们依旧以vim 7.0的源代码为例(源代码放在~/src/vim70/目录中)。

对于这个项目,我们的path选项设置如下:

set path=.,/usr/include,,~/src/vim70/** 

稍微解释一下各项的含义,更详细的信息,请查看path选项的帮助页:

  • .        在当前文件所在目录中搜索
  • /usr/include   在/usr/include目录中搜索
  • ,,        在当前工作路径中搜索
  • ~/src/vim70/**  在~/src/vim70的所有子目录树中进行搜索

设置了path选项后,怎么用呢?

我们还是回到序言中的屏幕抓图,我们把光标定位到src/main.c文件第22行的”fcntl.h”单词上,然后在Normal模式下按”gf“。咦,vim打开了/usr/include/fcntl.h文件!

现在我们按”CTRL-^“回到刚才的位置,光标仍旧定位在第22行的”fcntl.h”单词上,然后按”CTRL-W f“。啊哈,这次vim打开了一个水平分隔窗口,在此窗口中打开了/usr/include/fcntl.h。

尽管在src/main.c中未指定fcntl.h的路径,但vim会在path选项定义的路径中搜索此文件,方便吧!

现在我们看一下”find“命令,输入:

:find netrw.vim 

vim打开了~/src/vim70/runtime/autoload/netrw.vim文件。用这种方法打开文件真是太方便了,你不用输入文件的路径,vim会自动在path选项定义的路径中搜索。不过”find“命令也有缺陷,如果你只记得文件名的一部分,那么就没有办法用find命令打开这个文件了。而且find命令也不允许使用正则表达式。没关系,我们还有更好的方法来打开文件,我将在Lookupfile插件中介绍这些方法。

path选项介绍完了,我们进入正题,如何把本项目相关的配置保存起来,下次打开本项目时自动恢复这些配置呢?

我们有两种方法做到这一点。

[方法1]

我们在~/src/vim70/目录下建立一个文件,假定文件名为workspace.vim,文件内容为:

"set project path
set path+=~/src/vim70/** 

这个文件中保存了项目相关的信息,例如选项值,键映射,函数定义,自动命令,等等。我们的例子中只定义的path选项,我们没有使用”set path=…”语句,在vim手册中建议使用”set path+=…”和”set path-=…”格式。

接下来,在你的vimrc文件中加入下面的语句:

" execute project related configuration in current directory
if filereadable("workspace.vim")
    source workspace.vim
endif 

以后,每次你在~/src/vim70/目录中启动vim时,vim都会自动载入workspace.vim,恢复项目的配置信息。

[方法2]

还记得本系列文章的第二篇使用会话(session)和viminfo吗?那篇文章中,我们介绍了使用session文件和viminfo保存项目环境的方法。如果你使用了会话文件,那么选项值,键映射,和其它很多信息都已经保存了。但会话的功能毕竟有限,不能把项目相关的配置全部保存下来,怎么办呢?

vim的作者已经想到了这个问题,并提供了解决办法。

在vim载入会话文件的最后一步,它会查找一个额外的文件并执行其中的ex命令。查找的规则是,把会话文件名的后缀去掉,然后在后面加上”x.vim“,。假设你的会话文件名为example.session,vim就会查找是否有examplex.vim,如果找到,就会执行此文件中的ex命令。

好了,我们先创建我们的会话文件:

:cd ~/src/vim70
:set sessionoptions-=curdir        '在session option中去掉curdir
:set sessionoptions+=sesdir        '在session option中加入sesdir
:mksession vim70s.vim              '创建一个会话文件 

然后再编辑一个名为~/src/vim70/vim70sx.vim的文件,文件的内容为(当然,你可以在这个文件中加入更多内容):

"set project path
set path+=~/src/vim70/** 

退出vim后,在命令行下执行”gvim &”,再次进入vim,这时看到的是一个空白窗口。然后执行下面的命令:

:source ~/src/vim70/vim70s.vim  '载入会话文件 

太棒了!原来的会话环境已经恢复,并且项目相关的配置也设置好了!

[参考文档]

  1. vim手册
  2. vim中文手册

<< 返回vim使用进阶: 目录

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/advanced-vim-skills-save-project-configuration/

文章的脚注信息由WordPress的wp-posturl插件自动生成

vi/vim使用进阶: vimrc初步

<< 返回vim使用进阶: 目录

上一章我们介绍了会话(session)文件和viminfo文件,其中‘sessionoptions’选项和‘viminfo’选项的配置可能会根据你的需要进行调整。但如何保存你所做的调整呢?我们将在这一章中介绍。

本节所用命令的帮助入口:

:help compatible
:help mapleader
:help map
:help autocmd 

为什么我的vim这么难用?不能语法高亮,没有折行,不能打开多个窗口多个buffer,不能……

为什么别人用几个键就可以完成一个很复杂的功能,而我不能?

为什么别人的vim看起来和我的很不一样?

……

当你开始问这些问题的时候,是时候去检查一下你的vimrc了。

当vim在启动时,如果没有找到vimrc或gvimrc,它缺省工作VI兼容的模式。这意味着,你只能使用VI所具备的功能,而vim中的大量扩展功能将无法使用。也许这就是你的vim如此难用的原因。

vim中自带了一个vimrc例子,让我们从这个例子开始吧。

下面我以Linux下的vim为例,windows版本的vim,会在后面提到。

示例的vimrc(名为vimrc_example.vim)通常位于/usr/share/vim/vimXXX/目录下,其中vimXXX与你所使用的vim版本有关。

首先把这个示例的vimrc拷贝到相应的目录,在Linux下,应该把它拷贝到你的home目录下,名字为”.vimrc”,下面是shell命令:

cp /usr/share/vim/vim70/vimrc_example.vim ~/.vimrc 

或者你在vim中执行下面的命令,和上面的shell命令完成相同的功能:

:!cp $vimRUNTIME/vimrc_example.vim ~/.vimrc 

现在,你退出vim后再进入,你的vim和刚才已经不一样了。

你可以先读一下你的vimrc,看看它都设定了什么:

:e ~/.vimrc 

这是一个注释良好的文件,不需要多解释。

对windows版本的vim,它已经缺省的有了一个vimrc,你可以在vim在使用下面的命令来查看它:

:e $vim/_vimrc 

在这个文件中,它包含了上面提到的vimrc_example.vim。同时,它会把vim设置的更符合windows的操作习惯。比如,支持CTRL-C拷贝,CTRL-V粘贴等等。Windows下的用户,可以使用$vim/_vimrc来做为你的第一个vimrc。

顺便提一句,在unix/linux中,文件名可以以”.”开头,表明此文件是隐藏的。而在windows中,不允许文件名以”.”开头,所以,windows版本的vim,将读取_vimrc来做为自己的配置文件。

在今后使用vim的日子里,你会频繁的更改你的vimrc。所以我们需要设置一些快捷方式,使我们能快速的访问vimrc。

把下面这段内容拷贝到你的vimrc中:

1    "Set mapleader
2    let mapleader = ","
3
4    "Fast reloading of the .vimrc
5    map <silent> <leader>ss :source ~/.vimrc<cr>
6    "Fast editing of .vimrc
7    map <silent> <leader>ee :e ~/.vimrc<cr>
8    "When .vimrc is edited, reload it
9    autocmd! bufwritepost .vimrc source ~/.vimrc 

为了方便解释,我给每一行都加了一个行号。

  • 在vimrc中,双引号开头的行,将被当作注释忽略。
  • 第2行,用来设置mapleader变量,当mapleader为未设置或为空时,使用缺省的”\”来作为mapleader。

    mapleader变量是作用是什么呢?看下面的介绍。

  • 第5行定义了一个映射(map),这个映射把<leader>ss,映射为命令:source ~/.vimrc<cr>。当定义一个映射时,可以使用<leader>前缀。而在映射生效时,vim会把<leader>替换成mapleader变量的值。也就是说,我们这里定义的<leader>ss在使用时就变成了”,ss“,当输入这一快捷方式时,就会source一次~/.vimrc文件(也就是重新执行一遍.vimrc文件)。
  • 第7行,定义了<leader>ee快捷键,当输入,ee时,会打开~/.vimrc进行编辑。
  • 第9行,定义了一个自动命令,每次写入.vimrc后,都会执行这个自动命令,source一次~/.vimrc文件。

有了上面的快捷键,我们就能快速的打开vimrc文件编辑,快速重新source vimrc文件,方便多了。

无论在windows还是在linux中,我都使用vim作为我的缺省编辑器。并且,我想使用同一个vimrc文件。因此,我定义了一个MySys()函数,用来区分不同的平台,以进行不同的配置。

另外,在编辑vimrc文件时,我更喜欢新开一个标签页来编辑,而不是在当前窗口中。因此,我定义了SwitchToBuf()函数,它在所有标签页的窗口中查找指定的文件名,如果找到这样一个窗口,就跳到此窗口中;否则,它新建一个标签页来打开vimrc文件。(注:标签页(tab)功能只有在vim 7.0版本以上才支持。)

下面是我的vimrc中使用的设定,希望能够抛砖引玉:

" Platform
function! MySys()
  if has("win32")
    return "windows"
  else
    return "linux"
  endif
endfunction

function! SwitchToBuf(filename)
    "let fullfn = substitute(a:filename, "^\\~/", $HOME . "/", "")
    " find in current tab
    let bufwinnr = bufwinnr(a:filename)
    if bufwinnr != -1
        exec bufwinnr . "wincmd w"
        return
    else
        " find in each tab
        tabfirst
        let tab = 1
        while tab <= tabpagenr("$")
            let bufwinnr = bufwinnr(a:filename)
            if bufwinnr != -1
                exec "normal " . tab . "gt"
                exec bufwinnr . "wincmd w"
                return
            endif
            tabnext
            let tab = tab + 1
        endwhile
        " not exist, new tab
        exec "tabnew " . a:filename
    endif
endfunction

"Fast edit vimrc
if MySys() == 'linux'
    "Fast reloading of the .vimrc
    map <silent> <leader>ss :source ~/.vimrc<cr>
    "Fast editing of .vimrc
    map <silent> <leader>ee :call SwitchToBuf("~/.vimrc")<cr>
    "When .vimrc is edited, reload it
    autocmd! bufwritepost .vimrc source ~/.vimrc
elseif MySys() == 'windows'
    " Set helplang
    set helplang=cn
    "Fast reloading of the _vimrc
    map <silent> <leader>ss :source ~/_vimrc<cr>
    "Fast editing of _vimrc
    map <silent> <leader>ee :call SwitchToBuf("~/_vimrc")<cr>
    "When _vimrc is edited, reload it
    autocmd! bufwritepost _vimrc source ~/_vimrc
endif

" For windows version
if MySys() == 'windows'
    source $VIMRUNTIME/mswin.vim
    behave mswin
endif 

注意:我在windows中也定义一个”HOME”环境变量,然后把_vimrc放在”HOME”环境变量所指向的目录中。如果你打算在windows中使用上面的设定,也需要这样做!

好了,现在我们知道如何永久更改‘sessionoptions’选项和‘viminfo’选项了,把对它们的配置放入你的vimrc即可。

vim自带的示例vimrc中,只定义最基本的配置。

http://www.amix.dk/vim/vimrc.html有一个非常强大的vimrc,有人戏称为”史上最强的vimrc”,或许有些言过其实。不过,如果你通读了这个vimrc,相信能从中学到很多……

这里有一个redguardtoo修改过的版本,可以对照参考一下。

我的vimrc也是基于Amix的模板,然后自已做了很多修改。

建议:不要照拷这个vimrc!可能这个文件的设定并不符合你的习惯。另外,这个文件的设定,可能也不能在你的工作环境中运行。

[参考文档]

<< 返回vim使用进阶: 目录

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/advanced-vim-skills-introduce-vimrc/

文章的脚注信息由WordPress的wp-posturl插件自动生成

vi/vim使用进阶: 使用会话和viminfo

<< 返回vim使用进阶: 目录

本节所用命令的帮助入口:

:help mksession
:help 'sessionoptions'
:help source
:help wviminfo
:help rviminfo
:help 'viminfo'

很多软件都具有这样一种功能:在你下一次启动该软件时,它会自动为你恢复到你上次退出的环境,恢复窗口布局、所打开的文件,甚至是上次的设置。

那么,vim有没有这种功能呢?

答案当然是肯定的!这需要使用vim的会话(session)及viminfo的保存和恢复功能。

使用会话(session)和viminfo,可以把你编辑环境保存下来,然后你在下次启动vim后,可以再恢复回这个环境。我们在开发项目或书写文档时,其周期不是一两天。如果你在中途退出了vim而不能恢复原先的编辑环境的话,你又要重新打开你所打开的文件,重新定义你的映射(map)、缩写(abbreviate),重新定位你所设定的标记的位置(mark),重新设置项目相关设置(options)……不是一般的麻烦!

要恢复上次的编辑环境,我们需要保存两种不同的信息,一种是会话(session)信息,另外一种是viminfo信息。

  • 会话信息中保存了所有窗口的视图,外加全局设置。
  • viminfo信息中保存了命令行历史(history)、搜索字符串历史(search)、输入行历史、非空的寄存器内容(register)、文件的位置标记(mark)、最近搜索/替换的模式、缓冲区列表、全局变量等信息。

我们在下面分别对其进行介绍。

[会话]

我们可以使用:mksession [file]命令来创建一个会话文件,如果省略文件名的话,会自动创建一个名为Session.vim的会话文件。会话文件,其本质上是一个vim脚本,你可以使用上述命令生成一个session文件,然后再查看其中的内容,就会对session文件有一个深入的认识。

会话文件中保存哪些信息,是由‘sessionoptions’选项决定的。缺省的‘sessionoptions’选项包括: “blank,buffers,curdir,folds,help,options,tabpages,winsize”, 也就是会话文件会恢复当前编辑环境的空窗口、所有的缓冲区、当前目录、折叠(fold)相关的信息、帮助窗口、所有的选项和映射、所有的标签页(tab)、窗口大小。

如果你使用windows上的vim,并且希望你的会话文件可以同时被windows版本的vim和UNIX版本的vim共同使用的话,在‘sessionoptions’中加入‘slash’‘unix’,前者把文件名中的’\’替换为’/’,后者会把会话文件的换行符保存成unix格式。

如果你不希望在session文件中保存当前路径,而是希望session文件所在的目录自动成为当前工作目录,那么,需要在‘sessionoptions’去掉‘curdir’,加入‘sesdir’,这样每次载入session件时,此文件所在的目录就被设为vim的当前工作目录。在你通过网络访问其它项目的session文件时,或者你的项目有多个不同版本(位于不同的目录),而你想始终使用一个session文件时,这个选项比较有用:你只需要把session文件拷贝到不同的目录,然后使用就可以了。设置此选项后,session文件中保存的是文件的相对路径,而不是绝对路径。

我们在上面使用:mksession命令创建了会话文件,那么怎么使用会话文件恢复编辑环境呢?很简单,你只需要使用:source session-file来导入会话文件。因为会话文件是一个脚本,里面保存的是Ex命令,所以”source“命令只是把会话文件中的Ex命令执行一遍。

[viminfo]

使用:wviminfo [file]命令,可以手动创建一个viminfo文件。

其实,在vim退出时,每次都会保存一个.viminfo文件在用户的主目录。我们使用:wviminfo命令则是手动创建一个viminfo文件,因为缺省的.viminfo文件会在每次退出vim时自动更新,谁知道你在关闭当前软件项目后,又使用vim做过些什么呢?这样的话,.viminfo中的信息,也许就与你所进行的软件项目无关了。还是手动保存一个保险。

“:wviminfo”命令保存哪些内容,以及保存的数量,由‘viminfo’选项决定,这个选项的值在windows上和在linux上的缺省值不同,具体含义参阅手册。

要读入你所保存的viminfo文件,使用:rviminfo [file]命令。

现在,回到我们的例子,依旧是上篇文章中的抓图,先看一下我们当前目录,执行:pwd,显示”/home/easwy/src/vim70″,接下来,执行下面的命令:

:cd src                            "切换到/home/easwy/src/vim70/src目录
:set sessionoptions-=curdir        "在session option中去掉curdir
:set sessionoptions+=sesdir        "在session option中加入sesdir
:mksession vim70.vim               "创建一个会话文件
:wviminfo vim70.viminfo            "创建一个viminfo文件
:qa                                "退出vim

退出vim后,在命令行下执行gvim &,再次进入vim,这时看到的是一个空白窗口。然后执行下面的命令:

:source ~/src/vim70/src/vim70.vim  '载入会话文件
:rviminfo vim70.viminfo            '读入viminfo文件

太棒了,又恢复到昨天退出时的状态了!继续工作~~~~

不过,每次都要手工修改‘sessionoptions’‘viminfo’吗?多麻烦啊……别着急,现在是时候介绍vimrc了,请移步下一章: vimrc初步。

[参考文档]

  1. vim手册
  2. vim中文手册

<< 返回vim使用进阶: 目录

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/advanced-vim-skills-session-file-and-viminfo/

文章的脚注信息由WordPress的wp-posturl插件自动生成

vi/vim使用进阶: 序言

<< 返回vim使用进阶: 目录

  从初次接触vim,到现在已经有好些年时间了。在软件开发中使用vim,不过是近两年的事情。对vim的了解远远算不上深入,不过还是把自己使用vim的一些经验写出来,希望对vim用户有所帮助。

  本系列文章介绍我自己使用vim的一些经验,主要包括vim使用技巧、vim配置、vim命令、vim插件等内容。本篇是序言,务虚为主。

  在使用vim进行软件开发之前,我使用的工具是Source Insight,相信大家并不陌生。Source Insight是一个不错的工具,特别是在浏览代码方面。在面对成百上千个文件组成的陌生源代码时,使用Source Insight可以让你很快的了解软件的主体流程、调用关系、类型定义……。使用Source Insight写代码也不错,它的自动补全功能很强,似乎使用拷贝、粘贴,加上自动补全,就可以完成代码了。不再使用Source Insight的原因有二个,一是Source Insight只支持windows,不能在Linux上用;二是不想再用盗版的Source Insight。

  在决定使用vim前,也在vim和emacs犹豫了很久,最终懒惰的天性让我放弃了emacs:实在是不习惯在移动光标时,也要用两只手按住CTRL/ALT/SHIFT再加个什么键;我的天性喜欢偷懒,能用一个手指做的事,不想用两个手指完成。所以最终选择了使用vim。现在感觉,vim和emacs在文本编辑方面不分伯仲。emacs的优势,在于它的可扩展性,使它可以完成很多和文本编辑无关的事情;不过这也造成了它的过于庞大。

  刚改用vim,最不适应的是不能再用鼠标指哪儿打哪儿了(vim当然支持鼠标,只是双手在键盘、鼠标间切换,很是影响效率),然后是拷贝、粘贴,然后是查看调用关系,函数间跳转,再然后……总之,刚开始的一段时间非常痛苦,效率也非常的低,甚至总是想着放弃。经过这段时间以后,逐渐摸到一些窍门,也渐渐的知道到哪里去寻求帮助,在哪儿可以找到vim的资源,工作效率一点点提升了上来。到现在,工作中已经离不开vim了,vim成了计算机中缺省的文本编辑工具!

  其实,对vim和emacs这样的工具来说,它们最强大之处,在于它们的可定制性。由于它们的可定制性,你完全可以定制出一个符合你自己编辑习惯的编辑器,在这样一个编辑器里,你的工作效率将达到最高。当然,要达到这样的境界,你需要付出非常坚苦的努力!如果你的工作是以文本编辑为主,例如,你是一个程序员,那么付出这种努力是值得的,也是有回报的。如果你没有很多文本编辑工作要做,那么也没有必要耗费这么大的力气,来学习这些工具。

  最后对vim的初学者提一些建议:

  1. 如果你的工作以文本编辑(不是指Microsoft word中的文本编辑)为主,那么学习vim或emacs是值得的;
  2. 刚开始使用vim或emacs的经历是很痛苦的,因为它们可能完全不同于你已经习惯的windows编辑器。我的建议是:坚持下去!咬牙坚持下去!你会获得回报的。
  3. vim手册 (help files) 是学习如何高效使用vim的重要资源,一定要多读手册。如果你是因为害怕读英文手册而不肯学习vim的话,那么,到vim中文文档下载vim 7.0的中文手册,安装好后,再使用”:help @cn”命令,你就可以看到中文手册了。
  4. 如果你是第一次接触vim,那么使用”:help tutor“或”:help tutor@cn“,你就会看到一个30分钟的vim教程,会教会你vim的一些基本命令。
  5. 有时间的话,一定要阅读一下Bram Moolenaar(vim的作者)写的Seven habits of effective text editing(七个有效的文本编辑习惯),你可以知道怎样提高你的编辑效率。在http://vimcdoc.sourceforge.net/下载PDF格式的手册,在附录二你可以看到它的中文译本。

  本系列文章都针对vim 7.0版本,如果这里介绍的功能在你的vim中不存在,不妨升级到vim 7.0后再试一次。

  我以Linux版本的vim 7.0为例。vim也有支持windows的版本,可以到vim主页下载预编译的的windows版vim 7.0。

  文章尽量不涉及具体的软件源代码,如果确实需要,则以vim 7.0的源代码为例。此代码可以也可以在vim主页下载,我把它解压在~/src/vim70目录下。后续文章以此目录为例进行讲解。

  附图是我所使用vim环境,在这副图中,我打开了三个标签页,一个是主编程区,一个是打开的.vimrc文件,另外一个是草稿区。在主编程标签页中有几个不同的窗口,分别是当前打开的buffer,当前文件中的tag,help窗口,lookupfile窗口,src/main.c和src/edit.c。其中使用了三个vim插件(plugin):winmanager, taglist, lookupfile

  从这副图中可以看出vim的一些特性:多标签支持(tab)、多窗口支持、插件支持(plugin)、语法高亮功能(syntax)文本折叠功能(folding)……这些特性,以及其它数不清的特性,我都将在后续文章中尽量给予介绍。

  上图是GUI界面的vim,下图是控制台(console)下的vim的抓图。这是我通常的开发方式:使用putty远程登录到linux服务器上,使用控制台的vim开发软件:

  对vim的了解有限,请多指教。

<< 返回vim使用进阶: 目录

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/advanced-vim-skills-prologue/

文章的脚注信息由WordPress的wp-posturl插件自动生成

vi/vim使用进阶: 目录

本系列文章,是原来我在CSDN的Easwy专栏撰写的”使用VIM开发软件项目”系列。Easwy的博客搬家以后,就把CSDN上的文章全部移到此处。

写本系列文章的最初想法,是介绍如何用vi/vim开发软件。但纵观整个系列,讲述的其实和软件开发关系并不大,基本都在讲vim的使用技巧、vim的配置及vimrc、vim的命令和vim的插件。因此,把文章移到新站后,我把本系列的名字改为”vi/vim使用进阶”,希望大家一如既往的支持该系列。

本文是这一系列文章的总目录,可由此访问本系列所有文章。

我使用docbook重新整理了一下这些文章,你可以在这里下载html版本的vi/vim使用进阶,现在也提供PDF版本下载。

[目录]

  • vi/vim使用进阶: 序言

    本文是本系列的序言,讲述我使用vi/vim的经历和心得,以及对vi/vim初学者的一些建议。文中的抓图展示了我的vim使用环境。

  • vi/vim使用进阶: 使用会话和viminfo

    本文介绍如何使用vim的会话 (session) 和viminfo来恢复vim的使用环境。如果你需要经常恢复到相同工作环境,此功能非常有用,你不必一次次重新打开文件、设置你的工作环境。

  • vi/vim使用进阶: vimrc初步

    本文简要介绍了vimrc的知识以及如何使用vimrc保存vim的配置。文中还提供了一些键映射(map),使用这些映射可以快速编辑和加载vimrc。关于vimrc的更多应用,参见本系列其它文章。

  • vi/vim使用进阶: 保存项目相关配置

    本篇主要以path选项为例,讲述如何保存和恢复项目相关的配置。在使用vim的过程中,你可能同时打开几个project,每个project的配置可能都不相同,文中介绍了两种方法来保存每个project自身的独有配置。一种是使用一个固定的vim配置脚本保存project相关的path设置、按键映射等;另外一种是利用前面文章所介绍的会话(session)机制。

  • vi/vim使用进阶: 使用标签(tag)文件

    本文介绍了如何使用Exuberant ctags生成tag文件以及在vim中如何使用tag文件进行跳转、查找等操作。还简要介绍了tag文件的格式,在后面介绍的Lookupfile插件中,会利用tag文件便捷的查找、打开文件。

  • vi/vim使用进阶: 使用taglist插件

    本文介绍如何使用taglist插件(plugin)来查看程序中的标签(tag),并介绍了taglist插件的配置和用法。taglist插件利用Exuberant ctags程序生成标签文件,并提供像Source Insight那样的标签窗口,可以方便的跳转到函数、变量等标签所在的位置。

  • vi/vim使用进阶: 文件浏览和缓冲区浏览

    本节介绍了如何在vim中浏览文件,以及如何查看当前打开的缓冲区。利用netrw插件,可以方便的在vim中浏览各个目录、打开指定文件,而不用切换到文件浏览器或shell;当然,netrw插件的作用并不仅仅局限于此。利用bufexplorer插件,则可以方便的查看打开的缓冲区(buffer),在缓冲区间进行切换。本文的最后介绍了winmanager插件,使用这个插件,可以把netrw插件、bufexplorer插件和taglist插件整合起来,使vim看起来更像一个集成开发环境(IDE)。

  • vi/vim使用进阶: lookupfile插件

    如果你在开发一个大的项目,当你想在一大堆文件中查找或者编辑指定文件时,Lookupfile插件是必不可少的。使用它,可以快速查找项目文件、可以在缓冲区查找指定文件、可以浏览指定目录等。在查找时甚至可以使用正则表达式(regex),在你只记得部分文件名或目录名时,这可是救命的手段。

  • vi/vim使用进阶: 开启文件类型检测

    vim最吸引人的一点是,它支持无穷多的文件类型,而且能够随意扩展。在本文主要介绍如何打开文件类型检测的功能,以及如何使用基于文件类型的插件(filetype plugin)。正因为有了文件类型检测的功能,我们才可能针对不同的类型的文件,定义不同的键映射(map)、设置不同的选项,进行语法高亮的染色(后续文章中介绍)…你可以实现任意你想实现的功能。

  • vi/vim使用进阶: 乱花渐欲迷人眼 – 语法高亮

    VIM并不是只有黑色两色。正相反,它提供了非常灵活的机制允许用户自定义色彩。运行在终端中的VIM,由于终端本身的限制,只能使用若干种固定的颜色;但对于GVIM来讲,你可以根据你的喜好调出任意的颜色。本文介绍的,正是vim的语法高亮功能。

  • vi/vim使用进阶: 程序员的利器 – cscope

    在前面的文章中介绍了利用ctags生成的tag文件,跳转到标签定义的地方。但如果想查找函数在哪里被调用,或者标签在哪些地方出现过,ctags就无能为力了,这时需要使用更为强大的cscope。本文就介绍如何使用cscope,有了它,你可以把source insight抛到一边去了。

  • vi/vim使用进阶: 剑不离手 – quickfix

    vim由一个程序员开发,并且为更多的程序员所使用,所以vim对开发人员的强大支持,也就可以理解了。quickfix模式的引入就是一个例子。quickfix模式,是一种加速你开发的工作方式,使你不必离开vim,就可以快速的完成”编辑-编译-修正”你的程序。它不仅仅对开发人员有用,只要你的工作有类似”编辑-编译-修正”的过程,它就可以极大的简化你的工作。

  • vi/vim使用进阶: 智能补全

    使用过Source Insight的人一定对它的自动补全功能印象深刻,在很多的集成开发环境中,也都支持自动补全。vim做为一个出色的编辑器,这样的功能当然少不了。本文主要介绍vim的OMNI补全。将在下一篇中介绍其它的补全方式。

  • vi/vim使用进阶: 自动补全

    本文继续介绍vim的补全功能。作为一个通用的编辑器,vim实现的补全功能并不仅仅限于对程序的补全,它可以对文件名补全、根据字典进行补全、根据本缓冲区或其它缓冲区类似的内容进行补全、根据文件语法补全等等,它甚至允许用户自己编写函数来实现定制的补全。本文简要介绍了这些补全的方法。

  • vi/vim使用进阶: 指随意动,移动如飞 (一)

    VIM提供的移动方式多如牛毛,但我们并不需要掌握全部这些命令,只需要掌握最适合自己的那些命令。本文介绍了最常用的一些移动命令,在下篇文章中将介绍更高级的移动方法。

  • vi/vim使用进阶: 指随意动,移动如飞 (二)

    本文介绍如何在vim中移动,主要涉及如何使用跳转表(jump-motions)、使用标记(mark)、使用折行(fold),以及如何在程序中移动。

  • vi/vim使用进阶: 在VIM中使用GDB调试 – 使用vimgdb

    本文介绍了如何使用vimgdb补丁在vim中用gdb调试程序,同时还介绍了vim的编译方法。然而,vim只是一个编辑器,而不是一个集成开发环境(IDE),所以它对调试的支持很有限。

  • vi/vim使用进阶: vimgdb调试时的常见问题及解决

    在上篇文章中我介绍了如何使用vimgdb补丁在vim/gvim中调试程序。后来陆续有一些读者反馈了他们在使用中遇到的问题。在本文中总结一下常见的问题及解决办法。

  • vi/vim使用进阶: 在gvim中使用GDB调试 – 使用pyclewn

    本文介绍了如何使用pyclewn在gvim中用gdb调试程序。pyclewn是vimgdb作者的另外一个作品,使用它可以使gvim在UNIX/LINUX以及windows上与gdb集成调试。

  • vi/vim使用进阶: vim编译中遇到的问题及解决方法

    本文主要介绍vim编译中遇到的问题及解决办法。文中介绍了如何通过看config.log,来了解配置失败的原因。有些网友编译图形化的gvim失败,可以参照本文的方法解决。

  • vi/vim使用进阶: 在vim中使用拷贝/粘贴

    未完待续

  • vi/vim使用进阶: 映射自己的vim按键

    未完待续

  • vi/vim使用进阶: 巧用vim的缩写功能

    未完待续

  • vi/vim使用进阶: 强大的自动命令(autocmd)

    未完待续

  • 其它你感兴趣的话题

    未完待续

原创文章,转载请注明:转载自Easwy的博客 [ http://easwy.com/blog/ ]

    本文链接地址: http://easwy.com/blog/archives/advanced-vim-skills-catalog/

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/advanced-vim-skills-catalog/

文章的脚注信息由WordPress的wp-posturl插件自动生成

xlink:href不能生成html超链接

刚开始使用Docbook 5.0,遇到一个很奇怪的问题,当我使用下面的代码时:

<link xmlns:xlink=’http://www.w3.org/1999/xlink/’
xlink:href=’http://easwy.com/blog/’>Easwy的博客</link>

然后转换成html格式,超链接总是丢失。为了解决这个问题,我进行了很多尝试。

刚开始怀疑Windows版本的xsltproc有Bug,于是换到Linux下,再进行转换,情况还是一样。接下来,把xsltproc换成其它的转换工具,但换成Saxon后,生成的html文件中依然没有超链接信息。

看来应该是自己Docbook文档写的有问题,于是尝试为xlink增加各种属性,先后试了xlink:type=’simple’,xlink:show=’new’,xlink:lable=’easwy.com’,可无论怎么改,最后的效果完全相同。于是我又尝试使用Docbook 4.4中的ulink来表示链接,这次一切正常。按DocBook V5.0 The Transition Guide的说法,应该”link xlink:href”在Docbook 5.0里已经取代了ulink,为什么不行呢?

在网上Google了很久,都没发现其它人出现过同样的问题,看来问题还是出在自己的Docbook文档中。无意在看一个网页时,发现它的xlink的namespace的URL写做

xmlns:xlink=’http://www.w3.org/1999/xlink’

而不是我的

xmlns:xlink=’http://www.w3.org/1999/xlink/

注意到区别了吗?我的URL在结尾处多了一个”/”。

当我把xlink的URL改成不带结尾”/”的后,生成的html文件终于包含超链接了。
原来,只要”xmlns:xlink”中的链接地址不正确,就不能生成超链接。

问题是如此简单!不知道还有没有人犯和我同样的错误。

原创文章,请阅读页脚的许可方式,转载请注明:转载自易水博客 [ http://easwy.com/blog/ ]

本文链接地址: http://easwy.com/blog/archives/xlink-href-can-not-generate-hyperlink/

文章的脚注信息由WordPress的wp-posturl插件自动生成