Nvim :help
页面,生成 于 源文件,使用 tree-sitter-vimdoc 解析器。
ctags *.c"ctags" 是一个单独的程序。大多数 Unix 系统都已安装。如果您还没有,可以在以下位置找到通用 ctags: https://ctags.io
:tag startlist此命令将找到函数 "startlist",即使它在另一个文件中也是如此。
CTRL-]
命令跳转到光标下单词的标签。这使得探索 C 代码的复杂结构变得容易。例如,假设您在函数 "write_block" 中。您可以看到它调用了 "write_line"。但是 "write_line" 做了什么?将光标放在对 "write_line" 的调用上并按 CTRL-]
,您将跳转到此函数的定义。函数 "write_line" 调用 "write_char"。您需要弄清楚它做了什么。因此,您将光标放在对 "write_char" 的调用上并按 CTRL-]
。现在您已在 "write_char" 的定义处。+-------------------------------------+ |void write_block(char **s; int cnt) | |{ | | int i; | | for (i = 0; i < cnt; ++i) | | write_line(s[i]); | |} | | +-----------|-------------------------+ | CTRL-] | | +----------------------------+ +--> |void write_line(char *s) | |{ | | while (*s != 0) | | write_char(*s++); | |} | | +--------|-------------------+ | CTRL-] | | +------------------------------------+ +--> |void write_char(char c) | |{ | | putchar((int)(unsigned char)c); | |} | +------------------------------------+
:tags
命令显示您遍历过的标签列表CTRL-T
命令转到前一个标签。在上面的例子中,您将回到 "write_line" 函数,在对 "write_char" 的调用中。此命令接受一个计数参数,指示要回跳多少个标签。您已经向前走了,现在又退了回来。让我们再次前进。以下命令转到列表顶部的标签:tag您可以在它前面加上一个计数,向前跳转那么多标签。例如: ":3tag"。
CTRL-T
也可以在其前面加上一个计数。因此,这些命令允许您使用 CTRL-]
下降调用树,并使用 CTRL-T
回到上面。使用 ":tags" 找出您的位置。:tag
命令将当前窗口中的文件替换为包含新函数的文件。但是假设您不仅想看到旧函数,还想看到新函数?您可以使用 :split
命令后跟 :tag
命令来拆分窗口。Vim 有一个简写命令可以同时完成这两件事:stag tagname要拆分当前窗口并跳转到光标下的标签,请使用此命令
CTRL-W ]如果指定了计数,新窗口将有那么多行高。
:set tags=./tags,./../tags,./*/tags这将在与当前文件相同的目录中查找一个标签文件,在更高一级目录中查找一个,并在所有子目录中查找。这是一个相当多的标签文件,但可能还不够。例如,在编辑 "~/proj/src" 中的文件时,您将找不到标签文件 "~/proj/sub/tags"。对于这种情况,Vim 提供在整个目录树中搜索标签文件。例如
:set tags=~/proj/**/tags
cd ~/proj ctags -R .这样做的好处是,通用/Exuberant ctags 识别各种文件类型。因此,这不仅适用于 C 和 C++ 程序,也适用于 Eiffel,甚至 Vim 脚本。请参阅 ctags 文档以调整此设置。现在您只需要告诉 Vim 您的大型标签文件在哪里即可
:set tags=~/proj/tags
:tag
命令将跳转到第一个。如果当前文件中存在匹配项,则首先使用该匹配项。现在您可以使用以下命令跳转到同一标签的其他匹配项:tnext重复此操作以查找更多匹配项。如果有很多,您可以选择要跳转到的匹配项
:tselect tagnameVim 将向您展示一个选择列表
<CR>
取消)<Tab>
:tag write_<Tab>您将获得第一个匹配项。如果这不是您想要的,请按
<Tab>
直到找到正确的匹配项。有时您只知道函数名称的一部分。或者您有很多以相同字符串开头,但结尾不同的标签。然后您可以告诉 Vim 使用模式查找标签。假设您要跳转到包含 "block" 的标签。首先键入以下内容:tag /block现在使用命令行补全:按
<Tab>
。Vim 将查找所有包含 "block" 的标签并使用第一个匹配项。标签名称前的 "/" 告诉 Vim 接下来的是一个模式,而不是文字标签名称。您可以在此处使用所有搜索模式项。例如,假设您要选择一个以 "write_" 开头的标签:tselect /^write_"^" 指定标签以 "write_" 开头。否则,它也会在标签名称的中间部分找到。同样,末尾的 "$" 确保模式匹配到标签的末尾。
CTRL-]
将您带到光标下标识符的定义,因此您可以使用标识符名称列表作为目录。这是一个例子。首先创建一个标识符列表(这需要通用或 Exuberant ctags)ctags --c-types=f -f functions *.c现在启动 Vim,但不要打开任何文件,并在 Vim 中编辑此文件,放在一个垂直拆分的窗口中
vim :vsplit functions窗口包含所有函数的列表。还有一些其他内容,但您可以忽略它们。执行 ":setlocal ts=99" 以清理它。在这个窗口中,定义一个映射
:nnoremap <buffer> <CR> 0ye<C-W>w:tag <C-R>"<CR>将光标移动到包含您要转到的函数的行。现在按
<Enter>
。Vim 将转到另一个窗口并跳转到所选函数。:ptag write_charVim 将打开一个窗口,并跳转到标签 "write_char"。然后它将带您回到原始位置。因此,您可以继续键入,而无需使用
CTRL-W
命令。如果函数名称出现在文本中,您可以使用以下命令在预览窗口中获取其定义CTRL-W }有一个脚本可以自动显示光标下单词定义的文本。请参阅 CursorHold-example。
:pclose要在预览窗口中编辑特定文件,请使用 ":pedit"。例如,这可以用于编辑头文件
:pedit defs.h最后,可以使用 ":psearch" 在当前文件和任何包含文件中查找单词,并在预览窗口中显示匹配项。当使用没有标签文件的库函数时,这尤其有用。例如
:psearch popen这将在预览窗口中显示 "stdio.h" 文件,其中包含 popen() 的函数原型。
FILE *popen __P((const char *, const char *));
您可以使用 'previewheight' 选项指定打开预览窗口时的窗口高度。#ifdef USE_POPEN
fd = popen("ls", "r")
#else
fd = fopen("tmp", "w")
#endif
但实际上要长得多,也可能嵌套。将光标放在 "#ifdef" 上并按 %。Vim 将跳转到 "#else"。再次按 % 将带您到 "#endif"。另一个 % 将带您回到 "#ifdef"。当结构嵌套时,Vim 将找到匹配的项目。这是一个很好的方法来检查您是否忘记了 "#endif"。当您在 "#if" - "#endif" 中的某个位置时,您可以使用以下命令跳转到它的开头[#如果您不是在 "#if" 或 "#ifdef" 之后,Vim 会发出蜂鸣声。要向前跳转到下一个 "#else" 或 "#endif",请使用
]#这两个命令会跳过它们遇到的任何 "#if" - "#endif" 块。例如
[(
])
/* - */
注释。+-> +-> /* | [/ | * A comment about --+ [/ | +-- * wonderful life. | ]/ | */ <-+ | +-- foo = bar * 3; --+ | ]/ /* a short comment */ <-+
[IVim 将列出它可以找到的匹配行。不仅在当前文件,而且在所有包含的文件(以及其中包含的文件等)中。结果如下
structs.h 1: 29 unsigned column; /* column number */与使用标签或预览窗口相比,它的优点是它会搜索包含的文件。在大多数情况下,这会导致找到正确的声明。即使标签文件已过期时也是如此。即使您没有包含文件的标签也是如此。但是,为了使 "[I" 起作用,必须满足一些条件。首先,'include' 选项必须指定文件的包含方式。默认值适用于 C 和 C++。对于其他语言,您需要更改它。
:checkpath它将列出找不到的包含文件。以及找到的文件包含的文件。输出示例
:set path+=/usr/local/X11当存在多个子目录时,您可以使用 "*" 通配符。示例
:set path+=/usr/*/include这将找到 "/usr/local/include" 以及 "/usr/X11/include" 中的文件。
:set path+=/projects/invent/**/include这将找到以下目录中的文件
:checkpath!您将获得一个(非常长的)包含文件列表,它们包含的文件,等等。为了缩短列表,Vim 会为之前找到的文件显示 "(Already listed)",并且不会在其中再次列出包含的文件。
[<Tab>您也可以使用 "[
CTRL-I
",因为 CTRL-I
等同于按 <Tab>
。3[<Tab>将跳转到列表中的第三项。请记住,您可以使用
CTRL-O
跳回开始的位置。[D同样,这会在包含的文件中搜索。'define' 选项指定定义 "[D" 项目的行看起来像什么。您可以更改它以使其适用于 C 或 C++ 以外的其他语言。与 "[D" 相关的命令是
gD提示:转到定义。此命令非常有用,可以找到在本地声明的变量或函数(在 C 术语中为 "static")。示例(光标位于 "counter" 上)
+-> static int counter = 0; | | int get_counter(void) gD | { | ++counter; +-- return counter; }
gd这将返回到当前函数的开头并找到光标下方的单词的第一次出现。实际上,它向后搜索到第一列中 "{" 上方的一行空行。从那里开始,它向前搜索标识符。示例(光标位于 "idx" 上)
int find_entry(char *name) { +-> int idx; | gd | for (idx = 0; idx < table_len; ++idx) | if (strcmp(table[idx].name, name) == 0) +-- return idx; }