Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1972071
  • 博文数量: 185
  • 博客积分: 10707
  • 博客等级: 上将
  • 技术积分: 1777
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-19 17:31
文章分类

全部博文(185)

文章存档

2014年(1)

2012年(6)

2011年(27)

2010年(13)

2009年(75)

2008年(63)

分类: LINUX

2011-03-20 12:33:32

一、引言

VimLinux下的标准文本编辑器,在日常工作中必不可少。而作为程序员,我们可能要花很多的时间和vim打交道。Vim虽然提供了语法高亮等方便编程的动能,但用惯了Source Insight和kscope等图形化IDE的人,还是不喜欢vim的简单。其实vim并不简单,如果稍稍发掘一下vim的潜在功能,你会发现,它比Kscope毫不逊色,而且和Kscope、Eclipse等IDE相比,它还有自己的先天优势,那就是快!下面我们就尝试用vim+ctags+taglist+cscope来打造Linux文本模式下的Kscope吧!我也是边学边练,如有不对之处,望不吝指正

 

二、说明 

本文中使用如下格式表示命令行输入

$cat /etc/hosts

其中$为命令行提示符。没有命令行提示符的表示命令行输出

127.0.0.1 localhost.localdomain localhost localhost

使用前加冒号的方式表示vim命令输入

:help

vim命令输出,会在正文中说明。

另外,对可以缩写的命令,我们会采用如下格式

:cs[cope] a[dd] cscope.out

“[]”内的字符是缩写时可以省略的,所以上面的命令用缩写给出就是

:cs a cscope.out

我们用”~”指当前登录目录,如果你切换到root用户,请注意使用相关用户的$HOME或绝对路径代替此处的"~”。

 

三、给函数贴上标签--ctags

ctags是一种能为多种语言源程序的函数,变量,类,宏定义等生成标签文件的应用程序。有了这些标签文件,文本编辑器或其他应用程序就可以简单快速的找到相关标签的定义,从而有效的提高编程效率。就像给每家住户贴上门牌,邮递员就可以很方便的找到投递地点一样。

标签(tag),有时也称为索引,但为了描述方便和避免混淆(在cscope中我们用索引),我们这里统一称tag为标签。

Vim作为Linux的标准编辑器,大都提供了对ctags的支持,要查看你使用的vim是否支持ctags,可以尝试获得ctags的帮助

:help ctags

如果支持ctags,vim会给出有关ctags的帮助,否则vim会提示出错,很不幸,那你就要自己安装ctags了。

下面就简单说一下vim中ctags的使用。

生成和加载标签文件

使用ctags,首先要生成标签文件

$ctags -R

使用-R选项递归的为当前目录生成标签文件,ctags生成的标签文件默认为tags,这也是vim启动时会默认搜索并加载的标签文件。当然,我们也可以使用-f选项指定自己的标签文件

$ctags -f ~/myproject/mytags -L myctags.files

但是如果指定的标签文件名不再是tags,vim启动时标签文件将不会自动加载。

这时我们可以使用如下方式来加载标签文件

:set tags=~/myproject/mytags

或者在~/.vimrc中添加一行

set tags=~/myproject/mytags

如果有多个标签文件,我们也可以一次加载多个,标签文件之间用逗号隔开

:set tags=~/myproject/mytags, ./mylocaltags

或者追加加载标签文件

:set tags+=./mylocaltags

还可以让vim去自动搜索并加载标签文件

:set tags=./tags, ./../tags, ./*/tags

这时vim会查找当前文件所在目录及其父目录和所有子目录下的标签文件,如果想让vim查找整个工程目录树下的所有标签文件,可以使用如下方式

:set tags=~/myproject/**/tags

当然,为了避免每次启动vim重复输入这些命令,我们可以把它们放在~/.vimrc里,但注意不能使用相路径。

你可能已经注意到,在上例中我们使用了ctags的-L选项,此选项允许我们指定需要生成标签的文件列表。有时可能并是项目里所有的文件都需要生成标签,这我们只需把要生成标签的文件放在一个文件列表里

$find ~/myproject -name “*.h” -o -name “*.c” -o -name “*.cpp” > mytags.files

然后使用-L指定该文件列表,ctags就会只为列表里的那些文件生成标签了。

注意,我们在这里使用了绝对路径。为什么要使用绝对路径呢?因为当我们由于工作需要,在不同的目录下来回切换时,在原先路径下有效的相对目录,在当前目录可能就无效了。这样vim就找不到需要的标签,因为标签文件里保存的相对路径此时失效了,而绝对路径可以保证在任何目录下都不会失效。

知道了如何生成和加载标签文件之后,接下来我们就来看看怎样使用vim的tag功能

使用标签

启动vim时自动跳转到指定标签

$vim -t 

vim启动时会自动搜索标签文件,找到定义指定标签的文件,打开它,并将光标定位到指定标签所在的那一行。

跳转到指定标签

:ta 

:tag 

跳转到指定标签定义的地方,如果有多个相同的标签,vim会给出一个列表,从中可以选择要跳转到哪里。

在分割窗口中查看标签

:stag 

标签跳转快捷键

Vim已经映射了几个用于标签之间跳转的快捷键,我们可以使用这些快捷键在标签之间来回跳转。

Ctrl-] 跳转到当前光标所在的标签;

Ctrl-O 返回到跳转前的位置;

Ctrl-T 沿着经过的标签列表向回跳转,也可以在其前面输入一个数字,如N-Ctrl-T会向回跳转N步,相当于按了N下Ctrl-T;

:tags 显示所有经过的标签列表;

标签补全

当我们不想输入完整的标签时,可以只输入要找标签的前几个字符,然后按键自动补全

:tag prefix_

默认会得到第一个匹配,如果它不是你想要的,可以重复按键直到找到正确的匹配。

模式匹配

ctags支持模式匹配查找,当我们无法记清楚要找的标签,或只知道标签的一部分时,就可以使用模式匹配来搜索。

:tag /pattern

匹配指定模式,按后,vim会自动搜索包含pattern的标签,默认会得到第一个匹配,如果这不是你想要的,可以重复按键直到找到正确的匹配。

我们可以使用有关查找模式匹配的所有特性,如只查找以foo开始的标签

:tag /^foo

:tselect /^foo

或只查找以bar结尾的标签

:tag /bar$

:tselect /bar$

你同可以用逐个查看,也可以直接按vim给出匹配的标签列表,然后从中选择你想查找的标签

预览窗口

有时我们可能不想跳转到指定标签,只是想查看或确认一下相关标签的定义,然后就返回。用Ctrl-]跳转然后再用Ctrl-O或Ctrl-T返回当然可以,但vim提供了一种更简单的方式,那就是预览窗口。预览窗口就是把当前编辑窗口分割出一小部分,用来显示预览,活动光标依然会停留在编辑窗口,不会影响编辑。

在预览窗口里显示标签定义

:ptag 

对于ptag,前面所讲的模式匹配同样适用,可以使用

:pclose

关闭预览窗口,而无论当前活动窗口是哪一个。

在预览窗口中编辑指定文件

:pedit 

查找当前文件和任何包含文件中的单词并在预览窗口中显示匹配

:psearch 

这在使用没有标签文件的库函数时十分有用,它可以找到库函数的声明,并在预览窗口显示,这样我们就可以查看传给函数的参数是否正确。psearch会根据vim中指定的path选项搜索包含的头文件,path选项的默认值为

.,/usr/include,,

即psearch默认搜索当前目录和/usr/include目录。如果你的头文件放在其他地方,可以用

:set path=~/myproject/include,./subdir/include

:set path+=~/myproject/include,./subdir/include

指定搜索路径。前一种方式会覆盖之前的path,后一种方式是在之前path上追加。当然,为了避免每次启动vim重复输入这些命令,我们可以把它们放在~/.vimrc里,但注意不能使用相对路径。

如果你不知道当前path是什么,可以用如下命令查看

:set path ?

我们也可以用此等命令查看vim其它选项的当前值,其格式为

:set option ?

其中option为要查看的选项。例如,如果我们想知道当前tags是什么,可以输入

:set tags ?

Vim会给出形如

tags=./tags,./TAGS,tags,TAGS

信息。这样我们就知道vim默认会在当前目录搜索并使用tags或TAGS作为标签文件。

要想更详细的了解ctags,请参考在线帮助

:help ctags

:help tags

PS: 可以用Ctrl-W加方向键或Ctrl-W-W在vim不同窗口之间切换。

四、把标签贴出来--taglist

虽然使用ctags我们可以在各个标签之间搜索和跳转,但是我们并不能看到这些标签,他们都隐藏在后台。就像一瓶化学药品,只有当我们知道它含有什么成分时才知道能从中提取出什么,对于我们不知道的成分,我们无从知道,哪怕其他人知道它还有很多其它成分。但是如果我们把所有成分的列表贴在瓶子上,其他人就能一目了然的知道瓶子到底装了什么东西。taglist就是就是把隐藏的标签贴出来。

Taglist是基于ctags的vim小插件,所以它只能在已经支持ctags的vim上使用。Taglist插件可以分组显示ctags生成的标签,使标签的查看更加方便和快捷。Taglist会从vim分割出一个窗口用来显示标签,在标签窗口中的标签上按<Enter>或鼠标单击/双击,该标签就会在另一窗口中显示,非常方便。

Taglist的安装

首先到下载taglist插件,当前最新版本是taglist_45.zip。解压后会得到两个文件:

./plugin/taglist.vim

./doc/taglist.txt

把这两个文件放到相应目录下

$cp ./plugin/taglist.vim ~/.vim/plugin/

$cp ./doc/taglist.txt /usr/share/vim/vim71/doc/

我的vim版本是7.1,所以这里是vim71。重启vim,用:Tlist或:TlistToggle就可以打开关闭标签列表了。

当然,我们还可以按如下方式安装Taglist:

把下载的zip文件解压到~/.vim,然后到~/.vim/doc目录下启动vim,用:helptags安装Taglist帮助就可以了。

另外,taglist需要ctags的支持,vim要支持system(),并且filetype选项是打开的。

如果ctags是自己安装的,Taglist可能找不到ctags程序。例如,我们把ctags安装在/usr/local/bin目录下,如果Taglist插件找不到ctags,可以采用如下方式:

1把/usr/local/bin加到搜索路径PATH里。在~/.bashrc里加一行

PATH=$PATH:/usr/local/bin

2指定Tlist_Ctags_Cm。修改~/.vim/plugin/taglist.vim,在if !exists('loaded_taglist')前设置Tlist_Ctags_Cmd

set cpo&vim

let Tlist_Ctags_Cmd=”/usr/local/bin/ctags”

if !exists('loaded_taglist')

可用如下命令检查vim是否支持system()

:echo exists('*system')

如果支持,vim应该显示1,否则你可能就要重新编译安装vim了。

如要查看vim的filetype是否打开,可用

:filetype

如果已经打开vim会显示”filetype on",否则需要在~/.vimrc中加上”filetype on"来打开filetype支持。

Taglist设置快捷键

我们还可以为taglist设置一个快捷键,这样就可以用快捷键打开和关闭taglist了。例如我们要设置F8为taglist的快捷键,在~/.vimrc中加入如下一行就可以了:

nnoremap  :TlistToggle

要想更详细的了解taglist,请参考在线帮助

:help taglist

五、统一的力量,让代码形成一个整体--cscope

虽然我们已经知道了瓶里药品的成分,但怎么才能知道有多少成分的分子,各成分含有哪些元素呢?就像在一个项目里,我们怎么知道那些文件使用了某个关键字,一个函数都被那些函数调用了呢?cscope,它能把整个项目的代码连成一个整体,让你可以在代码的世界里面自由驰骋……

cscope是一个基于索引的代码查看工具,它可以帮助你更详细的搜索和查看代码。有了cscope的支持,vim不仅可以查看函数,变量,宏的定义,还可以更详细的搜索函数调用,文件包含,变量引用,甚至对一个符号进行全局搜索!有了cscope,vim简直就是文本模式下的Kscope!

目前很多Linux发行版的vim都提供了cscope的支持。我们可以使用如下方式查看自己的vim是否支持cscope

$vim –version | grep cscope

+cryptv +cscope +cursorshape +dialog_con +diff +digraphs -dnd -ebcdi

如果有+cscope,说明你的vim已经支持cscope,否则你可能需要打开cscope支持,重新编译安装vim了。

生成索引文件

使用cscope,我们首先要生成索引文件

$cscope -Rbkq

-R 递归搜索当前目录

-b 只生成索引文件,不进入cscope界面

-k 在生成索引文件时,不搜索/usr/include目录

-q 生成cscope.in.out和cscope.po.out文件,加快cscope的索引速度

你也可以不用-b选项,这样cscope会打开一个界面显示索引状态,索引完成后可以用Ctrl-D退出cscope界面。

cscope生成索引文件时默认只会搜索有限类型的文件(.c, .h, .l, .y),如果要搜索其他类型的源文件如c++,就要先产生一个搜索文件列表,然后再对列表里的文件生成索引:

$find ~/project/ -name “*.c” -o -name “*.h” -o -name “*.cpp” > cscope.files

$cscope -bkq -f ~/project/cscope.out -i cscope.files

-f选项告诉cscope要生成的指定的索引文件,而不是默认的cscope.out,-i选项是让cscope从文件中读入要生成索引文件的列表。

如上面介绍ctags时所说,如果要对一个项目使用cscope,就需要使用绝对路径建立索引,否则将无法根据索引正常跳转。

链接索引文件

要把cscope生成的索引文件链接进vim之后,才能正常使用cscope的功能

:cs[cope] a[dd] cscope.out

可以分多次add单个索引文件,也可以一次add多个索引文件

:cs a cscope.out ./others/othercscope.out

注意,这里使用空格区分不同的索引文件,不像vim中的:set那使用逗号区分。

查看已链接的索引文件

:cs[cope] s[how]

删除链接的索引文件

:cs[cope] k[ill] 

是命令:cs s显示在第一列的连接号。

重新初始化所有的链接

:cs[cope] r[eset]

vim会重新搜索并链接索引文件。

开始使用cscope搜索

下面我们看看怎样用cscope进行搜索

:cs[cope] f[ind]  

type是搜索类型,cscope支持以下类型的搜索

c: 查找有那些函数调用了指定的函数

d: 查找指定函数调用了哪些函数

e: 查找指定的正则表达式,此时不宜用键盘映射

f: 查找指定的文件

g: 查找指定标示符的定义位置,此时用tag会好一点

I: 查找指定文件被哪些文件包含

s: 查找指定标示符的使用位置

t: 查找指定的文本字符串,会全局搜索所有包含此字符串的匹配,所以会比较慢

使用键盘映射

每次查找都要输入庸长难记的cscope命令有时是一件很头痛的事情,那么有没有一种简单有效的方法提供搜索功能呢?有,那就是cscope键盘映射插件。它把cscope查找命令映射成vim快捷键,这样你就不用每次都要输入繁琐的cscope命令了。

cscope_maps有三种快捷键映射模式,可以分别在不同方式下打开搜索窗口

Ctrl-\-cmd 相当于 :cs f   普通模式,在当前窗口打开指定索引;

Ctrl-Space-cmd 相当于 :scs f   它会在水平分割窗口内打开指定索引;

Ctrl-Space-Space-cmd 相当于 :vert scs f   它会在垂直分割窗口内打开指定索引;

其他考虑

在启动vim时,你可能会碰到如下错误

Error detected while processing /home/xingang/.vim/plugin/cscope_maps.vim:

line   42:

E568: duplicate cscope database not added

Press ENTER or type command to continue

这是由于重复装载cscope索引文件导致的,其实索引文件已经装载,所以可以不必对这个错误过分担心。但如果你觉得不爽,你也可以把~/.vim/plugin/cscope_maps.vim中链接索引文件的命令注释掉

" add any cscope database in current directory

"if filereadable("cscope.out")

"    cs add cscope.out  

" else add the database pointed to by environment variable 

"elseif $CSCOPE_DB != ""

"    cs add $CSCOPE_DB

"endif

然后启动vim时,自己链接索引文件。

另外一种方法是设置环境变量CSCOPE_DB

CSCOPE_DB=/project/cscope.out

export CSCOPE_DB

vim启动时就会自动搜索并链接$CSCOPE_DB指定的索引文件,所以我们只要把上面两行放到~/.bashrc里就可以了,注意要使用绝对路径。

要想更详细的了解cscope,请参考在线帮助

:help cscope

六、结语

十年磨一剑,在Unix/Linux多年的发展史中,程序员是没有图形化IDE的,那他们是怎么协调代码之间的关系呢?什么东西都会有一个从无到有的过程,他们为了能使自己的工作更加高效,就自己动手开发出了这些有用的小程序。所以我辈们才有幸拿着先辈的利剑,披荆斩棘……

七、参考资料

ctags和vim

使用vim + cscope/ctags实现Source Insight的功能

阅读(2565) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~