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: "\>">

它是一种文本处理语言(想想类固醇降价),所以文本块必须是非限制性的。

我在为此编写 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)' ...

因为,即使regex to match name and arg list不可怕,这也破坏了我语法高亮嵌套函数的能力。

我想要的是类似于a 的nextgroup东西,但我找不到。startsyntax region

这可能吗?我如何在 vimscript 中执行此操作?

4

2 回答 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
于 2012-11-29T07:39:44.980 回答
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
于 2012-11-29T08:07:58.897 回答