4

I am currently trying to set a custom syntax highlighting using a mysyntax.vim file. I have several keywords (int, real, real2D, real1D, etc) currently highlighted using

syn keyword VariableType real real1D real2D real3D int
hi VariableType ctermfg=darkgreen

Now I would like to also highlight the 'word' that comes right after. I added nextgroup=VarName to my first line above, and tried a few things like

syn match VarName '\w' contained
syn region VarName start=' ' end=' ' 

(in my understanding, '\w' accounts for a word). However none of the solutions I tried worked. Am I missing something ?

The problem seems to come from the way I define this : it should neither be a "region" or "match", that would be evaluated as true basically at each word...

  • 4
    I think \w matches only one character of a word, what if you use \w+ to match several word characters? (I can't test it right now unfortunately) – statox May 10 '16 at 10:07
  • Using syn match VarName '\w' or \w\+ give the same result (I think you meant \w\+ but correct me if I'm wrong), it basically highlights all the words (except the keywords previously defined). – Feffe May 10 '16 at 10:21
6

It is possible to tell Vim to match something after a keyword, using nextgroup:

nextgroup={group-name},..                               :syn-nextgroup

The "nextgroup" argument is followed by a list of syntax group names,
separated by commas (just like with "contains", so you can also use patterns).

If the "nextgroup" argument is given, the mentioned syntax groups will be
tried for a match, after the match or region ends.  If none of the groups have
a match, highlighting continues normally.  If there is a match, this group
will be used, even when it is not mentioned in the "contains" field of the
current group.  This is like giving the mentioned group priority over all
other groups.

So, something like:

syn keyword VariableType real real1D real2D real3D int nextgroup=VarName skipwhite
syn match VarName '\i\+' contained
hi VariableType ctermfg=darkgreen
hi VarName ctermfg=darkblue
  • skipwhite tells Vim to skip spaces and tabs when looking for the nextgroup.
  • \i might be better than \w. \i matches identifier characters.
  • VarName is still contained so that it doesn't automatically apply to every identifier string in the file.

Effect:

enter image description here


You could also define a region or match containing these keywords and the word that follows, and then contain the keywords within. For example:

syn match VarDecl '\v<(real([123]D)?|int)\s+\i+>' contains=VariableType,VarName
syn keyword VariableType real real1D real2D real3D int contained
syn match VarName '\i' contained
hi VariableType ctermfg=darkgreen
hi VarName ctermfg=darkblue

The regex:

  • \v: "very magic". See :h /magic. Saves a lot on backslashes.
  • \< and \> match at word boundaries. This way, we won't match in the middle of a word (the middle line was intended to test this).
  • real([123]D)? matches real with an optional 1D, 2D or 3D after it.
  • (real([123]D)?|int) matches either the above or int.
  • \s+ matches one or more whitespace characters.
  • \i+ matches one or more identifier characters.
  • \(, \), \<, \>, \|, \? and \+ don't need backslashes because of \v.
  • 1
    do you know if there is any way to include the matched keywords inside the regex? Instead of building it by hand – nobe4 May 10 '16 at 11:24
  • 1
    If you have time, could you explain the '\v<(real([123]D)?|int)\s+\i+>' ? It seems very useful and powerful, but a little too involved for me to understand it... – Feffe May 10 '16 at 12:15

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.