虚拟文档
文本文档内容提供程序 API 允许您在 Visual Studio Code 中从任意来源创建只读文档。您可以在以下位置找到带有源代码的示例扩展: https: //github.com/microsoft/vscode-extension-samples/blob/main/virtual-document-sample/README.md。
文本文档内容提供者
该 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,然后编辑器应显示该 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 });
}
});
该命令提示输入,创建 -scheme 的 uri cowsay
,打开该 uri 的文档,最后打开该文档的编辑器。在第 3 步中,打开文档,要求提供者提供该 uri 的内容。
这样我们就有了一个功能齐全的文本文档内容提供程序。接下来的部分将介绍如何更新虚拟文档以及如何为虚拟文档注册 UI 命令。
更新虚拟文档
根据具体情况,虚拟文档可能会发生变化。为了支持这一点,提供者可以实现一个onDidChange
事件。
-typevscode.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"
}
]
}
这引用了-cowsay.backwards
部分中定义的 - 命令contributes/commands
,并表示它应该出现在编辑器标题菜单(右上角的工具栏)中。现在,这意味着该命令始终为每个编辑器显示。这就是when
- 子句的用途 - 它描述了必须满足什么条件才能显示操作。在此示例中,它指出编辑器中文档的方案必须是 -scheme cowsay
。然后对菜单重复配置commandPalette
- 默认情况下显示所有命令。
事件和能见度
文档提供者是 VS Code 中的一等公民,它们的内容出现在常规文本文档中,它们使用与文件相同的基础设施等。但是,这也意味着“您的”文档无法隐藏,它们将出现在 -events 中,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 窗口中打开时,会通过左下角的远程指示器中的标签显示,类似于远程窗口。请参阅虚拟工作空间指南,扩展如何支持该设置。