前言
自從習慣 Vim 操作之後,就越來越精簡 GUI 介面。接著把 Tab 顯示 workbench.editor.showTabs
也關閉了。編輯視窗瞬時舒爽許多,除了不再擔心切換 Tab 時點選不小心將之關閉,也開始習慣使用快捷鍵 Ctrl/Cmd-P 快速找檔案。接著我才發現一個問題,原本的 Pinned Tab 設計是釘選在 Tab 列的最左側。也就是說,關閉了 Tab 顯示之後,Pin 功能也就如同作廢。其實 VS Code 在側邊欄有一個 OPEN EDITORS 的 View 顯示目前開啟的所有 Editor 視窗,But 就是這個但是,沒有 Pinned Editors!只好自幹了。來看成果:
欸你說 OPEN EDITORS 也會顯示一個圖釘表示釘選!但當你開了一百個 Tab 之後那個釘選就飛向宇宙浩瀚無敵了。所以搞了一個專門顯示釘選檔案的 View,使用起來方便許多,點選即可跳轉,也就不用浪費頂部 Tab Bar 的空間。
Extension Development
VS Code 的 Extension(套件)主要分為以下幾種:
- Extension (Typescript/Javascript) 一般性套件
- Color Theme 顏色主題
- Language Support 新程式語法支援
- Code Snippets 常用程式模板
- Keymap 快捷鍵
沒意外,一般都是選擇 Extension,我選用 Typescript(一種強型別的 Javacript),感覺比較厲害。VS Code 不愧為全世界使用者最多(2023 年 zhung 數據)的文字編輯器,連套件的開發手冊都手把手帶你開始。
基本上,按照連結的步驟按完,就可以按 ▶ 開始 Debug 我們的第一個 VS Code Extension 啦!
這次要做的事情其實很簡單:
- 獲取所有 Pin 的 Editor
- 顯示在 VS Code 的側邊欄
- 搭配 Tree View API 使用
- 點選跳轉該檔案
底下一一說明。
Retrieve All Pinned Tabs
翻閱 API 找半天,最後還是求助 Stackoverflow 大神。不曉得有沒有文件再解釋 tabGroup
是什麼,因為 tabGroup
裡面還有一層 tabs
才可以拿到我需要的 Tab
實體。
// https://stackoverflow.com/questions/72772981/how-do-i-get-all-the-tabs-in-a-visual-studio-code-window-as-an-array-of-filename
const tabArray = vscode.window.tabGroups.all[0].tabs;
Register a New Panel Called “Pinned Files”
對 npm 不是很熟,但 VS Code 會使用 Package.json 來管理套件需要的資源,例如所有註冊的 Command、View 等等。新增以下欄位,請注意 views
裡面的 explorer
是 VS Code內建的檔案總管 Panel。
{
"activationEvents": [
"onView:packagePinnedExplorer"
],
"contributes": {
"views": {
"explorer": [
{
"name": "Pinned Files",
"id": "packagePinnedExplorer"
}
]
}
}
}
然後在 Code 裡面註冊 ID 的實體。
const pinnedProvider = new PinnedFilesProvider()
const tree = vscode.window.createTreeView('packagePinnedExplorer', {
treeDataProvider: pinnedProvider,
showCollapseAll: false
});
這個 view 做的事情很簡單,就是提供一個 vscode.TreeDataProvider
讓 VS Code 去顯示 Tree View。詳細實作可以參考我 Github 上的原始碼。
Click Item to Jump to Editor
這次應該就這裡卡關最久,因為我不知道要監聽哪一個 Event,也不知道要如何監聽事件。搞了半天終於找到了一個暫解。
tree.onDidChangeSelection(async e => {
let t = e.selection[0].tab;
await vscode.window.showTextDocument(t.input.uri);
});
這有一個 Bug 就是當 Selection 沒有變化的時候,無法跳轉。目前是可以先點旁邊,再點選以繞過此問題,未來需要找個更好的寫法。
Update View When Pin Changed
還有一個很重要的,當解除釘選、或是新加入釘選的時候,需要更新列表。
vscode.window.tabGroups.onDidChangeTabs(unused => {
pinnedProvider.refresh();
});
需要額外在 PinnedFilesProvider
中實作 Refresh 方法。
export class PinnedFilesProvider implements vscode.TreeDataProvider {
// ...
private changeEvent = new vscode.EventEmitter();
public get onDidChangeTreeData(): vscode.Event {
return this.changeEvent.event;
}
refresh(): void {
this.changeEvent.fire();
}
}
搞定!雖然都是一些簡單的實作,但終於完成自己的第一個 VS Code 套件,開心!接下來就要發佈給全世界使用啦 🤩
Publish to Extension Marketplace
不得不說,發佈這一步真的比 Sublime Text 簡單的多。再次來參考官方 Publish Extension 手冊。
要先用 npm 安裝轉譯程式 @vscode/vsce
,以將 Typescript 原始碼製作成 VSIX 檔案(VS Code 套件的離線安裝檔案)。
$ vsce package
# myExtension.vsix generated
雖然直接使用 vsce publish
指令可能會比較方便,但接下來我還是選擇手動上傳此檔案。會需要一個帳號來管理自己發佈的套件。
- 前往 VS Code Extension Marketplace,註冊一個新的帳號,也可以選用 Github 授權登入。然後就可以再右上角選擇 [Publish extensions]。
- 接著需要新增一個 Publisher 發布商,填好必要資訊就可以了。
- 點選 [+ New extension] > [Visual Studio Code],上傳,點擊 [Upload]。
- 等一會兒,你的套件就可以在全世界的 VS Code 中搜尋到啦。
撒花 🎉
Extension Page
Pinned PanelSource Code
ukyouz/VSCode-PinnedPanel