You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在VSCode扩展中通过脚本动态修改编辑器标题菜单栏选项?

动态管理VS Code编辑器标题菜单选项(运行时)

当然可以实现!在VS Code扩展开发中,完全不需要一直依赖package.json的静态配置,咱们可以通过VS Code的API在运行时动态注册、更新和移除菜单命令,完美匹配你的需求。下面是具体的实现方案:

核心思路

要实现“编辑器标题菜单显示当前已打开文件列表”的功能,我们需要做这几件事:

  1. 监听编辑器的文件打开/关闭/切换事件,实时获取当前所有已打开的文件
  2. 每次事件触发时,先清理之前注册的旧菜单命令,避免重复或无效项
  3. 为每个当前打开的文件注册对应的菜单命令和标题菜单项
  4. 实现点击菜单项时打开对应文件的逻辑

完整TypeScript代码示例

你可以直接把这段代码放到扩展的主文件(比如extension.ts)中:

import * as vscode from 'vscode';

// 存储已注册的命令ID,方便后续清理
let registeredCommandIds: string[] = [];

export function activate(context: vscode.ExtensionContext) {
    // 初始化时先更新一次菜单
    updateOpenFilesMenu();

    // 监听可见编辑器变化:文件打开、关闭、切换都会触发这个事件
    const editorChangeDisposable = vscode.window.onDidChangeVisibleTextEditors(() => {
        updateOpenFilesMenu();
    });

    context.subscriptions.push(editorChangeDisposable);
}

function updateOpenFilesMenu() {
    // 第一步:清理旧的命令和菜单项,防止内存泄漏
    registeredCommandIds.forEach(cmdId => {
        // 移除已注册的命令
        vscode.commands.registeredCommands.get(cmdId)?.dispose();
        // 通过上下文变量隐藏对应的菜单项
        vscode.commands.executeCommand('setContext', `myExtension.showFile.${cmdId}`, false);
    });
    registeredCommandIds = [];

    // 第二步:获取当前所有可见的编辑器(即已打开的文件)
    const visibleEditors = vscode.window.visibleTextEditors;

    // 第三步:为每个文件注册命令和菜单项
    visibleEditors.forEach((editor, index) => {
        const fileUri = editor.document.uri;
        // 提取文件名(如果是未保存文件则显示"Untitled")
        const fileName = fileUri.fsPath.split('/').pop() || 'Untitled';
        // 生成唯一的命令ID,避免冲突
        const cmdId = `myExtension.openFile.${index}.${fileName.replace(/\s+/g, '-')}`;

        // 注册命令:点击菜单项时打开对应文件
        const cmdDisposable = vscode.commands.registerCommand(cmdId, () => {
            vscode.window.showTextDocument(fileUri);
        });

        // 通过上下文变量控制菜单项显示
        vscode.commands.executeCommand('setContext', `myExtension.showFile.${cmdId}`, true);
        // 记录命令ID,方便后续清理
        registeredCommandIds.push(cmdId);
        // 将命令添加到扩展的订阅中,确保扩展停用后自动清理
        vscode.extensions.getExtension('your-extension-id')?.exports.context.subscriptions.push(cmdDisposable);
    });
}

export function deactivate() {
    // 扩展停用时清理所有注册的命令
    registeredCommandIds.forEach(cmdId => {
        vscode.commands.registeredCommands.get(cmdId)?.dispose();
    });
}

配合package.json的动态菜单配置

你需要在package.json中添加一个动态菜单项模板,通过上下文变量来控制显示:

"contributes": {
    "menus": {
        "editor/title": [
            {
                "command": "%command.openFile%",
                "when": "myExtension.showFile.${command}",
                "group": "workbench@10"
            }
        ]
    },
    "commands": [
        {
            "command": "myExtension.openFile.dummy",
            "title": "Open File from List",
            "hidden": true
        }
    ]
}

关键细节说明

  • 上下文变量(setContext):这是VS Code扩展动态控制菜单显示的核心,通过设置不同的上下文变量值,我们可以精准控制每个菜单项的显示/隐藏状态。
  • 命令清理:每次更新菜单时一定要先清理旧命令,否则会出现重复菜单项,还可能导致内存泄漏。
  • 可见编辑器事件onDidChangeVisibleTextEditors事件会覆盖所有文件打开、关闭、切换的场景,确保菜单始终和当前已打开的文件保持同步。

这样实现后,编辑器标题菜单就会实时显示当前所有已打开的文件,点击对应的文件名就能直接切换到该文件啦!

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

火山引擎 最新活动