用Vim已经很久了,但从来没有真正用它来看工程文件。也曾用过taglist,但感觉功能有限,或许是我没有仔细看文档,总之不能满足我的要求。
ctags也用过,但也没有深入研究过,因为需求也不是很强烈。然后现在只能是在VS2008(不要问我为什么用这么老的版本,那个某软件发布的工程文件就是vc9.sln,懒得改了)里看源码的关系。
我的基本要求是:
跨文件跳转到定义
在VS中快捷键是 F12 ,然后 Ctrl+- 返回。在Vim的内置功能中也有跳转到定义的功能,按 gd 即可,但这只是基于文本的搜索,没有分析语法,而且只能在当前文件中搜索,不是很实用。标准的解决方案应该是用 ctags 生成tags文件,然后在Vim中就可以用
-
:tag <varname>
-
或者 Ctrl+] (写到这里突然想到了Vim的帮助文档的tags就是这么跳转的)
-
甚至 Ctrl+鼠标左键
来跳转到定义了。具体做法如下:
-
按 Ctrl+t 从一个tag返回到原来的位置。或者 Ctrl+o ,用Vim本身的上一个位置返回(如果移动了很多次,需要按好多次才能返回到原来位置)。
-
首先系统需要安装ctags,这个通过软件源或者 ctags官方网站 都可以安装。
-
在工程目录下生成tags文件:
ctags -R # 遍历所有目录,默认输出文件是 tags
ctags -e -R # 同上,但是生成的TAGS是给Emacs用的
-
在 ~/.vimrc 中添加
set tags=./tags;/
这是Stackoverflow上 有个答案 给出的解决方案,目的是先在当前目录下找tags,如果没有,就一直向上层目录搜索,直到根目录。这样就只需要生成一个tags文件就行了。
之所以要这样设置,是因为默认的 set tags=./tags,./TAGS,tags,TAGS 不好用。实际的代码文件往往分散在工程文件下的多个子目录下,如果Vim默认只在当前目录下搜索tags或者TAGS,就需要分别为每个目录生成tags文件。另外如果没有设置 set autochdir ,在子目录A中,打开了另外子目录B中的某个源文件file.c,此时Vim并不会改变你的当前目录到B,而仍旧在A目录下寻找B/file.c的tags,当然不是想要的结果!不知道Vim的默认选项为什么这么设计(此处省略一万字吐槽)。
另外,还可以直接 vim -t main 来直接打开含有main函数的文件并把光标也放到main上!
搜索某个变量或函数在工程内所有文件中出现的位置
函数的调用关系
在VS中要右键→调用浏览器。在Vim中需要用到cscope。
cscope -R # 在源文件根目录下生成cscope.out,并打开cscope自带的ncurse界面。但每次进行新的搜索时,需要退出vim
cscope -R -b # 仅生成cscope.out,然后退出
-
源文件根目录下打开Vim,输入 :cscope add cscope.out 命令,连接到已生成的cscope数据库。
-
:cscope help 查看帮助
-
:cscope find
-
c 哪些函数调用了该函数
-
d 该函数被哪些函数调用
-
e egrep查找
-
g 变量定义
-
f 在该文件中查找
-
i 哪些文件#include了本文件
-
s 查找C符号
-
t 查找文本
-
-
cscope_maps.vim 中的默认快捷键也比较好用。
跳转到函数开始或者结尾
有时在一个很长的函数中,希望定位到函数的开始或者结尾,以便知道自己的相对位置,或者跳转到下一个函数。taglist插件可以实现,但其实Vim内置就有此功能:
-
[{ 跳转到前一个未匹配的_{_,即函数开始
-
}] 跳转到后一个未匹配的_}_,即函数结尾
-
]] 跳转到下一个以_{_ 开始的行。
-
[[ 和 ][,[] 都有类似的功能,多用就行,不需要记忆。
-
在开始(结尾)大括号上,按 % 可以跳转到结尾(开始)。自从我第一次设置 nnoremap <Tab> % 后,就再也离不开它了。
其它Vim的跳转功能
-
H 屏幕顶端
-
M 屏幕中间
-
L 屏幕底端
-
:h 29.3
-
:h motion.txt
-
:h tagsrch.txt