虛擬文件
文字文件內容提供者 API 允許您從任意來源在 Visual Studio Code 中建立唯讀文件。您可以在以下位置找到包含原始碼的範例擴充功能:https://github.com/microsoft/vscode-extension-samples/blob/main/virtual-document-sample/README.md。
TextDocumentContentProvider
此 API 的運作方式是宣告一個 URI 結構描述,您的提供者會針對該結構描述傳回文字內容。結構描述必須在註冊提供者時提供,且之後無法變更。相同的提供者可用於多個結構描述,且可以為單一結構描述註冊多個提供者。
vscode.workspace.registerTextDocumentContentProvider(myScheme, myProvider);
呼叫 registerTextDocumentContentProvider
會傳回一個可處置物件,可用於還原註冊。提供者僅必須實作 provideTextDocumentContent
函式,該函式會使用 URI 和取消符號呼叫。
const myProvider = new (class implements vscode.TextDocumentContentProvider {
provideTextDocumentContent(uri: vscode.Uri): string {
// invoke cowsay, use uri-path as text
return cowsay.say({ text: uri.path });
}
})();
請注意,提供者不會為虛擬文件建立 URI - 其角色是針對指定的 URI 提供內容。反過來說,內容提供者會連線到開啟文件邏輯,以便始終考量提供者。
此範例使用 'cowsay' 命令,該命令會製作編輯器應顯示的 URI
vscode.commands.registerCommand('cowsay.say', async () => {
let what = await vscode.window.showInputBox({ placeHolder: 'cow say?' });
if (what) {
let uri = vscode.Uri.parse('cowsay:' + what);
let doc = await vscode.workspace.openTextDocument(uri); // calls back into the provider
await vscode.window.showTextDocument(doc, { preview: false });
}
});
此命令會提示輸入,建立 cowsay
結構描述的 URI,開啟該 URI 的文件,最後開啟該文件的編輯器。在步驟 3 開啟文件時,系統會要求提供者提供該 URI 的內容。
有了這個,我們就有了一個功能完整的文字文件內容提供者。接下來的章節將說明如何更新虛擬文件,以及如何為虛擬文件註冊 UI 命令。
更新虛擬文件
虛擬文件可能會根據情境而變更。為了支援這一點,提供者可以實作 onDidChange
事件。
vscode.Event
類型定義了 VS Code 中事件處理的合約。實作事件最簡單的方法是 vscode.EventEmitter
,如下所示
const myProvider = new (class implements vscode.TextDocumentContentProvider {
// emitter and its event
onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>();
onDidChange = this.onDidChangeEmitter.event;
//...
})();
事件發射器具有 fire
方法,可用於在文件發生變更時通知 VS Code。已變更的文件會透過其 URI 識別,URI 會以引數形式提供給 fire
方法。然後,系統將再次呼叫提供者以提供更新的內容,前提是文件仍為開啟狀態。
這就是讓 VS Code 監聽虛擬文件變更所需的一切。若要查看更複雜的範例,其中運用了此功能,請參閱:https://github.com/microsoft/vscode-extension-samples/blob/main/contentprovider-sample/README.md。
新增編輯器命令
可以新增僅與相關聯內容提供者所提供文件互動的編輯器動作。這是一個範例命令,可反轉乳牛剛才說的話
// register a command that updates the current cowsay
subscriptions.push(
vscode.commands.registerCommand('cowsay.backwards', async () => {
if (!vscode.window.activeTextEditor) {
return; // no editor
}
let { document } = vscode.window.activeTextEditor;
if (document.uri.scheme !== myScheme) {
return; // not my scheme
}
// get path-components, reverse it, and create a new uri
let say = document.uri.path;
let newSay = say
.split('')
.reverse()
.join('');
let newUri = document.uri.with({ path: newSay });
await vscode.window.showTextDocument(newUri, { preview: false });
})
);
上面的程式碼片段檢查我們是否有活動中的編輯器,以及其文件是否為我們的結構描述之一。需要這些檢查,因為命令對所有人皆可用 (且可執行)。然後,URI 的路徑元件會反轉,並從中建立新的 URI,最後開啟編輯器。
若要使用編輯器命令來完成工作,則需要在 package.json
中新增宣告式部分。在 contributes
區段中,新增此組態
"menus": {
"editor/title": [
{
"command": "cowsay.backwards",
"group": "navigation",
"when": "resourceScheme == cowsay"
}
]
}
這會參考 contributes/commands
區段中定義的 cowsay.backwards
命令,並說明它應出現在編輯器標題選單 (右上角的工具列) 中。現在,僅此一項就表示命令始終顯示,適用於每個編輯器。這就是 when
條件子句的用途 - 它描述了必須為真才能顯示動作的條件。在此範例中,它指出編輯器中文件的結構描述必須為 cowsay
結構描述。然後,針對 commandPalette
選單重複組態 - 預設會顯示所有命令。
事件與可見性
文件提供者在 VS Code 中是一等公民,其內容會顯示在一般文字文件中,它們使用與檔案等相同的基礎結構。然而,這也表示「您的」文件無法隱藏,它們會出現在 onDidOpenTextDocument
和 onDidCloseTextDocument
事件中,它們是 vscode.workspace.textDocuments
的一部分等等。適用於所有人的規則是檢查文件的 scheme
,然後決定您是否要對文件執行某些操作/為了文件執行某些操作。
檔案系統 API
如果您需要更高的彈性和功能,請查看 FileSystemProvider
API。它允許實作完整檔案系統,具有檔案、資料夾、二進位資料、檔案刪除、建立等功能。
您可以在以下位置找到包含原始碼的範例擴充功能:https://github.com/microsoft/vscode-extension-samples/tree/main/fsprovider-sample/README.md。
當 VS Code 在此類檔案系統的資料夾或工作區上開啟時,我們稱之為虛擬工作區。當虛擬工作區在 VS Code 視窗中開啟時,這會顯示在左下角遠端指示器中的標籤中,類似於遠端視窗。請參閱虛擬工作區指南,了解擴充功能如何支援該設定。