Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TextEditorEdit.replace is async, how to execute code when it is finished?

While I was developing this VS Code extension, I had to move the cursor to a line that I created with vscode.window.activeTextEditor.edit method, but then I realised that the line didn't exist when I tried to move the cursor, so I had to put a setTimeout to try to move the cursor:

let editor: TextEditor = vscode.window.activeTextEditor;
let selections: Selection[] = editor.selections;
let doc: TextDocument = editor.document;

editor.edit(function (edit: TextEditorEdit): void {
    selections.forEach((selection: Selection, index: number) => {
        for (let i = selection.start.line; i <= selection.end.line; i++) {
            let selLine: TextLine = doc.lineAt(i);
            let insertPos: Range = selLine.range;
            let insertLineText: string = selLine.text;

            // This is async :(
            edit.replace(insertPos, insertSemicolon(insertLineText, newLine));
        }
    });

    if (newLine) {
        // Move cursor to the next line
        setTimeout(() => {
            vscode.commands.executeCommand("cursorMove", {
                to: "down",
                by: "wrappedLine",
                select: false,
                value: 1
            }).then(() => {
                vscode.commands.executeCommand("cursorMove", {
                    to: "wrappedLineEnd",
                    by: "wrappedLine",
                    select: false
                })
            });
        }, 50);
    }
});

As I know that this isn't a good practice, because I cannot be sure that the line will be there when the code executes, I'm trying to find a way to execute this code only when the edit is finished to replace everything.

like image 844
Christian Valentin Avatar asked Oct 21 '25 20:10

Christian Valentin


1 Answers

You need to move the cursor operations outside of the edit block. The callback in TextEditor.edit builds up a set of edits which are then applied asynchronously. edit returns a Thenable<boolean> to indicate if the edits completed successfully.

Try something like:

let editor: TextEditor = vscode.window.activeTextEditor;
let selections: Selection[] = editor.selections;
let doc: TextDocument = editor.document;

editor.edit(function (edit: TextEditorEdit): void {
    selections.forEach((selection: Selection, index: number) => {
        for (let i = selection.start.line; i <= selection.end.line; i++) {
            let selLine: TextLine = doc.lineAt(i);
            let insertPos: Range = selLine.range;
            let insertLineText: string = selLine.text;

            edit.replace(insertPos, insertSemicolon(insertLineText, newLine));
        }
    });
}).then(success => {
    if (!success) {
        return
    }
     if (newLine) {
        // Move cursor to the next line
        ...
    }
})
like image 184
Matt Bierner Avatar answered Oct 23 '25 16:10

Matt Bierner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!