Vim: 寻求帮助创建自定义语法高亮

4

以下是我目前的翻译:

syntax match cfg_Comment '#.*$' contains=cfg_DocTag
syntax match cfg_DocTag  '#\s*\zs[\\@]\l\+' contained

highlight default link cfg_Comment Comment
highlight default link cfg_DocTag  SpecialComment

对于像这样的东西,完美地发挥作用:

##
#   @brief The maximum.
#    @type number
# @default 1

我接下来想要做的是突出显示在@type后面的下一个单词,并将其标记为Type组。所以我进行了以下操作:
syntax match cfg_Comment '#.*$' contains=cfg_DocTag,cfg_DocField_type
syntax match cfg_DocTag  '#\s*\zs[\\@]\l\+' contained

syntax match cfg_DocTag_type   '@type' containedin=cfg_DocTag nextgroup=cfg_DocField_type skipwhite
syntax match cfg_DocField_type '\a\+' contained

highlight default link cfg_Comment       Comment
highlight default link cfg_DocTag        SpecialComment
highlight default link cfg_DocField_type Type

这里有两个问题:
  1. 现在,@type没有被高亮显示。我明白这是因为我没有为它指定组,但我希望它能从父容器cfg_DocTag继承颜色。
  2. 现在,注释中的所有内容都是Type颜色,而不仅仅是@type后面的单词。我又明白了,因为我指定了cfg_Commentcfg_DocField_type的容器。
我知道问题出在哪里,但我不知道如何优雅地解决它们并尽可能少地编写样板代码。
最后,请问一下为什么?
syntax match cfg_DocTag_type '@type' containedin=cfg_DocTag nextgroup=cfg_DocField_type skipwhite

并且

syntax keyword cfg_DocTag_type @type containedin=cfg_DocTag nextgroup=cfg_DocField_type skipwhite

它们不一样吗?即在第一种情况下,就像我上面描述的那样:@type不再被突出显示,因为组未指定,但这是预期的。但在第二种情况下,即使未指定组,它也会被突出显示,这是意外的,因此它似乎根本不匹配作为关键字。而且通过最简单的测试用例很容易证明:

  1. Highlighting works:

    syntax match Test '@type'
    
    highlight default link Test Keyword
    
  2. Highlighting doesn't work:

    syntax keyword Test @type
    
    highlight default link Test Keyword
    

更新


根据Ingo的回答,提出的解决方案确实有效。但是我感兴趣的是为什么这个不行?

syntax match cfg_Comment '#.*$' contains=cfg_DocTag
syntax match cfg_DocTag  '#\s*\zs[\\@]\l\+' contained

syntax match cfg_DocTag_type   '@type' transparent containedin=cfg_DocTag nextgroup=cfg_DocField_type skipwhite
syntax match cfg_DocField_type '\a\+' contained

highlight default link cfg_Comment       Comment
highlight default link cfg_DocTag        SpecialComment
highlight default link cfg_DocField_type Type

这个东西如果能正常工作就完美了。它可以避免我们重复匹配评论,并实现自然继承。顺便提一句,省略 @type 前面并不会改变任何东西,即继承效果保持不变。但为什么 cfg_DocField_type 没有被突出显示呢?有什么想法吗?

抱歉我的问题有点菜,但你能否解释一下你具体做了什么?只是把所有东西放在 vimrc 中吗? - EverythingRightPlace
@bashophil:当然不是!如果你想扩展一些已经存在于Vim中的标准语法高亮,比如cpp,那么你需要将自己的cpp.vim文件放到.vim/after/syntax目录下。如果你要从头开始编写新的语法高亮文件或者完全覆盖Vim自带的标准文件,比如cpp,那么你需要将文件放到.vim/syntax目录下。 - Alexander Shukaev
1个回答

1
你已经很接近了。你将cfg_DocTag_type包含在cfg_DocTag中是不起作用的,因为它们会在同一位置匹配。从前者中省略前导的@可以解决这个问题,但是nextgroup=cfg_DocField_type仍然无法匹配,因为显然cfg_DocTag的匹配结束(标记之后)使Vim不应用nextgroup

我所做的是将cfg_DocTag_typecfg_DocTag放在同一级别上,即不包含在后者中。唯一的缺点是预匹配#\s*\zs出现重复。
syntax match cfg_Comment '#.*$' contains=cfg_DocTag,cfg_DocTag_type
syntax match cfg_DocTag  '#\s*\zs[\\@]\l\+' contained

syntax match cfg_DocTag_type   '#\s*\zs@type' nextgroup=cfg_DocField_type skipwhite
syntax match cfg_DocField_type '\a\+' contained

highlight default link cfg_Comment       Comment
highlight default link cfg_DocTag        SpecialComment
highlight default link cfg_DocTag_type   cfg_DocTag
highlight default link cfg_DocField_type Type

回答1:它不包含在内;只有当您省略@时才是如此。然后,添加transparent将使您获得继承效果。

关于“最后”:我怀疑@不是'iskeyword'的一部分(默认情况下不是),但对于:syn keyword来说必须是这样。

专业提示:安装SyntaxAttr.vim-显示光标下字符的语法突出显示属性插件可以使语法脚本开发更加容易。


谢谢,Ingo,像往常一样 - 高质量的答案!请看一下我的更新,因为我还有一个问题。 - Alexander Shukaev
正如我所说,如果你扩展匹配 cfg_DocTag 的范围以包括(某些)DocField_type(例如 '#\s*\zs[\\@]\l\+\s\w'),那么它才能匹配成功。但是当父级匹配结束时,nextgroup 就不再适用了。尽管我无法在帮助文件中找到支持该说法的语句。 - Ingo Karkat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接