简体   繁体   English

如何在vscode扩展中实现保存到文件检查覆盖?

[英]How to implement save-to-file-check-overwrite in a vscode extension?

I have to implement a very typical programming pattern in a Visual Studio Code extension: save something to a file, but check if the target file exists before doing so and ask the user if it is ok to overwrite it, if it does. 我必须在Visual Studio Code扩展中实现一种非常典型的编程模式:将某些内容保存到文件中,但是在这样做之前检查目标文件是否存在,并询问用户是否可以覆盖它,如果存在。

Usually I would just open a file save dialog to ask the user to give me a file name and this dialog would do all necessary checks and gets the user confirmation, if necessary. 通常,我只是打开一个文件保存对话框,要求用户给我一个文件名,并且该对话框将进行所有必要的检查,并在必要时得到用户确认。 In vscode however we don't have a file save dialog (however there is a feature request for it). 但是在vscode中,我们没有文件保存对话框(但是有功能要求 )。 So I'm trying to implement this with the limited means we have there. 因此,我正在尝试以有限的方式来实现这一目标。 Fortunately a few weeks ago a new option parameter was added to message dialogs to allow making them modal. 幸运的是,几周前,在消息对话框中添加了一个新的option参数,以使其成为模态。 But somehow I can't get the timing right. 但是不知何故我无法把握时机。 Here's my code: 这是我的代码:

    window.showInputBox({
        placeHolder: "<Enter full file name here>",
        prompt: "Enter the name to an html file to save the diagram\n" }
    ).then((value: string) => {
        if (value) {
            let canWrite = true;
            if (fs.existsSync(value)) {
                canWrite = false;
                window.showWarningMessage("The specified file exists already", { modal: true }, ...[ "Overwrite" ]).then((action: string) => {
                    if (action === "Overwrite") {
                        canWrite = true;
                    }
                });
            }

            if (canWrite) {
                var stream = fs.createWriteStream(value, { encoding: "utf-8", autoClose: true });
                stream.on("error", function (error: any) {
                    window.showErrorMessage("Could not write to file '" + value + "'. " + error);
                });
                stream.once('open', function (fd) {
                    stream.write(text);
                    stream.end();

                    window.showInformationMessage("Diagram successfully written to file '" + value + "'.");
                });
            }
        }
    })

The problem is that the call to window.showWarningMessage is non-blocking, that means while the dialog (which itself is modal) opens the code after if (canWrite) is already executed. 问题在于对window.showWarningMessage的调用是非阻塞的,这意味着对话框(本身是模式的)在if (canWrite)已执行之后打开代码。 This is not a big issue since canWrite is false in this moment, however, once the showWarningMessage thenable returns no code is executed anymore in the outer thenable (from showInputBox ), ie the if (canWrite) is not executed again (as I would expect). 这不是大问题,因为canWrite在此刻为false ,但是,一旦showWarningMessage thenable返回,则外部thenable中不再执行任何代码(来自showInputBox ),即if (canWrite)不再执行(正如我期望的那样) )。 Is it impossible to nest 2 thenables or what else am I doing wrong? 不能嵌套2个罐头,还是我做错了什么?

How would an experienced typescript/vscode develper approach this task? 有经验的打字员/ vscode开发人员将如何处理此任务?

The showWarningMessage is not thenable as you need, you can't nest it. showWarningMessage不thenable你需要,你不能嵌套它。 Instead, you have to create your own Thenable approach, which would require a bit of refactoring. 相反,您必须创建自己的thenable方法,这需要一些重构。

The main idea is that your Saving must return a Promise , and it will control the showWarningMessage return (when needed) 主要思想是您的Saving必须返回Promise ,并且它将控制showWarningMessage返回(必要时)

function saveDiagram(text, filename): Promise<string | boolean> {
    return new Promise((resolve, reject) => {
        if (fs.existsSync(filename)) {
            vscode.window.showWarningMessage("The specified file exists already", { modal: true }, ...[ "Overwrite" ]).then((action: string) => {
                if (action === "Overwrite") {
                    resolve(filename);
                } else {
                    resolve(false);
                }
            });
        } else {
            resolve(filename);
        }
    });
}

Also extract your Writing Diagram on Disk as a new function, to be called latter: 另外,将磁盘上书写图解压缩为新功能,称为新功能:

function writeDiagramOnDisk(text, filename) {
    var stream = fs.createWriteStream(filename, { encoding: "utf-8", autoClose: true });
    stream.on("error", function (error: any) {
        vscode.window.showErrorMessage("Could not write to file '" + filename + "'. " + error);
    });
    stream.once('open', function (fd) {
        stream.write(text);
        stream.end();

        vscode.window.showInformationMessage("Diagram successfully written to file '" + filename + "'.");
    });
}

And now your extension's code will have the thenable approach, as you would expect: 现在,扩展程序的代码将具有您所期望的可行方法:

vscode.window.showInputBox({
    placeHolder: "<Enter full file name here>",
    prompt: "Enter the name to an html file to save the diagram\n" }
).then((value: string) => {
    if (value) {
        saveDiagram(text, value)
            .then((filename) => {
                if (filename) {
                    writeDiagramOnDisk(text, filename)
                }
            });

    }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM