可以使vim语法区域接触/重叠吗?


13

所以不久前,我决定通过创建自己的文件来学习更多有关vim语法文件如何工作的信息。我的目标是创建一个简单的语法文件,该文件将基于定界符将文件分为3个部分,并包括这三个部分中两个部分的预先存在的语法文件。

这是一个示例文件:

Some text, unstyled

==================== Log
(Output of git log)

==================== Diff
(Output of diff)

目标是git.vim仅应用于日志,仅应用于diff.vim差异,不包括两个标头。1 这是我的语法文件最终看起来像:

if exists("b:current_syntax")
    finish
endif

syntax include @gitlog $VIMRUNTIME/syntax/git.vim
syntax region GitLog
    \ start=/^===* Log/
    \ end=/^===* Diff/
    \ contains=@gitlog

syntax include @gitdiff $VIMRUNTIME/syntax/diff.vim
syntax region Diff
    \ start=/^===* Diff/
    \ end=/\n\n/
    \ contains=@gitdiff

let b:current_syntax = "logdiff"

请注意end,第一个区域start上的内容与第二个区域上的相同。这行不通;显然没有检测到第二区域,并且未应用语法突出显示。

我可以通过将正则表达式放宽到end=/^===/和来使其工作start=/=== Diff/,以使区域不接触,但又不是特别喜欢-一个人应该从另一个结束处开始就不太明显了。

有没有办法允许两个区域定义接触相同的字符(和/或使匹配的边缘互斥,而不是互斥),或者我被松散的正则表达式所困扰?

1(是的,我知道git.vim包括diff.vim,但这是一次学习练习)


我认为应该可以通过使用“ Region End”偏移量使边缘互斥(请参阅:h :syn-pattern-offset参考资料),或者通过更改GitLog区域以扩展到文件的末尾,而Diff区域完全位于GitLog区域内,来实现。不过,我无法使用这些方法中的任何一种。
丰富

正如您所注意到的那样,由于git.vim已经突出显示了diff输出,因此对其进行测试变得更加困难。可能是一个想法,以相应地更改您的示例!
丰富

Answers:


4

您可以告诉Vim regex引擎从哪里开始下一场比赛。

到目前为止,我知道有两种方法:

  1. 使用\ze设置比赛结束:

    syntax region GitLog
        \ start=/^===* Log/
        \ end=/\ze^===* Diff/
        \ contains=@gitlog
    
  2. 使用正向超前,\@=在Vim中称为零宽度匹配:

    syntax region GitLog
        \ start=/^===* Log/
        \ end=/\(^===* Diff\)\@=/
        \ contains=@gitlog
    

因此,比赛结束的“指针”倒退到行的开头^===* Diff,这样region Diffstart就会^===* Diff在行再次开始其匹配。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.