iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 6
1
Software Development

自己用的工具自己做! 30天玩轉VS Code Extension之旅系列 第 6

Day06 | 用Command API來操控使用者的VSCode吧

哈囉大家好,我是韋恩,今天是第六天,讓我們來練習Command API吧!

今天我幫大家會有一個練習小試身手,動手玩玩吧!

環境準備


讓我們先準備開發環境,請參照以下順序建立專案:

  1. 使用yo執行vscode的code generator:
yo code

2.依序輸入專案名稱、id等資訊,參考筆者輸入的資訊建立專案:

如果環境建立有問題,請再次參照昨天的詳細教學建立專案與環境喔!

Command API簡介


讓我們先開啟一個extension專案吧!

Command API主要只有四個,當我們在extension.tsimport * as vscode from 'vscode';的下面輸入vscode.commands.,我們會看到vscode的intellisense(程式碼自動補全)幫我們列出commands下面可用的方法:

這四個方法的用途分別是:

Command API 描述
getCommands 取得vscode中註冊的commands,可以給一個boolean值決定是否列出vscode內部使用的command(預設會列出),內部command的id均以下劃線開頭。
registerCommand 跟vscode註冊一個可以被keyborad shortcut、extension程式或其他ui元件呼叫(invoke)的命令。註冊同一個command id兩次會產生錯誤。
registerTextEditorCommand 與registerCommand類似,但只有在vscode有開啟文件的editor(active Editor)時才會觸發。
executeCommand 透過給定的commandId執行對應的內建或extension註冊的command。

簡單介紹完,讓們開始動手練習吧,練習才是最實在的。

Day06專案範例配置


經過昨天的教學,相信大家都了解怎麼樣設定extension吧,這裡不多贅述。

  • 專案Contribution Points配置:

讓我們照以下指示設定extension專案,首先於packagage.json,我們要在Contribution Points裡設定四個Command練習API,如下所示:

{
    ...
    "contributes": {
		"commands": [
			{
				"command": "day06-command-practice.helloWorld",
				"title": "Hello World"
			},
			{
				"command": "day06-command-practice.getCommand",
				"title": "getCommand"
			},
			{
				"command": "day06-command-practice.textEditorCommand",
				"title": "textEditorCommand"
			},
			{
				"command": "day06-command-practice.executeCommand",
				"title": "executeCommand"
			}
		]
	},
    ...
}
  • 專案activationEvents配置:

設置完Command後,我們一樣要在package.json配置activationEvents,不過今天的設定有點不一樣,我們不會直接指定onCommand事件,如下所示:

{
    ...
    "activationEvents": [
		"*"
	],
    ...
}

ActiveEvents這邊我們設為*,表示說我們開發用的extenions將在VSCode啟動(Startup)的時候自動活躍並執行active function。為什麼這麼設定呢?就User的角度,會希望安裝的extension在需要使用的時候再執行,避免再不需要使用extension的時候開著extension消耗系統資源。所以會利用指令ActivationEvents來適當的激活我們的extension。但我們在開發時,會相當的不方便,因此在開發或練習階段,我們先直接設定extension自vscode啟動時即會開始活躍。

  • 專案extension.ts範例程式配置:

我們會在extension.ts的active funtion這邊註冊四個對應Contribution Points的commands清單的command,分別執行並展示getCommand、registerTextEditorCommand、registerCommand、executeCommand這四個api,如下所示:

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {

	const getCmd = vscode.commands.registerCommand('day06-command-practice.getCommand', () => {
		vscode.commands.getCommands(false).then((data) => {
			console.log('commands', data);
		});
	});

	const txtCmd = vscode.commands.registerTextEditorCommand('day06-command-practice.textEditorCommand', () => {
		vscode.window.showInformationMessage('Show Message Only when there is an active editor!');
	});

	const registerCmd = vscode.commands.registerCommand('day06-command-practice.helloWorld', () => {
		vscode.window.showInformationMessage('Hello World from day06-command-practice!');
	});

	const registerExecCmd = vscode.commands.registerCommand('day06-command-practice.executeCommand', async () => {
		await vscode.commands.executeCommand('workbench.action.togglePanel');
		vscode.window.showInformationMessage('Panel has been toggle!');
	});

	context.subscriptions.push(getCmd, txtCmd, registerCmd, registerExecCmd);
}

export function deactivate() {}

請讀者照順序配置今天的vscode專案,接下來,我們要開始啟動extension,並演示對應的結果。

執行專案範例程式


範例專案中註冊的command分別對應到四個api,由於registerCommand昨天已經演示過,因此這裡不多做說明,讀者可以自行嘗試執行這個api,讓我們一一執行其餘三個command,並查看對應結果。

首先,讓我們按F5執行我們的extension程式。

  • 使用getCommands:
const getCmd = vscode.commands.registerCommand('day06-command-practice.getCommand', () => {
    vscode.commands.getCommands(false).then((data) => {
        console.log('commands', data);
    });
});

像昨天一樣,我們透過Command Palette搜尋到對應的getCommand命令。

選中後執行它,getCommands方法會回傳一個thenable,thenable等同js裡的promise,因此我們可以像promise一樣操縱它。在then的callback裡拿到command的資料後,我們會在debug console那邊看到拿到的command array,多達千個,並點擊將其展開。

我們可以看到commands裡面,有著以下劃線(underscore)開頭的command,那即是vscode內部使用的命令。

若我們傳給getCommand一個true的boolean,如

vscode.commands.getCommands(true).then((data) =>  ... );

內部command即不會被顯示出來。

  • 使用registerEditorCommand:

reisterEditorCommand需要在有editor開啟的狀況下才會觸發,因此我們先關掉editor執行看看。

Ok,什麼都不會發生,這是正常的。

讓我們打開任一個文件並再次執行看看,

開啟編輯器後,我們執行textEditorCommand總算在右下角順利地跳出訊息,

- 使用executeCommand:

const registerExecCmd = vscode.commands.registerCommand('day06-command-practice.executeCommand', async () => {
    await vscode.commands.executeCommand('workbench.action.togglePanel');
    vscode.window.showInformationMessage('Panel has been toggle!');
});

總算,我們來到今天的重頭戲了,executeCommand,可以讓我們執行任意被註冊的command。

讓我們先來看看上面的範例程式,我們可以看到這裡我們一樣可以使用async跟await處理非同步的executeCommand事件回傳的thenable。executeCommand會執行VSCode內建的togglePanel的命令,用於開關我們的terminal,當我們在vscode裡面使用+`開關terminal時,其實用的就是這個指令。

動手看看吧,我們一樣使用Command Palette執行指令。

成功後,右下方一樣會跳出訊息,同時panel會被開關。

隋堂小練習:找出vscode內建的command開關sidebar,並使用executeCommand執行它


恭喜,您已經嘗試過手動執行這幾個api了,相信一定更為熟悉。現在,我們有一個練習,讓我們找出內建的command操作Editor的Sidebar元件吧!

這裡推薦的解答方向有兩個:

  1. 查找官方文件,最詳細的莫過於keybings.json這一章。

  2. 使用keyborad shortcut搜尋command

這裡我會使用第二種方式示範如何找到未知的command,先讓我們進入keyboard shortcut。

然後,還記得嗎,第二天我們提到了workbench這個namespace,workbench的namespace下面會有種種跟editor元件有關的設定跟command。因此,我們使用這個作為第一個關鍵字做查找。

接下來,讓我們第二天介紹的sidebar,它也是重要的關鍵字,因此我們這麼輸入:

可以看到,keyboard shortcut支援fuzzy search,因此在多個關鍵字下很快就定位到了符合我們需求的command id: workbench.action.toggleSidebarVisibility

讓我們直接選取它,並按上右鍵,此時會跳出一個選單。

Wow,原來選單上面有一個copy command id選項! 真的太好了,恩,你知道的,複製下來吧!

現在,讓我們把新的command id貼在原本要執行的command上

const registerExecCmd = vscode.commands.registerCommand('day06-command-practice.executeCommand', async () => {
    await vscode.commands.executeCommand('workbench.action.toggleSidebarVisibility');
    vscode.window.showInformationMessage('Panel has been toggle!');
});

我們很快速的滿足了上述需求。

讓我們再次按下F5執行我們的extension,並檢視結果吧!

註: VSCode提供的編輯器command,像今天練習查找到的workbench下command,為simple command,不需要特別傳入參數並拿到回傳結果,另外有build-in command,為更複雜的command,無法在keyboard shortcut上找尋的到,如要查找這類command就一定需要查找官方文件了。

結語


好啦,今天我們的練習就在這裡告一個段落了,不小心又超過了6000多字,然而,真的要更詳細,其實還有很多detail可以說明啊!

請讀者別擔心! 其實啊,說不完、學不完,很正常的。

這些學不完的東西,是要靠著我們自學摸索而獲得的。天底下,從來沒有不勞而獲的東西,唯有自己練習過的,嘗試過的,才會是自己的。因此,筆者這裡主要在這裏帶大家嘗試練習api並練習找尋答案查找文件,學習的api雖然不多,但唯希望,在這一章節嘗試過、找尋過答案的經驗,能夠能為你未來學習任何程式語言或框架的寶貴資產。

本日參考文件



上一篇
Day05 | 在Extension專案裡執行第一個Command命令吧
下一篇
Day07 | 那些你可以自訂選項的Context Menu
系列文
自己用的工具自己做! 30天玩轉VS Code Extension之旅36

尚未有邦友留言

立即登入留言