正则表达式和字体锁定中未知数量的匹配项

时间:2011-05-25 06:34:48

标签: regex emacs elisp font-lock

我正在尝试使用font-lock和elisp的正则表达式突出显示如下内容:

class Foo implements A, B, C, D { }

问题是implements之后逗号分隔列表的未知长度。我已经完成了正则表达式,它突出显示了列表中的所有单词(使用re-buider,A,B,C和D突出显示):

"implements\\s-+\\(?:\\(\\sw+\\)\\s-*,\\s-*\\)*\\(\\sw+\\)"

但我无法将其与font-lock结合使用。

显然

'("implements\\s-+\\(?:\\(\\sw+\\)\\s-*,\\s-*\\)*\\(\\sw+\\)"
  (1 font-lock-type-face) (2 font-lock-type-face))

不起作用,因为它仅突出显示在第一次反向引用后忽略星号(*)的最后一次出现(C和D)。

有没有办法捕获所有匹配单词的列表,或者可能采用不同的方式来解决这个问题?

2 个答案:

答案 0 :(得分:2)

如果您不希望也突出显示逗号,则您的方法无效。当您使用表格的subexp-highlighter

(subexp facespec)

subexp指的是正则表达式的子组,并使用给定的facespec突出显示。现在,正则表达式匹配的子组是具有开始和结束的连续文本跨度。实际上,无论何时进行正则表达式搜索,都可以使用(match-beginning subexp)(match-end subexp)函数查询这些值。

但这意味着您无法匹配可变数量的类名,不包括逗号和单个子表达式,因为该子表达式必须是连续的跨度。覆盖不同数量的类名的连续跨度也必须始终包含逗号,没有办法解决这个问题。

这是为什么你的方法不是一个好主意的另一个原因:你的regexp显式使用空格。如果空白被排除在突出显示之外并不重要,但即使在正则表达式中使用它也不是一个好主意,因为只要允许空格,你总是可以遇到注释。

考虑以下代码行:

class Foo implements A, /*B, C,*/ D { }

在这种情况下,您希望使用/*B, C,*/以及font-lock-comment-face中的周围类突出显示范围font-lock-type-face中的字符。如果仅在其他所有内容都已突出显示之后突出显示注释,并允许注释覆盖其他字体锁定匹配,则仍可以实现此效果。但是这会导致相当低效的匹配,因为每个注释首先会被突出显示,就好像它是代码一样,然后在第二遍中突出显示为注释。

这两个问题的解决方案可能是将关键字(“implements”)和类的匹配分成两个不同的匹配规则,也许你可以将它作为起点:

'(("\\bimplements\\b" . font-lock-keyword-face)
  ("\\b[A-Z]\\w*\\b" . font-lock-type-face))

答案 1 :(得分:1)

这样的事情似乎在这里起作用:

'("\\(implements\\)\\s-+\\(\\(\\sw+\\s-*,\\s-*\\)*\\sw+\\)"
   (1 font-lock-warning-face)
   (2 font-lock-keyword-face))

(显然你可能想要不同的面孔......)