语法定义
版
Sublime Text 可以使用 .sublime-syntax 和 .tmLanguage 文件来进行语法高亮。本文档介绍了 .sublime-syntax 文件。
概述🔗
Sublime Syntax 文件是 YAML 文件,包含一个小标题,后面跟着一个上下文列表。每个上下文都有一个模式列表,描述了如何在该上下文中高亮显示文本,以及如何更改当前文本。
以下是一个用于高亮显示 C 语言的语法文件的小示例。
%YAML 1.2
---
name: C
file_extensions: [c, h]
scope: source.c
contexts:
main:
- match: \b(if|else|for|while)\b
scope: keyword.control.c
从本质上讲,语法定义将作用域(例如,keyword.control.c
)分配给文本区域。这些作用域由配色方案用于高亮显示文本。
此语法文件包含一个上下文 main
,它匹配单词 [if, else, for, while]
,并将它们分配给作用域 keyword.control.c
。上下文名称 main
是特殊的:每个语法都必须定义一个主上下文,因为它将在文件开头使用。
键 match
是一个正则表达式,支持来自 Oniguruma 正则表达式引擎 的功能。在上面的示例中,\b
用于确保只匹配单词边界,以确保诸如 elsewhere
之类的单词不被视为关键字。
请注意,由于 YAML 语法,.sublime-syntax 文件中不允许使用制表符。
头部🔗
头部区域中允许的键是
- name
这定义了在菜单中显示的语法名称。它是可选的,如果未使用,将从文件名推断出来。
- file_extensions
一个字符串列表,定义了应该使用此语法的文件扩展名。此处列出的扩展名将在某些操作系统上的文件对话框下拉菜单中显示。
如果文件没有基名,例如 .gitignore,则应指定包括前导
.
在内的整个文件名。
- hidden_file_extensions 4075
一个字符串列表,也定义了应该使用此语法的文件扩展名。这些扩展名不会在文件对话框中列出。
- first_line_match
当打开一个没有识别扩展名的文件时,将使用此正则表达式测试文件的首行内容,以查看是否应该应用此语法。
- scope
分配给文件中所有文本的默认作用域
- version 4075
一个整数,可以是
1
或2
,用于控制 向后兼容性。新的语法应该针对2
,因为它修复了作用域应用方式中的一些不一致。
- extends 4075
一个字符串,表示此语法应该继承的基语法。基语法必须使用其包路径指定,例如 Packages/JavaScript/JavaScript.sublime-syntax。有关语法继承的概述,请参见 继承。
- hidden
隐藏的语法定义不会在菜单中显示,但仍然可以由插件分配或由其他语法定义包含。
上下文🔗
对于大多数语言,您将需要多个上下文。例如,在 C 语言中,我们不希望字符串中间的 for
单词被高亮显示为关键字。以下是如何处理此问题的示例
%YAML 1.2
---
name: C
file_extensions: [c, h]
scope: source.c
contexts:
main:
- match: \b(if|else|for|while)\b
scope: keyword.control.c
- match: '"'
push: string
string:
- meta_scope: string.quoted.double.c
- match: \\.
scope: constant.character.escape.c
- match: '"'
pop: true
在主上下文中添加了第二个模式,该模式匹配双引号字符(注意,'"'
用于此,因为独立的引号将是 YAML 语法错误),并将一个新的上下文 string
推入上下文堆栈。这意味着文件其余部分将使用字符串上下文进行处理,而不是主上下文,直到字符串上下文从堆栈中弹出。
字符串上下文引入了新的键:meta_scope
。这将为所有文本分配 string.quoted.double.c
范围,只要 string
上下文在堆栈中。
在 Sublime Text 中编辑时,可以通过按下 Ctrl+Shift+P(Mac)或 Ctrl+Alt+Shift+P(Windows/Linux)来检查已应用于插入符号下文本的范围。
string
上下文有两个模式:第一个匹配反斜杠字符后跟任何其他字符,第二个匹配引号字符。请注意,最后一个模式指定了遇到未转义引号时的操作,字符串上下文将从上下文堆栈中弹出,返回到使用主上下文分配范围。
当上下文具有多个模式时,将找到最左边的模式。当多个模式在同一位置匹配时,将选择第一个定义的模式。
元模式🔗
- meta_scope
这将给定范围分配给此上下文中的所有文本,包括将上下文推入堆栈和从堆栈中弹出的模式。
- meta_content_scope
如上所述,但不适用于触发上下文的文本(例如,在上面的字符串示例中,内容范围不会应用于引号字符)。
- meta_include_prototype
用于阻止当前上下文自动包含
prototype
上下文。
- clear_scopes
此设置允许从当前堆栈中删除范围名称。它可以是整数,也可以是值
true
以删除所有范围名称。它在meta_scope
和meta_content_scope
之前应用。这通常仅在一种语法嵌入另一种语法时使用。
- meta_prepend 4075
布尔值,控制 继承 期间的上下文名称冲突解决。如果指定此值,则此上下文中的规则将插入到祖先语法定义中具有相同名称的上下文的任何现有规则之前。
- meta_append 4075
布尔值,控制 继承 期间的上下文名称冲突解决。如果指定此值,则此上下文中的规则将插入到祖先语法定义中具有相同名称的上下文的任何现有规则之后。
元模式必须在上下文中列出,在任何匹配或包含模式之前。
匹配模式🔗
匹配模式可以包含以下键
- match
用于匹配文本的 正则表达式。YAML 允许许多字符串在不加引号的情况下编写,这有助于使正则表达式更清晰,但重要的是要了解何时需要引用正则表达式。如果正则表达式包含字符
#
、:
、-
、{
、[
或>
,那么您可能需要引用它。正则表达式仅在一次运行时针对单行文本运行。
- scope
分配给匹配文本的范围。
- captures
数字到范围的映射,将范围分配给匹配正则表达式的捕获部分。请参阅下面的示例。
- push
要推入堆栈的上下文。这可以是单个上下文名称、上下文名称列表或内联匿名上下文。
- pop
从堆栈中弹出上下文。值
true
将弹出单个上下文。大于零的整数将弹出相应数量的上下文。
4050
4075pop
键可以与push
、set
、embed
和branch
结合使用。组合使用时,在执行其他操作之前,将从堆栈中弹出指定数量的上下文。对于push
、embed
和branch
操作,pop 将匹配视为前瞻,这意味着匹配将不会接收被弹出的上下文的meta_scope
。
- set
接受与 push 相同的参数,但会先弹出当前上下文,然后将给定的上下文推入堆栈。
任何匹配都将接收被弹出的上下文的
meta_scope
以及被推入的上下文的meta_scope
。
- embed 3153
接受要推入的单个上下文的名称。虽然类似于
push
,但它会在找到escape
模式后立即从任何数量的嵌套上下文中弹出。这使其成为将一种语法嵌入另一种语法的理想工具。- escape
如果使用
embed
,则需要此键,它是一个用于退出嵌入上下文的正则表达式。此模式中的任何反向引用都将引用match
正则表达式中的捕获组。
- embed_scope
分配给
match
之后和escape
之前匹配的所有文本的范围。概念上类似于meta_content_scope
。
- escape_captures
捕获组到范围名称的映射,用于
escape
模式。使用捕获组0
将范围应用于整个转义匹配。
- branch 4050
接受两个或多个上下文的名称,这些上下文按顺序尝试。如果遇到
fail
操作,文件的突出显示将从branch
发生的位置的字符重新开始,并将尝试下一个上下文。- branch_point
这是
branch
的唯一标识符,当匹配使用fail
操作时指定。
branch
操作允许处理语法结构的歧义,并允许处理跨越多行的结构。为了获得理想的性能,上下文应按其被接受的可能性顺序排列。注意:由于使用分支进行突出显示需要在每次更改文档时重新处理整个分支,因此突出显示引擎在发生
fail
时不会回溯超过 128 行。
- fail 4050
接受要回溯到的
branch_point
的名称,并重试下一个上下文。如果fail
操作指定了一个从未推入堆栈的branch_point
,或者已经从堆栈中弹出,它将不会有任何效果。
以下键控制排他性行为,每个匹配模式只能指定一个
push
<4075pop
set
3153embed
4050branch
4050fail
匹配示例🔗
将单个范围分配给整个匹配的基本匹配
- match: \w+
scope: variable.parameter.c++
将不同的范围分配给正则表达式捕获组
- match: ^\\s*(#)\\s*\\b(include)\\b
captures:
1: meta.preprocessor.c++
2: keyword.control.include.c++
推入名为 function-parameters
的另一个上下文
- match: \b\w+(?=\()
scope: entity.name.function.c++
push: function-parameters
从上下文弹出
- match: \)
scope: punctuation.section.parens.end.c++
pop: true
从当前上下文弹出并推入另一个上下文
- match: \}
scope: punctuation.section.block.end.c++
set: file-global
嵌入另一种语法
- match: (```)(js|javascript)
captures:
1: punctuation.section.code.begin.markdown
2: constant.other.markdown
embed: scope:source.js
embed_scope: meta.embedded.js.markdown
escape: ^```
escape_captures:
0: punctuation.section.code.end.markdown
使用 branch
尝试一种突出显示,并能够回退到另一种
expression:
- match: (?=\()
branch_point: open_parens
branch:
- paren_group
- arrow_function
paren_group:
- match: \(
scope: punctuation.section.parens.begin.js
push:
- include: expressions
- match: \)
scope: punctuation.section.parens.begin.js
set:
- match: =>
fail: open_parens
- match: (?=\S)
pop: 2
arrow_function:
- match: \(
scope: punctuation.section.parens.begin.js
push:
- match: \w+
scope: variable.parameter.js
- match: ','
scope: punctuation.separator.comma.js
- match: \)
scope: punctuation.section.parens.begin.js
set:
- match: =>
scope: storage.type.function.arrow.js
push: arrow_function_body
使用 pop
与其他操作
paragraph:
- match: '(```)(py|python)'
captures:
1: punctuation.definition.code.begin.md
2: constant.other.language-name.md
pop: 1
embed: scope:source.python
embed_scope: source.python.embedded
escape: ^```
escape_captures:
0: punctuation.definition.code.end.md
包含模式🔗
通常,将一个上下文的内容包含在另一个上下文内非常方便。例如,您可以定义几个不同的上下文来解析 C 语言,并且几乎所有上下文都可以包含注释。与其将相关的匹配模式复制到每个上下文,不如将它们包含进来
expr:
- include: comments
- match: \b[0-9]+\b
scope: constant.numeric.c
...
在这里,注释上下文定义的所有匹配模式和包含模式都将被拉入。它们将被插入到包含模式的位置,因此您仍然可以控制模式顺序。注释上下文定义的任何元模式都将被忽略。
包含外部原型🔗
当从另一个语法中包含一个上下文时,可能希望也包含该语法中任何适用的原型。默认情况下,包含模式不包含此类原型。如果在包含模式中添加了键值对 apply_prototype: true
,上下文没有指定 meta_include_prototype: false
并且另一个语法具有 prototype
上下文,那么这些模式也将被包含。
tags:
- include: scope:source.html.basic
apply_prototype: true
原型上下文🔗
对于诸如注释之类的元素,包含它们非常普遍,因此更简单的方法是在每个上下文中自动包含它们,而只列出例外情况。您可以通过创建一个名为 prototype
的上下文来实现这一点,它将自动包含在每个其他上下文的顶部,除非上下文包含 meta_include_prototype
键。例如
prototype:
- include: comments
string:
- meta_include_prototype: false
...
在 C 中,字符串内的 /*
不会开始注释,因此字符串上下文表示不应包含原型。
包含其他文件🔗
Sublime Syntax 文件支持一个语法定义包含另一个语法定义的概念。例如,HTML 可以包含嵌入式 JavaScript。以下是一个基本的 HTML 语法定义示例,它就是这样做的
scope: text.html
contexts:
main:
- match: <script>
push: Packages/JavaScript/JavaScript.sublime-syntax
with_prototype:
- match: (?=</script>)
pop: true
- match: '<'
scope: punctuation.definition.tag.begin
- match: '>'
scope: punctuation.definition.tag.end
请注意上面的第一个规则。它表明,当我们遇到一个 <script>
标签时,JavaScript.sublime-syntax 中的主要上下文应该被推送到上下文堆栈中。它还定义了另一个键,with_prototype
。它包含一个将被插入到 JavaScript.sublime-syntax 中定义的每个上下文中的模式列表。请注意,with_prototype
在概念上类似于 prototype
上下文,但是它将始终被插入到每个引用的上下文,而不管它们的 meta_include_prototype
键。
在这种情况下,插入的模式将在下一个文本是 </script>
标签时弹出当前上下文。请注意,它实际上并没有匹配 </script>
标签,它只是使用了一个前瞻断言,它在这里扮演着两个关键角色:它既允许 HTML 规则匹配结束标签,并按照正常方式突出显示它,又可以确保所有 JavaScript 上下文都被弹出。例如,上下文堆栈可能处于 JavaScript 字符串的中间,但是当遇到 </script>
时,JavaScript 字符串和主上下文都将被弹出。
请注意,虽然 Sublime Text 支持 .sublime-syntax 和 .tmLanguage 文件,但无法在 .sublime-syntax 文件中包含 .tmLanguage 文件。
另一个常见的情况是模板语言包含 HTML。以下是一个示例,这次使用 Jinja 的子集
scope: text.jinja
contexts:
main:
- match: ''
push: Packages/HTML/HTML.sublime-syntax
with_prototype:
- match: '{{'
push: expr
expr:
- match: '}}'
pop: true
- match: \b(if|else)\b
scope: keyword.control
这与 HTML 嵌入 JavaScript 的示例有很大不同,因为模板语言往往是从内到外操作:默认情况下,它需要充当 HTML,只在某些表达式上转义到底层的模板语言。
在上面的示例中,我们可以看到它默认情况下以 HTML 模式运行:主上下文包含一个始终匹配的模式,不消耗任何文本,只是包含 HTML 语法。
在包含 HTML 语法的地方,Jinja 语法指令 ({ { ... }}
) 通过 with_prototype
键包含进来,因此被注入到 HTML 语法(以及 JavaScript,通过传递性)中的每个上下文。
变量🔗
多个正则表达式经常会有一些共同的部分。为了避免重复输入,可以使用变量。
variables:
ident: '[A-Za-z_][A-Za-z_0-9]*'
contexts:
main:
- match: '\b{{ident}}\b'
scope: keyword.control
变量必须在 .sublime-syntax 文件的顶层定义,并在正则表达式中通过 {{varname}}
引用。变量本身可以包含其他变量。请注意,任何不匹配 {{[A-Za-z0-9_]+}}
的文本都不会被视为变量,因此正则表达式仍然可以包含字面量 {{
字符,例如。
继承🔗
在语法是另一种语法的轻微变体,并进行了一些添加或更改的情况下,继承是一个有用的工具。
继承语法时,使用 extends
键,其值为父语法的包路径。包路径将以 Packages/ 开头,并将包含包名称和语法文件名。例如
%YAML 1.2
---
name: C++
file_extensions: [cc, cpp]
scope: source.c++
extends: Packages/C++/C.sublime-syntax
使用继承的语法将继承其父语法的 variables
和 contexts
值。所有其他顶层键,例如 file_extensions
和 scope
不会被继承。
变量继承🔗
扩展语法时,variables
键将与父语法合并。具有相同名称的变量将覆盖以前的值。
变量替换是在所有变量值都实现之后执行的。因此,扩展语法可以更改父语法中的变量,并且父上下文中的所有变量使用都将使用覆盖的值。
上下文继承🔗
扩展语法中的上下文将是父语法中的上下文以及在 contexts
键下定义的所有上下文的组合。
具有相同名称的上下文将覆盖父语法中的上下文。要更改上下文名称重复时的行为,可以使用两种选项。这些元键必须在扩展语法中指定
- meta_prepend: true
— 扩展语法中的所有模式都将在父语法中的模式之前插入。- meta_append: true
— 扩展语法中的所有模式都将在父语法中的模式之后插入。
多重继承🔗
当语法源自两个其他语法的组合时,可以使用多重继承。这允许 extends
键成为指向两个或多个父语法的包路径列表。父语法将按从上到下的顺序处理,并且必须源自相同的基类。
默认语法中多重继承的两个示例是
Objective-C++: 扩展C++ 和 Objective-C,两者都扩展C
TSX: 扩展JSX 和 TypeScript,两者都扩展JavaScript
限制🔗
语法可以扩展本身扩展另一个语法的语法。除了所有语法必须共享相同的 版本 之外,没有对扩展施加任何强制限制。
选定示例🔗
括号平衡🔗
此示例突出显示了没有对应开括号的闭括号
name: C
scope: source.c
contexts:
main:
- match: \(
push: brackets
- match: \)
scope: invalid.illegal.stray-bracket-end
brackets:
- match: \)
pop: true
- include: main
顺序上下文🔗
此示例将重点介绍包含过多分号的 C 样式 for 语句
for_stmt:
- match: \(
set: for_stmt_expr1
for_stmt_expr1:
- match: ';'
set: for_stmt_expr2
- match: \)
pop: true
- include: expr
for_stmt_expr2:
- match: ';'
set: for_stmt_expr3
- match: \)
pop: true
- include: expr
for_stmt_expr3:
- match: \)
pop: true
- match: ';'
scope: invalid.illegal.stray-semi-colon
- include: expr
高级堆栈使用🔗
在 C 中,符号通常使用 typedef
关键字定义。为了使“转到定义”能够识别这些符号,这些符号应该具有 entity.name.type
范围。
这样做可能有点棘手,因为虽然 typedef 有时很简单,但它们也会变得相当复杂。
typedef int coordinate_t;
typedef struct
{
int x;
int y;
} point_t;
为了识别这些符号,在匹配 typedef 关键字后,将有两个上下文被推入堆栈:第一个将识别一个类型名称,然后弹出,而第二个将识别为该类型引入的名称。
main:
- match: \btypedef\b
scope: keyword.control.c
set: [typedef_after_typename, typename]
typename:
- match: \bstruct\b
set:
- match: '{'
set:
- match: '}'
pop: true
- match: \b[A-Za-z_][A-Za-z_0-9]*\b
pop: true
typedef_after_typename:
- match: \b[A-Za-z_][A-Za-z_0-9]*\b
scope: entity.name.type
pop: true
在上面的示例中,typename
是一个可重用的上下文,它将读取一个类型名称并在完成时从堆栈中弹出自身。它可以在任何需要使用类型的上下文中使用,例如在 typedef 中或作为函数参数。
The main
上下文使用一个匹配模式,该模式将两个上下文推入堆栈,其中列表中最右边的上下文成为堆栈中最顶层的上下文。一旦 typename
上下文弹出自身,typedef_after_typename
上下文将位于堆栈的顶部。
还要注意上面在 typename
上下文中为了简洁而使用匿名上下文。
PHP Heredocs🔗
此示例展示了如何在 PHP 中匹配 Heredocs。主上下文中的匹配模式捕获 heredoc 标识符,而 heredoc 上下文中的相应弹出模式使用 \1
符号引用此捕获的文本。
name: PHP
scope: source.php
contexts:
main:
- match: <<<([A-Za-z][A-Za-z0-9_]*)
push: heredoc
heredoc:
- meta_scope: string.unquoted.heredoc
- match: ^\1;
pop: true
测试🔗
在构建语法定义时,您可以定义一个语法测试文件来为您执行检查,而不是使用 show_scope_name
命令手动检查范围。
// SYNTAX TEST "Packages/C/C.sublime-syntax"
#pragma once
// <- source.c meta.preprocessor.c++
// <- keyword.control.import
// foo
// ^ source.c comment.line
// <- punctuation.definition.comment
/* foo */
// ^ source.c comment.block
// <- punctuation.definition.comment.begin
// ^ punctuation.definition.comment.end
#include "stdio.h"
// <- meta.preprocessor.include.c++
// ^ meta string punctuation.definition.string.begin
// ^ meta string punctuation.definition.string.end
int square(int x)
// <- storage.type
// ^ meta.function entity.name.function
// ^ storage.type
// @@@@@@ definition
{
printf("check %d\n", x);
// @@@@@@ reference
return x * x;
// ^^^^^^ keyword.control
}
"Hello, World! // not a comment";
// ^ string.quoted.double
// ^ string.quoted.double - comment
要创建一个,请遵循以下规则:
确保文件名以 syntax_test_ 开头。
确保该文件保存在 Packages 目录中的某个位置:与相应的 .sublime-syntax 文件并排是一个不错的选择。
确保文件的第一行以以下内容开头:
<comment_token> SYNTAX TEST "<syntax_file>"
。请注意,语法文件可以是 .sublime-syntax 或 .tmLanguage 文件。
满足上述条件后,运行 build
命令并选择语法测试或语法定义文件将运行所有语法测试,并在输出面板中显示结果。下一个结果 (F4) 可用于导航到第一个失败的测试。
语法测试文件中的每个测试必须首先启动注释标记(在第一行建立,它实际上不必根据语法是注释),然后是 ^
、<-
或 @
标记。
三种类型的测试是:
插入符:
^
这将测试以下选择器与最近的非测试行上的范围。它将在与^
相同的列中进行测试。连续的^
将测试每一列与选择器。箭头:
<-
这将测试以下选择器与最近的非测试行上的范围。它将在与注释字符相同的列中进行测试。At:
@
这将测试以下符号类型与最近的非测试行上的文本。符号类型必须是以下之一:none
:文本不是符号local-definition
: 文本是符号的定义,但未被索引global-definition
: 文本是符号的定义,并且被索引definition
: 文本是符号的定义,无论是否被索引reference
: 文本是对符号的引用
当存在这些测试之一时,文件中的所有符号都会被彻底检查。可以使用
partial-symbols
选项禁用此功能。
4087
测试选项可以在 SYNTAX TEST
后面直接指定,用空格隔开,可以是以下任何一项
partial-symbols
: 通常,当存在符号测试(@
)时,文件中的所有符号都必须被检查。此选项禁用此行为。
4087reindent-unchanged
: 将整个文件作为缩进规则的测试。检查在整个文件上运行 reindent 命令时,是否没有更改任何行。
4069reindent-unindented
: 将整个文件作为缩进规则的测试。检查如果所有行都被取消缩进,reindent 命令是否可以重现文件。
4069reindent
: 同时包含reindent-unchanged
和reindent-unintented
。
4069
兼容性🔗
当 Sublime Text 的语法高亮引擎需要进行会破坏现有语法的更改时,这些修改或错误修复将被放在 version
键后面。
目前存在两个版本:1 和 2。没有 version
键表示版本 1。
以下是版本 1 中保留的错误和行为列表,这些错误和行为在版本 2 中已修复或更改。此列表主要用于了解在更新语法版本时需要查找的内容。
embed_scope
与其他语法的scope
堆叠描述:
当嵌入另一个语法的
main
上下文时,embed_scope
将与另一个语法的scope
相结合。在版本 2 语法中,只有在未指定embed_scope
时,才会包含另一个语法的scope
。语法 1:
scope: source.lang contexts: paragraph: - match: \( scope: punctuation.section.group.begin embed: scope:source.other embed_scope: source.other.embedded escape: \) escape_captures: 0: punctuation.section.group.end
语法 2:
scope: source.other contexts: main: - match: '[a-zA-Z0-9_]+' scope: identifier
文本:
'abc'
结果:
文本
abc
在版本 1 语法中将获得范围source.other.embedded source.other identifier
。在版本 2 语法中,它将获得source.other.embedded identifier
。使用
set
和meta_content_scope
的匹配模式描述:
在对匹配项执行
set
操作时,匹配的文本将获得被弹出上下文的meta_content_scope
,即使pop
操作不会,而set
等效于pop
然后push
。语法:
scope: source.lang contexts: function: - meta_content_scope: meta.function - match: '[a-zA-Z0-9_]+' scope: variable.function - match: \( scope: punctuation.section.group.begin set: function-params function-params: - meta_scope: meta.function.params - match: \) scope: punctuation.section.group.end pop: true
文本:
abc()
结果:
文本
(
应该获得范围meta.function.params punctuation.section.group.begin
。但它却错误地获得了范围meta.function meta.function.params punctuation.section.group.begin
。使用
set
匹配模式,使用clear_scopes
匹配目标描述:
如果一个
set
操作的目标具有clear_scopes
值,则范围将无法正确清除。语法:
scope: source.lang contexts: main: - match: \bdef\b scope: keyword push: - function - function-name function: - meta_scope: meta.function function-name: - match: '[a-zA-Z0-9_]+' scope: variable.function - match: \( scope: punctuation.section.group.begin set: function-params function-params: - meta_scope: meta.function.params - clear_scopes: 1 - match: \) scope: punctuation.section.group.end pop: 2
文本:
def abc()
结果:
文本
(
应该获得范围meta.function.params punctuation.section.group.begin
。但它却错误地获得了范围meta.function meta.function.params punctuation.section.group.begin
。嵌入转义匹配和元范围
描述:
由
embed
操作的escape
模式匹配的文本将不会获得包含它的上下文的meta_scope
或meta_content_scope
。语法:
scope: source.lang contexts: context1: - meta_scope: meta.group - meta_content_scope: meta.content - match: \' scope: punctuation.begin embed: embed escape: \' escape_captures: 0: punctuation.end embed: - match: '[a-z]+' scope: word
文本:
'abc'
结果:
第二个
'
应该获得范围meta.group meta.content punctuation.end
。但它却错误地获得了范围punctuation.end
。具有
clear_scopes
的多个目标推送操作描述
如果一次推送多个上下文,并且多个上下文指定了
clear_scopes
,其值大于1
,则结果范围将不正确。语法:
scope: source.lang contexts: main: - meta_content_scope: meta.main - match: '[a-zA-Z0-9]+\b' scope: identifier push: - context2 - context3 context2: - meta_scope: meta.ctx2 - clear_scopes: 1 context3: - meta_scope: meta.ctx3 - clear_scopes: 1 - match: \n pop: true
文本:
abc 1
结果:
所有目标上下文的
clear_scopes
值将被加起来并应用,然后再应用任何目标的meta_scope
和meta_content_scope
。因此,文本abc
将被赋予范围meta.ctx2 meta.ctx3 identifier
,而不是正确的范围source.lang meta.ctx3 identifier
。正则表达式捕获组顺序
描述:
如果编号较低的捕获组匹配的文本出现在编号较高的捕获组匹配的文本之后,则编号较低的捕获组将不会应用其捕获范围。
语法:
scope: source.lang contexts: main: - match: '(?:(x)|(y))+' captures: 1: identifier.x 2: identifier.y
文本:
yx
结果
文本
y
由捕获组 2 匹配,文本x
由捕获组 1 匹配。x
将不会被赋予范围indentifier.x
,因为它出现在捕获组 2 的匹配之后。