ctags
是用来生成标记的程序,在
vim
中可以方便的用
tags
标记进行代码之间的跳转,更高级的是,利用
ctags
进行自动补全的功能,就跟
VC
的
virtual assitant
一样,很酷吧。
ctags
可以方便的生成
tags
,进行函数和变量的跳转,见下例:
1.ctags 的简单应用
a) 通过 vim test.cpp 建立 cpp 文件
b) 插入代码
#include
using namespace std;
int g_tag;
void test_tags()
{
printf("gtags is %d/n",g_tag);
}
int main()
{
test_tags();
}
c) 建立 tags 文件,通过 ":!ctags -R .", 可以对本目录下的文件进行 tags 索引
d) 查看当前 tags 路径,通过 ":set tags" 可以看到当前的 tags 路径,如果没有当前目录,可以通过 " :settags+=./tags " 将刚生成的 tags 文件加到 tags 路径中。
e) 在将光标移动到 main 函数中的 test_tags 上,按 Ctrl+], 可以跳转到 test_tags 的定义中,同样,在 test_tags() 函数中的 g_tag 上按 Ctrl+], 可以跳转到 g_tag 的定义。
1.ctags 的简单应用
a) 通过 vim test.cpp 建立 cpp 文件
b) 插入代码
#include
using namespace std;
int g_tag;
void test_tags()
{
printf("gtags is %d/n",g_tag);
}
int main()
{
test_tags();
}
c) 建立 tags 文件,通过 ":!ctags -R .", 可以对本目录下的文件进行 tags 索引
d) 查看当前 tags 路径,通过 ":set tags" 可以看到当前的 tags 路径,如果没有当前目录,可以通过 " :settags+=./tags " 将刚生成的 tags 文件加到 tags 路径中。
e) 在将光标移动到 main 函数中的 test_tags 上,按 Ctrl+], 可以跳转到 test_tags 的定义中,同样,在 test_tags() 函数中的 g_tag 上按 Ctrl+], 可以跳转到 g_tag 的定义。
上面所述的虽然能体现出
ctags
的能力,但是,对于一些大的项目,仅仅使用来生成
tags
文件,是远远不够的,比如
ACE
的项目里面,包含了很多的
inl
文件,这些都是定义的
inline
的函数,这些文件
ctags -R .
是没有办法解析的,再比如说
std
库,甚至有些文件没有后缀,比如
map,vecotr,
而且由于其中
namespace std
使用宏来代替的,如果直接
ctags ,
没有办法对它们生成
tags
,这些都是很简单但是需要注意细节的问题。在下面的例子中都会讨论到。
2.
对
ACE
代码生成
tags
ACE 是一个很棒的 c++ 网络库,我刚开始用 vim 的时候就用 ctags -R . 简单对 ACE 库进行处理过,但是后来在使用的过程中,我发现有些函数居然跳转 tags ,后来发现有些函数它放在 .inl 文件中,而 ctags ,则自动忽略了对 .inl 文件的检测,我用了 --langmap 选项以后,这个问题就解决了。
ctags -R --langmap=c++:+.inl .
这个选项是说,除了普通的 c++ 文件(如 cpp 等)以外,把 inl 文件也当作 c++ 文件处理。
实际上我用的是 :
ctags -R --kinds-c++=+p --fields=+iaS --extra=+q --langmap=c++:+.inl .
多余的这些选项是用来生成类成员函数 tags ,以及用于自动补全的( omnicppcomplete)
需要提一下的是,虽然 ctags 可以通过 -f 制定生成 tags 的位置,但是我觉得在代码当前目录生成 tags 比较方便,至于因此可能要设置多个 tags 路径,因为 tags 路径设置可以写在脚本中自动执行,所以也不是很麻烦的事情,这个是后话了。
ACE 是一个很棒的 c++ 网络库,我刚开始用 vim 的时候就用 ctags -R . 简单对 ACE 库进行处理过,但是后来在使用的过程中,我发现有些函数居然跳转 tags ,后来发现有些函数它放在 .inl 文件中,而 ctags ,则自动忽略了对 .inl 文件的检测,我用了 --langmap 选项以后,这个问题就解决了。
ctags -R --langmap=c++:+.inl .
这个选项是说,除了普通的 c++ 文件(如 cpp 等)以外,把 inl 文件也当作 c++ 文件处理。
实际上我用的是 :
ctags -R --kinds-c++=+p --fields=+iaS --extra=+q --langmap=c++:+.inl .
多余的这些选项是用来生成类成员函数 tags ,以及用于自动补全的( omnicppcomplete)
需要提一下的是,虽然 ctags 可以通过 -f 制定生成 tags 的位置,但是我觉得在代码当前目录生成 tags 比较方便,至于因此可能要设置多个 tags 路径,因为 tags 路径设置可以写在脚本中自动执行,所以也不是很麻烦的事情,这个是后话了。
3.
对
std
代码生成
tags
std 代码,以我的计算机为例, std 代码在 /usr/include/c++/4.1.2 里面。
很多文件的 namespace 是这样定义的 namespace _GLIBCXX_STD
在 VC7 下面的好像是 STD_BEGIN 吧,但是他们其实都代表 namespace std{ ( 注意这里的花括号 ),
因此在生成 tags 之前,最好把这些文件的宏都替换掉,步骤如下:
std 代码,以我的计算机为例, std 代码在 /usr/include/c++/4.1.2 里面。
很多文件的 namespace 是这样定义的 namespace _GLIBCXX_STD
在 VC7 下面的好像是 STD_BEGIN 吧,但是他们其实都代表 namespace std{ ( 注意这里的花括号 ),
因此在生成 tags 之前,最好把这些文件的宏都替换掉,步骤如下:
a)
备份文件,
cp -R /usr/include/c++/4.1.2 /usr/include/c++/4.1.2.bak
a) 进到 /usr/include/c++/4.1.2 目录 cd /usr/include/c++/4.1.2
b) 运行 vim
c) 读取所有文件
:args **
这里 ** 表示递归读取文件
d) 然后将 namespace _GLIBCXX_STD 替换成 namespace std{
:argdo %s/^namespace _GLIBCXX_STD$/namespace std{/g
对于 VC7 而言,可能还要处理 STD_END, 将它们替换成 }
e) 通过 ctags 生成 tags
:!ctags -R --kinds-c++=+p --fields=+iaS --extra=+q --language-force=c++ .
注意这个 --languague-force, 因为有些文件没有后缀,而且我看 std 目录里面也挺干净的,就直接当成 c++ 文件都处理了。这里可以 show 一下效果
a) 进到 /usr/include/c++/4.1.2 目录 cd /usr/include/c++/4.1.2
b) 运行 vim
c) 读取所有文件
:args **
这里 ** 表示递归读取文件
d) 然后将 namespace _GLIBCXX_STD 替换成 namespace std{
:argdo %s/^namespace _GLIBCXX_STD$/namespace std{/g
对于 VC7 而言,可能还要处理 STD_END, 将它们替换成 }
e) 通过 ctags 生成 tags
:!ctags -R --kinds-c++=+p --fields=+iaS --extra=+q --language-force=c++ .
注意这个 --languague-force, 因为有些文件没有后缀,而且我看 std 目录里面也挺干净的,就直接当成 c++ 文件都处理了。这里可以 show 一下效果
4
对
VC
进行
tags
处理,其实
vc7
也能用到
tags
,但是因为
VC7
比较庞大,所有需要用
ctags
处理的地方很多,比如
%VCINSTALLDIR%/include;%VCINSTALLDIR%/altmfc
等等,这些在
vc7
的选项中的环境选项卡里面应该可以找到
对它们一一进行 ctags 处理,然后通过脚本将这些 tags 自动保存到 tags 路径中,就可以解决在 vc 下利用 vim 的问题了。如果是 vc6 的工程,更可以很方便的把 vc 文件导出成 .mak 文件,这样就能直接在 vim 中 make 了,呵呵,不过不能调试。
对它们一一进行 ctags 处理,然后通过脚本将这些 tags 自动保存到 tags 路径中,就可以解决在 vc 下利用 vim 的问题了。如果是 vc6 的工程,更可以很方便的把 vc 文件导出成 .mak 文件,这样就能直接在 vim 中 make 了,呵呵,不过不能调试。
至于将
tags
自动添加,可以通过
autocm
事件,也能通过
Project
插件的一些小技巧,就我而言,我把这个脚本的处理放在
ftplugin
里面,这个在
omnicppcomplete
插件介绍里面再进一步详叙吧。