This is an example of my file format basically it follows this layout:

<word> <wordWithNumbers> <wraped text>


sadfa 23eafa asdfasdf asdfdsf sflsdkjf ;lkja flksad ks adfsdf
             asdfasdf dfas fasd fadsfaslf;ajdf;lkadjfadjfasdf

ccsfe f32eee asdfasdf asdfdsf sflsdkjf ;lkja flksad ks adfsdf
             asdfasdf dfas fasd fadsfaslf;ajdf;lkadjfadjfasdf

Here is my syntax file that aims to color each of the 3 parts differently

:sy case match

:sy region A start=/^/ end=/^[a-zA-Z]\+ [0-9a-zA-Z]\+ / contains=B,C

:sy match B /^[a-zA-Z]\+ / contained        " seems to work fine.
:sy match C / [0-9a-zA-Z]\+ / contained     " alternatively colors words in
                                            " <wraped text>!

:hi B ctermfg=blue
:hi C ctermfg=green

Specifically, I'm amused why match C escapes its parent region A. This results in miscolouring <wordwithnumbers> and <wraped text>.

Any idea where is my error please?


Your error is simply that you've misunderstood the contains/contained keywords. See :h syn-contains:

The "contains" argument is followed by a list of syntax group names. These groups will be allowed to begin inside the item (they may extend past the containing group's end).

(emphasis mine)

So "match C escapes its parent region" is the correct behaviour.

There are a number of ways I could think of to adapt your solution to be do what you want (B Layer has already suggested making the regular expressions more specific), but the code you've given actually works correctly (with regards to the matching of syntax groups) for me on the example you've given: <word> is matched by B and A (and therefore coloured blue), <wordwithnumbers> is matched by A alone (no colour), and words in <wrappedtext> alternate between A alone (no colour) and C and A (green).

I do note that the last words on the line don't always match group C when they should. This is because you have specified that group C must end with a space, which doesn't occur if the word is at the end of the line. One quick fix for this is to match whitespace-including-line-breaks instead of a literal <space> character by using \_s (See :h 27.8):

:sy match C / [0-9a-zA-Z]\+\_s/ contained

If you can clarify more precisely what problems you're seeing in the sample text given, or add further examples where the highlighting fails, I should be able to come up with a complete solution as well as simply describing the errors in your code.

  • Thank you. That exactly answers my specific question about the behaviour boundaries of region.
    – caveman
    Oct 17 '17 at 15:05

I'm no expert on syntax highlighting but I thought I'd take a crack at this as I'd like to learn this stuff.

You are seeing the alternating coloring because a) your pattern will match any space surrounded letter/number words on the line and b) by putting spaces on both ends you prevent adjacent words from matching.

I was able to get it to work like this

:sy region A start=/^/ end=/$/ contains=B,C
:sy match B /^\([a-zA-Z]\+\)/ contained
:sy match C /\(^[a-zA-Z]\+\)\@<= \(0-9a-zA-Z\+\)/ contained

This will result in blue colored first word, green second word, and the remainder of the line whatever color is assigned to A. (I assume this is what you mean by coloring the 3 parts differently.)

The issue with your version is the patterns are too permissive. They need to be constrained to the exact location desired. And some advanced regex concepts are needed for this, i.e. lookarounds. For C I'm using a positive look-behind atom (\@<=) which confirms that the preceding pattern is present but does not count it as part of the match.

I encourage you to look at existing syntax files. They are verbose but quite illuminating.

P.S. At least that's my inexperienced understanding. I'll defer to any experts who chime in!

  • Thank you very much for the help, and introducing me to more advanced concepts.
    – caveman
    Oct 17 '17 at 15:07

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.