MT官方博客
Always dream. Always explore.
MT官方博客

MT 语法文件开发文档

MT 语法文件 (.mtsx) 用于文本编辑器的语法高亮功能,其核心是通过正则表达式按一定规则进行匹配,并将匹配到的文本进行着色处理,因此你需要熟练掌握正则表达式才能进行编写。

在 MT2.11.0 版本为 .mts 后缀,由于会被系统识别成视频文件,后续版本改成 .mtsx

正则表达式写法

首先介绍下 MT 语法文件的正则表达式写法,主要有两种:

"正则表达式\\s+"
/正则表达式\s+/

第一种是把正则表达式写在双引号之间,与 Java 代码中字符串的写法完全一样,缺点是需要对\"等字符进行转义,因为在正则表达式中经常会用到\,转义会影响可读性,正常我们推荐第二种写法。

第二种是把正则表达式写在/之间,如果正则表达式中包含/,你需要把它写成\/,其它字符均无需转义。

"abc/def\\s\""
/abc\/def\s"/

你可以将多个子表达式使用+连接,子表达式可以不写在同一行,以下三个正则表达式是一样的:

/123456789/
"123" + /456789/
/132/
+ /456/
+ /789/

keywordsToRegex 函数

对于大多数语言,我们需要对该语言的关键字进行高亮,因此需要编写正则表达式对关键字进行匹配。例如一个语言包含关键字 ifelse,那么我们编写的正则表达式应该是/\b(if|else)\b/

但将关键字换成 movemove-wide,如果你编写的正则表达式是/\b(move|move-wide)\b/,那么你会发现这个正则表达式只能匹配到 move,永远无法匹配到 move-wide

为了正确匹配,你需要将它写成/\b(move-wide|move)\b/,但这样性能不是很好,更高效率的写法是/\b(move(-wide)?)\b/

再进一步优化下,写成/(?:\b(?:move(?:-wide)?)\b)/,其中最外层的括号是为了方便其作为一个子表达式连接其它子表达式。

这还只是仅有两个关键字的情况,如果有很多个关键字,那么情况会更加复杂,为了解决该问题,你可以使用 keywordsToRegex 函数,它自动帮你完成以上各个优化工作,并返回一个正则表达式。

keywordsToRegex(
     "while volatile void try true transient throws throw this"
     "synchronized switch super strictfp static short return"
     "public protected private package null new native long"
     "interface int instanceof import implements if goto for"
     "float finally final false extends enum else double do"
     "default continue const class char catch case byte break"
     "boolean assert abstract"
 )

该函数输入参数为一个或多个字符串,每个字符串内的关键字用空格隔开,字符串之间直接换行,无需使用+连接

因为 keywordsToRegex 函数返回的是一个正则表达式,所以你可以把它当作一个子表达式去连接其它表达式,十分方便。

/(?m)^[ \t]*/ + keywordsToRegex("if else")

文件结构一览

// 注释内容
{
    name: ["语法名称", ".后缀名1", ".后缀名2"]
    hide: false
    ignoreCase: false
    colors: [
        "颜色名称", #RRGGBB, #RRGGBB
        "颜色名称" > "已有的颜色名称"
    ]
    comment: {startsWith: "/*", endsWith: "*/"}
    lineBackground: {match: /正则表达式/, color: "颜色名称"}
    contains: [
        {match: /正则表达式/, 0: "颜色名称"}
        {
            start: {match: /正则表达式/}
            end: {match: /正则表达式/}
            color: "颜色名称"
            contains: [
                ......
            ]
        }
        {builtin: #内置的匹配器#}
    ]
    codeFormatter: #内置的代码格式化器#
    codeShrinker: #内置的代码压缩器#
}

属性:name

name: ["语法名称", ".后缀名1", ".后缀名2"…]

指定语法名称与文件后缀,第一个字符串为语法名称,第二个开始均为后缀名,后缀名可以有多个。

属性:hide

hide: true | false

设置是否隐藏,隐藏后在文本编辑器中手动选择语法时将无法看到该语法,默认为 false。

属性:ignoreCase

ignoreCase: true | false

设置是否不区分大小写,设置为 true 后,所有正则表达式在匹配时均不会区分大小写,默认为 false。

如果只是想要部分正则表达式不区分大小写,可使用 i 标志,如/(?i)[a-z]+/

属性:colors

colors: [
    "颜色名称", #RRGGBB, #RRGGBB
    "颜色名称" > "已有的颜色名称"
]

自定义颜色,有两种格式。

一种是直接定义颜色值,包含日间模式和夜间模式的颜色。

另一种是使用已有的颜色,相当于给已有颜色取个别名。

内置的颜色可在 MT.apk/assets/syntax/init/colors.mtsx 文件中找到,包含以下内容:(未来可能发生改动,请以安装包内文件为准)

"default"       #000000     #A9B7C6 
"string"        #067D17     #6A8759 
"strEscape"     #0037A6     #CC7832 
"comment"       #8C8C8C     #808080 
"meta"          #9E880D     #BBB529 
"number"        #1750EB     #6897BB 
"keyword"       #0033B3     #CC7832 
"keyword2"      #800000     #AE8ABE 
"constant"      #871094     #9876AA 
"type"          #808000     #808000 
"label"         #7050E0     #6080B0 
"variable"      #1750EB     #58908A 
"operator"      #205060     #508090 
"propKey"       #083080     #CC7832 
"propVal"       #067D17     #6A8759 
"tagName"       #0030B3     #E8BF6A 
"attrName"      #174AD4     #BABABA 
"namespace"     #871094     #9876AA 
"error"         #F50000     #BC3F3C 

属性:comment

// 行注释
comment: {startsWith: "//"}
// 块注释
comment: {startsWith: "/*", endsWith: "*/"}

定义注释,支持行注释与块注释。

定义注释之后,语法引擎会自动添加正则表达式对注释内容进行高亮,您无需额外配置,并且可同时开启该语法的注释切换功能,当存在多个注释配置时,注释切换功能将优先使用第一个行注释。

默认在切换为注释时,注释符号与代码内容之间会增加一个空格,如果不希望增加空格,可配置insertSpace选项。

comment: {startsWith: "//", insertSpace: false}
原内容
abc
切换注释(insertSpace: true)
// abc
切换注释(insertSpace: false)
//abc

另外如果你仅仅只想开启注释切换功能,不希望语法引擎自动添加正则表达式对注释内容进行高亮,可添加addToContains选项。

comment: {startsWith: "//", insertSpace: false, addToContains: false}

注意,startsWithendsWithinsertSpaceaddToContains这四个选项的先后顺序不能变,也就是说addToContains不能放在insertSpace的前面。

属性:lineBackground

lineBackground: {match: /正则表达式/, color: "颜色名称"}

如果正则表达式可以完全匹配某一行的文本内容,则为该行添加背景颜色。

例如Smali语法中会对.method所在行进行高亮:

// 注意:这里的 methodHeader 不是内置颜色,需单独定义
lineBackground: {match: /[\t ]*\.method .*/, color: "methodHeader"}
https://blog.mt2.cn/wp-content/uploads/2022/04/lineBackgroundSmali.jpg

属性:contains

contains: [
    {match: /正则表达式/, 0: "颜色名称"}
    {
        start: {match: /正则表达式/}
        end: {match: /正则表达式/}
        color: "颜色名称"
        contains: [
            ......
        ]
    }
    {builtin: #内置的匹配器#}
]

如果你看到这里已经忘了上文的正则表达式写法,建议再看一遍。

contains内包含着多个匹配器,匹配器是语法文件的核心,有三种类型:

  • match 匹配器
  • startEnd 匹配器
  • builtin 匹配器

match 匹配器

{match: /正则表达式/, <捕获组序号>: "颜色名称"}

match 匹配器使用指定的正则表达式进行匹配,一旦匹配成功,会根据匹配组的颜色对文本进行着色,如果要对整个匹配到的文本进行着色,则对应的捕获组序号为 0,具体请参考以下例子:

{match: /[a-z]+\d+[a-z]+/, 0: "string"}

abc123456def
{match: /[a-z]+\d+([a-z]+)/, 1: "string"}

abc123456def
{match: /([a-z]+)(\d+)([a-z]+)/, 1: "string", 2: "error", 3: "meta"}

abc123456def

如果同时使用捕获组序列号 0 与其它序列号,则序列号 0 对应的颜色相当于整个匹配文本段的默认颜色。

{match: /([a-z]+)(\d+)([a-z]+)/, 0: "string", 2: "error"}

abc123456def // abc与def使用默认颜色进行着色

startEnd 匹配器

{
    start: 起点的匹配器
    end: 终点的匹配器
    color: "默认颜色名称,可空"
    contains: [
        子匹配器1
        子匹配器2
        ......
    ]
}

startEnd 匹配器是比较高级的用法,其匹配算法是首先使用起点匹配器进行匹配,一旦匹配成功,将不断使用终点匹配器与子匹配器进行匹配,其中子匹配器可能匹配多次,而一旦终点匹配器匹配成功,或者到达文字末尾,将结束匹配。

以字符串为例,字符串开头是一个",结尾也是一个",那么就可以这么写:

{
    start: {match: /"/}
    end: {match: /"/}
    color: "string"
}

高亮结果如下:

"abcdefg"
"abcd\"efg"

可以看到第二个字符串没有识别出转义符,导致高亮有误,此时我们就需要子匹配器去和终点匹配器竞争。

{
    start: {match: /"/}
    end: {match: /"/}
    color: "string"
    contains: [
        {match: /\\./}
    ]
}

这样就可以正确匹配了,我们来分析一下:

" a b c d \ " e f g "
0 1 2 3 4 5 6 7 8 9 10  >> 字符位置参照

终点匹配器第一次搜索到的是",其位置是 6,子匹配器第一次搜索到的是\",其位置是 5,而 56 前面,因此高亮引擎会优先选择子匹配器的搜索结果,并从位置 7 重新开始下一轮匹配,直到完成终点匹配器的匹配。这个算法的核心在于终点匹配器会和子匹配器同步搜索,谁的搜索结果在前就使用谁。

startEnd 匹配器的强大之处在于起点匹配器、终点匹配器、子匹配器都是可以单独控制着色的,嵌套使用后可以处理非常复杂的情况。

{
    start: {match: /<(\w+)/, 1: "error"}
    end: {match: /(\w+)>/, 1: "error"}
    contains: [
        {match: /\d+/, 0: "number"}
        {match: /\w+/, 0: "meta"}
    ]
}

高亮结果如下:

123 abc <aaa abc 123 abc 123 bbb> abc 123

可以看到只有范围内的 abc123 会被高亮。

builtin 匹配器

{builtin: #内置的匹配器#}

builtin 匹配器可以直接调用 MT 内置的匹配器,包含一些常用的规则,如匹配字符串、匹配数字,拿来即用十分方便。

内置的匹配器包含:

//
// 普通字符串
//

// 匹配转义符号,仅包含\x
#ESCAPED_CHAR#

// 单引号字符串
#SINGLE_QUOTED_STRING#

// 双引号字符串
#DOUBLE_QUOTED_STRING#

// 单双引号字符串
#QUOTED_STRING#

//
// Java字符串
//

// 匹配Java转义符号,包含 \b \t \n \f \r \" \' \\ \000 \u0000,匹配失败时会进行红色标记
#JAVA_ESCAPED_CHAR#

// Java单引号字符串
#JAVA_SINGLE_QUOTED_STRING#

// Java双引号字符串
#JAVA_DOUBLE_QUOTED_STRING#

// Java单双引号字符串
#JAVA_QUOTED_STRING#

//
// C字符串
//

// 匹配C转义符号,包含 \b \t \n \f \r \x \" \' \\ \000 \u0000,匹配失败时会进行红色标记
#C_ESCAPED_CHAR#

// C单引号字符串
#C_SINGLE_QUOTED_STRING#

// C双引号字符串
#C_DOUBLE_QUOTED_STRING#

// C单双引号字符串
#C_QUOTED_STRING#

//
// 数字相关
//

// 匹配数字,支持整数与小数
#NORMAL_NUMBER#

// 编程语言数字,大多数语言适用,支持二进制、八进制、十进制、十六进制、小数、科学计数
#PROGRAM_NUMBER#

// 编程语言数字,与上面比取消了二进制支持,支持八进制、十进制、十六进制、小数、科学计数
#PROGRAM_NUMBER2#

// Java数字,与#PROGRAM_NUMBER#相比增加了FL后缀,C语言同样适用
#JAVA_NUMBER#

查看最新内置匹配器列表以及其具体规则请查看MT.apk/assets/syntax/init/builtins.mtsx 文件。

属性:codeFormatter

codeFormatter: #内置的代码格式化器#

指定该语法的代码格式化器,设置后可以在文本编辑器中使用代码格式化功能。

目前仅支持指定内置的代码格式化器,不支持自定义,具体包含 CSS、HTML、JavaScript、JSON、XML 代码格式化器,分别对应:

#BUILT_IN_CSS_FORMATTER#
#BUILT_IN_HTML_FORMATTER#
#BUILT_IN_JS_FORMATTER#
#BUILT_IN_JSON_FORMATTER#
#BUILT_IN_XML_FORMATTER#

属性:codeShrinker

codeShrinker: #内置的代码压缩器#

指定该语法的代码压缩器,设置后可以在文本编辑器中使用代码压缩功能。

目前仅支持指定内置的代码压缩器,不支持自定义,具体包含 CSS、HTML、JSON 代码格式化器,分别对应:

#BUILT_IN_CSS_SHRINKER#
#BUILT_IN_HTML_SHRINKER#
#BUILT_IN_JSON_SHRINKER#

安装语法高亮文件

将写好的语法规则保存为 .mtsx 文件,在 MT 管理器内打开它即可安装。

没有标签
首页      默认分类      MT 语法文件开发文档

MT官方博客

MT 语法文件开发文档
MT 语法文件 (.mtsx) 用于文本编辑器的语法高亮功能,其核心是通过正则表达式按一定规则进行匹配,并将匹配到的文本进行着色处理,因此你需要熟练掌握正则表达式才能进行编写。 在 MT2…
扫描二维码继续阅读
2022-05-01