I am trying to add a language called lesim
to compilation mode so that errors are parsed correctly. The error line does not include the file name. Among the ways I have tried to get around this, what has worked best has been to store the filename in a variable and then set compilation-buffer-name-function
to return that variable. This is what I have in the command that defines the major mode for the language:
(setq lesim--script-path (buffer-file-name))
(setq compilation-buffer-name-function (lambda (buf) lesim--script-path))
I then configure the compilation error alists like this:
(add-to-list 'compilation-error-regexp-alist 'lesim)
(add-to-list 'compilation-error-regexp-alist-alist
'(lesim "Error on line \\([0-9]+\\): " nil 1))
I can see that providing nil
for the FILE slot in the alist-alist
causes compilation mode to run compilation-buffer-name-function
(I can add a message
in the lambda
above and see that displayed in *Messages*
). I can also see that "Error on line XXX" messages are highlighted, but when I follow the link I end up in the wrong file (at the correct line for the error message).
Here are other details: the language is implemented as a python program and when parsing fails there are first some python error messages and then the language's "Error on line XXX" message. When I follow the "Error on line XXX" link, I end up in one of the python files mentioned in one of the earlier python messages.
Another (more minor) issue is that I would like compilation mode to ignore the python messages as that's not something that needs concern the user trying to fix their own program.
EDIT: I found a partial solution but I am not 100% happy with it because it sets a global variable. So, this works:
(setq lesim--file (buffer-file-name)) ; store filename
(add-to-list 'compilation-error-regexp-alist 'lesim)
(add-to-list 'compilation-error-regexp-alist-alist
'(lesim
"Error on line \\([0-9]+\\): "
(lambda () lesim--file)
1))
but it no longer works if I replace (lambda () lesim--file)
with a function that looks for the file name in the compilation buffer for the file name. That is, the last part of the above code is:
(add-to-list 'compilation-error-regexp-alist-alist
'(lesim
"Error on line \\([0-9]+\\): "
(lambda () (lesim-file))
1))
where lesim-file
is:
(defun lesim-file ()
""
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(when (re-search-forward (concat lesim-command " \\(.+\\)$"))
(substring-no-properties (match-string 1))))))
I have tested that this correctly locates the file name in the compilation buffer.
As said, the solution with the global variable works, but it would be great if I could avoid the global variable since I can scan the compilation buffer for the file name...