如何在Monaco Editor中获取悬停处引号包裹的完整内容?
Monaco Editor 精准匹配引号内悬停内容的实现方案
核心思路
通过手动遍历当前行字符,定位悬停位置所在的未转义双引号对,确保只提取有效引号包裹内的内容——既解决getWordAtPosition截断含分隔符文本的问题,也避免findPreviousMatch匹配错误引号的情况。
具体实现代码
1. 引号内容提取函数
function getQuotedContentAtPosition(model, position) { const lineContent = model.getLineContent(position.lineNumber); const charOffset = position.column - 1; // Monaco列索引从1开始,转换为0-based // 收集当前位置左侧所有未转义的双引号 const leftQuotes = []; for (let i = 0; i < charOffset; i++) { if (lineContent[i] === '"') { // 跳过被转义的引号 if (i > 0 && lineContent[i - 1] === '\\') continue; leftQuotes.push(i); } } if (leftQuotes.length === 0) return null; // 收集当前位置右侧所有未转义的双引号 const rightQuotes = []; for (let i = charOffset + 1; i < lineContent.length; i++) { if (lineContent[i] === '"') { if (i > 0 && lineContent[i - 1] === '\\') continue; rightQuotes.push(i); } } if (rightQuotes.length === 0) return null; // 匹配最近的左引号与对应的右引号 const targetLeftQuote = leftQuotes[leftQuotes.length - 1]; for (const targetRightQuote of rightQuotes) { if (targetRightQuote <= targetLeftQuote) continue; // 确认当前位置处于引号对之间 if (charOffset > targetLeftQuote && charOffset < targetRightQuote) { return { // 提取引号内的纯文本 content: lineContent.slice(targetLeftQuote + 1, targetRightQuote), // 生成引号内内容的范围(用于悬停提示定位) range: new monaco.Range( position.lineNumber, targetLeftQuote + 2, // 转换回1-based列索引 position.lineNumber, targetRightQuote + 1 ) }; } } return null; }
2. 注册悬停提供器
// 替换为你的语言ID,比如'javascript'、'python'等 monaco.languages.registerHoverProvider('your-language-id', { provideHover: (model, position) => { const quotedContent = getQuotedContentAtPosition(model, position); if (!quotedContent) return null; // 这里编写你的动态内容生成逻辑,比如根据content返回对应提示 return { range: quotedContent.range, contents: [ { value: `**引号内内容:** ${quotedContent.content}` }, { value: '这里可以添加自定义的动态提示内容' } ] }; } });
补充说明
- 单行/多行支持:上述代码默认处理单行引号,若需支持多行引号包裹内容,需扩展逻辑跨多行遍历查找未转义的引号对。
- 转义引号处理:代码已跳过
\"这类转义引号,若存在更复杂的转义场景(如\\\\\"),需调整转义检查逻辑,判断连续反斜杠数量是否为奇数。 - 性能优化:仅遍历当前行字符,相比全局查找更高效,适合实时悬停场景。
内容的提问来源于stack exchange,提问作者janarvaez
相关产品推荐
相关产品推荐

