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

如何在VSCode扩展API中监听右键菜单打开并动态修改菜单项

VSCode扩展实现动态上下文菜单(右键触发前执行检查)

方法一:通过上下文变量控制菜单项显隐(推荐)

适合基于检查结果显示/隐藏预定义菜单项,实现简单高效。

1. 在package.json中注册基础菜单项

定义菜单项时,使用自定义上下文变量作为when条件,控制菜单项是否显示:

{
  "contributes": {
    "menus": {
      "editor/context": [
        {
          "command": "myExtension.doAction1",
          "when": "editorTextFocus && myExtension.canShowAction1",
          "group": "myGroup@1"
        },
        {
          "command": "myExtension.doAction2",
          "when": "editorTextFocus && myExtension.canShowAction2",
          "group": "myGroup@2"
        }
      ]
    },
    "commands": [
      {
        "command": "myExtension.doAction1",
        "title": "执行操作1"
      },
      {
        "command": "myExtension.doAction2",
        "title": "执行操作2"
      }
    ]
  }
}

2. 监听菜单触发事件,执行检查并更新上下文

在扩展激活时,监听菜单显示前的事件,执行自定义检查逻辑后,通过setContext更新上下文变量,从而控制菜单项显隐:

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  // 监听上下文菜单即将显示的事件
  const menuListener = vscode.window.onDidShowContextMenu(async () => {
    const editor = vscode.window.activeTextEditor;
    let canShowAction1 = false;
    let canShowAction2 = false;

    if (editor) {
      // 示例检查逻辑:根据选中内容长度判断显示哪个菜单项
      const selectedText = editor.document.getText(editor.selection);
      canShowAction1 = selectedText.length > 10;
      canShowAction2 = selectedText.length <= 10;
    }

    // 更新上下文变量,触发菜单条件重新计算
    await vscode.commands.executeCommand('setContext', 'myExtension.canShowAction1', canShowAction1);
    await vscode.commands.executeCommand('setContext', 'myExtension.canShowAction2', canShowAction2);
  });

  context.subscriptions.push(menuListener);

  // 注册命令具体实现
  context.subscriptions.push(
    vscode.commands.registerCommand('myExtension.doAction1', () => {
      vscode.window.showInformationMessage('执行操作1');
    })
  );

  context.subscriptions.push(
    vscode.commands.registerCommand('myExtension.doAction2', () => {
      vscode.window.showInformationMessage('执行操作2');
    })
  );
}

方法二:动态注册全新菜单项

适合根据检查结果生成完全自定义的菜单项,而非显隐预定义项。

实现代码

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  let dynamicMenuDisposables: vscode.Disposable[] = [];

  const menuListener = vscode.window.onDidShowContextMenu(async () => {
    // 清理上一次注册的动态菜单项,避免重复
    dynamicMenuDisposables.forEach(dispose => dispose.dispose());
    dynamicMenuDisposables = [];

    const editor = vscode.window.activeTextEditor;
    if (!editor) return;

    // 执行自定义检查逻辑
    const isJSFile = editor.document.languageId === 'javascript';
    const hasConsoleLog = editor.document.getText().includes('console.log');

    // 根据检查结果动态创建菜单项
    if (isJSFile && hasConsoleLog) {
      // 注册命令
      const removeLogCmd = vscode.commands.registerCommand('myExtension.removeConsoleLog', () => {
        editor.edit(editBuilder => {
          const newText = editor.document.getText().replace(/console\.log\(.*?\);?/g, '');
          editBuilder.replace(new vscode.Range(0, 0, editor.document.lineCount - 1, Infinity), newText);
        });
      });

      // 注册菜单项到右键菜单
      const menuItem = vscode.menus.create('editor/context', {
        command: 'myExtension.removeConsoleLog',
        title: '移除所有console.log',
        group: 'myGroup@1'
      });

      dynamicMenuDisposables.push(removeLogCmd, menuItem);
    }
  });

  context.subscriptions.push(menuListener);
}

注意事项

  • 检查逻辑尽量轻量化,避免菜单弹出延迟;异步检查需处理好时序,防止菜单显示后才完成更新。
  • 动态注册菜单项时,必须在每次菜单触发前清理旧的注册,避免重复创建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:20:35