Usr_30

Nvim :help 页面,生成 使用 tree-sitter-vimdoc 解析器。


VIM 用户手册 - 由 Bram Moolenaar 编写
编辑程序
Vim 有各种命令来帮助编写计算机程序。编译程序并直接跳转到报告的错误。自动设置许多语言的缩进并格式化注释。
30.1 编译 30.2 缩进 C 文件 30.3 自动缩进 30.4 其他缩进 30.5 制表符和空格 30.6 格式化注释
下一章: usr_31.txt 利用 GUI 上一章: usr_29.txt 在程序中移动 目录: usr_toc.txt

编译

Vim 有一组所谓的“快速修复”命令。它们允许你从 Vim 内部编译程序,然后遍历生成的错误并修复它们(希望如此)。然后,你可以重新编译并修复发现的任何新错误,直到最终你的程序在没有任何错误的情况下编译完成。
以下命令运行程序“make”(提供你给出的任何参数)并捕获结果
:make {arguments}
如果生成了错误,它们将被捕获,并且编辑器会将你定位在第一个错误发生的位置。看看一个示例“:make”会话。(典型的“:make”会话会生成更多错误,但愚蠢的错误更少。)在输入“:make”后,屏幕看起来像这样
:!make | &tee /tmp/vim215953.err
gcc -g -Wall -o prog main.c sub.c
main.c: In functionmain
main.c:6: too many arguments to function 'do_sub'
main.c: At top level
main.c:10: parse error before '}'
make: *** [prog] Error 1
2 returned
"main.c" 11L, 111C
(3 of 6): too many arguments to function 'do_sub'
Press ENTER or type command to continue
由此你可以看到你在文件“main.c”中存在错误。当你按下<Enter>时,Vim 会显示文件“main.c”,光标定位在第 6 行,即第一行出现错误的代码行。你无需指定文件或行号,Vim 通过查看错误信息就知道了要跳转到哪里。
          +---------------------------------------------------+
          |int main()                                            |
          |{                                                    |
          |        int i=3;                                    |
cursor -> |        do_sub("foo");                                    |
          |        ++i;                                            |
          |        return (0);                                    |
          |}                                                    |
          |}                                                    |
          | ~                                                    |
          |(3 of 12): too many arguments to function 'do_sub' |
          +---------------------------------------------------+
以下命令跳转到下一个错误出现的位置
:cnext
Vim 跳转到第 10 行,即文件中的最后一行,该行存在多余的'}'。如果空间不足,Vim 会缩短错误信息。要查看完整信息,请使用
:cc
你可以使用“:clist”命令查看所有错误信息的概览。输出看起来像这样
:clist
3 main.c: 6:too many arguments to function 'do_sub'
5 main.c: 10:parse error before '}'
这里只列出了 Vim 识别出文件名和行号的代码行。它假设这些是有趣的代码行,而其余代码只是枯燥的信息。但是,有时未识别的代码行确实包含你想要查看的内容。例如,来自链接器关于未定义函数的输出。要查看所有信息,请在命令中添加一个“!”
:clist!
1 gcc -g -Wall -o prog main.c sub.c
2 main.c: In functionmain
3 main.c:6: too many arguments to function 'do_sub'
4 main.c: At top level
5 main.c:10: parse error before '}'
6 make: *** [prog] Error 1
Vim 会突出显示当前错误。要返回到上一个错误,请使用
:cprevious
在错误列表中移动的其他命令
:cfirst 跳转到第一个错误 :clast 跳转到最后一个错误 :cc 3 跳转到错误编号为 3 的错误

使用其他编译器

当执行“:make”命令时,要运行的程序名称由 'makeprg' 选项定义。通常将其设置为“make”,但 Visual C++ 用户应通过执行以下命令将其设置为“nmake”
:set makeprg=nmake
你也可以在此选项中包含参数。特殊字符需要用反斜杠转义。示例
:set makeprg=nmake\ -f\ project.mak
你可以在命令规范中包含特殊的 Vim 关键字。% 字符展开为当前文件的名称。因此,如果你执行以下命令
:set makeprg=make\ %:S
当你正在编辑 main.c 时,“:make”会执行以下命令
make main.c
这不太有用,因此你需要稍微调整一下命令并使用:r(根)修饰符
:set makeprg=make\ %:r:S.o
现在执行的命令如下
make main.o
有关这些修饰符的更多信息,请参见: filename-modifiers.

旧的错误列表

假设你“:make”一个程序。在一个文件中有一个警告信息,在另一个文件中有一个错误信息。你修复了错误,并再次使用“:make”检查它是否确实已修复。现在你想查看警告信息。它没有显示在最后一个错误列表中,因为包含警告信息的代码文件没有重新编译。你可以使用以下命令返回到上一个错误列表
:colder
然后使用“:clist”和“:cc {nr}”跳转到包含警告信息的位置。要向前跳转到下一个错误列表,请使用
:cnewer
Vim 会记住十个错误列表。

切换编译器

你必须告诉 Vim 你的编译器产生的错误信息的格式。这可以通过 'errorformat' 选项完成。此选项的语法相当复杂,可以适应几乎任何编译器。你可以在此处找到解释: errorformat.
你可能正在使用各种不同的编译器。每次设置 'makeprg' 选项,尤其是 'errorformat' 并不容易。Vim 为此提供了一种简单的方法。例如,要切换到使用 Microsoft Visual C++ 编译器,请执行以下操作
:compiler msvc
这将找到“msvc”编译器的 Vim 脚本并设置相应的选项。你可以编写自己的编译器文件。参见 write-compiler-plugin.

输出重定向

“:make”命令将执行程序的输出重定向到一个错误文件。这如何工作取决于各种因素,例如 'shell'。如果你的“:make”命令没有捕获输出,请检查 'makeef''shellpipe' 选项。 'shellquote''shellxquote' 选项也可能很重要。
如果你无法让“:make”为你重定向文件,另一种方法是在另一个窗口中编译程序并将输出重定向到一个文件。然后让 Vim 使用以下命令读取此文件
:cfile {filename}
跳转到错误的功能与“:make”命令相同。

30.2 缩进 C 样式文本

当代码行正确缩进时,程序更容易理解。Vim 提供了多种方法来减少此操作的工作量。对于 C 或 C 样式程序(如 Java 或 C++),请设置 'cindent' 选项。Vim 对 C 程序了如指掌,会尽力自动为你设置缩进。将 'shiftwidth' 选项设置为你想用于更深层次的空格数。四个空格就可以了。一个“:set”命令就足够了
:set cindent shiftwidth=4
启用此选项后,当你输入诸如“if (x)”之类的内容时,下一行将自动缩进一个额外的级别。
if (flag) 自动缩进 ---> do_the_work(); 自动取消缩进 <-- if (other_flag) { 自动缩进 ---> do_file(); 保持缩进 do_some_more(); 自动取消缩进 <-- }
当你输入花括号 ({}) 时,文本将在开头缩进,并在结尾取消缩进。取消缩进将在输入“}”后发生,因为 Vim 无法猜测你要输入什么。
自动缩进的一个副作用是,它可以帮助你尽早发现代码中的错误。当你输入“}”来结束一个函数,却发现自动缩进给它比你预期的缩进更多时,可能缺少一个'}'。使用“%”命令找出哪个 '{' 与你输入的 '}' 匹配。缺少 ')' 和 ';' 也会导致额外的缩进。因此,如果你得到了比你预期的更多空白,请检查前面的代码行。
当你拥有格式错误的代码,或者插入和删除了代码行时,你需要重新缩进代码行。“=”运算符可以做到这一点。最简单的形式是
==
这会缩进当前代码行。与所有运算符一样,可以使用三种方法。在 Visual 模式下,“=”会缩进选定的代码行。一个有用的文本对象是“a{”。这会选择当前的 {} 代码块。因此,要重新缩进光标所在的代码块,请使用以下命令
=a{
如果你有格式极其糟糕的代码,你可以使用以下命令重新缩进整个文件
gg=G
但是,不要在手动精心缩进的文件中执行此操作。自动缩进做得很好,但在某些情况下,你可能希望覆盖它。

设置缩进样式

不同的人有不同的缩进风格。默认情况下,Vim 在 90% 的程序员使用的缩进方式方面做得相当不错。但是,存在不同的风格;所以,如果你想,你可以使用 'cinoptions' 选项自定义缩进风格。默认情况下,'cinoptions' 为空,并且 Vim 使用默认风格。你可以在需要更改的地方添加各种项目。例如,要使花括号像这样放置
if (flag)
{
i = 8;
j = 0;
}
使用以下命令
:set cinoptions+={2
这些项目很多。参见 cinoptions-values.

30.3 自动缩进

你不想每次编辑 C 文件时都手动开启 'cindent' 选项。以下是自动执行此操作的方法
:filetype indent on
实际上,这不仅仅是在 C 文件中开启 'cindent'。首先,它会启用检测文件类型的功能。这与用于语法高亮的相同功能。当文件类型已知时,Vim 会为此类型的文件搜索缩进文件。Vim 发行版包含许多针对各种编程语言的缩进文件。然后,此缩进文件将为专门针对此文件的自动缩进做好准备。
如果你不喜欢自动缩进,可以将其关闭
:filetype indent off
如果你不喜欢针对特定类型文件的缩进,可以使用以下方法避免它。创建一个仅包含以下一行代码的文件
:let b:did_indent = 1
现在你需要将此代码写入具有特定名称的文件
{directory}/indent/{filetype}.vim
{filetype} 是文件类型的名称,例如“cpp”或“java”。你可以使用以下命令查看 Vim 检测到的确切名称
:set filetype
在此文件中,输出为
filetype=help
因此,对于 {filetype},你需要使用“help”。对于 {directory} 部分,你需要使用你的运行时目录。查看以下命令的输出
set runtimepath
现在使用第一个项目,即第一个逗号之前的名称。因此,如果输出看起来像这样
runtimepath=~/.config/nvim,/usr/local/share/vim/vim60/runtime,~/.config/nvim/after
你使用“~/.config/nvim”作为 {directory}。然后,生成的文件名是
~/.config/nvim/indent/help.vim
与其关闭缩进,不如编写自己的缩进文件。这里解释了如何操作:indent-expression

30.4 其他缩进

最简单的自动缩进形式是使用 'autoindent' 选项。它使用前一行的缩进。稍微智能一点的是 'smartindent' 选项。这对于没有缩进文件的语言很有用。 'smartindent' 不如 'cindent' 智能,但比 'autoindent' 智能。设置 'smartindent' 后,每遇到一个 { 就会增加一层缩进,每遇到一个 } 就会减少一层缩进。对于 'cinwords' 选项中的任何单词,也会增加一层缩进。以 # 开头的行将被特殊处理:所有缩进都将被删除。这样做是为了使预处理器指令都从第 1 列开始。下一行的缩进将恢复。

更正缩进

当您使用 'autoindent''smartindent' 获取前一行的缩进时,您可能需要多次添加或删除一个 'shiftwidth' 的缩进量。快速执行此操作的方法是在插入模式下使用 CTRL-D 和 CTRL-T 命令。例如,您正在键入一个应该像这样显示的 shell 脚本
if test -n a; then
echo a
echo "-------"
fi
首先设置这些选项
:set autoindent shiftwidth=3
您首先键入第一行,<Enter> 和第二行的开头
if test -n a; then
echo
现在您看到您需要额外的缩进。键入 CTRL-T。结果
if test -n a; then
echo
在插入模式下,CTRL-T 命令会在您位于行的任何位置时,将缩进增加一个 'shiftwidth'。您继续键入第二行,<Enter> 和第三行。这次缩进是正确的。然后 <Enter> 和最后一行。现在您有以下内容
if test -n a; then
echo a
echo "-------"
fi
要删除最后一行中多余的缩进,请按 CTRL-D。这会删除一个 'shiftwidth' 的缩进量,无论您位于行的什么位置。当您处于普通模式时,您可以使用 ">>" 和 "<<" 命令来移动行。">" 和 "<" 是运算符,因此您可以通过三种通常的方式来指定要缩进的行。一个有用的组合是
>i{
这会将当前块内(在 {} 中)的行的缩进量增加一个。{ 和 } 行本身保持不变。">a{" 会包含它们。在这个例子中,光标位于 "printf" 上
执行 ">i{" 后的原始文本 执行 ">a{" 后的原始文本
if (flag) if (flag) if (flag)
{ { {
printf("yes"); printf("yes"); printf("yes");
flag = 0; flag = 0; flag = 0;
} } }

30.5 选项卡和空格

'tabstop' 默认设置为 8。尽管您可以更改它,但您很快就会遇到麻烦。其他程序将不知道您使用了什么 tabstop 值。它们可能使用默认值 8,您的文本突然看起来非常不同。此外,大多数打印机使用固定的 tabstop 值 8。因此,最好保持 'tabstop' 不变。(如果您编辑的是使用不同 tabstop 设置编写的文件,请参阅 25.3,了解如何解决此问题。)对于缩进程序中的行,使用 8 的倍数个空格会让您很快遇到窗口的右边界。使用单个空格不会提供足够的视觉差异。许多人更喜欢使用四个空格,这是一个很好的折衷方案。由于一个 <Tab> 是 8 个空格,而您想使用 4 个空格的缩进,因此您不能使用 <Tab> 字符来进行缩进。有两种方法可以处理这种情况
1. 使用 <Tab> 和空格字符的组合。由于一个 <Tab> 会代替 8 个空格,因此您在文件中使用的字符更少。插入一个 <Tab> 比 8 个空格更快。退格键的速度也更快。
2. 只使用空格。这可以避免使用不同 tabstop 值的程序带来的麻烦。
幸运的是,Vim 都很好地支持这两种方法。

空格和选项卡

如果您使用的是选项卡和空格的组合,则只需正常编辑即可。Vim 的默认设置可以很好地处理这些问题。您可以通过设置 'softtabstop' 选项让操作更轻松一点。此选项告诉 Vim 使 <Tab> 键看起来和感觉起来就像选项卡设置在 'softtabstop' 的值一样,但实际上使用的是选项卡和空格的组合。执行以下命令后,每次您按 <Tab> 键时,光标都会移动到下一个 4 列边界
:set softtabstop=4
当您从第一列开始并按 <Tab> 时,您会在文本中插入 4 个空格。第二次,Vim 会删除这 4 个空格并插入一个 <Tab>(因此您会移动到第 8 列)。因此 Vim 会尽可能多地使用 <Tab>,然后用空格填充空白。当您退格时,操作方式相反。一个 <BS> 将始终删除用 'softtabstop' 指定的数量。然后使用 <Tab>,尽可能多地使用,最后用空格填充空白。下面显示了按 <Tab> 几次,然后使用 <BS> 的情况。一个 "." 代表空格,"------->" 代表一个 <Tab>
键入 结果
<Tab> .... <Tab><Tab> -------> <Tab><Tab><Tab> ------->.... <Tab><Tab><Tab><BS> -------> <Tab><Tab><Tab><BS><BS> ....
另一种方法是使用 'smarttab' 选项。当它被设置时,Vim 会对在行缩进处键入的 <Tab> 使用 'shiftwidth',并在键入第一个非空白字符之后使用真正的 <Tab>。但是,<BS> 的工作方式与 'softtabstop' 不同。

只有空格

如果您希望文件中绝对没有选项卡,则可以设置 'expandtab' 选项
:set expandtab
当此选项被设置时,<Tab> 键会插入一系列空格。因此,您会获得与插入 <Tab> 字符相同数量的空白,但文件中没有真正的 <Tab> 字符。退格键会自行删除每个空格。因此,在键入一个 <Tab> 后,您必须按 <BS> 键最多 8 次才能撤消它。如果您在缩进处,按 CTRL-D 会快得多。

将选项卡更改为空格(反之亦然)

设置 'expandtab' 不会影响任何现有的选项卡。换句话说,文档中的任何选项卡都将保留为选项卡。如果您想将选项卡转换为空格,请使用 ":retab" 命令。使用这些命令
:set expandtab
:%retab
现在 Vim 会将所有缩进都更改为使用空格而不是选项卡。但是,所有在非空白字符之后出现的选项卡都会保留。如果您希望将这些选项卡也转换,请添加一个 !
:%retab!
这有点危险,因为它也会更改字符串内的选项卡。要检查是否存在这些选项卡,您可以使用以下命令
/"[^"\t]*\t[^"]*"
建议不要在字符串内使用硬选项卡。将它们替换为 "\t" 以避免出现问题。
反向操作也一样有效
:set noexpandtab
:%retab!

30.6 格式化注释

Vim 的一大优点是它可以理解注释。您可以让 Vim 格式化注释,它会执行正确的操作。例如,假设您有以下注释
/*
 * This is a test
 * of the text formatting.
 */
然后您让 Vim 格式化它,方法是将光标定位在注释的开头并键入
gq]/
"gq" 是格式化文本的运算符。"]/" 是将您带到注释末尾的动作。结果是
/*
 * This is a test of the text formatting.
 */
请注意,Vim 正确地处理了每行的开头。另一种方法是在 Visual 模式下选择要格式化的文本,然后键入 "gq"。
要向注释添加新行,请将光标定位在中间行并按 "o"。结果如下
/*
 * This is a test of the text formatting.
 *
 */
Vim 自动为您插入了一个星号和一个空格。现在您可以键入注释文本。当注释的长度超过 'textwidth' 时,Vim 会换行。同样,星号会自动插入
/*
 * This is a test of the text formatting.
 * Typing a lot of text here will make Vim
 * break
 */
为了使此功能正常工作,'formatoptions' 中必须存在一些标志
r 在插入模式下键入 <Enter> 时插入星号 o 在普通模式下使用 "o" 或 "O" 时插入星号 c 根据 'textwidth' 换行注释文本
有关更多标志,请参阅 fo-table
定义注释
'comments' 选项定义了注释的外观。Vim 区分单行注释和开头、结尾和中间部分不同的注释。许多单行注释以特定字符开头。在 C++ 中使用 //,在 Makefiles 中使用 #,在 Vim 脚本中使用 "."。例如,要使 Vim 理解 C++ 注释
:set comments=://
冒号将项目的标志与识别注释的文本分隔开。 'comments' 中项目的通用形式是
{flags}:{text}
{flags} 部分可以为空,在本例中就是如此。这些项目中的几个可以串联在一起,用逗号分隔。这允许同时识别不同类型的注释。例如,让我们编辑一封电子邮件。回复时,其他人写的文本前面会加上 ">" 和 "!" 字符。此命令将起作用
:set comments=n:>,n:!
有两个项目,一个用于以 ">" 开头的注释,一个用于以 "!" 开头的注释。两者都使用标志 "n"。这意味着这些注释是嵌套的。因此,以 ">" 开头的行之后可能还有另一个注释。这允许格式化如下所示的消息
> ! 你看到了那个网站吗?
> ! 看起来真的很棒。
> 我不喜欢它。那
> 颜色太难看了。
那个网站的 URL 是什么?
网站?
尝试将 'textwidth' 设置为不同的值,例如 80,然后通过以 Visual 模式选择文本并键入 "gq" 来格式化文本。结果是
> ! 你看到了那个网站吗?看起来真的很棒。
> 我不喜欢它。那颜色太难看了。
那个网站的 URL 是什么?
您会注意到 Vim 没有将文本从一种类型的注释移动到另一种类型的注释。第二行中的 "I" 可以放在第一行的末尾,但是由于该行以 "> !" 开头,而第二行以 ">" 开头,因此 Vim 知道这是不同类型的注释。
三部分注释
C 注释以 "/*" 开头,中间有 "*",以 "*/" 结尾。 'comments' 中的 C 注释条目如下所示
:set comments=s1:/*,mb:*,ex:*/
开头由 "s1:/*" 定义。 "s" 表示三部分注释的开头。冒号将标志与识别注释的文本分隔开:"/*"。有一个标志:"1"。这告诉 Vim 中间部分的偏移量为一个空格。中间部分 "mb:*" 以 "m" 开头,表示它是中间部分。 "b" 标志意味着文本之后必须有一个空格。否则 Vim 会将类似 "*pointer" 的文本也视为注释的中间部分。结尾部分 "ex:*/" 有 "e" 用于识别。 "x" 标志具有特殊含义。这意味着在 Vim 自动插入一个星号后,键入 / 会删除多余的空格。
更多详细信息请参见 format-comments
下一章:usr_31.txt 利用 GUI
版权:参见 manual-copyright vim:tw=78:ts=8:noet:ft=help:norl
主要
命令索引
快速参考