2

考虑以下 3 组高亮组和语法匹配:

hi  Foo     ctermfg=black   ctermbg=red     guifg=black     guibg=red
hi  Filler  ctermfg=black   ctermbg=green   guifg=black     guibg=green
hi  Bar     ctermfg=black   ctermbg=blue    guifg=black     guibg=blue
syn match   Foo     "foo"       nextgroup=Filler
syn match   Filler  "\_s*"      nextgroup=Bar       contained
syn match   Bar     "bar"                           contained

hi  Baz     ctermfg=black   ctermbg=cyan    guifg=black     guibg=cyan
hi  Qux     ctermfg=black   ctermbg=yellow  guifg=black     guibg=yellow
syn match   Baz     "baz\_s*"   nextgroup=Qux
syn match   Qux     "qux"                           contained

hi  Abc     ctermfg=black   ctermbg=magenta guifg=black     guibg=magenta
hi  Xyz     ctermfg=black   ctermbg=white   guifg=black     guibg=white
syn match   Abc     "abc"       nextgroup=Xyz       skipwhite   skipnl
syn match   Xyz     "xyz"                           contained

Filler并且Bar仅在Foo;之后匹配 同样,Qux仅在 之后Baz,并且Xyz仅在 之后Abc:set list为了清楚起见,以下示例说明了除非有尾随空格,否则如何匹配FillerBar不匹配:FooFoo

Baz Qux示例验证匹配换行符,那么为什么在拆分为and\_s时这不起作用?这句话是相关的:BazFooFiller:help syn-skipnl

当存在“skipnl”时,下一行可能会找到与 nextgroup 的匹配项。这只发生在当前项目在当前行的末尾结束时!当“skipnl”不存在时,下一个组只会在同一行中的当前项目之后找到。

Abc Xyz示例完全使用skipwhite skipnl和不使用\_s,确实在这两种情况下都匹配。这是否意味着EOL不符合“在同一行中的当前项目之后”的条件?当然它不能成为下一行的一部分?这似乎与正常搜索\_s\n导致EOL字符在同一行匹配的事实相矛盾。

4

1 回答 1

2

如果匹配\n在. _ _nextgroupskipnlnextgroup\n

在给定的例子中,由于第一个Foo匹配在之前立​​即结束\n并且Foo没有指定skipnl,Vim 甚至不尝试匹配Filler。其他空格的引入允许Filler在第二次匹配之后进行Foo匹配,并且由于Filler包含\nBar也可以在不Filler指定的情况下匹配skipnl

相关代码在src/syntax.c

/* nextgroup ends at end of line, unless "skipnl" or "skipempty" present */
if (current_next_list != NULL
        && syn_getcurline()[current_col + 1] == NUL
        && !(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY)))
    current_next_list = NULL;

/* handle next_list, unless at end of line and no "skipnl" or
 * "skipempty" */
current_next_list = cur_si->si_next_list;
current_next_flags = cur_si->si_flags;
if (!(current_next_flags & (HL_SKIPNL | HL_SKIPEMPTY))
        && syn_getcurline()[current_col] == NUL)
    current_next_list = NULL;
于 2013-08-09T14:01:54.867 回答