Praveen's Blog

An Eternal Quest for Incremental Improvement

Making GNU Emacs detect custom error messages - A Maven Example

GNU Emacs's compilation mode is capable of detecting error messages from various standard compilers and build tools. However, it is fairy common for one to run into a format of error message that Emacs can't handle by default.

As you know, Emacs is highly extensible and it provides compilation-error-regexp-alist for accomplishing this. I have done this a couple of times earlier and I had to do it one more time lately for adding regular expression for Maven error messages. Construction of these regular expressions is not fun for everyone. However, regexp-builder makes it easier to construct the regular expression interactively.

In summary, here is the customization that has to be added to .emacs.

(add-to-list 'compilation-error-regexp-alist
   "\\[ERROR\\] \\(.+?\\):\\[\\([0-9]+\\),\\([0-9]+\\)\\].\*" 1 2 3))

Here is what Emacs's inbuilt documentation says about compilation-error-regular-expression-alist:

Because the documentation around compilation-error-regexp-alist isn't very intuitive for most, I have decided to make this screencast that describes how to approach this from scratch. Sorry about the typos! For best quality, watch it in HD.

compilation-error-regexp-alist is a variable defined in `compile.el'.
Its value is shown below.

Alist that specifies how to match errors in compiler output.
On GNU and Unix, any string is a valid filename, so these
matchers must make some common sense assumptions, which catch
normal cases.  A shorter list will be lighter on resource usage.

Instead of an alist element, you can use a symbol, which is
looked up in `compilation-error-regexp-alist-alist'.  You can see
the predefined symbols and their effects in the file
`etc/compilation.txt' (linked below if you are customizing this).

HIGHLIGHT...]).  If REGEXP matches, the FILE'th subexpression
gives the file name, and the LINE'th subexpression gives the line
number.  The COLUMN'th subexpression gives the column number on
that line.

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.

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.

LINE can also be of the form (LINE . END-LINE) meaning a range
of lines.  COLUMN can also be of the form (COLUMN . END-COLUMN)
meaning a range of columns starting on LINE and ending on
END-LINE, if that matched.

TYPE is 2 or nil for a real error or 1 for warning or 0 for info.
TYPE can also be of the form (WARNING . INFO).  In that case this
will be equivalent to 1 if the WARNING'th subexpression matched
or else equivalent to 0 if the INFO'th subexpression matched.
See `compilation-error-face', `compilation-warning-face',
`compilation-info-face' and `compilation-skip-threshold'.

What matched the HYPERLINK'th subexpression has `mouse-face' and
`compilation-message-face' applied.  If this is nil, the text
matched by the whole REGEXP becomes the hyperlink.

Additional HIGHLIGHTs take the shape (SUBMATCH FACE), where
SUBMATCH is the number of a submatch and FACE is an expression
which evaluates to a face name (a symbol or string).
Alternatively, FACE can evaluate to a property list of the
form (face FACE PROP1 VAL1 PROP2 VAL2 ...), in which case all the
listed text properties PROP# are given values VAL# as well.

You can customize this variable.

For more information check the manuals.