🚀 在 VS Code 中

命令

命令會觸發 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})`);

        // To enable command URIs in Markdown content, you must set the `isTrusted` flag.
        // When creating trusted Markdown string, make sure to properly sanitize all the
        // input content so that only expected command URIs can be executed
        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 貢獻點告訴 VS Code,您的擴充功能提供指定的命令,並且應在叫用該命令時啟用,同時也讓您控制命令在 UI 中的顯示方式。現在我們的命令將會顯示在命令面板中

The contributed command in the Command Palette

現在,當使用者第一次從命令面板或透過按鍵綁定叫用 myExtension.sayHello 命令時,擴充功能將會啟用,而 registerCommand 會將 myExtension.sayHello 繫結到正確的處理常式。

注意:目標為 1.74.0 之前 VS Code 版本的擴充功能,必須為所有使用者面向的命令明確註冊 onCommand activationEvent,以便擴充功能啟用並執行 registerCommand

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

內部命令不需要 onCommand 啟用事件,但您必須為以下任何命令定義它們:

  • 可以使用命令面板叫用的命令。
  • 可以使用按鍵綁定叫用的命令。
  • 可以透過 VS Code UI 叫用的命令,例如透過編輯器標題列。
  • 預期作為其他擴充功能取用的 API 的命令。

控制命令在命令面板中的顯示時機

預設情況下,透過 package.jsoncommands 區段貢獻的所有使用者面向的命令都會顯示在命令面板中。但是,許多命令僅在特定情況下才相關,例如當存在指定語言的作用中文字編輯器時,或當使用者設定了特定的組態選項時。

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