Any application that can be written in JavaScript, will eventually be written in JavaScript. 任何可以用 JavaScript 来写的应用,最终都将用 JavaScript 来写
大部分人也许会认为 Monaco Editor 是从 VS Code 开源出来的库,也即先有 VS Code ,在此基础上抽离并开源了 Monaco Editor,而实际上正好相反,Monaco 的历史比 VS Code 更早一些。
VS Online 当时的代号是 Monaco,在新的 VS Online (2019 年,基于 VS Code Web 版本)短暂的运营了一段时间以后,目前已经改名叫做 GitHub Codespaces。
下图为现在的 GitHub Codespaces
-
行号
-
Overlay Widget,可以渲染任意的内容小部件,能选择放置在顶部、底部或编辑器中间。例如编辑器内的查找框即是一个 Overlay Widget
-
ViewLine,每一行都表示一个 ViewLine
-
Decorations 装饰块,可以指定某个位置的代码块以何种样式呈现,例如修改其背景色、前景色等
-
Content Widget,与 Overlay Widget 类似,但可以基于行、列指定其位置。例如自动补全的列表框就是一个 Content Widget
-
View Zone, 与 Overlay、Content Widget 不同,它可以插入到特定的行之间将其撑开。例如在上图中88行与89行之间的查找引用窗口
除了这些标配的部件之外,Monaco 还支持通过 Decorations API 来添加更多的装饰,例如版本控制中为修改过的行号添加一个色块,又或者在调试状态下显示断点信息等。
// Create your own language definition here
// You can safely look at other samples without losing modifications.
// Modifications are not saved on browser refresh/close though -- copy often!
return {
// Set defaultToken to invalid to see what you do not tokenize yet
// defaultToken: 'invalid',
keywords: [
'abstract', 'continue', 'for', 'new', 'switch', 'assert', 'goto', 'do',
'if', 'private', 'this', 'break', 'protected', 'throw', 'else', 'public',
'enum', 'return', 'catch', 'try', 'interface', 'static', 'class2',
'finally', 'const', 'super', 'while', 'true', 'false'
],
typeKeywords: [
'boolean', 'double', 'byte', 'int', 'short', 'char', 'void', 'long', 'float'
],
operators: [
'=', '>', '<', '!', '~', '?', ':', '==', '<=', '>=', '!=',
'&&', '||', '++', '--', '+', '-', '*', '/', '&', '|', '^', '%',
'<<', '>>', '>>>', '+=', '-=', '*=', '/=', '&=', '|=', '^=',
'%=', '<<=', '>>=', '>>>='
],
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
// C# style strings
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[/[a-z_$][\w$]*/, { cases: { '@typeKeywords': 'keyword',
'@keywords': 'keyword',
'@default': 'identifier' } }],
[/[A-Z][\w\$]*/, 'type.identifier' ], // to show class names nicely
// whitespace
{ include: '@whitespace' },
// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[/@symbols/, { cases: { '@operators': 'operator',
'@default' : '' } } ],
// @ annotations.
// As an example, we emit a debugging log message on these tokens.
// Note: message are supressed during the first load -- change some lines to see them.
[/@\s*[a-zA-Z_\$][\w\$]*/, { token: 'annotation', log: 'annotation token: $0' }],
// numbers
[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
[/0[xX][0-9a-fA-F]+/, 'number.hex'],
[/\d+/, 'number'],
// delimiter: after number because of .\d floats
[/[;,.]/, 'delimiter'],
// strings
[/"([^"\\]|\\.)*$/, 'string.invalid' ], // non-teminated string
[/"/, { token: 'string.quote', bracket: '@open', next: '@string' } ],
// characters
[/'[^\\']'/, 'string'],
[/(')(@escapes)(')/, ['string','string.escape','string']],
[/'/, 'string.invalid']
],
comment: [
[/[^\/*]+/, 'comment' ],
[/\/\*/, 'comment', '@push' ], // nested comment
["\\*/", 'comment', '@pop' ],
[/[\/*]/, 'comment' ]
],
string: [
[/[^\\"]+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/"/, { token: 'string.quote', bracket: '@close', next: '@pop' } ]
],
whitespace: [
[/[ \t\r\n]+/, 'white'],
[/\/\*/, 'comment', '@comment' ],
[/\/\/.*$/, 'comment'],
],
},
};
Monaco 默认的方案与 VS Code 不同,这主要是因为 Textmate 的方案依赖 Oniguruma 这款正则引擎,而在 WebAssembly 大热以后,VS Code 团队推出了 wasm 版本,这使得 Monaco 也可以使用与 VS Code 一致的高亮方案 (同时社区也早有人做了移植,可以参考 monaco-editor-textmate)。
对于高级的语言特性支持,Monaco 也提供了遵循 LSP 标准的 API,例如自动补全、鼠标悬停、查找引用、定义跳转等常见功能都可以通过注册语言服务器来实现,而 Monaco 本身自带了包括 TypeScirpt/JavaScript、CSS、HTML 的语言服务支持。
文章评论