头图

vscode插件开发中文文档教程(9)——扩展API之命令篇

原文链接:Commands\
作者:Microsoft\
译者:倔强青铜三

前言

大家好,我是倔强青铜三。是一名热情的软件工程师,我热衷于分享和传播IT技术,致力于通过我的知识和技能推动技术交流与创新,欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!!!

扩展API之命令篇

命令在 Visual Studio Code 中触发操作。如果您曾经 配置过快捷键,那么您就已经使用过命令了。命令还被扩展用于向用户公开功能、绑定到 VS Code 的 UI 操作以及实现内部逻辑。

使用命令

VS Code 包含了一套丰富的 内置命令,您可以使用这些命令与编辑器交互、控制用户界面或执行后台操作。许多扩展也将其核心功能作为命令公开,供用户和其他扩展使用。

程序化执行命令

vscode.commands.executeCommand API 可以程序化地执行命令。这使您可以使用 VS Code 的内置功能,并基于扩展(如 VS Code 的内置 Git 和 Markdown 扩展)进行扩展。

例如,editor.action.addCommentLine 命令会在活动文本编辑器中注释当前选中的行:

import * as vscode from 'vscode';
function commentLine() {
  vscode.commands.executeCommand('editor.action.addCommentLine');
}

某些命令接受参数以控制其行为。命令也可能返回结果。例如,类似 API 的 vscode.executeDefinitionProvider 命令会在给定位置查询文档的定义。它接受文档 URI 和位置作为参数,并返回一个包含定义列表的 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})`);
        // 要在 Markdown 内容中启用命令 URI,必须设置 `isTrusted` 标志。
        // 创建可信的 Markdown 字符串时,请确保正确清理所有输入内容,
        // 以确保只有预期的命令 URI 能够被执行。
        contents.isTrusted = true;
        return new vscode.Hover(contents);
      }
    })()
  );
}

命令的参数列表以 JSON 数组的形式传递,并经过正确的 URI 编码。以下示例使用 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);
      }
    })()
  );
}

您可以通过在创建 Webview 时的 WebviewOptions 中设置 enableCommandUris 来启用 Webview 中的命令 URI。

创建新命令

注册命令

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));
}

每当 myExtension.sayHello 命令被执行时,无论是通过 executeCommand 程序化执行、VS Code UI 还是快捷键,处理函数都会被调用。

创建面向用户的命令

vscode.commands.registerCommand 只是将命令 ID 绑定到处理函数。要将命令公开到命令面板中,以便用户可以发现它,您还需要在扩展的 package.json 中添加对应的命令 contribution

{
  "contributes": {
    "commands": [
      {
        "command": "myExtension.sayHello",
        "title": "Say Hello"
      }
    ]
  }
}

commands contribution 告诉 VS Code,您的扩展提供了一个特定的命令,并且当该命令被调用时,扩展应该被激活。它还允许您控制命令在 UI 中的显示方式。现在我们的命令会出现在命令面板中:

命令面板中的贡献命令

现在,当用户首次从命令面板或通过快捷键调用 myExtension.sayHello 命令时,扩展将被激活,registerCommand 将把 myExtension.sayHello 绑定到正确的处理函数。

注意:针对 VS Code 1.74.0 之前的版本,扩展必须为所有面向用户的命令显式注册 onCommand activationEvent,以便扩展在命令调用时激活并执行 registerCommand

{
  "activationEvents": ["onCommand:myExtension.sayHello"]
}

您不需要为内部命令注册 onCommand 激活事件,但您必须为以下命令定义它们:

  • 可以通过命令面板调用的命令。
  • 可以通过快捷键调用的命令。
  • 可以通过 VS Code UI 调用的命令,例如通过编辑器标题栏。
  • 作为其他扩展 API 提供的命令。

控制命令在命令面板中的显示

默认情况下,通过 package.json 中的 commands 部分贡献的所有面向用户的命令都会出现在命令面板中。然而,许多命令仅在某些特定情况下才相关,例如当活动文本编辑器是某种语言时,或者用户设置了某个配置选项。

menus.commandPalette允许您限制命令在命令面板中显示的条件。它接受目标命令的 ID 和一个 when 子句,用于控制何时显示该命令:

{
  "contributes": {
    "menus": {
      "commandPalette": [
        {
          "command": "myExtension.sayHello",
          "when": "editorLangId == markdown"
        }
      ]
    }
  }
}

现在,myExtension.sayHello 命令仅在用户处于 Markdown 文件时才会出现在命令面板中。

命令的启用

命令支持通过 enablement 属性启用或禁用,其值是一个 when 子句。启用状态适用于所有菜单和注册的快捷键。

注意enablement 和菜单项的 when 条件之间存在语义重叠。后者用于防止菜单中充斥着禁用的项。例如,一个分析 JavaScript 正则表达式的命令应该文件是 JavaScript 时显示,并且只有当光标位于正则表达式上时才启用when 子句通过不显示该命令来防止菜单混乱,因为该命令对其他语言文件没有意义。强烈推荐避免菜单混乱。

最后,显示命令的菜单(如命令面板或上下文菜单)以不同的方式处理启用状态。编辑器和资源管理器上下文菜单会渲染启用/禁用状态的项,而命令面板则会过滤掉这些项。

使用自定义 when 子句上下文

如果您正在编写自己的 VS Code 扩展,并且需要使用 when 子句上下文来启用或禁用命令、菜单或视图,而现有的键无法满足您的需求,那么您可以添加自己的上下文。

以下第一个示例将键 myExtension.showMyCommand 设置为 true,您可以在命令的启用状态或 when 属性中使用它。第二个示例存储一个值,您可以使用它与 when 子句检查打开的“酷炫”事物数量是否大于 2。

vscode.commands.executeCommand('setContext', 'myExtension.showMyCommand', true);
vscode.commands.executeCommand('setContext', 'myExtension.numberOfCoolOpenThings', 2);
最后感谢阅读!欢迎关注我,微信公众号倔强青铜三。欢迎点赞收藏关注,一键三连!!!

倔强青铜三
41 声望0 粉丝