MT管理器语法文件强化语法, 主要作用就是可以自动展开regexp include定义中的颜色组
例如如下代码
{
name: ["TEST", ".test"],
hide: false,
defines: [
//!includeBegin
string-escape = /\\(?:[nrt'"\\]|(.))/
$0: "strEscape"
$1: "error"
string = /"(?:[^"\\]|/ @string-escape /)*"/
string-def := @string
$recordAllGroups: true
$0: "string"
r-string-def := /r/ @string
$recordAllGroups: true
$0: "keyword2"
num = /\b\d+\b/
$0: "number"
value-def := {
::string-def
::r-string-def
: @num
}
//!includeEnd
]
contains: [
{include: "value-def"}
]
}
将被编译为
{
name: ["TEST", ".test"],
hide: false,
defines: [
// Generated by mtsyntax-plus begin
"string-escape": /(\\(?:[nrt'"\\]|(.)))/
"string": /"(?:[^"\\]|/ + include("string-escape") + /)*"/
"string-def": {
match: /(/ + include("string") + /)/
recordAllGroups: true
1: "string"
2: "strEscape"
3: "error"
}
"r-string-def": {
match: /(r/ + include("string") + /)/
recordAllGroups: true
1: "keyword2"
2: "strEscape"
3: "error"
}
"num": /(\b\d+\b)/
"value-def": [
{include: "string-def"}
{include: "r-string-def"}
{
match: include("num")
1: "number"
}
]
// Generated by mtsyntax-plus end
]
contains: [
{include: "value-def"}
]
}
该程序将处理由独占单行的注释 //!includeBegin 直至 //!includeEnd 间的内容
// 表示注释
使用=来定义正则, 使用:=来定义匹配器, 使用:= { ... }来定义匹配器组
匹配器定义由若干匹配组成, 尾随一系列属性定义, 与颜色定义
或一个匹配器组定义
表示基本的匹配单元, 可使用的匹配如下:
-
普通的正则, 如
/[a-z]+/,"[a-z]+",([0-9]+)[a-z]*, 该方法参与本地组计数 -
使用
@name来引用内部定义的正则, 会展开定义正则时附带的颜色组, 该方法不参与本地组计数 -
使用
&name(count)来引入外部定义的正则, 这种方法不会展开定义正则时附带的颜色组- 当
(count)被省略时, 默认该正则不含捕获组 - 当
count为一个数字时, 手动指定含有多少个捕获组 - 当
count为@时, 将在内部定义的正则中查找捕获组数量, 通常用于覆盖定义正则时附带的颜色组
该方法参与本地组计数
- 当
-
使用
include(name, count),, count可省略, 类似&name(count), 但是count只能为一个数字, 用于方便迁移的语法 -
使用
(,(?:,|,),)*,)+,){1,2},)+?,){1,2}?, 此种方法用于快速表示常用正则操作符, 例如(表示/(/,|表示/|/, 该方法参与本地组计数 -
使用
($color定义一个内联颜色组, 表示/(/但是不参与本地组计数, 展开时会生成如1: "color"的颜色 -
使用
keywordsToRegex("...")来定义一系列关键字, 就像在MT语法文件中直接编写那样, 没有多大区别, 参与本地组计数
每个匹配通过可选的加号连接, 如 @foo + @bar 和 @foo @bar 是等价的
在匹配器组 := { ... } 中, 可以编写如下语法:
- 使用
:表示创建一个匹配器, 后面尾随一个匹配器 - 使用
::表示引用一个匹配器, 后面尾随匹配器名称, 相当于{include: "..."} - 直接定义匹配器, 而无需使用
:, 该种用法只能写一个匹配器 - 使用
{...}表示里面的内容不做任何处理, 直接输出, 用于插入其它匹配器, 例如这个
定义本地捕获组的颜色, 当该捕获组成功匹配将会使用该颜色对其上色
例如:
foo := /"([^"]*)"/
$0: "string"
$1: "keyword"
将生成出如下内容
"foo": {
match: /("([^"]*)")/
1: "string"
2: "keyword"
}
表示将整个匹配结果染色为 "string", 将引号中内容染色为 "keyword"
该颜色可以使用 parseColor(...) 或匹配器组, 例如:
foo := /[0-9a-f]{6}/
$0: parseColor(auto,0,HEX,error)
$0: {/[a-f]/ $0: propKey}
将生成出如下内容:
"foo": {
match: /([0-9a-f]{6})/
1: "parseColor(auto,1,HEX,error)"
1: {
match: /([a-f])/
1: "propKey"
}
}
定义匹配器的属性, 也就是非颜色组的其它属性
例如将之前的例子改变一下:
foo := /"([^"])*"/
$recordAllGroups: true
$0: "string"
$1: "keyword"
将生成出如下内容
"foo": {
match: /("([^"])*")/
recordAllGroups: true
1: "string"
2: "keyword"
}
当你使用参与本地组计数的匹配时, 你可以在当前的正则或匹配器中直接引用局部的捕获组编号
例如@foo不参与本地组计数, 而普通的正则匹配参与本地组计数:
foo = /(b)/
bar := /(a)/ @foo /(c)/
$1: "string"
$2: "string"
将生成出如下内容
"foo": /(b)/
"bar": {
match: /(a)/ + include("foo") + /(c)/
1: "string"
3: "string"
}
由于 @foo 不参与本地组计数, 而 /(a)/ 和 /(b)/ 参与本地组计数,
所以对于颜色组编号来说, 不参与本地组计数的 @foo 中的颜色组是 "不存在的"
所以 $2 表示的 "第二个颜色组" 就是 /(c)/,
而不是 @foo 内部 "不存在的" 颜色组
模板, 用于处理批量的重复语法
模板可以应用在匹配器、匹配器组或正则定义上, 应用时将被应用的一系列匹配传入模板, 模板可以将传入的一系列匹配在某处展开
模板可以定义一系列颜色及属性(属性仅支持匹配器模板), 将在应用时与被应用的颜色组及属性进行合并
例如:
[[grouped]] := /(\{)/ [[]] /(\})/
$1: "keyword"
$2: "keyword"
[[grouped]]
foo := /(foo): (\d+)/
$1: "meta"
$2: "number"
将生成出如下内容
"foo": {
match: /(\{)(foo): (\d+)(\})/
1: "keyword"
2: "meta"
3: "number"
4: "keyword"
}
上述例子中, [[grouped]] := 是定义一个匹配器模板, 可以应用在匹配器上,
而模板中的 [[]] 则是表示被应用的一系列匹配在何处展开
如果使用 = 而不是 := 的话将定义一个正则模板,
与匹配器模板区别在于无法包含属性且只能应用在正则上
[[foo]] := /./ [[]]
// 匹配器组上的属性将应用到内部每一个匹配器, 例如
[[foo]]
all := {
: /a/
: /b/
}
// 类似于
all1 := {
[[foo]]
: /a/
[[foo]]
: /b/
}
如果应用多个模板, 例如 [[foo]] [[bar]] x := /x/, 将会先应用 bar,
然后应用结束后在 bar 的输出上应用 foo
你可以从 Releases 下载已经编译好的成品进行使用, 又或者你可以手动编译, 如下:
在拥有rust编译环境的情况下, 在项目目录下输入
cargo run
即可编译并运行, 要处理的文件从标准输入重定向给程序, 结果会输出到标准输出
如果使用vim编辑MT语法文件的话, 可以使用该MT高亮进行高亮等