对于一线程序员来说,大部分的工作场景应该都是:编辑 - 编译 - 编辑 - 编译…

对于使用 Vim 的一线程序员来说,大部分的工作场景应该都是:使用 Vim 编辑代码 - 编译代码…如此循环往复,直到你变成一个不再需要写代码的程序员 (偷笑)!

假设你正在使用 C++ 语言开发一个项目,如果你是刚刚接触 Vim,可能会在使用 Vim 完成代码编辑工作后,退出 Vim 到终端再使用 make 命令编译代码;若对 Vim 有一定的熟悉度,你可能会通过 :!make 直接在 Vim 内部执行外部shell命令make

当 make 时遇到了编译错误,你还需要找到具体报错的文件和代码行,修复错误后再重新编译。如果你是根据编译器输出的错误信息,一个个打开出错的文件,找到出错的行再进行修改,那效率未免太低下了!!!

在文章Vim中的重复操作与高效率提到过,大部分工作其实都是可重复的,Vim 对于各种重复性的操作和场景都提供了高效率的支持。

针对上述程序员日常:”编辑 - 编译”,Vim 同样提供了非常高效的支持方案,那就是 quickfix 列表。

一、Vim quickfix列表介绍

quickfix 列表是 Vim 不同于大多数文本编辑器的一项核心功能,旨在将外部工具融入到使用 Vim 的工作过程当中。

从它的名字可以看出,quickfix 用于实现快速修复(quick fix),它通过对 “编译器” 输出的错误信息进行解析,并生成 quickfix 列表供 Vim 使用者浏览和快速跳转,中途并不需要退出Vim进行额外操作,从而帮助我们简化工作过程。

简单来说,Vim quickfix 列表会保存一组针对单个或多个文件内容的、由文件名、行号、列号(可选)与消息组成的注释定位信息,并提供快速跳转能力。每一项记录可以是在执行 :make 时由编译器产生的出错信息,也可以是在执行 :grep 时找到的查找匹配。

假设在当前工作目录下,有一个名为 demo.cpp 的文件,里面是一段简单的 C 代码,且有几处语法错误。

1
2
3
4
5
6
7
8
#include <stdio.h>

int main(int argc, char **argv)
{
int i;
print("hello world\n")
return 0;
}

现在,我们尝试直接在 Vim 内部编译这个文件。

首先,在 Vim 命令行模式下,执行命令 :set makeprg=gcc\ -Wall\ -odemo\ demo.cpp 来设置 makeprg 选项,指定使用gcc编译 demo.cpp文件,并打开所有的Warnning。

注意:如果编译命令中有空格,需要使用 \ 对空格进行转义。

设置完 makeprg 选项后,可以直接在 Vim 中执行命令 :make 来进行源码编译。

在执行 :make 时,Vim 会自动调用 makeprg 选项定义的命令进行编译,并把编译输出重定向到一个临时文件中。当编译出现错误时,Vim 会从上述临时文件中读出错误信息,根据这些信息形成 quickfix 列表,并跳转到第一个错误出现的地方。

对于上面描述的例子,在 Vim 内部执行 :make 得到的结果与在 shell 中运行 gcc -Wall -odemo demo.cpp 的结果完全一致。唯一的不同是 Vim 除了会显示 make 命令的输出结果外,还会解析结果中的每一行内容,并把文件名、行号以及错误信息提取出来。

对于每一条出错信息,Vim 都会在 quickfix 列表中为其创建一项记录。我们可以上下浏览这些记录项,让 Vim 跳转到产生错误信息所在的源文件行上

具体来说,对于本文介绍的例子,Vim 会将光标停在第一个出错的位置 (即停在 print(“hello world\n”) 这一行),同时,Vim 还会提示出错信息 error: ‘print’ was not declared in this scope。

如果没看清出错信息,可以输入 :cc 命令让 Vim 再次显示此信息。也可以使用 :cw 命令打开一个 quickfix 窗口,把所有的出错信息显示出来。下面的Vim视频教程详细地展示了上述操作。

vim-quickfix

二、浏览/跳转quickfix列表

Vim 提供了方便的命令用于快速浏览 quickfix 列表,下表展示了其中最有用的几种命令及其用途,其命令和含义类似缓冲区列表跳转。Vim 命令行模式下执行 :h quickfix 可以找到一份详尽的命令列表介绍。

命令 用途
:copen:cw 如果有错误,打开 quickfix 窗口
:cc N 跳转到第 n 项,显示详细内容
:cclose 关闭 quickfix 窗口
:cnext:cn 跳转到下一项
cprevious:cprev:cp 跳转到上一项
:cfirst 跳转到第一项
:clast 跳转到最后一项
:cnfile 跳转到下一个文件中的第一项
:cpfile 跳转到上一个文件中的最后一项

:copen 命令可以打开一个包含 quickfix 列表内容的窗口,可以用 kj 键进行上、下滚动,如果将光标置于某个列表项并按 回车 键,Vim 将会打开相应的文件,并将光标置于包含匹配结果的那一行上。

通过 :cnext:cprevious 这两条命令,可以向下或者向上遍历整个 quickfix 列表。如果想直接跳转到列表的起始或结尾项,可以用 cfirst:clast 命令分别实现。

无论是 :cnext 还是 :cprev,都可以在其前面附加执行次数。因此,可以使用 :5cnext 实现每次间隔 5 项进行浏览,而不是依次浏览 quickfix 列表中的每一项。

三、定制外部编译器

Vim 的 :make 命令不仅限于调用外部的 make 程序,也可以调用任何安装在操作系统上的编译器。

在 Vim 的术语中,编译器是指任何可以对文档进行处理并生成错误或警告列表的外部程序。而 :make 命令只负责调用外部编译器,并对其输出进行解析,以此构建一个可供浏览的 quickfix 列表。

makeprg 选项用于指定 Vim 运行 :make 时所调用的程序;errorformat 选项 (缩写形式:efm) 用于指示 Vim 如何解析由 :make 产生的输出结果,通过命令 :setglobal errorformat? 可以查看该选项的缺省值。

由于 errorformat 选项的配置很难记忆,Vim提供了一种将其保存到某个文件并使用 :compiler 命令来激活式对 makeprgerrorformat 的配置。更多细节,请参考Vim教程网上的其他内容。

嗯,扫一扫就可以找到小女子我啦~