命令
在 VS Code 中,命令用于触发动作。如果你曾经配置过键位绑定,那么你已经用过命令了。命令同样用于向用户暴露方法、向 VS Code 用户界面绑定动作、实现内部逻辑等。
使用命令
VS Code 拥有大量的 内置命令,你可以使用它们来与编辑器交互,同时也可以用来控制用户界面、执行后台操作等。很多插件同样将它们的内部方法作为命令暴露出来,用户或是其它插件可以使用这些命令。
以编程的方式执行命令
你可以使用 vscode.commands.executeCommand
API 来以编程的方式执行一个命令。这让你可以使用 VS Code 的内置的方法,在类似于 Git 和 Markdown 等 VS Code 内置的插件之上开发功能。
举例来说,editor.action.addCommentLine
命令会将当前选中的文本打上注释。
import * as vscode from 'vscode';
function commentLine() {
vscode.commands.executeCommand('editor.action.addCommentLine');
}
一些命令则需要在运行时传入参数,同样也会有一些命令返回一个结果。举个例子,vscode.executeDefinitionProvider
命令会在给定的位置查询文档中的定义。它需要传入一个文档路径和一个位置信息,返回一个 Promise 形式的定义的列表。
import * as vscode from 'vscode';
async function printDefinitionsForActiveEditor() {
const activeEditor = vscode.window.activeTextEditor;
if (!activeEditor) {
return;
}
const definitions = await vscode.commands.executeCommand<vscode.Location[]>(
'vscode.executeDefinitionProvider',
activeEditor.document.uri,
activeEditor.selection.active
);
for (const definition of definitions) {
console.log(definition);
}
}
你可以在这查询命令:
命令 URI
命令 URI 是一个可以执行指定命令的链接。它可以用在例如鼠标悬浮在文本上显示的链接上、自动补全项目的详情中、webview 内部等。
一个命令 URI 使用 command
模式命名,后面跟着命令名。例如 editor.action.addCommentLine
命令的 URI 是 command:editor.action.addCommentLine
。下面是一个鼠标悬浮程序,在当前活动的编辑器中显示的当前行注释中,显示一个链接的例子。
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
vscode.languages.registerHoverProvider(
'javascript',
new class implements vscode.HoverProvider {
provideHover(
_document: vscode.TextDocument,
_position: vscode.Position,
_token: vscode.CancellationToken
): vscode.ProviderResult<vscode.Hover> {
const commentCommandUri = vscode.Uri.parse(`command:editor.action.addCommentLine`);
const contents = new vscode.MarkdownString(`[Add comment](${commentCommandUri})`);
// 要使命令 URI 在 Markdown 内容中可用,你需要设置 `isTrusted` 标志
//
// 当创建受信任的 Markdown 内容时,你需要确保正确地清空了输入的内容,以便让命令 URL 按预期正确地执行
contents.isTrusted = true;
return new vscode.Hover(contents);
}
}()
);
}
传入命令的参数列表,必须是一个经过正确的 URI 编码的 JSON 数组。下面的例子使用 git.stage
命令创建了一个悬停链接,用于储存当前文件。
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
vscode.languages.registerHoverProvider(
'javascript',
new class implements vscode.HoverProvider {
provideHover(
document: vscode.TextDocument,
_position: vscode.Position,
_token: vscode.CancellationToken
): vscode.ProviderResult<vscode.Hover> {
const args = [{ resourceUri: document.uri }];
const stageCommandUri = vscode.Uri.parse(
`command:git.stage?${encodeURIComponent(JSON.stringify(args))}`
);
const contents = new vscode.MarkdownString(`[Stage file](${stageCommandUri})`);
contents.isTrusted = true;
return new vscode.Hover(contents);
}
}()
);
}
你可以通过配置 WebviewOptions
中的 enableCommandUris
,当 Webview 创建时,让命令 URL 在 Webview 中可用。
创建新的命令
注册一个命令
你可以使用 vscode.commands.registerCommand
,在你的插件中将一个命令 ID 绑定到一个处理函数上。
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
const command = 'myExtension.sayHello';
const commandHandler = (name: string = 'world') => {
console.log(`Hello ${name}!!!`);
};
context.subscriptions.push(vscode.commands.registerCommand(command, commandHandler));
}
无论是使用 executeCommand
进行编程式调用此命令,还是通过快捷键,还是直接点击 VS Code 的界面,只要是执行 myExtension.sayHello
命令,都会调用此函数。
创建面向用户的命令
vscode.commands.registerCommand
只会将一个命令 ID 绑定到一个处理函数上。如果想要让这个命令显示在命令面板中,你需要在你的 package.json
中正确地配置 Contribute 配置项。
{
"contributes": {
"commands": [
{
"command": "myExtension.sayHello",
"title": "Say Hello"
}
]
}
}
commands
Contribute 配置项会告诉 VS Code,你的插件提供了一个命令,这个命令会在被调用时激活,同样你可以配置这个命令在界面上如何显示。现在你的这个命令将会在命令面板中显示了。
现在无论是用户在命令面板中触发,还是通过快捷键触发,你的插件都会被激活,并且 registerCommand
会将你的命令 myExtension.sayHello
绑定到指定的处理函数上。
提示:针对 1.74.0 之前版本的 VS Code,插件必须为所有面向用户的命令显式注册
onCommand
activationEvent
,以便该插件激活并执行registerCommand
:
json{ "activationEvents": ["onCommand:myExtension.sayHello"] }
内部命令不需要 onCommand
,但必须为下列事件使用 onCommand
:
- 会被命令面板激活的
- 会被快捷键激活的
- 会被 VS Code 用户界面(例如编辑器的标题栏)激活的
- 为了被其它插件作为 API 使用的
控制命令何时显示在命令面板中
默认情况下,通过 package.json
中 commands
字段配置的命令,都会显示在命令面板中。然而,很多命令只在特定情况下会用到,例如当存在特定语言的编辑器时、当用户配置了特定的配置选项时。
menus.commandPalette
Contribute 配置项允许你配置何时在命令面板中显示你的命令。它使用命令 ID 和一个when 表达式,这样可以控制命令的显示时机。
{
"contributes": {
"menus": {
"commandPalette": [
{
"command": "myExtension.sayHello",
"when": "editorLangId == markdown"
}
]
}
}
}
现在 myExtension.sayHello
命令将只会在用户打开 Markdown 文件时在命令面板中显示了。
命令的启用
命令可以使用 enablement
属性来配置是否启用,enablement
的值是一个 when 表达式。这个启用适用于所有菜单和注册的快捷键。
提示:菜单项的
enablement
和when
条件之间存在语义重叠。后者用于防止菜单中全都是禁用的项目。例如,一个分析 JavaScript 正则表达式的命令,应该是 当 文件为 JavaScript 时,并且仅当光标位于正则表达式上时才应启用。when
表达式通过这种不显示所有其它不相关的命令来防止出现混乱的情况。在插件的开发中,应尽量避免让菜单变得混乱。
诸如命令面板或是右键菜单等显示插件命令的菜单,它们各自实现了不同的启用命令的方式。编辑器和浏览器的右键菜单中,显示了启用的或是禁用的菜单项,同时命令面板对其进行筛选。
使用自定义的 when 表达式
如果你正在开发你自己的插件,并且需要使用 when
表达式来禁用或启用一些命令、菜单、视图,而现有的方式都不符合你的需求,那么你可以添加你自己的表达式。
下面第一个例子将 myExtension.showMyCommand
设置为 true,你可以在启用命令时或者使用 when
属性时和它一起使用。
第二个例子传入了一个值 2
,你可以在 when
表达式中使用这个值,例子中用于检查某些变量是否等于 2。
vscode.commands.executeCommand('setContext', 'myExtension.showMyCommand', true);
vscode.commands.executeCommand('setContext', 'myExtension.numberOfCoolOpenThings', 2);