Command 系统深入
命令(Command)是 VS Code 插件交互的核心:用户点击菜单、按快捷键、运行命令面板,最终都执行一条命令。掌握命令系统,就掌握了插件能力的出口。
命令的本质
一条命令 = 一个唯一的 命令 ID + 一个 处理函数:
命令 ID(字符串) → 处理函数(回调)用户触发命令时,VS Code 根据 ID 查找处理函数并执行。命令可以在任意地方触发:命令面板、菜单、快捷键、代码调用、其他插件。
注册命令 registerCommand
使用 vscode.commands.registerCommand 注册:
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
// 注册命令,返回 Disposable
const disposable = vscode.commands.registerCommand('myExt.hello', () => {
vscode.window.showInformationMessage('Hello from my extension');
});
// 必须加入 subscriptions,否则停用时不会自动注销
context.subscriptions.push(disposable);
}注册时机
命令注册在 activate() 中完成。注意:
- 必须在插件激活后注册,命令才能被找到
- 多次注册同一 ID 会覆盖(最后一次生效)
- 建议所有注册都 push 到
context.subscriptions
命令声明 vs 注册
命令需要声明 + 注册两步配合:
| 步骤 | 位置 | 作用 |
|---|---|---|
| 声明 | package.json 的 contributes.commands | 让命令出现在命令面板 |
| 注册 | activate() 中 registerCommand | 绑定实际处理逻辑 |
只声明不注册 → 命令显示但点击报错; 只注册不声明 → 命令可用但不出现在面板。
调用命令 executeCommand
使用 vscode.commands.executeCommand 执行任意命令:
typescript
// 执行自己注册的命令
await vscode.commands.executeCommand('myExt.hello');
// 执行带参数的命令
await vscode.commands.executeCommand('myExt.log', 'message', 2);
// 执行内置命令
await vscode.commands.executeCommand('editor.action.formatDocument');executeCommand 返回 Promise,可 await 等待完成;部分命令返回结果。
内置命令复用
VS Code 自带大量内置命令,插件可以直接调用,实现「站在内置能力之上」:
| 内置命令 | 作用 |
|---|---|
editor.action.formatDocument | 格式化文档 |
workbench.action.openSettings | 打开设置 |
vscode.open | 打开文件/URL |
vscode.openFolder | 打开文件夹 |
editor.action.addSelectionToNextFindMatch | 多光标选择 |
workbench.view.explorer | 打开资源管理器 |
setContext | 设置上下文键 |
workbench.action.closeActiveEditor | 关闭当前编辑器 |
查看所有内置命令
命令面板执行 「Developer: Show Running Extensions」 或 「Preferences: Open Keyboard Shortcuts」 可查看;vscode.commands.getCommands() 可编程获取全部命令列表:
typescript
const commands = await vscode.commands.getCommands();命令参数传递
命令处理函数可以接收任意参数:
typescript
// 注册带参命令
vscode.commands.registerCommand('myExt.say', (name: string, count: number) => {
vscode.window.showInformationMessage(`Hi ${name}, count=${count}`);
});
// 调用方传参
vscode.commands.executeCommand('myExt.say', 'Alice', 3);菜单传入上下文参数
命令被菜单触发时,会自动传入上下文对象作为参数:
| 菜单位置 | 传入参数 |
|---|---|
编辑器右键 editor/context | Uri(当前文件) |
资源管理器右键 explorer/context | Uri |
树视图项右键 view/item/context | 节点对象 |
typescript
// 资源管理器右键命令,直接拿到当前文件 Uri
vscode.commands.registerCommand('myExt.openInEditor', (uri: vscode.Uri) => {
vscode.window.showInformationMessage(`打开: ${uri.fsPath}`);
});内置命令传参
vscode.open 接收 Uri 与列号:
typescript
await vscode.commands.executeCommand('vscode.open', uri, vscode.ViewColumn.Two);命令 ID 命名约定
命令 ID 是全局字符串,命名约定至关重要:
| 约定 | 示例 |
|---|---|
<扩展名>.<动作> | myExt.helloWorld |
| 小写驼峰 | myExt.refreshTree |
| 层级用点分隔 | myExt.tree.refresh |
命名原则
- 前缀必须为扩展名,避免与其他扩展冲突
- 名称要表达动作语义(
transform、format、refresh) - 多个相关命令用层级组织(
git.commit、git.pull)
反例与正例:
| 反例 | 正例 |
|---|---|
hello | myExt.helloWorld |
refresh | myExt.tree.refresh |
format-json | myExt.formatJson |
命令可见性控制
when 条件
通过 when 子句控制命令何时可见/可用:
json
{
"contributes": {
"commands": [
{
"command": "myExt.convert",
"title": "Convert to Uppercase",
"when": "editorHasSelection"
}
]
}
}常用上下文键:
| 键 | 含义 |
|---|---|
editorHasSelection | 编辑器有选区 |
resourceLangId | 当前文件语言 |
isFile | 资源是文件 |
view | 当前视图 ID |
inDebugMode | 调试模式中 |
enablement
命令不可用但可见(置灰):
json
{
"command": "myExt.save",
"title": "Save",
"enablement": "config.myExt.enabled"
}完整示例
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
// 注册命令:格式化选中 JSON
const command = vscode.commands.registerCommand(
'myExt.formatJson',
async () => {
const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
const selection = editor.selection;
const text = editor.document.getText(selection);
try {
const formatted = JSON.stringify(JSON.parse(text), null, 2);
await editor.edit((editBuilder) => {
editBuilder.replace(selection, formatted);
});
} catch (error) {
vscode.window.showErrorMessage('JSON 解析失败');
}
}
);
context.subscriptions.push(command);
}常见问题
| 问题 | 处理 |
|---|---|
| 命令报「找不到命令」 | 检查注册 ID 与调用 ID 一致 |
| 命令面板没有显示 | 检查 contributes.commands 声明 |
| 点击命令无反应 | 确认 activate 已注册并 push subscriptions |
| 菜单不显示 | 检查 when 条件是否满足 |
Command 系统是插件与编辑器交互的枢纽,配合菜单、快捷键与内置命令,能构建完整的操作入口体系。