Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim errorformat: include part of expression in message string

With vim's errorformat syntax, is there any way to use part of the message in filtering results?

As an example, some linker errors don't have anything explicit to distinguish them as an error on the line, other than the error itself:

/path/to/foo.cpp:42: undefined reference to 'UnimplementedFunction'

or

/path/to/foo.cpp:43: multiple definition of 'MultiplyDefinedFunction'

Using an errorformat of:

set efm=%f:%l:\ %m

would catch and display both of these correctly, but will falsely match many other cases (any line that starts with "[string]:[number]: ").

Or, explicitly specifying them both:

set efm=
set efm+=%f:%l:\ undefined\ reference\ to\ %m
set efm+=%f:%l:\ multiple\ definition\ of\ %m

removes the false positives, but the 'message' becomes far less useful -- the actual error is no longer included (just whatever is after it).


Is there anything in the syntax I'm missing to deal with this situation?

Ideally I'd like to be able to say something along the lines of:

set efm+=%f:%l:\ %{StartMessage}undefined\ reference\ to\ %*\\S%{EndMessage}
set efm+=%f:%l:\ %{StartMessage}multiple\ definition\ of\ %*\\S%{EndMessage}

... where everything matched between StartMessage and EndMessage is used as the error's message.

like image 496
Jeremy Nikolai Avatar asked Jun 29 '13 01:06

Jeremy Nikolai


2 Answers

The errorformat can also use vim's regular expression syntax (albeit in a rather awkward way) which gives us a solution to the problem. We can use a non-capturing group and a zero-width assertion to require the presence of these signaling phrases without consuming them. This then allows the %m to pick them up. As plain regular expression syntax this zero-width assertion looks like:

\%(undefined reference\|multiple definition\)\@=

But in order to use it in efm we need to replace \ by %\ and % by %% and for use in a :set line we need to escape the backslashes, spaces and vertical bar so we finally have:

:set efm=%f:%l:\ %\\%%(undefined\ reference%\\\|multiple\ definitions%\\)%\\@=%m

With that the error file

/path/to/foo.cpp:42: undefined reference to 'UnimplementedFunction'
/path/to/foo.cpp:43: multiple definition of 'MultiplyDefinedFunction'
notafile:123: just some other text

comes out as the following in :copen:

/path/to/foo.cpp|42| undefined reference to 'UnimplementedFunction'
/path/to/foo.cpp|43| multiple definition of 'MultiplyDefinedFunction'
|| notafile:123: just some other text
like image 110
Geoff Reedy Avatar answered Nov 13 '22 01:11

Geoff Reedy


I've been using sed to rewrite the output in cases like this where I want to get some arbitrary output that's not nessicarily homogenous into the quickfix window.

You could write make.sh that fires off make (or whatever your're using to build) and trims off stuff you're not concerned with:

make | sed '/undefined reference\|multiple definition/!d'

(Deletes lines not containing 'undefined reference' or 'multiple definition')

If that's going to get too unweildly because of the number of error strings you care about, you could do the inverse and just kill stuff you don't care about:

make | sed 's/some garbage\|other useless message//'

then :set makeprg=make.sh in vim

like image 44
jjbandit Avatar answered Nov 13 '22 02:11

jjbandit