说明
尝试实现(弯路)
主题的直接转换
- 刚开始本以为是两者主题的格式不同,尝试转换后发现还是不能正常使用
- 结果发现两者的token根本不同,也就是分割代码每一部分的命名不同
monarch转换textmate
- 发现monaco使用的是自己设计的monarch来实现语法高亮,但是vscode使用的是textmate的格式
textmate是苹果的那种
- 于是想到如果实现一种转换逻辑,将textmate->monarch,那么monaco就可以使用vscode的主题了(因为token一样了)
- 当学完双方的逻辑后,研究了posix与pcre正则的转换,进行事件时,发现一个致命问题..monach无法实现后行断言(
(?<=})
),这就导致了普通的转换根本无法实现.(复杂的...可能有生之年系列吧)
最终解决方案
- 使用vscode-textmate代替原monarch
- 其实这个在开始研究的时候就有了,但是网上说因为不能直接调用c,所以使用wasm的效率比桌面端低,所以并没有有限考虑(有点自大了...)
- 最终性能这块,看到了
vscode-textmate
有benchmark
,测试了一波.发现除了js的解析比桌面端慢两倍,其他的甚至比桌面端快...有点费解了(不知道自己有没有研究错,如果有说的不对请拍砖)
jQuery v2.0.3
TOKENIZING 250971 lines using grammar source.js
Oniguruma: 550 ms., Onigasm: 381 ms. (1.4x faster)
Bootstrap CSS v3.1.1
TOKENIZING 127005 lines using grammar source.css
Oniguruma: 217 ms., Onigasm: 91 ms. (2.4x faster)
vscode.d.ts
TOKENIZING 264938 lines using grammar source.ts
Oniguruma: 356 ms., Onigasm: 191 ms. (1.9x faster)
JSON
TOKENIZING 103784 lines using grammar source.ts
Oniguruma: 312 ms., Onigasm: 185 ms. (1.7x faster)
Bootstrap CSS v3.1.1 minified
TOKENIZING 99967 lines using grammar source.css
Oniguruma: 231 ms., Onigasm: 167 ms. (1.4x faster)
jQuery v2.0.3 minified
TOKENIZING 83618 lines using grammar source.js
Oniguruma: 254 ms., Onigasm: 480 ms. (1.9x slower)
Bootstrap with multi-byte minified
TOKENIZING 116201 lines using grammar source.css
Oniguruma: 248 ms., Onigasm: 196 ms. (1.3x faster)
实现原理
- 这个方案是从monaco-tm中得来的,但是最终完善了主题使用,可以从vscode中无缝移植主题,完善了语言插件,可以从vscode无缝迁移tmLanguage的插件,并且支持语言点注入
- grammar是用来解析语法的,会在调用这个语言的时候,加载对应的语法文件
具体需要实现monaco.languages.EncodedTokensProvider
接口传给setTokensProvider
做参数setTokensProvider
代替了setMonarchTokensProvider
- configuration是用来配置一些折叠,括号,注释等东西...和原来的monaco一样
- theme就是用来请求加载主题的
因为语法的解析变成了vscode-textmate,所以不能使用传统的方式来加载主题,需要从Registry
中拿到ColorMap
然后定义给主题
使用
- ng下已经封装好了依赖包的使用,非ng框架也可以稍作修改使用
- 包地址cyia-ngx-common
- 引入模块
CyiaMonacoTextmateModule
,组件中通过依赖注入拿到CyiaMonacoTextmateService
服务
this.service.setMonaco(monaco);
this.service.init().then(async () => {
const themeList = await this.service.getThemeList();
this.themeList = themeList;
this.selectedTheme = themeList[1];
const name = await this.service.defineTheme(this.selectedTheme);
this.instance = monaco.editor.create(
this.containerElement?.nativeElement,
{
theme: name,
value: `let a=6;`,
language: this.selectedLanguage,
minimap: {
enabled: false,
},
automaticLayout: true,
}
);
});
//切换主题
async change(e) {
const name = await this.service.defineTheme(e);
monaco.editor.setTheme(name);
}
相关地址
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。