vscode extension API editor.replace replace only first match while match 2 instances

46 Views Asked by At

developing an VS code extension where

  • search for color hex code in whole css document
  • replace the color hex code with variable name

although it match all color hex code but replace the only first instance and stops

below is the code snippet


export function activate(context: vscode.ExtensionContext) {
    let activeEditor = vscode.window.activeTextEditor;
    function replaceWithinDocument() {
        if (!activeEditor) {
            return;
        }
        const text = activeEditor.document.getText();

        const reg = new RegExp('(?<color>#[0-9a-f]{3,6})', 'gim');

        const matches = text.matchAll(reg);

        const variableList = {};
        let i = 0;

        for (const match of matches) {
            const { index, groups } = match;
            i++;
            console.log({ match });
            const startPos = activeEditor.document.positionAt(index!);
            const endPos = activeEditor.document.positionAt(index! + match[0].length);
            console.log({ i, startPos, endPos });
            //Creating a new range with startLine, startCharacter & endLine, endCharacter.
            let range = new vscode.Range(startPos, endPos);
            // eslint-disable-next-line @typescript-eslint/naming-convention
            Object.assign(variableList, { [`--var-${i}`]: groups?.color });
            activeEditor.edit(editBuilder => {
                editBuilder.replace(range, `--var-${i}`);
            });
        }

        console.log({ variableList });
    }

   function triggerUpdateDecorations(throttle = false) {
        if (timeout) {
            clearTimeout(timeout);
            timeout = undefined;
        }
        if (throttle) {
            timeout = setTimeout(replaceWithinDocument, 500);
        } else {
            replaceWithinDocument();
        }
    }

    if (activeEditor) {
        triggerUpdateDecorations();
    }

Debug console for extension

final document


body {
  background-color: --var-1;
  color: #223344;
}

you can see in the screenshot that console.log({ variableList }); have both color code in it

so what is wrong here?

1

There are 1 best solutions below

1
On BEST ANSWER

See allow delay between edits via vscode extension api. Because of the particular nature of the editBuilder object

The editBuilder "expires" once you return from the callback passed to TextEditor.edit.

you should put your matches loop inside the call to the edit call like this sample code:

  //  get your matches above first

  editor.edit(editBuilder => {

    let i = 0;

    for (const match of matches) {

      // build your replacement here

      const matchStartPos = document.positionAt(match.index);
      const matchEndPos = document.positionAt(match.index + match[0].length);
      const matchRange = new Range(matchStartPos, matchEndPos);
      editBuilder.replace(matchRange, resolvedReplace);

    }
  }).then(async (resolved) => {

  });