The fix
syntax region xBCD start="b" end="d"
syntax region xBlock start="abcde::"hs=s+5 end=";" contains=xBCD
Explanation
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 xBlock
:
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 xBCD
region.
I therefore don't think it's possible to get this working using \zs
.