I am writing vim syntax highlighting for a DSL where functions follow the following format:
# 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: "\>">
It's a text-processing language (think markdown on steroids), so the text blocks must be non-restrictive.
I'm having a lot of trouble writing a vim syntax file for this.
I can do
syn region myFunction start='<' end='>' skip='\\>'
syn region myArgs start='(' end=')' skip='\\)'
But myFunction
can't contain myArgs
, because then the parens are wrongly highlighted in the following example:
<function(arg) some text (with parenthesis) that aren't arguments>
Specifically, I want the function name and argument list to be highlighted only at the immediate beginning of the region. However, I can't do
syn region myFunction start='<(regex to match name and arg list)' ...
Because, even if regex to match name and arg list
weren't horrifying, this breaks my ability to syntax highlight nested functions.
What I want is something like nextgroup
for the start
of a syntax region
, but I can't find one.
Is this possible? How do I do this in vimscript?
Define a contained syntax match for the function name that overlaps with the leading <
character of the myFunction
region, then use nextgroup
to attempt a match with myArgs
only directly after it, not subsequent occurrences.
:syn region myFunction start='<' end='>' contains=myFunctionName
:syn match myFunctionName '<\i\+' contained nextgroup=myArgs
:syn region myArgs start='(' end=')' contained
Edit: Here's a variant with matchgroup
on the <...>
elements; the matchgroup
cannot be used for the start element, because that prevents the anchoring of 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With