Monaco Editor获取光标处方括号内容 正则匹配返回null如何解决
问题原因
findNextMatch的搜索规则(正则模式、大小写敏感、多行匹配)是通过方法自身的第3到第6个参数控制的,直接传入带g/s等flag的原生JS正则对象时,这些flag不会被识别,反而会干扰匹配逻辑导致返回null。- 该API不支持正则的
s(dotAll,点匹配所有字符)特性,即使通过参数开启正则模式,.也无法匹配换行符。 - 现有逻辑仅从光标位置向后查找匹配项,无法覆盖光标位于包裹块内部、块起始标记之前的场景,不符合「获取光标所在位置包裹内容」的需求。
可行实现方案
方案1:修正正则匹配逻辑
去掉正则上自带的所有flag,用 [\s\S] 代替 . 实现跨行匹配,同时遍历所有匹配块判断光标是否落在块区间内:
const model = editor.getModel(); const position = editor.getPosition(); const cursorOffset = model.getOffsetAt(position); // 仅保留正则匹配规则,不带任何flag const blockReg = /\[\%([\s\S]*?)%\]/g; const fullText = model.getValue(); let matchRes = null; let targetContent = null; blockReg.lastIndex = 0; while((matchRes = blockReg.exec(fullText)) !== null) { const blockStart = matchRes.index; const blockEnd = blockStart + matchRes[0].length; // 光标落在当前块区间内则命中 if(cursorOffset >= blockStart && cursorOffset <= blockEnd) { targetContent = matchRes[1]; break; } } console.log('光标所在块包裹内容:', targetContent);
方案2:纯文本匹配实现(无正则兼容问题,更稳定)
直接用Monaco原生的前后查找API定位边界标记,避免正则兼容问题,同时支持嵌套场景校验:
const model = editor.getModel(); const position = editor.getPosition(); // 纯文本查找光标前最近的开标记[%、光标后最近的闭标记%] const prevOpen = model.findPreviousMatch('[%', position, false, false, null, true); const nextClose = model.findNextMatch('%]', position, false, false, null, true); let targetContent = null; if(prevOpen && nextClose) { // 取两个标记中间的内容 const betweenContent = model.getValueInRange({ startLineNumber: prevOpen.range.endLineNumber, startColumn: prevOpen.range.endColumn, endLineNumber: nextClose.range.startLineNumber, endColumn: nextClose.range.startColumn }); // 校验中间没有其他开/闭标记,避免嵌套场景匹配错误 if(!betweenContent.includes('[%') && !betweenContent.includes('%]')) { targetContent = betweenContent; } } console.log('光标所在块包裹内容:', targetContent);
测试说明
将原有F9快捷键绑定的匹配逻辑替换为上述任意一种实现,即可在测试用例 dzqdqzdqz [%function()%] dzdzqdqzd 中正常获取到括号内的 function() 内容,跨行的包裹块也能正常识别。
内容的提问来源于stack exchange,提问作者Akarimichi
相关产品推荐
相关产品推荐

