问题
I'm trying to built a lighter syntax file for reStructuredText in Vim. In rst, literal blocks start when "::" is encountered at the end of a line:
I'll show you some code::
if foo = bar then
do_something()
end
Literal blocks end when indentation level is lowered.
But, literal blocks can be inside other structures that are indented but not literal:
.. important::
Some code for you inside this ".. important" directive::
Code comes here
Back to normal text, but it is indented with respect to ".. important".
So, the problem is: how to make a region that detects the indentation? I did that with the following rule:
syn region rstLiteralBlock start=/^\%(\.\.\)\@!\z(\s*\).*::$/ms=e-1 skip=/^$/ end=/^\z1\S/me=e-1
It works pretty fine but has a problem: any match or region that appear in line that should be matched by "start" takes over the syntax rules. Example:
Foo `this is a link and should be colored`_. Code comes here::
It will not make my rule work because there is a "link" rule that takes over the situation. This is because the ms
and me
matching parameters but I cannot take them off, because it would just color the whole line.
Any help on that?
Thanks!
回答1:
By matching the text before the ::
as the region's start, you're indeed preventing other syntax rules from applying there. I would solve this by positive lookbehind; i.e. only assert the rules for the text before the ::
, without including it in the match. With this, you even don't need the ms=e-1
, as the only thing that gets matched for the region start is the ::
itself:
syn region rstLiteralBlock start=/\%(^\%(\.\.\)\@!\z(\s*\).*\)\@<=::$/ skip=/^$/ end=/^\z1\S/me=e-1
The indentation will still be captured by the \z(...\)
.
来源:https://stackoverflow.com/questions/33907858/define-a-syntax-region-which-depends-on-the-indentation-level