You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Monaco Editor:XML标签自动闭合后如何设置光标到标签中间

解决Monaco Editor XML标签自动闭合后光标定位问题

我用以下代码实现了输入XML开始标签的>时自动闭合标签,功能正常,但光标目前会停在闭合标签末尾,希望能定位到开始标签与闭合标签的中间位置:

当前效果:<myTag>[期望光标位置]</myTag> [实际光标位置]

原代码实现:

monaco.languages.registerOnTypeFormattingEditProvider('xml', {
    autoFormatTriggerCharacters: ['>'],
    provideOnTypeFormattingEdits: (model: any, position: any, ch: any) => {
        if (ch === '>') {
            const codePre = model.getValueInRange({
                startLineNumber: position.lineNumber,
                startColumn: 1,
                endLineNumber: position.lineNumber,
                endColumn: position.column,
            });

            const match = codePre.match(/.*<(\w+)>$/);
            if (match) {
                const tag = match[1];
                const closingTag = `</${tag}>`;
                const edit = {
                    range: {
                        startLineNumber: position.lineNumber,
                        startColumn: position.column,
                        endLineNumber: position.lineNumber,
                        endColumn: position.column,
                    },
                    text: `${closingTag}`,
                };

                return [edit];
            }
        }

        return [];
    },
}); 

问题原因与解决方案

原代码使用的OnTypeFormattingEditProvider仅能提供文本编辑操作,无法直接控制光标位置。要实现光标定位到标签中间,需要直接监听编辑器的键盘事件,在插入闭合标签后主动调整光标位置。

修改后的代码:

// 假设已创建Monaco Editor实例
const editor = monaco.editor.create(document.getElementById('container'), {
    value: '',
    language: 'xml'
});

editor.onKeyUp((event) => {
    if (event.key === '>') {
        const position = editor.getPosition();
        const model = editor.getModel();
        if (!model) return;

        // 获取当前行中>之前的内容
        const lineContent = model.getValueInRange({
            startLineNumber: position.lineNumber,
            startColumn: 1,
            endLineNumber: position.lineNumber,
            endColumn: position.column - 1
        });

        // 匹配未闭合的开始标签(如<myTag)
        const tagMatch = lineContent.match(/<(\w+)$/);
        if (tagMatch) {
            const tagName = tagMatch[1];
            const closingTag = `</${tagName}>`;

            // 插入闭合标签
            editor.executeEdits('xml-auto-close', [{
                range: {
                    startLineNumber: position.lineNumber,
                    startColumn: position.column,
                    endLineNumber: position.lineNumber,
                    endColumn: position.column
                },
                text: closingTag
            }]);

            // 将光标移动到开始标签的>后面,即两个标签中间
            editor.setPosition({
                lineNumber: position.lineNumber,
                column: position.column
            });
        }
    }
});

代码说明

  • 监听编辑器的keyUp事件,捕获输入>的动作
  • 获取当前行中>之前的内容,匹配是否为未闭合的XML开始标签
  • 插入闭合标签后,调用setPosition将光标定位到开始标签结束的位置,实现光标在两个标签中间的效果
  • 这种方式直接操作编辑器实例,同时处理文本插入与光标定位,逻辑更直观

内容的提问来源于stack exchange,提问作者magdeyemoody

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 14:02:47