正则表达式在查找中有效,但在 .sublime-syntax 文件中无效
Regex expression works in find, but not in .sublime-syntax file
我想突出显示 $( 和 $) 之间的任何内容。在 .sublime-syntax 文件中,我写:
%YAML 1.2
---
name: Metamath
file_extensions: mm
scope: source.mm
contexts:
main:
- match: $\([\w\W]*?$\)
scope: comment
在sublime中查找时匹配正确,在YAML文件中使用时匹配失败。
如有任何关于更好的方法的建议,我们将不胜感激。
您的根本问题是 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
上下文专门命名并按名称使用。有一个额外的条目匹配以 @
开头的任何单词并以不同方式突出显示它,但仅在评论内部。
通过这种方式,您可以在多种情况下应用评论规则,而不必重复(尽管在本例中这是人为设计的)。
当上下文中有多个规则时,例如在本例中,这样看起来会更清晰一些;对于类似于您的原始示例的内容,可以说匿名上下文更容易阅读,并且使事情更清晰、更独立。
我想突出显示 $( 和 $) 之间的任何内容。在 .sublime-syntax 文件中,我写:
%YAML 1.2
---
name: Metamath
file_extensions: mm
scope: source.mm
contexts:
main:
- match: $\([\w\W]*?$\)
scope: comment
在sublime中查找时匹配正确,在YAML文件中使用时匹配失败。
如有任何关于更好的方法的建议,我们将不胜感激。
您的根本问题是 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
上下文专门命名并按名称使用。有一个额外的条目匹配以 @
开头的任何单词并以不同方式突出显示它,但仅在评论内部。
通过这种方式,您可以在多种情况下应用评论规则,而不必重复(尽管在本例中这是人为设计的)。
当上下文中有多个规则时,例如在本例中,这样看起来会更清晰一些;对于类似于您的原始示例的内容,可以说匿名上下文更容易阅读,并且使事情更清晰、更独立。