我终于回到了我想要添加到YI的GitCommit消息模式,但我似乎错过了一些基本的东西。我似乎无法匹配语法中的单个字符,所有规则只有在匹配整行时才有效。我知道这必须是可能的,因为YI中的其他语法显然会这样做,但做同样的事情似乎不起作用。
我希望有一个提交模式,最终看起来与vim中的提交模式非常相似。在vim模式中有用的一点是关键字突出显示内部注释。 Git在其所做的大部分工作(提交,rebase等)中都会在注释中放入一堆信息,因此这很有用。我的想法是匹配git注释中的起始'#'字符,并切换到匹配关键字的不同上下文。但是我似乎无法制定匹配只是'#'的规则,规则会在仅包含'#'的行上切换为注释样式但在行上在'#'之后包含任何内容,它不会切换样式。
我现在拥有的是:
<0> {
\# { m (const $ LineComment) Style.commentStyle }
$commitChars*$ { c Style.defaultStyle }
}
<lineComment> {
$nl { m (const Digest) Style.defaultStyle }
· { c Style.regexStyle }
}
明显省略了细节。我们的想法是当我们看到'#'并以不同的方式设置不同的样式时切换到'lineComment'模式,直到我们看到该行的结尾。根据文档和示例,应该有一种方法来做我想要的。我已经尝试了几乎所有我能想到的'#'模式的排列,但没有改变我所看到的行为。
我错过了什么明显的事情?
编辑:
上面的代码来自我的YI分支中的实现。我有一个独立的解析器,它表现出同样的问题here。如果您运行alex GitCommit.x && ghc --make GitCommit.hs && ./GitCommit < shortmsg
,您会看到评论行的内容已解析为MessageLine
,并且空注释行已正确标记为CommentStart
。
答案 0 :(得分:1)
好的,我终于弄明白了。看起来Alex总是接受最长的比赛,而不是第一场比赛。匹配提交行的规则将始终更长,因为它匹配整行。这导致Alex总是在评论分支上选择该分支。引自Alex docs
When the input stream matches more than one rule, the rule which matches the longest prefix of the input stream wins. If there are still several rules which match an equal number of characters, then the rule which appears earliest in the file wins.
我想我应该不止一次阅读过这些文档。解决方案是从$commitChars
字符集中删除“#”。