vim: 如何语法高亮一行,使其一部分格式为 A 而另一部分格式为 B?

vim: How do I syntax highlight a line so that one part of it is formatted as A and the other part is formatted as B?

我今天已经花了几个小时,在线研究并阅读了 vim 手册。我已经无计可施了。我想用时间戳格式化行,使它们有绿色文本,同时将时间戳本身加粗。例如,如果我有以下 4 行:

1  [ 20:42:57 20190601 ] Apple car truck a whole bunch of other nonsense
2  ball baby zebra more nonsense
3  [ 20:43:12 20190601 ] dog blah blah blah
4  circle mouse rat up down left right b a b a select start

然后包含时间戳的两行(第 2 行和第 4 行)将有绿色文本,时间戳本身([ 20:42:57 20190601 ][ 20:43:12 20190601 ]) 将是粗体。

我的第一个想法是只使用一个正则表达式模式来匹配所有带有时间戳的行并将它们着色为绿色,然后使用另一个正则表达式模式来只匹配时间戳本身并将它们设为粗体,如下所示:

syntax match timestampline "\[ \([0-9]\{2}\:\)\{2}[0-9]\{2} [0-9]\{8} \].*$"
highlight timestampline ctermfg=green ctermbg=NONE
syntax match timestamponly "\[ \([0-9]\{2}\:\)\{2}[0-9]\{2} [0-9]\{8} \]"
highlight timestamponly cterm=bold

但这只会导致时间戳被加粗,任何地方都没有绿色文本。

然后我想也许我需要告诉每个语法在哪里停止或开始匹配,就像这样:

syntax match timestampline "\[ \([0-9]\{2}\:\)\{2}[0-9]\{2} [0-9]\{8} \]\{-}\zs.*$"
highlight timestampline ctermfg=green ctermbg=NONE
syntax match timestamponly "\[ \([0-9]\{2}\:\)\{2}[0-9]\{2} [0-9]\{8} \]\ze"
highlight timestamponly ctermfg=green ctermbg=NONE cterm=bold

但这只会导致时间戳变为绿色和粗体,而其他所有内容都未格式化。

我不明白我做错了什么。为什么第二个亮点陈述完全否定了第一个?他们不应该只是格式化他们匹配的东西而不影响他们不匹配的东西吗?

:help :syn-priority:

When several syntax items may match, these rules are used:

  1. When multiple Match or Region items start in the same position, the item defined last has priority.

所以在你的代码中 timestamponly 总是赢,timestampline 永远不会被使用。

你可以这样得到你想要的效果:

syntax match timestampline /.*$/ contained
highlight timestampline ctermfg=green

syntax match timestamponly /\[ \d\{2}:\d\{2}:\d\{2} \d\{8} \]/ nextgroup=timestampline
highlight timestamponly ctermfg=green cterm=bold