EMACS-DOCUMENT

=============>集思广益

在Emacs中编译

许多Emacs新手常常因为想定位编译出错的位置而询问如何获取buffer中行号. 然而这并不是定位编译出错位置的正确方法.

Emacs内置了一个compilation mode,该mode定义在compile.el中. It uses a very generic text-based approach.

这是一个为Emacs新手准备的指南. 有经验的读者可以之间跳到本文最下面查看如何为error解析器增加新的规则.

1 使用方法

  • 执行 M-x compile.
  • Emacs会提示你输入编译要运行的命令. 输入命令然后按回车.
  • Emacs运行编译命令,解析编译结果,拆分frame然后弹出结果buffer.

若编译时出现error,有很多方法可以跳转到出现error的地方.

  • 若你按下 C-x `,就会跳转到当前buffer的下一个error处. 这样你根本无需查询出错的行号
  • 若你切换到编译结果的buffer(一般名为*compilation*),你可以直接在报错信息那一行上直接按下回车,就能跳转到出错信息对应的位置了.

若已经运行过 M-x compile ,你可以通过 M-x recompile 来使用上一次编译时的命令来重新编译. 若你想使用不同的编译命令,则只需再次运行 M-x compile 即可.

当然,就像大多数Emacs中的prompt一样,你也可以通过 M-nM-p 遍历你的输入历史.

2 相关快捷键

当处于编译buffer中时,可以使用以下快捷键:

g
重新编译
q
退出编译buffer
TAB / M-n
跳转到下一个error
S-TAB (shift tab / backtab) / M-p
跳转到上一个error
C-c C-k
杀掉编译进程

3 一般配置

若你习惯于一键编译, 你可以向下面这个例子一样,将 recompile 命令绑定到 F9 键上.

;; eval this or place it your .emacs    
(global-set-key (kbd "<f9>") 'recompile)

4 工作原理是什么?

变量 compilation-error-regexp-alist 是一个存储了如何解析出错信息规则(从错误信息中抽取出文件名,行号等内容)的列表.

列表中的每个元素可以是一个symbol或者列表.

  • 若元素是一个symbol,则Emacs会根据该symbol从变量 compilation-error-regexp-alist-alist 中寻找真正的解析规则. symbol的名字常常就是编译程序的名字.
  • 若元素是一个list,则该list被作为解析规则. 只有当定义的规则很普遍化或者缺失很懒的情况下才使用这种格式.

最简单的规则是以下格式的列表

(REGEXP FILE [LINE COLUMN])
  • REGEXP 是一个匹配输出的正则表达式字符串.
  • 剩下的元素是正则表达式中对应内容的分组编号. 你至少需要提供文件名的分组编号,其他的信息是可选的.

当然,你还可以提供其他用于的信息.

想进一步了解,可以查看该变量的文档字符串(C-h v compilation-error-regexp-alist RET).

5 添加新规则

若你编译的结果Emacs无法正确解析,则你需要添加自己的规则. 假设编译结果有如下一行错误信息.

Error in the file foobar.c at the line 42

你可以使用下面的正则表达式从中抽取出文件名与行号:

"^Error in the file \\(.+\\) at the line \\([0-9]+\\)$"

其中文件名被第一个分组捕获,行号被第二个分组捕获. 因此最终规则如下:

("^Error in the file \\(.+\\) at the line \\([0-9]+\\)$" 1 2)

要应用该规则,你可以在*scratch* buffer中执行以下代码,或者使用 M-: 来执行以下代码

(add-to-list
 'compilation-error-regexp-alist
 '("^Error in the file \\(.+\\) at the line \\([0-9]+\\)$" 1 2))

将上面代码存入你的 .emacs 文件中,使之永久有效.

若你为某个工具添加了解析规则,而该工具对他人有用的话,请不要犹豫,将其分享到Emacs mailing-list中去吧!