分类: LINUX
2008-03-11 09:47:14
linux下阅读源码的利器:vi+ctags
生成tags文件、配置vi
-------------------------------------------
(1)进入源码所在目录:
# cd /usr/src/linux
(2)生成针对源码的tags,因为ctags确省不把函数声明作为tag所以要加--c-types=+px(见注1)
# ctags -R --c-types=+px
(3)在vi配置文件中加入生成的tags
# vi /etc/vim/vimrc
set tags=/usr/src/linux/tags
使用tag查找对象:
-------------------------------------------
ctags -R
"-R"表示递归创建,也就包括源代码根目录下的所有子目录下的源程序。"tags"文件中包括这些对象的列表:
(1)用#define定义的宏
(2)枚举型变量的值
(3)函数的定义、原型和声明
(4)名字空间(namespace)
(5)类型定义(typedefs)
(6)变量(包括定义和声明)
(7)类(class)、结构(struct)、枚举类型(enum)和联合(union)
(8)类、结构和联合中成员变量或函数
vim用这个"tags"文件来定位上面这些做了标记的对象(见注1),下面介绍一下定位这些对象的方法:
1) 用命令行。在运行vim的时候加上"-t"参数,例如:
# vim -t foo_bar
这个命令将打开定义"foo_bar"(变量或函数或其它)的文件,并把光标定位到这一行。
2) 在vim编辑器内用":ta"命令,例如:
:ta foo_bar
3) 最方便的方法是把光标移到变量名或函数名上,然后按下" Ctrl-]";用"Ctrl-o"退回原来的地方。用 Ctrl-]延着调用树向前跳转, 用Ctrl-t向回跳转
4) 分割窗口
":tag"命令会将当前窗口的文件替换为包含新函数的文件。怎样才能同时查看两个文件呢?你可以使用 ":split"命令将窗口分开然后再用":tag"命令。vim 有个缩写命令可以做到这些:
:stag tagname
使用下面的命令可以分割当前窗口并跳转到光标下的标签:
Ctrl-w-]
如果指定了计数参数,新窗口将包含指定的那么多行。
5) 多个匹配
当一个函数(或类中的方法)被定义多次, ":tags" 命令会跳转到第一处。如果在当前文件中存在匹配,那它将会被首先使用。 你现在可以跳转到同一个标签的其它匹配处:
:tnext
重复执行这个命令可以找到更多的匹配。如果存在很多匹配,你可以选择要跳转到哪一个:
:tselect tagname
vim 会为你展示一个选择列表:
# pri kind tag file
1 F f mch_init os_amiga.c
mch_init()
2 F f mch_init os_mac.c
mch_init()
3 F f mch_init os_msdos.c
mch_init(void)
4 F f mch_init os_riscos.c
mch_init()
Enter nr of choice (
你现在可以输入要跳转到的匹配代号(在第一列)。其它列的信息可以让你知道匹配在何处被定义。
以用这些命令在各匹配的标签间移动:
:tfirst 到第一个匹配
:[count]tprevious 向前 [count] 个匹配
:[count]tnext 向后 [count] 个匹配
:tlast 到最后一个匹配
如果没有指定,[count] 省缺为一。
6) 猜测标签名
命令行补全是避免输入长标签名的好办法。只需输入开始的一部分然后按
:tag write_
你会得到第一个匹配。如果这不是你想要的,重复输入
有时你只知道一个函数名的一部分,或是你有很多以相同字符串开头而结尾不同的标记。这时你可以告诉vim使用一个模式来查找标签。
假设你要跳转到一个包含 "block" 的标签。首先输入:
:tag /block
现在再利用命令行补全功能:输入
标签名前面的 "/" 告诉vim这不是一个确定的标签名而是一个模式。你可以利用有关查找模式的所有特性。举个列子,假设你要选择所有以 "write_" 开头的标签:
:tselect /^write_
"^" 指定标签以 "write_" 开头,否则在中间含有 "write_" 的标签名也会被找到。类似地,"$" 指定标签名结尾处的匹配。
7) 预览窗口
当编辑含有函数调用的代码时,你需要使用正确的调用参数。要获知所要传递的值,你可以查看这个函数是如何定义的。标签机制对此十分适用。如果定义可在另一个窗口内显示那就更好了。对此我们可以利用预览窗口。
打开一个预览窗口来显示函数 "write_char":
:ptag write_char
vim 会打开一个窗口,跳转到 "write_char" 标签。然后它会回到原来的位置。这样你可以继续输入而不必使用 CTRL-w w命令在两个分割窗口移动光标。
如果函数名出现在文本中,你可以用下面的命令在预览窗口中得到其定义:
Ctrl-w-]
用下面的命令关闭预览窗口:
:pclose
要在预览窗口中编辑一个指定的文件,用 ":pedit" 。这在编辑头文件时很有用,比如:
:pedit defs.h
最后, "psearch" 可用来查找当前文件和任何包含文件中的单词并在预览窗口中显示匹配。这在使用没有标签文件的库函数时十分有用。例如:
:psearch popen
这会在预览窗口中显示含有 popen() 原型的 "stdio.h" 文件:
FILE *popen __P((const char *, const char *));
你可以用 'previewheight' 选项指定预览窗口打开时的高度。
注:
-------------------------------------------
(1)
--
--
The specific sets of flags recognized for each language, their
meanings and defaults may be list using the --list-kinds option.
# ctags --list-kinds
C
c classes
d macro definitions
e enumerators (values inside an enumeration)
f function definitions
g enumeration names
l local variables [off]
m class, struct, and union members
n namespaces
p function prototypes [off]
s structure names
t typedefs
u union names
v variable definitions
x external variable declarations [off]
(2)
--- 对 c++
--- ctags -R --language-force=c++ --c++-types=+px --verbose --extra=+q
--- extra=+q 用来增加生成 Class::member 的形式, 默认没有这样就可以用 :ts CView::OnDraw 这种形式看
--- 因为c++一些头文件不用.h所以要用--language-force
--- 对 java
--- ctags -R --languages=java c:/jdk131/src
--- 要把src.jar展开