对 Vim 的 sed 语法着色文件的这种更改是好的还是破坏性的?
Posted
技术标签:
【中文标题】对 Vim 的 sed 语法着色文件的这种更改是好的还是破坏性的?【英文标题】:Is this change to Vim's syntax coloring file for sed good or disrupting? 【发布时间】:2020-07-26 09:29:26 【问题描述】:总结
我不是在询问您对提议的更改是好、坏、惊人或什么的看法。 我只是请求您帮助回答这个问题:我为 cmets 的语法着色提出的更改是否打破其他事物的语法着色(关键字、字符串、语法错误,...)? 上述问题不是基于意见的,因为我的更改要么确实破坏了某些东西,要么没有。就是这样。原问题
我已经在 Vim 的 GitHub 页面上创建了 issue #5876 来提议对 vim/runtime/syntax/sed.vim
进行更改,但它没有受到太多关注,所以我正在考虑为更改创建一个 PR。
事实上,我创建了一个问题而不是 PR,因为我不完全相信更改不会造成破坏,因此提出了这个问题。
问题在于第 20 行:
syn match sedComment "^\s*#.*$"
因为只有“全线”cmets 被着色为 cmets。在命令之后使用尾随 cmets(例如 GNU sed 允许)会刺激一些红色背景着色(因为我猜它被语法着色逻辑认为是错误)。
我认为放宽 cmets 的定义以允许 GNU sed 样式的 cmets 是合理的,原因很简单,因为该规则限制较少。
在这方面,我注意到将该行更改为
syn match sedComment "\s*#.*$"
即只需移除锚^
,似乎就足够了。我还尝试通过将一些 #
放在搜索中并在 sed 脚本中替换字符串来对其进行测试,看起来还不错。
但是我对 Vim 语法着色文件没有信心,所以我想确保我编辑的正则表达式不会导致误报。
为了证明我对此没有信心,请使用这个单行 sed
脚本
s/aaa/bbb/#ccc
这里#
没有作为评论着色,ccc
的背景是红色的(就像一个错误?),而只是添加一个空格,给出正确的着色:
s/aaa/bbb/ #ccc
因此,我认为我的编辑工作(或似乎工作)是因为几个语法着色指令之间的优先规则(关于s/aaa/bbb/#ccc
的这个特定示例,我认为#
就在结束分隔符之后s
命令在语言中是有含义的,但我不知道;GNU Sed man
页面对此没有任何说明)。
编辑
cmets 中建议的另一个示例如下,其语法着色没有被提议的更改破坏
s/#if !defined(\([^)]*)/#ifndef \1/ # with or without this comment is fine
【问题讨论】:
\s*#.*$
与\s*#.*
基本相同,但请记住,它可以匹配0+ 个空格、#
以及一行中任意位置的其余行。例如。它将匹配text="This is a string #abc"; # SOME COMMENT
中的#abc"; # SOME COMMENT
是的,@WiktorStribiżew,我知道该正则表达式匹配什么,但语法文件似乎没有给它机会。例如,如果我将 #
放在 sed 脚本中的某个位置,它不会像注释那样着色,即使 \s*#.*$
会匹配,我也会写 would 因为我很确定它永远不会应用于它,可能是因为其他一些语法规则优先。这就是我问这个问题的原因。
@WiktorStribiżew,我试图澄清我为什么要问这个问题以及我在寻找什么。
我不明白为什么它被关闭为opinion-based。没有意见。我提出的改变要么很好,要么破坏了某些东西,我正在寻求帮助以了解是哪种情况。而已。相反,如果有人认为这是题外话,因为我应该将其发布到 Vi and Vim Beta,那就是另一回事了。
你的建议对s/#if !defined(\([^)]*)/#ifndef \1/
有什么作用?我认为这可能是一个问题——该代码中没有注释,但是您的更改会将其视为注释,不是吗?此外,全世界都不使用 GNU sed
。
【参考方案1】:
我的研究
我终于找到了一些时间来研究:h E410
,现在我有了答案。
从那里我读到了
1. Keyword [...] It will only match with a complete word [...] 2. Match This is a match with a single regexp pattern. 3. Region This starts at a match of the "start" regexp pattern and ends with a match with the "end" regexp pattern. Any other text can appear in between. A "skip" regexp pattern can be used to avoid matching the "end" pattern.
由于我要更改的行使用语法 2.,
第 1 点不相关, 第 3 点。是相关的,因为通常syn match
和syn region
匹配之间可能存在重叠。
(顺便说一句,我验证了syn region
使用了惰性正则表达式,可能是\_.\-
之后查看了一些示例,以匹配start
和end
正则表达式模式之间的内容。)
然后来自:h :syn-priority
An item that starts in an earlier position has priority over items that start in later positions.
答案
因此,改变
syn match sedComment "^\s*#.*$"
到
syn match sedComment "\s*#.*$"
不应该引入任何语法错误,原因是如果匹配上述正则表达式的文本实际上不是注释(例如命令s/#/hash/
的情况),那么它必须被一些非注释语法放在之前,这些语法将被其他syn match
/syn region
组匹配。由于本场比赛在sedComment
组开始比赛之前开始,因此前者优先于后者。
总而言之,除非 sed.vim
已经出现问题,否则建议的更改不会导致语法着色错误。
进一步观察
其实sed.vim
中已经有问题了,我提议的编辑并没有解决(我应该编辑sed.vim
中的其他行来修复它,但我现在有点懒)。
例如,在下面的行中,这是非法的,因为a
不是有效标志,a
没有得到Error
着色。
s/x/y/a
我提议的修改没有解决这个错误。
出于同样的原因,由于某些其他语法规则在替换命令中的第三个分隔符后吃 1 个字符,因此以下命令中的 GNU-sed
-valid 注释颜色不正确
s/x/y/#hello
# │└───┴─── colored as Error
# └─ not colored
即使对于不允许尾随 cmets 的旧版本 sed
,着色也会出错,因为 Error
着色也应该包括 #
。
我提议的修改也没有解决这个错误。
再观察
我提出的更改会导致单字母命令被突出显示为Error
,如果它们后跟注释
p # this is a comment
│ └─────────────────┴─── colored as Comment (ok)
└────── colored as Error (bad)
这又不是恶化,因为当前的sed.vim
几乎将上面的整行都涂成了Error
。
【讨论】:
以上是关于对 Vim 的 sed 语法着色文件的这种更改是好的还是破坏性的?的主要内容,如果未能解决你的问题,请参考以下文章