大家好,我是韋恩,今天是鐵人賽的二十三天,讓我們來幫專案實現創建樹狀元件並讀取工作區程式碼片段的功能吧!
在昨天和前天的練習裡面,我們已經了解如何取得使用者程式碼,也知道怎麼讓使用者設置我們code snippet工作區。現在我們就要來讓使用者可以讀取工作區的snippet並顯示樹狀元件。
在vscode裡面,我們可以透過幫使用者在不同專案的workspace新增一個**.code-snippet
的json檔案,來設定我們個人的code-snippet。現在我們要幫使用者儲存程式碼片段,將照一樣的副檔名格式儲存檔案在擴充套件的snippet工作區中,這樣有一個好處,就是我們之後可以在使用者程式碼工作區使用git指令,讓使用者可以將工作區的程式碼片段與github同步。
現在我們要處理json檔案,會用一個處理json檔案的函式庫jsonfile。讓我們在專案先安裝這個工具
yarn add jsonfile
安裝完以後,我們可以使用以下的方法取得程式碼片段
import * as jsonfile from 'jsonfile';
const snippets = 'workspacePath/code-manager.code-snippet'
const snippetsJSON = jsonfile.readFileSync(snippets);
已經了解讀取的方法了,讓我們在樹狀元件中實作讀取的方法,並展示資料吧!
讓我們先在工作區的資料夾創建模擬用的snippet檔案與資料夾。
接著,在各分類的snippet檔案設定簡單的snippet設定如下
{
"Print Global to console": {
"prefix": "global log",
"body": [
"console.log('$1');",
],
"description": "Log output to console"
}
}
上面各分類的檔案我們照分類名稱稍微改寫prefix和Print to Console的Key即可。
現在我們可以開始實作先前的treeview類別,讓我們新增一個loadDataStorage方法,並載入TreeView的資料吧!
因為上面的workspace可以設定多個分類與對應的snippet檔案,我們的樹狀元件要是能夠嵌套並有各自的item作為snippet。讓我們把前面定義的TreeViewItem做個調整
export class TreeViewItem extends vscode.TreeItem {
public config: SnippetJsonObject | undefined;
constructor(public label: string, public children?: TreeViewItem[]) {
super(label, children ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.None);
this.contextValue = 'snippetItem';
this.iconPath = !children ? new vscode.ThemeIcon('file-code') : undefined;
}
public setSnippet(config: SnippetJsonObject) {
this.config = config;
return this;
}
}
上面我們幫TreeViewItem指定自己的children,並且根據有沒有children來決定展開的狀態。完成後,讓我們再來處理TreeView的資料。
export class DataProvider implements vscode.TreeDataProvider<TreeViewItem> {
...
constructor(private context: vscode.ExtensionContext) { }
private snippetToItem(title: string, snippet: SnippetJsonObject) {
return new TreeViewItem(title).setSnippet(snippet);
}
private snippetJsonToItems(jsonPath: string) {
const snippetJson: { [key: string]: SnippetJsonObject } = jsonfile.readFileSync(jsonPath);
return Object.entries(snippetJson).map(([k, v]) => this.snippetToItem(k, v));
}
private loadDataStorage() {
const worksapcePath = this.context.globalState.get<string>('workspace') as string;
const files = fs.readdirSync(worksapcePath);
try {
this.dataStorage = files.map((foldername) => {
if (fs.statSync(path.join(worksapcePath, foldername)).isDirectory()) {
const snippetItems = this.snippetJsonToItems(path.join(worksapcePath, foldername, `${foldername}.code-snippets`));
return new TreeViewItem(foldername, snippetItems);
}
return new TreeViewItem('global', this.snippetJsonToItems(path.join(worksapcePath, `global.code-snippets`)));
}).sort((a, _) => (a.label === 'global') ? -1 : 1);
} catch (error) {
console.log(error);
}
return this.dataStorage;
}
public getTreeItem(element: TreeViewItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
return element;
}
public getChildren(element: TreeViewItem): vscode.ProviderResult<TreeViewItem[]> {
if(!element) {
return this.dataStorage ?? this.loadDataStorage();
}
return element.children;
}
...
}
上面的改動完成後,我再在執行extension,並點擊choose a workspace,會見到展示的treeview。
好的,今天我們實作了treeview的資料載入,並了解如何顯示多個children item。
明天我們會繼續專案開發,我們明天見,掰掰!