2

I wrote a syntax highlighting .vim file. One of the expressions is used to color the label in a JavaScript object declaration:

name: 'value'
^^^^

I want to see the name in a different color.

My expression looks like this:

syn match label "\<[a-zA-Z_$][a-zA-Z_$0-9]*[ \t]*:[^=:]\="

The idea is to avoid seeing name as a label if the colon is immediately followed by an equal (=) or a colon (:) as in these two lines, the highlight should not happen:

name:=assignment
name::space

However, my current expression fails in this situation:

name:'value'
     ^
     |
     +---  no space here

The effect is that the string ('value') doesn't get highlighted as expected since the first quote (') is viewed as being part of the label expression.

How do I test that an expression is not followed by another without eating that expression?

3

Here's what I would do:

syn match label "\<[a-zA-Z_$][a-zA-Z_$0-9]*\s*:[:=]\@!"

First off, general comments.

  • [ \t] could be \s, which match the exact same things.
  • [:=]\@! is called a negative lookahead. So if you have <atom>\@! then it only matches if <atom> does not match at that position, but it also doesn't "eat" that atom. So it's like saying "all that stuff, not followed by a colon or an equals."

  • This could also be a bit shorter by taking advantage of character classes:

    syn match label "\v(\h|\$)(\w|\$)*\s*:[:=]@!"
    

    \h is the same as [a-zA-Z_], and \w is the same as [a-zA-Z0-9_]. And using \v at the beginning allows us to make a bit shorter by removing some backslashes.

  • Ah! That works, I tried with \@! but left \= behind it... without the \= it works as expected. Great! – Alexis Wilke Jan 17 at 19:57

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.