背景
有时候我们在使用VS Code编辑一个文件时 会看到这样的效果
在上述的图片中,1720行和1721行之间,有一行不属于该文件本身内容的注释。这一效果能够方便开发者快速地理解代码,看到代码的提交人,时间,可能还会有备注。在复制内容时,这部分是不会被复制的。 这一交互的实现,是借助了monaco的代码信息指示器 CodeLens
,而其中的Git信息则是借助了VS code 插件 GitLens
。
本篇文章就来解析一下monaco中CodeLens
的使用,帮助大家实现一个更加优秀的WEB IDE。
代码信息指示器CodeLens
CodeLens的含义是代码信息指示器,是一种能够帮助开发者理解代码,并不存在于文章内容的辅助信息。不同于直接写到文件的代码注释(和之前讲解的Marker来帮助开发者理解代码含义),CodeLens它是不存在于文件内容中的,但它直接显示在编辑器的特定行内。并且在复制文件内容是,它不会被复制。这就是它区别于其他辅助信息,备注信息的特性。它的内容是和Maker一样都是来自于文件外,人为设置或利用插件获取。
CodeLens通常是以一行信息来表现。但它并不是真正的一行。同样它是作用于语言模型的,而不是直接在editor对象上直接添加。
下面就来从它是使用方面和API来对其详细地解析。
如何使用CodeLens
要使用codeLens,首先要使用 monaco.languages.registerCodeLensProvider(languageSelector: LanguageSelector, provider: CodeLensProvider): IDisposable
方法。
该方法是在monaco.languages
对象下, 需要输如两个参数,一个是语言选择器, 可以是语言字符串如javascript
,也可以是语言字符串 数组如['javascript', 'java','python']
第二参数是配置的CodeLens,叫做他的类型是 CodeLensProvider
CodeLensProvider
下有一个属性和二个方法。分别是
onDidChange
属性 codelens 事件改变
provideCodeLenses
函数 传入语言模型与token, 返回 CodeLensList
用于定义 codelens
resolveCodeLens
函数 codeLens 暂时不清楚啊,文档上也没写。
在CodeLensList
对象中,又有一个下级对象lenses
。lenses
下定义是这样
这里给出一个结构图
registerColorProvider
方法中 需要定义 provideCodeLenses
方法,provideCodeLenses
方法 需要用户返回 CodeLensList
对象,
CodeLensList
对象的内部是 lenses
。 lenses
内部包含range
与command
。 看起来很复杂,那让我们直接看一个例子吧。
var editor = monaco.editor.create(document.getElementById('container'), {
value: '{\n\t"dependencies": {\n\t\t\n\t}\n}\n',
language: 'json',
})
// 声明一个用于codeLens的 comand,点击codelens 弹窗提示。
var commandId = editor.addCommand(
0,
function() {
// services available in `ctx`
alert('It is Fizz Code')
},
'',
)
monaco.languages.registerCodeLensProvider('json', {
provideCodeLenses: function(model, token) {
return {
lenses: [
{
range: {
startLineNumber: 3,
startColumn: 111,
endLineNumber: 8,
endColumn: 10,
},
id: 'Fizz CodeLens',
command: {
id: commandId,
title: `在第3行添加拿我格子衫来
12
121`,
},
},
],
dispose: () => {},
}
},
resolveCodeLens: function(model, codeLens, token) {
return codeLens
},
})
从上面可以看到,在使用时,注意在registerCodeLensProvider
方法内定义provideCodeLenses
方法,返回一个lenses
数组。
在每一个lenses
中, 需要定义range(必填),可以定义id, command(非必填)。
看一下具体效果
具体效果
经过调试发现,在定义range
时,能够影响到codelens的 只有startLineNumber
属性。 其他的属性都影响不到codelens的位置。
出现codelens 的哪一行,无法聚焦,只可以点击codelens中的文字内容。codelens的内容无法多行。
完整代码
完整html代码
<!DOCTYPE html>
<html>
<head>
<title>Hello World Monaco Editor</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<h2>Hello World Monaco Editor</h2>
<button onclick="setValue()">设置Python内容</button>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<script src="./monaco-editor/package/min/vs/loader.js"></script>
<script src="./const.js"></script>
<script>
require.config({ paths: { vs: './monaco-editor/package/min/vs' } });
let editor
require(['vs/editor/editor.main'], function () {
editor = monaco.editor.create(document.getElementById('container'), {
value: oldVersion,
language: 'javascript'
});
var commandId = editor.addCommand(
0,
function () {
alert('It is Fizz Code')
},
'',
)
monaco.languages.registerCodeLensProvider(['javascript', 'python'], {
provideCodeLenses: function (model, token) {
return {
lenses: [
{
range: {
startLineNumber: 3,
startColumn: 111,
endLineNumber: 8,
endColumn: 13,
},
id: 'Fizz CodeLens',
command: {
id: commandId,
title: `在第3行添加拿我格子衫来
323
2323`,
},
},
],
dispose: () => { },
}
},
resolveCodeLens: function (model, codeLens, token) {
return codeLens
},
})
});
function setValue() {
// 第二种重新设置值
var currentModel = editor.getModel();
const model = monaco.editor.createModel(`
// 重新设置值
x = y = z = 1
print(x) #1
`, 'python');
editor.setModel(model);
model.onDidChangeContent(e => {
console.log(e)
});
if (currentModel) {
currentModel.dispose();
}
}
</script>
</body>
</html>
总结
今天我们又学到了一种在编辑器中 添加辅助备注信息的方式。不用于之前介绍的Mark,codelens是占用编辑器虚拟行,却不是文件内容。