配合 tag 文件可以实现定义跳转。
:tags" 命令显示你经过的标签列表:
下面的命令跳转到标签列表中最上面的标签:
:tag
你可以在前面加上要向前跳转的标签个数。比如:":3tag"。 CTRL-T 同样可以加上一个
计数参数。
:stag tagname
使用下面的命令可以分割当前窗口并跳转到光标下的标签:
CTRL-W ]
你现在可以跳转到同一个标签的其它匹配处:
:tnext
重复执行这个命令可以找到更多的匹配。如果存在很多匹配,你可以选择要跳转到哪一
个:
:tselect tagname
你现在可以输入要跳转到的匹配代号(在第一列)。其它列的信息可以让你知道匹配在何
处被定义。
可以用这些命令在各匹配的标签间移动:
:tfirst 到第一个匹配
:[count]tprevious 向前 [count] 个匹配
:[count]tnext 向后 [count] 个匹配
:tlast 到最后一个匹配
如果没有指定,[count] 省缺为一。
猜 测 标 签 名
命令行补全是避免输入长标签名的好办法。只需输入开始的一部分然后按 :
:tag write_
你会得到第一个匹配。如果这不是你想要的,重复输入 直到你找到正确的匹配。
有时你只知道一个函数名的一部分,或是你有很多以相同字符串开头而结尾不同的标
记。这时你可以告诉 Vim 使用一个模式来查找标签。
假设你要跳转到一个包含 "block" 的标签。首先输入:
:tag /block
现在再利用命令行补全功能:输入 。Vim 会找到所有包含 "block" 的标签并使用
第一个匹配。
标签名前面的 "/" 告诉 Vim 这不是一个确定的标签名而是一个模式。你可以利用有
关查找模式的所有特性。举个列子,假设你要选择所有以 "write_" 开头的标签:
:tselect /^write_
"^" 指定标签以 "write_" 开头,否则在中间含有 "write_" 的标签名也会被找到。类似
地,"FCKpd0quot; 指定标签名结尾处的匹配。
标 签 浏 览 器
CTRL-] 可以让你跳转到光标所在标识符的定义处,因此你可以利用标识符的列表来形成
一个目录。这里给出一个例子。
首先生成一个标识符列表(需要 Exuberant ctags):
ctags --c-types=f -f functions .c
现在打开 Vim 并在一个垂直分割窗口中编辑这个文件:
vim
:vsplit functions
窗口中包含一个所有函数的列表。其它的东西可以被忽略。用 ":setlocal ts=99" 命令
使其显示得更清晰些。
在这个窗口中,定义一个 mapping:
:nnoremap 0yew:tag "
移动光标至要跳转到函数的所在行,输入 。Vim 会在另一个窗口中跳转到所选择
的函数定义处。
相 关 杂 项
你可以设定 'ignorecase' 选项来忽略标签名里的大小写。
'tagbsearch' 选项标明标签文件是否经过排序。省缺是假定为标签文件已排序,这样会
使查找更快,但如果文件没有被排序是无法工作的。
'taglength' 选项可用来告诉 Vim 一个标签的有效字符个数。
当你使用 SNiFF+ 程序时,你可以利用 Vim 的有关接口 |sniff| 。SNiFF+ 是一个商业
软件。
Cscope 是一个自由软件。它不仅可以找到一个标识符被声明的地方,还可以找到标识符
被使用的地方。 请参考 |cscope|。
29.2 预览窗口
当编辑含有函数调用的代码时,你需要使用正确的调用参数。要获知所要传递的值,你可以
查看这个函数是如何定义的。标签机制对此十分适用。如果定义可在另一个窗口内显示那
就更好了。对此我们可以利用预览窗口。
打开一个预览窗口来显示函数 "write_char":
:ptag write_char
Vim 会打开一个窗口,跳转到 "write_char" 标签。然后它会回到原来的位置。这样你可
以继续输入而不必使用 CTRL-W 命令。
如果函数名出现在文本中,你可以用下面的命令在预览窗口中得到其定义:
CTRL-W }
有一个脚本可以自动显示光标处的标签定义。请参考 |CursorHold-example| 。
用下面的命令关闭预览窗口:
:pclose
要在预览窗口中编辑一个指定的文件,用 ":pedit" 。这在编辑头文件时很有用,比如:
:pedit defs.h
最后, "psearch" 可用来查找当前文件和任何包含文件中的单词并在预览窗口中显示匹
配。这在使用没有标签文件的库函数时十分有用。例如:
:psearch popen
这会在预览窗口中显示含有 popen() 原型的 "stdio.h" 文件:
FILE popen __P((const char , const char ));
你可以用 'previewheight' 选项指定预览窗口打开时的高度。
29.3 在代码间移动
因为程序代码是结构化的,Vim 可以识别其中的有关项目。一些特定的命令可用来完成相
关的移动。
C 程序中经常包含类似下面的代码:
#ifdef USE_POPEN
fd = popen("ls", "r")
#else
fd = fopen("tmp", "w")
#endif
有时会更长,也许还有套嵌。将光标置于 "#ifdef" 处按 %。Vim 会跳转到"#else"。继
续按 % 会跳转到 "#endif"。再次按下 % 又回到原来的 "#ifdef"。
当代码套嵌时,Vim 会找到相匹配的项目。这是检查你是否忘记了一个 "#endif" 的
好办法。
当你在一个 "#ifdef" - "#endif" 块内的某个位置,你可以用下面的命令回到开始
处:
[#
如果你的位置不是在 "#if" 或 "#ifdef" 之后, Vim 会鸣音。用下面命令可以跳转到下
一个 "#else" 或 "#endif":
]#
这两个命令会跳过它所经过的 "#if" - "#endif" 块。
例如:
#if defined(HAS_INC_H)
a = a + inc();
# ifdef USE_THEME
a += 3;
# endif
set_width(a);
如果光标在最后一行,"[#" 会移动到第一行。中间的 "#ifdef" - "#endif" 块被跳过。
在 代 码 块 内 移 动
C 代码块包含在 {} 中,有时一个代码会很长。要跳转到外部代码块的开始处,用 "[["
命令。用 "][" 找到结尾处。(前提是 "{" 和 "}" 都在第一列。)
"[{" 命令跳转到当前代码块的开始处。它会跳过同一级别的 {} 对。"]}" 跳转到结尾。
一点概述:
function(int a)
+-> {
| if (a)
| +-> {
[[ | | for (;;) --+
| | +-> { |
| [{ | | foo(32); | --+
| | [{ | if (bar(a)) --+ | ]} |
+-- | +-- break; | ]} | |
| } }
|
[] | int func2(void)
| +-> {
| [[ | if (flag)
start +-- +-- return flag;
| ][ | return 2;
| +-> }
]] |
| int func3(void)
+----------> {
return 3;
}
不要忘了你还可以用 "%" 在匹配的 (), {} 和 [] 间移动。这在它们相距很多行时仍然
适用。
在 括 号 内 移 动
"[(" 和 "])" 命令"[}" 和 "]}" 类似,只不过它们适用于 () 对而不是 {} 对。
[(
f)) && x > y)
-------------->
-------------------------------->
])
在 注 释 间 移 动
移动到一个注释的开始用 "[/";向前移动到注释的结尾用 "]/"。这只对 / - / 注释
有效。
+-> +-> /
| [/ | * A comment about --+
[/ | +-- * wonderful life. | ]/
| /
vim.h -->
文件 "io.h" 被当前文件包含但无法找到。"vim.h" 可以找到,这样 ":checkpath" 跟进 这个文件并检查其中的包含文件。结果显示无法找到 "vim.h" 包含的 "functions.h" 和 "clib/exec_protos.h" 文件。 Note: Vim 不是一个编译器。它无法识别 "#ifdef" 语句。这就是说所有的 "#include" 语句都会被使用,即使它在 "#if NEVER" 之后。 给 'path' 选项增加一个目录可以修正无法找到文件的错误。一个好得参考是 Makefile。 注意那些包括 "-I" 的条目,比如 "-I/usr/local/X11"。要增加这个目录,用: :set path+=/usr/local/X11 如果有很多的子目录,你可以用 "" 通配符。例如: :set path+=/usr//include 这会找到 "/usr/local/include" 以及 "/usr/X11/include" 目录下的文件。 如果你的工程项目的包含文件都在一个套嵌的目录树下,"" 就非常有用。它会搜索所 有的子目录。例如: :set path+=/projects/invent//include 这会找到这些目录下的文件: /projects/invent/include /projects/invent/main/include /projects/invent/main/os/include etc. 还有其它的可能性。更多信息,请查看 'path' 选项。 如果你想查看找到的包含文件,用这个命令: :checkpath! 你会得到一个(很长)的包含文件列表。为使它更短些,Vim 会对已经找到的文件显示 "(Already listed)" 而不再重新显示一遍
this guy is lazy, nothing leave