Tyler James Leonhardt
Tyler James Leonhardt

Reputation: 884

Implementing a "Save As" using the vscode API

I've been trying to figure out the best way to implement a "Save As" using the vscode extension API.

So far, here's the best I've got:

// First turn the path we were given into an absolute path
// Relative paths are interpreted as relative to the original file
const newFileAbsolutePath = path.isAbsolute(saveFileDetails.newPath) ?
    saveFileDetails.newPath :
    path.resolve(path.dirname(saveFileDetails.filePath), saveFileDetails.newPath);  
// Create an "untitled-scheme" path so that VSCode will let us create a new file with a given path
const newFileUri = vscode.Uri.parse("untitled:" + newFileAbsolutePath); 
// Now we need to copy the content of the current file,
// then create a new file at the given path, insert the content,
// save it and open the document
return vscode.workspace.openTextDocument(saveFileDetails.filePath)
    .then((oldDoc) => {
        return vscode.workspace.openTextDocument(newFileUri)
            .then((newDoc) => {
                return vscode.window.showTextDocument(newDoc, 1, false)
                    .then((editor) => {
                        return editor.edit((editBuilder) => {
                            editBuilder.insert(new vscode.Position(0, 0), oldDoc.getText());
                        })
                        .then(() => {
                            return newDoc.save()
                                .then(() => EditorOperationResponse.Completed);
                        });
                    });
            });
    });

We open the old doc, then open a new doc (which is an untitled document), then insert the old doc's text into the new doc and then save the new doc.

The new doc then closes (for some reason).

Anyone have any advice?

Upvotes: 1

Views: 1697

Answers (1)

Gama11
Gama11

Reputation: 34158

It seems like this is a known issue and caused by the use of the untitled:// scheme:

TextDocument.save() closes untitled documents (#29156)

For now, you could work around it by just reopening the file again since you know the final URI (unlike in the case of the person who reported the issue).

newDoc.save().then((completed) => {
    const finalUri = vscode.Uri.file(newFileAbsolutePath);
    vscode.workspace.openTextDocument(finalUri).then((doc) => {
        vscode.window.showTextDocument(doc, {preview: false});
    })
});

Unfortunatenly this does lead to a noticable "flicker"-effect. To avoid this, I'd suggest to simply bypass the VSCode API and use fs for file IO, and only use vscode for showing the file at the end. This also simplifies the code quite a bit:

import * as fs from 'fs';

function runCommand() {
    // obtain newFileAbsolutePath / oldFileAbsolutePath

    var oldDocText = fs.readFileSync(oldFileAbsolutePath);
    fs.writeFileSync(newFileAbsolutePath, oldDocText);

    const finalUri = vscode.Uri.file(newFileAbsolutePath);
    vscode.workspace.openTextDocument(finalUri).then((doc) => {
        vscode.window.showTextDocument(doc, {preview: false});
    });
}

Upvotes: 2

Related Questions