Thursday, September 29, 2016

Re: syntax match bug: 'keepend' not officially supported, but required in some cases

On Thu, Sep 29, 2016 at 12:09 PM, Bram Moolenaar <Bram@moolenaar.net> wrote:
>
> Brett Stahlman wrote:
>
>> The syntax documentation suggests that the 'keepend' argument applies
>> only to syntax regions, not syntax matches. But if I highlight a
>> buffer containing only the following line...
>>
>> ABCDE
>>
>> ...with the following syntax definitions...
>>
>> syn match A /A/
>> syn match Inside /[A-Z]\+/ transparent contained containedin=A
>> hi A guifg=blue
>>
>> ...the match group "A" extends (apparently incorrectly) from A through
>> E, though its pattern matches only the "A". Stranger still, one
>> additional nested "Inside" group is recognized in each successive
>> letter. I.e., "Inside" is contained within "Inside", in spite of the
>> `containedin=A'. Thus, running synstack on successive characters, I
>> see...
>>
>> -- cursor on A --
>> A
>> Inside
>> -- cursor on B --
>> A
>> Inside
>> Inside
>> -- cursor on C --
>> A
>> Inside
>> Inside
>> Inside
>>
>>
>> I can fix the problem by adding the 'keepend' argument to the
>> definition for match group "A", but the "keepend" is highlighted as an
>> error by the vim syntax, and the help on :syn-match gives me no reason
>> to believe the argument should be supported.
>
> Yes, the "keepend" actually works, although it's not documented. I'll
> add a note in the documentation.

Thanks.

>
>> Here are the results of synstack() with the following, "fixed" definition for A:
>> syn match A /A/ keepend
>>
>> -- cursor on A --
>> A
>> Inside
>> -- cursor on B --
>> -- cursor on C --
>>
>> Is 'keepend' meant to be supported for syn-match? The purpose of
>> 'keepend' is to prevent a nested group from obscuring a match with a
>> containing group's "end pattern". Although a match group has no
>> explicit end pattern, the principle of checking for the end of the
>> match pattern certainly still applies, so I suppose it makes sense
>> that 'keepend' would be accepted for both syn-match and syn-region. If
>> that is the intent, then the documentation needs fixing.
>>
>> As for the infinitely nested "Inside" groups, I can't account for
>> that, and suspect it's a bug, but perhaps I'm misunderstanding
>> something about contained and containedin?
>
> This is actually working as intended. When using a transparent item,
> checking for contained items ignores that transparent item. So the
> "containedin=A" applies every time.
>
> This can be avoided by add "contains=NONE to the Inside item:
>
> syn match Inside /[A-Z]\+/ transparent contained containedin=A contains=NONE

Hmm... I see it now:
"The "contains=" argument is also inherited from the item it is contained in..."

Excluding the transparent item itself from the inherited list might
have produced less surprising behavior, but I guess this is sort of an
uncommon corner case, and I agree that Vim's behavior is consistent
with the documentation.

Thanks for looking into it.
Brett Stahlman

>
> --
> A mathematician is a device for turning coffee into theorems.
> Paul Erdos
> A computer programmer is a device for turning coffee into bugs.
> Bram Moolenaar
>
> /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
> /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
> \\\ an exciting new programming language -- http://www.Zimbu.org ///
> \\\ help me help AIDS victims -- http://ICCF-Holland.org ///

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments: