我可以像nano一样级联vim语法高亮规则吗?

nvbavucw  于 2022-11-11  发布在  其他
关注(0)|答案(2)|浏览(145)

我有一个自定义文件类型,其中包含许多字段,如

FieldName: FieldValue

我尝试在nano和vim中为这种文件类型创建语法高亮显示,这样“Fieldname”显示为蓝色,而从冒号开始的任何内容,包括冒号,显示为黄色。在nano中,由于其“级联”特性,我很容易实现这一点:

color yellow     start="^FieldName: " end="$"   # Make the whole thing yellow
color brightblue       "^FieldName"             # Then change the first part to blue

在Vim中,它看起来不像规则级联,但我可以使用'matchgroup'实现上述操作,它允许将'boundary'匹配与'content'区别对待:

syn region Yellow matchgroup=Blue start="^FieldName" end="$"

到目前为止一切顺利。问题出现在特殊情况下,一些FieldValue需要不同的颜色,因为它们是特殊的。在nano中,我可以简单地在级联中添加另一个规则:

color yellow         start="^FieldNAme: " end="$"     # Make the whole thing yellow
color bold,lightyellow,red "^FieldName: SpecialValue" # Then change up to the special value to red
color yellow               "^FieldName: "             # Then up to the colon to yellow again
color brightblue           "^FieldName"               # Then up to the fieldname to blue

然而,当我尝试在vim中做同样的事情时,我被卡住了。我不知道如何在多个级别上匹配组。有没有一种方法可以在vim中实现这种级联行为?或者,有人能给我指出正确的方向来实现上述效果吗?

yc0p9oo0

yc0p9oo01#

在Vim中,如果在另一个语法匹配/区域内,则只尝试一些子匹配。这些匹配必须出现在上层匹配的contains=xxx,yyy,zzz属性中(或者,它们可以具有属性containedin=aaa,其中aaa是高级别匹配项)。此外,子匹配项通常应具有contained属性,该属性禁止在全局级别上进行匹配(即未包含)。
最后要注意的是,如果出现冲突(即两个或更多的子匹配可以在同一位置匹配),那么最后一个获胜。
这个例子非常简单,不需要很多规则。然而,确切的正则表达式定义可能会有所不同,所以给出它只是为了说明。
变量1

syn match MyFileFieldWhole /^\w\+: .*/ contains=MyFileFieldName,MyFileFieldSpecial
syn match MyFileFieldName /^\w\+/ contained
syn keyword MyFileFieldSpecial SpecialValue contained

hi def MyFileFieldWhole guifg=yellow
hi def MyFileFieldName guifg=lightblue
hi def MyFileFieldSpecial guifg=red

变量2

syn match MyFileFieldName /^\w\+: /me=e-2 nextgroup=MyFileFieldValue
syn match MyFileFieldValue /: .*/ contains=MyFileFieldSpecial contained
syn keyword MyFileFieldSpecial SpecialValue contained

hi def MyFileFieldName guifg=lightblue
hi def MyFileFieldValue guifg=yellow
hi def MyFileFieldSpecial guifg=red
093gszye

093gszye2#

这就是我解决上述问题的方法,(使用与上面相同的伪域,这里只显示相关的规则)。希望这对其他面临同样挑战的人有用。

" Vim syntax file
" Language   : myfiletype
" Filenames  : *.myfileextension
" Maintainer : Me
" Last Change: 2022-06-19

" Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax")
  finish
endif

" SpecialValue is special, put it in red box. Fieldname in blue.
syn match Group1 "^FieldName: SpecialValue$"    contains=Group2
syn match Group2 "^FieldName: \zeSpecialValue$" contains=Group3 contained
syn match Group3 "^FieldName\ze: SpecialValue$" contained

" all other values in plain yellow, with fieldname in blue.
syn match Group2 "^FieldName: \(SpecialValue$\)\@!.*$"    contains=Group3
syn match Group3 "^FieldName\ze: \(SpecialValue$\)\@!.*$" contained

" Group-code color definitions ==
hi def Group3             ctermfg=blue
hi def Group2             ctermfg=darkyellow
hi def Group1 cterm=bold  ctermfg=yellow  ctermbg=darkred

let b:current_syntax = "myfiletype"

一些解释性说明:

  • 最后我使用syn-match而不是syn-region,因为前者保证了单行匹配。
  • \ze位用作“剪切”;该正则表达式首先完全匹配,然后“剪切”到\ze部分,然后将其用于突出显示。
  • \@!导致regexp在前一个原子(在本例中为括号中的位)不存在时成功。
  • 在各种“包含”级别中,“外部匹配”是相同的,但在每个级别上,由\ze导致的“内部匹配”越来越短,设法模拟我所追求的“级联”效果。但是,必须添加一个明确排除特殊值的附加情况,以说明不存在特殊值的“默认”情况(相反,在nano中,不需要明确的排除,只要这个“默认”规则被放置在“级联”的顶部即可)。
  • 上面的例子演示了一个特殊值的规则。如果你有多个特殊值要排除(我的实际问题就是这种情况),你可以将\(SpecialValue$\)\@!转换为\(SpecialValue1\|SpecialValue2\)\@!,等等,以解释'default'规则中 all 特殊值的显式排除。

相关问题