用于多行的Emacs编译模式正则表达式

时间:2011-06-27 20:37:54

标签: regex emacs compilation

所以我有一个工具lints python我做的更改并产生错误和警告。我希望这可以在Emacs的编译模式下使用,但我有一个问题。文件名在开头只输出一次,然后只显示包含错误和警告的行号。这是一个例子:

Linting file.py
E0602: 37: Undefined variable 'foo'
C6003: 42: Unnecessary parens after 'print' keyword
2 new errors, 2 total errors in file.py.

它与pylint非常相似,但没有output-format = parseable选项。我查看了compilation-error-regexp-alist的文档,发现了一些有希望的东西:

  

如果FILE,LINE或COLUMN为零或索引不匹配,则为<   匹配的行上不存在信息。在那种情况下   假定文件名与中的前一个相同   缓冲区,行号默认为1,列默认为
  线的缩进开始。

所以我尝试编写一个正则表达式,它可以选择匹配文件行并将其拉出一个组,然后其余的将与其他行匹配。我以为它会先匹配

Linting file.py
E0602: 37: Undefined variable 'foo'

并且没事。然后它会继续并匹配

C6003: 42: Unnecessary parens after 'print' keyword

没有档案。由于没有文件,它应该使用上一个匹配的文件名吗?这是我正在使用的正则表达式:

(add-to-list 'compilation-error-regexp-alist 'special-lint)
(add-to-list 'compilation-error-regexp-alist-alist
         '(special-lint
           "\\(Linting \\(.*\\)\\n\\)?\\([[:upper:]][[:digit:]]+:\\s-+\\([[:digit:]]\\)+\\).*"
           2 4 nil nil 3))

我已经通过重新构建并在临时缓冲区中手动检查了它。它的行为与预期一致。第二组是文件名,第四组是行号,第三组是我想要突出显示的。每当我尝试这个时,我都会收到错误:

signal(error ("No match 2 in highlight (2 compilation-error-face)"))

我有一个解决方法,涉及在编译模块查看之前转换输出,但我更愿意摆脱它并拥有一个“纯粹”的解决方案。我会很感激任何建议或指出我可能犯过的任何愚蠢错误。

修改

下面托马斯的伪代码效果很好。他提到做一个向后重新搜索可能会弄乱匹配数据,而且确实如此。但是,通过在save-match-data之前添加save-excursion特殊表单来解决这个问题。

2 个答案:

答案 0 :(得分:3)

  

FILE也可以有表格(FILE   FORMAT ...),其中FORMAT(例如   “%s.c”)将依次应用于   识别文件名,直到文件为   找到那个名字。或文件也可以   是一个返回的函数(FILENAME)   或(RELATIVE-FILENAME.DIRNAME)。在   前一种情况,FILENAME可能是   相对的或绝对的。

您可以尝试编写与文件名完全匹配的正则表达式,只编写列。然后,对于该文件,编写一个向后搜索该文件的函数。可能效率不高,但它应该具有以下优势:您可以向上移动错误消息,并且当您跨越文件边界时它仍然会识别正确的文件。

我没有安装必要的东西来试试这个,但是请使用以下伪代码作为灵感:

(add-to-list 'compilation-error-regexp-alist-alist
         '(special-lint
           "^\\S-+\\s-+\\([0-9]+\\):.*" ;; is .* necessary?
           'special-lint-backward-search-filename 1))

(defun special-lint-backward-search-filename ()
  (save-excursion
    (when (re-search-backward "^Linting \\(.*\\)$" (point-min) t) 
      (list (match-string 1)))))

(可能是在special-lint-backward-search-filename中使用搜索功能会搞砸compilation-error-regexp的子组匹配,这会很糟糕。)

答案 1 :(得分:0)

我认为你不能在这里做你想要的编译,因为它不会假设后续错误与先前看到的文件名有关。但这是另一种选择;写一个flymake插件。 Flymake始终在当前文件上运行,因此您只需要告诉它如何查找行(以及可选的列)数字。

尝试入侵something like this,您可能会感到惊喜。