2

The below example, straight out of the VIM documentation, uses an "at sign" yet nowhere else in the entire document is it mentioned or explained.

Another example: Think of a Python interpreter that produces the
following error message (line numbers are not part of the actual
output):

     1  ==============================================================
     2  FAIL: testGetTypeIdCachesResult (dbfacadeTest.DjsDBFacadeTest)
     3  --------------------------------------------------------------
     4  Traceback (most recent call last):
     5    File "unittests/dbfacadeTest.py", line 89, in testFoo
     6      self.assertEquals(34, dtid)
     7    File "/usr/lib/python2.2/unittest.py", line 286, in
     8   failUnlessEqual
     9      raise self.failureException, \
    10  AssertionError: 34 != 33
    11
    12  --------------------------------------------------------------
    13  Ran 27 tests in 0.063s

Say you want |:clist| write the relevant information of this message
only, namely:

   5 unittests/dbfacadeTest.py:89:  AssertionError: 34 != 33

Then the error format string could be defined as follows:

:set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m

Note that the %C string is given before the %A here: since the
expression '' %.%#' (which stands for the regular expression '' .*')
matches every line starting with a space, followed by any characters
to the end of the line, it also hides line 7 which would trigger a
separate error message otherwise. Error format strings are always
parsed pattern by pattern until the first match occurs.

I have spent quite a few hours pouring over the quickfix & errorformat documentation to trying to find an explanation of the at sign and what it represents.

  • I've also looked through the scanf documentation just in case it means something there

  • I've also looked through VIM's regular expression documentation but not so thoroughly

What I do understand:

%C\ %.%#

A continuation line that must start with a space, and then any text until the end of the line (via the .* equivalent)

%A\ \ File\ \"%f\"\\,\ line\ %l%.%#

A non-specified starting line that must start with space, space, 'File', space - and then a quoted filename (extracted), followed by a comma some more literal text and a line number to be extracted. Lastly any other text is matched and ignored (via the .* equivalent)

What I do not understand:

%Z%[%^\ ]%\\@=%m

I think i got this part: is a terminating line that must start with a non-space character.

  • This seems like an attempt to match line 10 which starts with an 'A'

Then my understanding breaks down...

%\\: is a literal slash (i have no idea the purpose, since the only '\' is at the end of line 9)

@=: does the @= mean something?

%m: then extract the message

-OR-

%\\@=: perhaps all this together means something I don't get?

%m: then extract the message

Can anyone shed some light on the point of the \@ within the errorformat string?

Or the \@=, or the =%m or the = by itself, ... I don't understand this last bit.

Thanks in advance

  • 2
    See :help \@=. – romainl Oct 29 '16 at 18:58
  • Well - I understand zero-width assertions. So thanks for the pointer. However I cannot mark a comment as the answer. Still - I clicked around the VIM docs for quite a while looking for something - and this feels like a needle (in a haystack) I would have taken many more hours to find. So thanks again. – CrashNeb Oct 29 '16 at 20:22
2

As suggested by CrashNeb, %\\@= means \\@= as in regexp, which does a lookup ahead without actually consuming the characters.

%[%^\ ], is [^\ ] (don't match \ or ) but escaped ([ and ^ needs to be escaped using %.

So, %Z%[%^\ ]%\\@=%m means if the line doesn't start with a space or \, end the multiline (%Z) errors and use THE FULL LINE as a the message. Without the %\\@=, %m will be missing the first character (used to test if it was space or not).

According to the documentation (errorformat)

Pattern matching

The scanf()-like "%*[]" notation is supported for backward-compatibility
with previous versions of Vim.  However, it is also possible to specify
(nearly) any Vim supported regular expression in format strings.
Since meta characters of the regular expression language can be part of
ordinary matching strings or file names (and therefore internally have to
be escaped), meta symbols have to be written with leading '%':
  %\    The single '\' character.  Note that this has to be
      escaped ("%\\") in ":set errorformat=" definitions.

%\\ is just the way to escape \ in an errorfmt context, so that %\\@= translates to \@= as in

\@= Matches the preceding atom with zero width.
  Like "(?=pattern)" in Perl.
  Example     matches ~
  foo\(bar\)\@=   "foo" in "foobar"
  foo\(bar\)\@=foo  nothing
              */zero-width*
  When using "\@=" (or "^", "$", "\<", "\>") no characters are included
  in the match.  These items are only used to check if a match can be
  made.  This can be tricky, because a match with following items will
  be done in the same position.  The last example above will not match
  "foobarfoo", because it tries match "foo" in the same position where
  "bar" matched.

  Note that using "\&" works the same as using "\@=": "foo\&.." is the
  same as "\(foo\)\@=..".  But using "\&" is easier, you don't need the
  braces.
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.