在Emacs中编译
Table of Contents
许多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-n
和 M-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中去吧!