因此,不久前,我决定通过创建自己的文件来学习有关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输出,因此对其进行测试变得更加困难。可能会相应地改变您的示例!

#1 楼

您可以告诉Vim regex引擎从哪里开始下一场比赛。到目前为止,我知道有2种方法:



使用\ze设置匹配结束:

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



使用正向提前量\@=,在Vim中称为零宽度匹配:

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



,所以匹配结束的“指针”倒退到^===* Diff行的开头,这样region Diffstart将再次在^===* Diff行开始其匹配。 />