You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vim语法文件中定义单行与多行字符串的语法高亮

解决Vim语法高亮中多行字符串与单行字符串的优先级问题

问题背景

你的自定义编程语言字符串规则如下(EBNF):

longstring ::= '"""' {'"'} newline chars newline '"""' {'"'}
newline ::= '\n'
string ::= '"' chars '"'

其中chars包含字母、数字、下划线、空白符及标点符号;多行字符串以≥3个双引号开头(可附加更多双引号),结束符需与开头双引号数量一致且位于新行,内容为原始字符串无需解析其他语法。

你当前的Vim语法规则:

syn region mylangLongString start=/\z("\{3,}\)\r/ end=/\z1/ contains=@Spell
syn region mylangString start=/"/ skip=/\\"/ end=/"/ contains=@mylangSpecial,@Spell

hi def link mylangLongString           String
hi def link mylangString               String

出现的问题:单行字符串规则优先匹配双引号,导致多行字符串匹配错误、高亮溢出至后续代码行。

解决方案

1. 调整规则优先级

Vim语法规则遵循先定义的规则优先级更高,因此只需将多行字符串的定义放在单行字符串之前,即可让Vim优先匹配多行字符串。

2. 修正多行字符串匹配正则

你原有的正则存在两个问题:

  • 仅匹配\r作为换行,未兼容通用的\n或\r\n换行格式
  • 未确保结束符位于新行的要求

修正后的多行字符串规则:

syn region mylangLongString start=/\z("\{3,})\n/ end=/\n\z1/ keepend contains=NONE
  • \z("\{3,}):捕获开头的≥3个双引号,用于结尾匹配
  • \n:匹配开头后的换行符(Vim会自动处理\r\n格式的跨平台换行)
  • end=/\n\z1/:匹配内容后的换行,再匹配与开头数量一致的双引号序列
  • keepend:确保结尾的双引号序列不被后续规则(如单行字符串)再次匹配
  • contains=NONE:符合原始字符串要求,不解析内容中的其他语法组

3. 最终完整语法规则

" 先定义多行字符串,确保优先级更高
syn region mylangLongString start=/\z("\{3,})\n/ end=/\n\z1/ keepend contains=NONE
" 再定义单行字符串
syn region mylangString start=/"/ skip=/\\"/ end=/"/ contains=@mylangSpecial,@Spell

hi def link mylangLongString String
hi def link mylangString String

额外说明

  • 如果你的编程语言允许开头双引号后有空白字符再换行,可将start正则调整为/\z("\{3,})\s*\n/,其中\s*匹配任意空白字符(空格、制表符等)
  • 若需要对多行字符串内容启用拼写检查,可将contains=NONE改为contains=@Spell

内容的提问来源于stack exchange,提问作者dlroweht

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 03:15:11