Vim语法:仅在区域开头突出显示匹配

5
我正在为一种DSL编写vim语法高亮,其中函数遵循以下格式:

# A function with no arguments
<function>

# A function with arguments
<function(arg1, arg2)>

# A function with text
<function block of normal text>

# A function with args and text
<function(arg1,arg2) text>

# Line breaks are allowed pretty much everywhere.
<function(
        arg1,
        arg2)
    a block of text>

# As is nesting
<function(<subfunc>) Some text with <another(subfunction) etc.>>

# Backslash escape
<function(single arg with a comma: "\,") contained bracket between quotes: "\>">

这是一种文本处理语言(类似于增强版的Markdown),因此文本块必须是非限制性的。

我在为此编写vim语法文件时遇到了很多麻烦。

我可以做到:

syn region myFunction start='<' end='>' skip='\\>'
syn region myArgs start='(' end=')' skip='\\)'

但是myFunction不能包含myArgs,因为这样在下面的例子中圆括号会被错误地突出显示:

<function(arg) some text (with parenthesis) that aren't arguments>

具体来说,我希望函数名和参数列表只在区域的最开始处突出显示。然而,我无法实现。

syn region myFunction start='<(regex to match name and arg list)' ...

因为即使用于匹配名称和参数列表的正则表达式不可怕,这也会破坏我的语法高亮嵌套函数的能力。
我想要的是像nextgroup一样用于语法区域开始的东西,但我找不到一个。
这个可能吗?我该如何在vimscript中实现?

你确定start='\<'吗? \<匹配单词的开头;要匹配字面意义上的<,请使用< - Ingo Karkat
哦,对了——我在所有的正则表达式前面都使用 '\v' 并将其剥离以使其更清晰,忘记了之后 '<' 不需要转义。 - So8res
2个回答

5

定义一个被包含的语法匹配,匹配函数名,并与myFunction区域的前导<字符重叠,然后使用nextgroup尝试仅在其直接之后匹配myArgs,而不是后续出现。

:syn region myFunction start='<' end='>' contains=myFunctionName
:syn match myFunctionName '<\i\+' contained nextgroup=myArgs
:syn region myArgs start='(' end=')' contained

编辑:以下是使用matchgroup变体的内容,matchgroup不能用于开始元素,因为这会阻止myFunctionName的定位:

:syn region myFunction start='<' matchgroup=myMarker end='>' contains=myFunctionName
:syn match myFunctionName '<\i\+' contained nextgroup=myArgs contains=myMarker
:syn match myMarker '<' contained
:syn region myArgs start='(' end=')' contained

如果在myFunction区域上使用[matchgroup],则此操作将失败。这是有意为之还是vim的一个错误? - So8res
然后,< 被匹配组“消耗”,不会尝试进行额外的匹配;我已经在我的答案中添加了一个替代方案。 - Ingo Karkat

2
也许您可以尝试以下方法,以更好地控制高亮显示效果:
syn region myFunction start='<' end='[^\\]>' contains=myFunctionName
syn match myFunctionName '<\i\+'hs=s+1 contained nextgroup=myArgs
syn region myArgs start='('hs=s+1 end=')'he=s-1 contained contains=myFunction

这里的hsshe是做什么的?它们来自哪里? - So8res
1
它们用于指定应该突出显示的部分。您可以在VIM中查看“:syn-pattern-offset”。 - Li Dong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接