So I have a language that looks something like this:

proc someprocess : (arg1: type1), (arg2: type2) ... |- (channel: type) =
    send $ch msg ;
    pay $ch {n} ;

I want the {n} to be highlighted however i don't want the code in the proc contained with { } to be highlighted. i.e. only want {..} region to be highlighted when it occurs after pay or get.

  • Additonal question not that we're here: the current highlight file i made is based of a haskell file I copied and edited. It only highlights $ as an operator but is there anyway to highlight the whole word after $? Like I want $ch to be highlighted the same color as the $ is highlighted. Commented Apr 21, 2021 at 20:16
  • Not sure if I understand your syntax right, but I wonder if you could also define the {n} group as having the { and } on the same line and that way you could differentiate it from the proc block? In any case, my answer addresses the {...} starting on the same line as the pay or get, so hopefully that works for you.
    – filbranden
    Commented Apr 21, 2021 at 21:58
  • Regarding your follow up, please post a separate question. I suggest you should include the actual rule you're using that is matching the $, since it's easier to give you a better suggestion on how to tweak it if we actually know what it is... Cheers!
    – filbranden
    Commented Apr 21, 2021 at 21:59
  • You might be able to steal an idea from the shell syntax files for $var
    – D. Ben Knoble
    Commented Apr 21, 2021 at 23:27

2 Answers 2


Your don't provide full spec for your language. But whenever possible, contained-matches should be preferred. I.e. something like this:

syn match xPayOrGet /pay\|get/ skipwhite nextgroup=xPayGetAfter
syn match xPayGetAfter /[^;]\+;/ contains=xPayGetBraces contained
syn match xPayGetBraces /{\a\+}/ contained

My suggestion here is to use a zero-width look-behind match to look up the specific keywords you're after (pay and get) and only consider the region when it's in that same context.


syntax region myGroup
  \ start=+\(\<\(pay\|get\)\>.*\)\@<={+
  \ end=+}+

See :help /\@<= for details on this operator, which performs the zero-width look-behind for the pattern that includes pay or get.

Note that the documentation will recommend that you generally use \zs instead, to mark the beginning of a match, but that doesn't work here since you'll want to have the pay or get and other components such as the $ch to match other groups. Using a pattern that matches those elements without a zero-width look-behind would fail to match them to other groups, even if the \zs means only the { would be highlighted with the current group. (For more details, see question “Syntax highlighting with multiple matches with \zs.)

  • A recent question I answered used the same technique, maybe take a look there too for more context: vi.stackexchange.com/a/31030/18609
    – filbranden
    Commented Apr 21, 2021 at 21:56
  • How the heck did you get so good at the syntax rules 😂
    – D. Ben Knoble
    Commented Apr 21, 2021 at 23:27
  • 1
    @Ben A lot of trial and error... I think there was also one specific question here (don't recall exactly which) that took me on a deep dive on the syntax engine...
    – filbranden
    Commented Apr 22, 2021 at 0:24
  • Like this one, I seem to remember it took quite a bit of research: vi.stackexchange.com/a/22293/18609
    – filbranden
    Commented Apr 22, 2021 at 2:46
  • 1
    Yeah, my own answer on that last one has a link to an answer with a link in the comments that also deals with it
    – D. Ben Knoble
    Commented Apr 22, 2021 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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