Zhengrenzhe

(°∀°)ノ 老打杂了

用户工具

站点工具


前端:monaco-editor:monaco-editor指南-断点管理

monaco-editor指南-断点管理

如果你的编辑器涉及调试,那么断点功能是必不可少的了。monaco自身没有单独用于断点的API,而是使用 deltaDecorations 进行统一的行装饰管理。

monaco playground中官方做了简单的示例,但这个还不足以称之为断点,只是长得看上去像断点,并没有一般编辑器中断点增删功能,所以我们要为其增加断点功能。

monaco内部维护着所有行装饰对象,它们都通过内部id进行标示,可以使用editorInstance.getModel().getAllDecorations()获取编辑器内所有装饰对象。行装饰的添加与删除都是通过deltaDecorations API完成的,它的第一个参数接收旧的装饰id,第二个参数是新的装饰对象。如果新的装饰对象的id不在旧的id列表中,那么将删除缺失的id对应的装饰,反之则增加一个装饰。通过它我们就能实现断点点击的增删功能:

function breakPointService(ins: editor.IStandaloneCodeEditor) {
    ins.onMouseDown(e => {
        const { target } = e;
        if (target.type === editor.MouseTargetType.GUTTER_GLYPH_MARGIN) {
            const old = ins
                .getModel()
                .getAllDecorations()
                .filter(x => x.options.glyphMarginClassName)
                .filter(
                    x =>
                        x.options.glyphMarginClassName.indexOf(
                            css.breakPoint,
                        ) !== -1,
                );
            const oldId = old.map(x => x.id);
            const existIndex = old.findIndex(
                x => x.range.startLineNumber === target.position.lineNumber,
            );

            if (existIndex === -1) {
                old.push({
                    id: "",
                    ownerId: 0,
                    range: new Range(
                        target.position.lineNumber,
                        target.position.column,
                        target.position.lineNumber,
                        target.position.column,
                    ),
                    options: {
                        isWholeLine: true,
                        glyphMarginClassName: css.breakPoint,
                        stickiness:
                            editor.TrackedRangeStickiness
                                .NeverGrowsWhenTypingAtEdges,
                    },
                });
            } else {
                old.splice(existIndex, 1);
            }

            ins.deltaDecorations(oldId, old);
        }
    });
}

这里我们使用函数breakPointService来为某一个编辑器实例添加断点服务。在编辑器接到onMouseDown事件后,判断点击来源是否为GUTTER_GLYPH_MARGIN,表示行号左边的区域,要显示这个区域,需要在editor.create时添加配置glyphMargin: true

接着获取当前的断点装饰数据,通过options.glyphMarginClassName中有没有css.breakPoint来判断这是不是一个断点装饰对象。接着判断当前行有没有断点,如果没有,则新增一个行装饰,反之则在旧id列表中将该id删除,最后调用deltaDecorations即可。

现在我们已经实现了断点管理了,点击行号左侧区域可以增删断点。这里有一个额外配置:stickiness: editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,表示换行时行装饰不随换行而扩展(除非该行是空白行)。通常我们添加断点肯定是只想对这一行添加,如果在该行按下回车,那么断点应该只留在上一行。默认情况下按下回车,行装饰会扩展至下一行,所以需要添加该配置确保断点的正确显示。

不幸的是,monaco只支持显示唯一的glyph,也就是断点哪一列只支持显示单个元素。如果你需要在glyph列显示多个状态图标,例如断点、书签或其他按钮,可以给glyphMarginClassName挂上多个class来实现。

现在我们已经实现了断点管理了,接着可以进行进一步开发了。

前端/monaco-editor/monaco-editor指南-断点管理.txt · 最后更改: 2020/03/22 02:05 由 zhengrenzhe