Monaco Editor自定义IntelliSense:引号内仅显示指定CompletionItemProvider
实现引号内手动触发专属补全的方案
当然可行!这在VS Code扩展开发中完全可以实现,核心是通过光标上下文检查和触发类型判断来精准控制补全提供者的行为。下面是具体的实现思路和代码示例:
核心思路
你需要在目标补全提供者(也就是标注// should only trigger inside quotes的areaCompl)中做两件事:
- 仅响应用户手动触发的补全(即按下
CTRL + SPACE,对应CompletionTriggerKind.Invoke) - 验证当前光标确实处于未闭合的单引号内部
同时,对于另一个“任意字母触发”的补全提供者,你也可以添加反向判断——如果光标在单引号内且是手动触发,则返回空补全列表,避免它干扰结果。
具体代码实现
1. 编写专属补全提供者
import * as vscode from 'vscode'; export class AreaCompletionProvider implements vscode.CompletionItemProvider { provideCompletionItems( document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext ): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> { // 第一步:只处理手动触发的补全请求 if (context.triggerKind !== vscode.CompletionTriggerKind.Invoke) { return []; } // 第二步:检查光标是否在单引号内部 const isInsideQuotes = this.isPositionInsideSingleQuotes(document, position); if (!isInsideQuotes) { return []; } // 返回你需要的专属补全项 return [ new vscode.CompletionItem('user_profile', vscode.CompletionItemKind.Variable), new vscode.CompletionItem('system_config', vscode.CompletionItemKind.Variable), new vscode.CompletionItem('app_logs', vscode.CompletionItemKind.Variable) ]; } // 辅助方法:判断光标是否在未闭合的单引号内 private isPositionInsideSingleQuotes(document: vscode.TextDocument, position: vscode.Position): boolean { const line = document.lineAt(position.line); const lineText = line.text; const cursorIndex = position.character; // 统计光标左侧的单引号数量 const leftQuotes = (lineText.substring(0, cursorIndex).match(/'/g) || []).length; // 统计光标右侧的单引号数量 const rightQuotes = (lineText.substring(cursorIndex).match(/'/g) || []).length; // 左侧引号数为奇数(说明处于未闭合的引号中),且右侧至少有一个闭合引号 return leftQuotes % 2 === 1 && rightQuotes > 0; } }
2. 注册补全提供者
注册时可以不指定触发字符(因为我们靠手动触发和上下文判断),或者仅指定'作为辅助触发:
// 注册专属补全提供者 vscode.languages.registerCompletionItemProvider( 'your-target-language', // 替换为你的目标语言ID(比如javascript、python等) new AreaCompletionProvider(), // 可选:如果需要输入'时也触发,可以添加'作为触发字符 "'" ); // 调整另一个通用补全提供者的逻辑(示例) export class GeneralCompletionProvider implements vscode.CompletionItemProvider { provideCompletionItems( document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext ): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> { // 如果是手动触发且在引号内,不返回补全项 if (context.triggerKind === vscode.CompletionTriggerKind.Invoke) { const isInsideQuotes = this.isPositionInsideSingleQuotes(document, position); if (isInsideQuotes) { return []; } } // 返回通用补全项 return [/* 你的通用补全内容 */]; } // 复用相同的引号检查方法 private isPositionInsideSingleQuotes(document: vscode.TextDocument, position: vscode.Position): boolean { // 同上实现 } }
关键细节说明
CompletionTriggerKind.Invoke:对应用户手动触发补全(CTRL + SPACE),而TriggerCharacter是输入特定字符触发,Automatic是编辑器自动触发。- 引号检查逻辑:通过统计光标左右的单引号数量,确保处于一对未闭合的引号内部,避免误判单行多个引号的情况。
这样配置后,当用户在单引号内按下CTRL + SPACE时,只会显示AreaCompletionProvider的补全项,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Devid
相关产品推荐
相关产品推荐

