zoukankan      html  css  js  c++  java
  • VSCode Extension中的Virtual Documents使用笔记

      我们在用TypeScript编写VSCode Extension应用时,可以通过VSCode API提供的内置Command "vscode.diff"来快速比较两个文档,有关该命令的参数介绍可以查看官方文档。基本用法如下:

    vscode.commands.executeCommand("vscode.diff", vscode.Uri.file(filePath1), vscode.Uri.file(filePath2), "Comparing Files");

      这里的filePath1和filePath2为要进行比较的两个文档的路径。也就是说,这两个文档是必须真实存在的,而且路径能够被VSCode访问。有时为了需要,在进行比较时我们也可以将文档内容暂时输出到系统临时目录,然后从临时目录加载文档内容。获取系统临时目录的方法可以参考下面的代码:

    import * as os from "os";
    import * as path from "path";
    import * as process from "process";
    
    let platform = os.platform();
    let isWin = platform === "win32";
    let isLinux = platform === "linux";
    let tempDir = isWin ? process.env.TEMP : (isLinux ? path.join(process.env.HOME, 'tmp') : process.env.TMPDIR);
    console.log(tempDir);

       但是使用系统临时目录会带来另外一个问题,看下面的截图,在比较文档的界面右上角,有一个菜单可以直接点击打开文档,此时是从临时目录打开的,但有时我们并不想让用户知道文档是暂时存放在临时目录里的。有没有什么解决办法呢?我没有找到通过配置的方式将该菜单隐藏或者改变其行为,但是有两个变通的方法:一是不使用系统临时目录,仍然从文档的原始位置进行加载;二是使用VSCode提供的Virtual Documents

      下面是使用Virtual Documents之后的界面,可以看到与之前相比少了显示文档的路径和打开文档的菜单。

      下面是具体的实现。

      按照官方文档的介绍,我们需要定义一个TextDocumentContentProvider类的实例,其中的provideTextDocumentContent方法会返回Virtual Documents的具体内容。

     1 private async getDocumentText(fileFullPath: string): Promise<string> {
     2     return new Promise<string>(resolve => {
     3         fs.readFile(fileFullPath, "UTF-8", (err, data) => {
     4             if (err) {
     5                 console.log(err);
     6                 resolve("");
     7             } else {
     8                 resolve(data);
     9             }
    10         });
    11     });
    12 }
    13 
    14 private sourceProvider = new class implements vscode.TextDocumentContentProvider {
    15     onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>();
    16     onDidChange = this.onDidChangeEmitter.event;
    17 
    18     async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
    19         let oSource = await getDocumentText(uri.path);
    20         let oSourceContent = JSON.stringify(oSource, null, "	");
    21         return oSourceContent;
    22     }
    23 };

      其中第19行通过getDocumentText方法从指定的路径读取了文档的内容,然后使用JSON.stringify将其格式化为标准的JSON文档,并返回对应的内容。onDidChange提供了文档被更新时的事件,我们可以在文档内容被修改时手动触发该事件,稍后会介绍。

      接下来是注册command。

    subscriptions.push(vscode.workspace.registerTextDocumentContentProvider("sourceSchema", sourceProvider));

      注意这里的第一个参数schema非常重要!后面在传递文件url时都要带上这个schema,相当于它是一个标识,用来表示对该url的操作都通过sourceProvider类提供的方法来处理。

      相应地,如果vscode.diff的第二个文档你也希望使用Virtual Documents,那么就还需要定义TextDocumentContentProvider类的另一个实例。provideTextDocumentContent方法

    1 subscriptions.push(vscode.workspace.registerTextDocumentContentProvider("compareSchema", new class implements vscode.TextDocumentContentProvider {
    2     onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>();
    3     onDidChange = this.onDidChangeEmitter.event;
    4 
    5     async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
    6         return ""; // return file content from here
    7     }
    8 }));

      这里我简化了代码实现,没有单独定义TextDocumentContentProvider类的实例,而是直接通过subscriptions.push来注册command。其中的provideTextDocumentContent方法可以根据需要返回文档的内容,这里就不再给出对应的代码。

      好了,下面我们来看看在vscode.diff中如何使用它们。

    const uriSource = vscode.Uri.parse("sourceSchema:" + filePath1);
    const uriCompare = vscode.Uri.parse("compareSchema:" + filePath2);
    vscode.commands.executeCommand("vscode.diff", uriSource, uriCompare, "Comparing Files");

      注意这里的filePath1和filePath2的前面都要加上对应的schema,否则文档被打开时就不会使用对应的TextDocumentContentProvider类的实例来处理,而会报找不到文档路径的错误。

      当修改文档内容后,可以手动触发TextDocumentContentProvider类的onDidChange事件来刷新已打开的文档内容,下面是对应的伪代码:

    await writeFile(vscode.Uri.parse(filePath1).fsPath, fileContent);
    sourceProvider.onDidChangeEmitter.fire(vscode.Uri.parse("sourceSchema:" + filePath1));

      另一个需要注意的地方是,通过Virtual Documents创建的文档都是以只读方式打开的,所以用户无法在编辑器中手动修改文件内容,我们可以在TextDocumentContentProvider类的provideTextDocumentContent方法中将已修改的内容返回。其它有关Document提供的事件可以查阅官方文档。

  • 相关阅读:
    JavaScript
    HTML
    DockerDesktop安装mysql
    c语言ld returned 1 exit status😂
    eclipse项目导入idea jdk版本不一致😵
    markdown语法
    【Kali】Kali Linux更新5.2.9后 Vmware Workstation无法正常启动
    【NetDevOps】网络自动化运维--1获取用户基本信息
    【NetDevops】网络自动化运维--1获取用户基本信息
    Kali Linux中安装Python虚拟环境
  • 原文地址:https://www.cnblogs.com/jaxu/p/15069474.html
Copyright © 2011-2022 走看看