syntax region xBCD start="b" end="d"
syntax region xBlock start="abcde::"hs=s+5 end=";" contains=xBCD
The problem is not that Vim cannot highlight a subset of
start. Instead it is your use of
\zs that is causing issues. We can show this is true by removing the
\zs and allowing the
xBCD to be inside the
syntax region xBlock start="abcde::" end=";" contains=xBCD
You will see that your
bcd is now highlighted, but obviously now your entire
xBlock is highlighted, which is not your goal.
Using a highlight offset (see
:help syn-pattern-offset) fixes this.
Using a "positive lookbehind" instead (see
:help /\@<=) is an alternative method of achieving your desired highlighting which might work better for your requirements:
syntax region xBlock start="\(abcde\)\@<=::" end=";"
(Your use of
\z() to mark the subexpression as "external" doesn't seem to be used anywhere in your example, so I removed it. The solution still works fine with it reinserted, though.)
Why your code failed
Here is my explanation of I think was going wrong with your code. It's conjecture, but based on a reasonable amount of experimentation:
When you use
\zs it moves the start of your match to after the
abcde. This means that your
xBlock is no longer the first piece of matching syntax in your sample file: the
xBCD is now found a few characters earlier, and thus is highlighted. Vim then starts looking after the end of the matching
xBCD, which is too far forwards for
xBlock to match, so no more matches are found.
Your attempt to fix it by adding
contains=xBCD to your
xBlock definition therefore failed because the
xBCD region is not inside
xBlock, it's a few characters before the start of where the
xBlock would be, if its own presence didn't prevent the
xBlock from being matched at all.
The reason your second attempt gave different results is that you also added
contained to your definition of
xBCD, which does not mean that
xBCD can be found inside other syntax groups, but instead that it cannot be found outside of them, at the top level. Therefore, the
xBCD region is no longer found, and now your highlighting for
xBlock starts working.
I also tried allowing the
xBlock to start within the
xBCD block (the opposite of what you tried) with appropriate use of
contains, because this is closer to how Vim would see it, but that failed too: I guess because regardless of whether Vim considers the
a or the
: to be the "start" of the match, neither is actually within the
I therefore don't think it's possible to get this working using