开发者

Emacs compilation-mode regex for multiple lines

So I have a tool lints python changes I've made and produces errors and warnings. I would like this to be usable in compile mode with Emacs, but I have an issue. The file name is output only once at the beginning, and then onl开发者_如何学JAVAy line numbers appear with the errors and warnings. Here's an example:

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

It's very similar to pylint, but there's no output-format=parseable option. I checked the documentation for compilation-error-regexp-alist, and found something promising:

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.

So I tried writing a regexp that would optionally match the file line and pull it out in a group, and then the rest would match the other lines. I assumed that it would first match

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

and be fine. Then it would continue and match

C6003: 42: Unnecessary parens after 'print' keyword

with no file. Since there was no file, it should use the file name from the previous match right? Here's the regexp I'm using:

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

I've checked it with re-builder and manually in the scratch buffer. It behaves as expected. the 2nd group is the file name, the 4th is the line number, and the 3rd is what I want highlighted. Whenever I try this, I get the error:

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

I have a workaround for this that involves transforming the output before the compile module looks at it, but I'd prefer to get rid of that and have a "pure" solution. I would appreciate any advice or pointing out any dumb mistakes I may have made.

EDIT

Thomas' pseudo code below worked quite well. He mentioned that doing a backwards re search could mess up the match data, and it did. But that was solved by adding the save-match-data special form before save-excursion.


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.

You could try to write a regex that doesn't match the file name at all, only the column. Then for the file, write a function that searches backwards for the file. Perhaps not as efficient, but it should have the advantage that you can move upwards through the error messages and it will still identify the correct file when you cross file boundaries.

I don't have the necessary stuff installed to try this out, but take the following pseudo-code as an inspiration:

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

(It could be that using a search function inside special-lint-backward-search-filename will screw up the sub-group matching of the compilation-error-regexp, which would suck.)


I don't think you can make compilation do what you want here, because it won't assume that a subsequent error relates to a previously-seen filename. But here's an alternative; write a flymake plugin. Flymake always operates on the current file, so you only need to tell it how to find line (and, optionally, column) numbers.

Try hacking something like this, and you'll likely be pleasantly surprised.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜