仮想ドキュメント
テキストドキュメントコンテンツプロバイダー 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 を呼び出すと、登録を解除するための Disposable が返されます。プロバイダーは 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 が与えられた際にコンテンツを提供する役割を担う点に注意してください。その代わり、コンテンツプロバイダーはドキュメントを開くロジックに組み込まれているため、常にプロバイダーが考慮されます。
このサンプルでは、エディターで表示すべき URI を作成する 'cowsay' コマンドを使用しています。
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 に通知できます。変更されたドキュメントは、fire メソッドの引数として渡される URI によって識別されます。ドキュメントが開いている場合、プロバイダーは更新されたコンテンツを提供するために再度呼び出されます。
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 ウィンドウで開かれているときは、リモートウィンドウと同様に、左下のリモートインジケーターにラベルが表示されます。拡張機能がこの設定をサポートする方法については、仮想ワークスペースガイドを参照してください。