我想突出显示$(和$)之间的任何内容。在.sublime语法文件中,我写:
%YAML 1.2
---
name: Metamath
file_extensions: mm
scope: source.mm
contexts:
main:
- match: \$\([\w\W]*?\$\)
scope: comment
当我在sublime中的find中使用它时,它正确匹配,但是在YAML文件中使用时失败。
任何有关更好的方法的建议都将受到赞赏。
答案 0 :(得分:2)
您的潜在问题是Sublime语法高亮显示是逐行进行的,因此需要跨多行匹配的任何正则表达式都不会匹配任何东西,因为它永远不会获得足够的输入。为了执行这种匹配,您需要使用context stack
逐行跟踪状态。
syntax documentation提供了有关该主题的更多信息,但是从本质上讲,您的想法是针对特定情况临时替换(push
到上下文堆栈中)一套新的语法规则,从而接管了语法高亮显示,直到有pop
删除这些规则并返回到之前发生的情况为止。
也许可以通过对问题语法的示例修改来最好地证明这一点:
%YAML 1.2
---
name: Metamath
file_extensions: mm
scope: source.mm
contexts:
main:
- match: \$\(
scope: punctuation.definition.comment.begin
push:
- meta_scope: comment
- match: \$\)
scope: punctuation.definition.comment.end
pop: true
这里main
上下文(所有语法匹配开始)中的单个规则仅对匹配序列\$\(
感兴趣,因此,除此以外的任何文本都将被忽略,最终成为纯文本
匹配$(
时,会发生一些事情。首先,为它分配了范围punctuation.definition.comment.begin
,以将其标记为注释开始序列。其次,它使用假设它们在注释内的规则将匿名上下文推入上下文堆栈。
尽管此上下文在堆栈上处于活动状态,但是仅适用的match
规则是该上下文中的那些规则,它们与\$\)
匹配,除此之外没有其他内容。任何不是该标记的文本都将被忽略,但是当看到该标记时,将为其分配一个范围,将其标记为注释的结尾,然后pop
从堆栈中删除此匿名上下文,以进行处理回到评论开始之前的规则(此处仅与其他评论匹配)
meta_scope
说,尽管此上下文位于堆栈的顶部,但除可能具有的其他范围外,还应为所有文本指定范围comment
。这也适用于导致推送此上下文的文本($(
)以及导致弹出该上下文的文本($)
)。
结果是,所有从$(
开始到$)
结束的内容(包括那些标记)都标记为comment
,而开始标记和结束标记也被分配了范围,以指示他们开始发表评论(并非严格要求,但形式尚好)。
您还可以使用专门命名的context
项,而不是使用匿名上下文(如此处所示);通常,对于可能需要多个地方的规则或只有许多规则要匹配的情况,这是一个更好的解决方案。
%YAML 1.2
---
name: Metamath
file_extensions: mm
scope: source.mm
contexts:
main:
- match: \$\(
scope: punctuation.definition.comment.begin
push: comment_rules
comment_rules:
- meta_scope: comment
- match: \@\w*
scope: keyword.other
- match: \$\)
scope: punctuation.definition.comment.end
pop: true
该示例与第一个示例几乎相同,但是现在comment_rules
上下文已被专门命名并按名称使用。有一个额外的条目可以匹配以@
开头的任何单词,并以不同的方式突出显示该单词,但仅在注释内部。
通过这种方式,您可以在多种情况下应用注释规则而无需重复操作(尽管在此示例中确实可以做到)。
当上下文中有多个规则(例如本例)时,这看起来会更清晰一些;对于像您原始示例这样的内容,可以说匿名上下文更易于阅读,并使事情更清晰,更独立。