regex - 多行的 Emacs 编译模式正则表达式

标签 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的文档,发现了一些有希望的东西:

If FILE, LINE or COLUMN are nil or that index didn't match, that
information is not present on the matched line. In that case the
file name is assumed to be the same as the previous one in the
buffer, line number defaults to 1 and column defaults to
beginning of line's indentation.

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

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)"))

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

编辑

下面 Thomas 的伪代码效果很好。他提到,进行向后研究可能会弄乱比赛数据,事实确实如此。但这是通过在 save-excursion 之前添加 save-match-data 特殊形式解决的。

最佳答案

FILE can also have the form (FILE FORMAT...), where the FORMATs (e.g. "%s.c") will be applied in turn to the recognized file name, until a file of that name is found. Or FILE can also be a function that returns (FILENAME) or (RELATIVE-FILENAME . DIRNAME). In the former case, FILENAME may be relative or absolute.

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

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

(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 中使用搜索函数可能会搞乱编译错误正则表达式的子组匹配,这会很糟糕。)

关于regex - 多行的 Emacs 编译模式正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6498665/

相关文章:

python - regex.WORD 如何影响\b 的行为?

emacs - emacs orgmode中的自定义时间戳

emacs - 如何在 emacs 艺术家模式下在矩形内写入文本?

c++ - 为什么 C++ 编译需要这么长时间?

c++ - 无法使用 Xcode 6.0.1 编译 Qt

C++17 编译器不应该发现对未定义值的引用传递吗?

PHP 匹配控制字符但不匹配空格?

php preg_match_all 返回数组数组

regex - 规则参数的模式匹配 Gitlab CI

emacs - 使用参数定义键绑定(bind)