前言
在编辑器中有很多交互,其中一种交互就是当鼠标放到一个class上,显示该类的定义,该类的行数,注释,这在monaco中很常见,有时这个class并不是在当前文件定义的,而是在其他未打开的文件中定义的。
如下图
鼠标放到insertSpaces 上,会显示该属性的上传路径,类型定义,以及备注。
上面这个是一个使用自定义Marker设置的分词备注。
对于一个较大的项目来说,在使用类,方法,参数时,这些注释能够极大地帮助开发者,排查错误,准确调用方法,参数定义。
这种分词注释的适用场景有很多,其中一个场景时,在系统中定义一些环境变量,在编辑文件时使用这些变量,但后来的开发者可能不理解这些变量的含义,用处,这个时候如果鼠标放到变量上,显示该变量的定义,用处,等一些重要注释,将会非常有助于开发者。
下面我们就来介绍一下在monaco编辑器中如何使用Marker来制作一些自定义的标记,注释。以此来提升用户的使用体验。
Marker
为了让大家对Marker功能有一个比较清晰的认识,想让大家来看一下使用Marker实现的几个效果。
当我们使用Position给global单词添加了marker后,
当光标移动到global上,会显示该单词的Marker信息。点击View Problem会显示更多的详细信息。
Marker实现的大致效果就是以上介绍的,其中的一些交互的细节都是由Marker的参数控制的,那么下面我们从文档定义上来看看Marker具体有哪些参数,有什么用处。
在monaco的类型定义文件 monaco.d.ts
中 marker是这定义的
export interface IMarker {
owner: string;
resource: Uri;
severity: MarkerSeverity;
code?: string | {
value: string;
target: Uri;
};
message: string;
source?: string;
startLineNumber: number;
startColumn: number;
endLineNumber: number;
endColumn: number;
relatedInformation?: IRelatedInformation[];
tags?: MarkerTag[];
}
- owner: 所属人,可以用于搜索marker
- resource: 相关资源的链接,如果是指了可以在marker中,点击链接直接跳转。
- severity: marker的信息等级,有四大类(MarkerSeverity的枚举值): Hint,Info,Warning,Error
- code:相关的代码,可以是参数的定义,函数的定义
- message:marker的主要信息,会直接显示在marker上
- source:代码的源头,与code搭配使用,可以表面该分词来源于那个文件,那个对象
- startLineNumber:markder的开始行
- startColumn:markder的开始列
- endLineNumber: markder的结束行
- endColumn:markder的结束列
- relatedInformation:相关信息,可以是多个
- tags:markder的标签,有二种,Unnecessary, Deprecated
参数与控制位置映射图
为了更加准确地理解Marker参数与显示的对应关系,下面对照着一个marker,来详细对应其参数。
下面这张图,完美地解释了marker的参数与控制位置的映射关系。
其中配置的resource是可以点击的一个链接,
secerity参数的效果图
secerity是marker的信息等级,一共有四种,对应效果如下
markder对应的方法
设置一个model的markder: monaco.editor.setModelMarkers(model: ITextModel, owner: string, markers: IMarkerData[]): void
获取一个model的markder: monaco.editor.getModelMarkers(filter: { owner?: string; resource?: Uri; take?: number }): IMarker[]
移除一个owner下的所有的marker: monaco.editor.removeAllMarkers(owner: string): void
一个事件 当marker改变时触发:
monaco.editor.onDidChangeMarkers(listener: (e: readonly Uri[]) => void): IDisposable
根据marker的定义可以看到,每一个marker都是绑定到model上,而每一个marker的显示位置,都需要有具体的Position,开始行列,结束行列。无法传入一个分词来进行添加Marker。所以在为某一分词添加Marker前,必须要知道它的Position。这个或许有其他简单的办法获取。后面查查文档再聊
完整代码
<!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>
<p>只在第11行的global上增加了Marker</p>
<button onclick="setMarker()">设置Marker</button>
<button onclick="getMarker()">获取Marker</button>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<p>
<span id="position"></span>
</p>
<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 () {
const uri = monaco.Uri.parse('http://baudu.com/fizz.js')
const model = monaco.editor.createModel(oldVersion, '', uri)
editor = monaco.editor.create(document.getElementById('container'), { model })
editor.onDidChangeCursorPosition(e => {
const { position: { column, lineNumber } } = e
document.querySelector('#position').innerText = `Ln ${lineNumber}, Col ${column}`
});
setMarker()
});
function setMarker() {
var currentModel = editor.getModel();
const markerArr = []
const range = {
startLineNumber: 11,
startColumn: 12,
endLineNumber: 11,
endColumn: 18,
}
const relatedInformation = [
{
owner: 'Fizz',
endColumn: '3',
endLineNumber: '4',
message: 'This is Realte Info',
resource: monaco.Uri.parse('https://fizzz.blog.csdn.net/pmc.js'),
startColumn: '1',
startLineNumber: '2'
}
]
const marker = {
code: 'code',
source: 'source',
message: 'It is my define variable',
severity: monaco.MarkerSeverity.Error, // Hint,Info,Warning,Error
tags: [monaco.MarkerTag.Deprecated], // Unnecessary, Deprecated
relatedInformation,
...range
}
markerArr.push(marker)
monaco.editor.setModelMarkers(currentModel, 'owner', markerArr);
}
function getMarker() {
const markers = monaco.editor.getModelMarkers()
console.log(markers, 'markers')
}
</script>
</body>
</html>