Miu
Miu

Reputation: 844

Set/use a keyboard shortcut to replace a character in Visual Studio Code

What I want to know

Purpose

I use Visual Studio Code on a Mac. I often replace "" with ''.

For example,

const foo = "foo";
const bar = "bar";

⬇️

const foo = 'foo';
const bar = 'bar';

I usually use Visual Studio Code's replace function with a regular expression like this. Replace VSCode

I want to register a keyboard shortcut for this operation because I do it frequently.

What I tried / Issue

I opened keybindings.json and tried to set a keyboard shortcut in it. But I have no idea what to write.

[
  {
    "key": "shift+cmd+'",
    "command": "actions.find" // ?????????
  }
]

What should I write in there? Or is there a default shortcut to replace "" with ''?


Edit:

According to Jeff Brower's answer (thank you!), "args" can be helpful for my purpose. I'm trying to change his/her code.

I wrote in keybindings.json like this but it doesn't work:

  {
    "key": "shift+cmd+'",
    "command": "editor.action.startFindReplaceAction",
    "args": {
      "query": "\"(.+)\"",
      "replace": "'$1'",
      "triggerSearch": true,
      "isRegex": true,
      "matchWholeWord": true,
      "isCaseSensitive": false
    }
  }

Upvotes: 1

Views: 2055

Answers (2)

Mark
Mark

Reputation: 180631

It can be done with an extension, I'll show the code for that. An extension allows you to set a keybinding if that is what you want.

But it is easy to accomplish what you want with these steps.

  1. Select any ".
  2. Cmd+Shift+L to select all occurrences of ".
  3. Type '.

The working part of the extension code:

let disposable = vscode.commands.registerCommand('yourExtensionName.someCommandName', async function () {

  const fileName = vscode.workspace.asRelativePath(vscode.window.activeTextEditor.document.uri);

  vscode.commands.executeCommand('workbench.action.findInFiles',
    {
      query: "\"(.+)\"",
      replace: "'$1'",
      triggerSearch: true,
      isRegex: true,
      filesToInclude: fileName
      // preserveCase: true,
      // useExcludeSettingsAndIgnoreFiles: true,
      // isCaseSensitive: true,
      // matchWholeWord: true,
      // filesToExclude: "./*.css"
      }).then(() => {
        setTimeout(() => {
          vscode.commands.executeCommand('search.action.replaceAll');
        }, 1000);
      });
});

context.subscriptions.push(disposable);

Demo:

find in file

The extension works with the findInFiles command, since actions.find will not take arguments. But it is restricted to the current file. It finds the current fileName:

const fileName = vscode.workspace.asRelativePath(vscode.window.activeTextEditor.document.uri);

and uses that in the filesToInclude argument.

Upvotes: 2

Jeff Brower
Jeff Brower

Reputation: 602

According to the answers of this question, there is no built-in way to do this. However, I did get a similar keybinding to work. This searches all files in the workbench:

{
    "key": "ctrl+shift+'",
    "command": "workbench.action.findInFiles",
    "args": {
        "query": "\"((?:\\\\[\"'\\\\bfnrt]|[^\\\\\"'\\n\\r])*)\"",
        "replace": "'$1'",
        "triggerSearch": true,
        "isRegex": true,
        "matchWholeWord": true,
        "isCaseSensitive": true
    }
}

The main caveat is that it doesn't automatically perform the replacement, but it does fill in the fields of the find and replace.

I also improved the regular expression a bit to handle javascript-style escaping, and allow empty strings (unit tests). To use your original regular expression, replace the whole string with:

"\"(.+)\""

Upvotes: 1

Related Questions