用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上!

搜索某个变量或函数在工程内所有文件中出现的位置

这个用Ack或者Ag插件可以完美实现。

Ag相比Ack:

  • 使用了多线程, mmap()等技术,搜索速度有数量级的提升

  • 可以识别.gitignore, .hgignore, .agignore文件

ack.vim, ag.vim长得很像。其实ack.vim可以被配置成使用ag作为搜索引擎。

函数的调用关系

在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的官方Vim教程

  • cscope_maps.vim 中的默认快捷键也比较好用。

跳转到函数开始或者结尾

有时在一个很长的函数中,希望定位到函数的开始或者结尾,以便知道自己的相对位置,或者跳转到下一个函数。taglist插件可以实现,但其实Vim内置就有此功能:

  • [{ 跳转到前一个未匹配的_{_,即函数开始

  • }] 跳转到后一个未匹配的_}_,即函数结尾

  • ]] 跳转到下一个以_{_ 开始的行。

  • [[][,[] 都有类似的功能,多用就行,不需要记忆。

  • 在开始(结尾)大括号上,按 % 可以跳转到结尾(开始)。自从我第一次设置 nnoremap <Tab> % 后,就再也离不开它了。

其它Vim的跳转功能

  • H 屏幕顶端

  • M 屏幕中间

  • L 屏幕底端

  • :h 29.3

  • :h motion.txt

  • :h tagsrch.txt