Virtuelle Dokumente
Die Text Document Content Provider API ermöglicht es Ihnen, schreibgeschützte Dokumente in Visual Studio Code aus beliebigen Quellen zu erstellen. Eine Beispielerweiterung mit Quellcode finden Sie unter: https://github.com/microsoft/vscode-extension-samples/blob/main/virtual-document-sample/README.md.
TextDocumentContentProvider
Die API funktioniert, indem ein URI-Schema beansprucht wird, für das Ihr Provider dann Textinhalte zurückgibt. Das Schema muss bei der Registrierung eines Providers angegeben werden und kann nachträglich nicht mehr geändert werden. Derselbe Provider kann für mehrere Schemata verwendet werden, und für ein einzelnes Schema können mehrere Provider registriert werden.
vscode.workspace.registerTextDocumentContentProvider(myScheme, myProvider);
Das Aufrufen von registerTextDocumentContentProvider gibt ein disposable Objekt zurück, mit dem die Registrierung rückgängig gemacht werden kann. Ein Provider muss nur die Funktion provideTextDocumentContent implementieren, die mit einem URI und einem Cancellation Token aufgerufen wird.
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 });
}
})();
Beachten Sie, dass der Provider keine URIs für virtuelle Dokumente erstellt – seine Aufgabe ist es, Inhalte zu **liefern**, wenn ein solcher URI gegeben ist. Im Gegenzug werden Content Provider in die Logik zum Öffnen von Dokumenten integriert, sodass Provider immer berücksichtigt werden.
Dieses Beispiel verwendet einen 'cowsay'-Befehl, der einen URI erstellt, den der Editor dann anzeigen soll.
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 });
}
});
Der Befehl fordert zur Eingabe auf, erstellt einen URI des cowsay-Schemas, öffnet ein Dokument für den URI und schließlich einen Editor für dieses Dokument. In Schritt 3, dem Öffnen des Dokuments, wird der Provider aufgefordert, Inhalte für diesen URI bereitzustellen.
Damit haben wir einen voll funktionsfähigen Text Document Content Provider. Die nächsten Abschnitte beschreiben, wie virtuelle Dokumente aktualisiert werden können und wie UI-Befehle für virtuelle Dokumente registriert werden können.
Virtuelle Dokumente aktualisieren
Je nach Szenario können sich virtuelle Dokumente ändern. Um dies zu unterstützen, können Provider ein onDidChange-Ereignis implementieren.
Der vscode.Event-Typ definiert den Vertrag für Ereignisse in VS Code. Die einfachste Möglichkeit, ein Ereignis zu implementieren, ist vscode.EventEmitter, wie folgt:
const myProvider = new (class implements vscode.TextDocumentContentProvider {
// emitter and its event
onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>();
onDidChange = this.onDidChangeEmitter.event;
//...
})();
Der Event-Emitter verfügt über eine fire-Methode, mit der VS Code benachrichtigt werden kann, wenn eine Änderung in einem Dokument aufgetreten ist. Das geänderte Dokument wird durch seinen URI identifiziert, der als Argument an die fire-Methode übergeben wird. Der Provider wird dann erneut aufgerufen, um den aktualisierten Inhalt bereitzustellen, vorausgesetzt, das Dokument ist noch geöffnet.
Das ist alles, was benötigt wird, damit VS Code auf Änderungen virtueller Dokumente hört. Ein komplexeres Beispiel, das diese Funktion nutzt, finden Sie unter: https://github.com/microsoft/vscode-extension-samples/blob/main/contentprovider-sample/README.md.
Editor-Befehle hinzufügen
Editor-Aktionen können hinzugefügt werden, die nur mit Dokumenten interagieren, die von einem zugehörigen Content Provider bereitgestellt werden. Dies ist ein Beispielbefehl, der das umkehrt, was die Kuh gerade gesagt hat.
// 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 });
})
);
Der obige Ausschnitt prüft, ob ein aktiver Editor vorhanden ist und ob dessen Dokument zu unserem Schema gehört. Diese Prüfungen sind notwendig, da Befehle für jeden verfügbar (und ausführbar) sind. Dann wird die Pfadkomponente des URI umgekehrt und ein neuer URI daraus erstellt, zuletzt wird ein Editor geöffnet.
Um das Ganze mit einem Editor-Befehl abzurunden, wird ein deklarativer Teil in package.json benötigt. Fügen Sie im Abschnitt contributes diese Konfiguration hinzu:
"menus": {
"editor/title": [
{
"command": "cowsay.backwards",
"group": "navigation",
"when": "resourceScheme == cowsay"
}
]
}
Dies verweist auf den cowsay.backwards-Befehl, der im Abschnitt contributes/commands definiert ist, und besagt, dass er im Editor-Titelmenü (der Werkzeugleiste in der oberen rechten Ecke) erscheinen soll. Nun würde allein dies bedeuten, dass der Befehl für jeden Editor immer angezeigt wird. Dafür wird die when-Klausel verwendet – sie beschreibt, welche Bedingung erfüllt sein muss, damit die Aktion angezeigt wird. In diesem Beispiel wird angegeben, dass das Schema des Dokuments im Editor das cowsay-Schema sein muss. Die Konfiguration wird dann für das commandPalette-Menü wiederholt – es zeigt standardmäßig alle Befehle an.

Ereignisse und Sichtbarkeit
Dokument-Provider sind First-Class-Citizens in VS Code; ihre Inhalte erscheinen in regulären Textdokumenten, sie verwenden dieselbe Infrastruktur wie Dateien usw. Das bedeutet jedoch auch, dass Ihre Dokumente nicht verborgen werden können; sie erscheinen in den onDidOpenTextDocument- und onDidCloseTextDocument-Ereignissen, sind Teil von vscode.workspace.textDocuments und mehr. Die Regel für alle lautet: Überprüfen Sie das scheme von Dokumenten und entscheiden Sie dann, ob Sie etwas mit/für das Dokument tun möchten.
File System API
Wenn Sie mehr Flexibilität und Leistung benötigen, werfen Sie einen Blick auf die FileSystemProvider API. Sie ermöglicht die Implementierung eines vollständigen Dateisystems mit Dateien, Ordnern, Binärdaten, Dateilöschung, -erstellung und vielem mehr.
Eine Beispielerweiterung mit Quellcode finden Sie unter: https://github.com/microsoft/vscode-extension-samples/tree/main/fsprovider-sample/README.md.
Wenn VS Code mit einem Ordner oder Arbeitsbereich eines solchen Dateisystems geöffnet wird, nennen wir dies einen virtuellen Arbeitsbereich. Wenn ein virtueller Arbeitsbereich in einem VS Code-Fenster geöffnet ist, wird dies durch eine Beschriftung in der Remote-Anzeige unten links angezeigt, ähnlich wie bei Remote-Fenstern. Sehen Sie sich den Leitfaden für virtuelle Arbeitsbereiche an, wie Erweiterungen diese Einrichtung unterstützen können.