Define a syntax region which depends on the indent

2019-04-11 23:08发布

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条回答
beautiful°
2楼-- · 2019-04-11 23:32

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(...\).

查看更多
登录 后发表回答