7

I can't seem to find a good list of documented commands that can be run from VSCode keybindings.

On the online VSCode documentation, the Commands Guide lists two ways to discover commands:

The commands found for keyboard shortcuts are usually "simple" commands that do not take arguments. The "advanced commands api" seems to be missing some very basic, fundamental commands.

For example, on the VSCode Keybindings page there is a section called "Command Arguments" that has the following example entry:

{ "key": "enter", "command": "type",
  "args": { "text": "Hello World" },
  "when": "editorTextFocus" }

But I don't see anywhere that the type command is documented. So I assume there are probably several other basic commands like this that exist but I don't know where to find documentation for them.

Anyway, what I am really looking for at the moment is a command that I can run to do a pre-defined search and replace in the current editor, specifying the find text, replacement text, and options... something like below:

{ "key": "ctrl+shift+8", 
  "command": "findReplaceAll",
  "args": { 
    "findText": "Company(\\w+)", 
    "replaceText": "User$1"
    "options": { "ignoreCase": false, "wholeWord": true, "regex": true }
  },
  "when": "editorTextFocus" }

But I haven't been able to find any such findReplaceAll command or anything similar in the documentation, but certainly something like this must exist, right?

Thanks!

drwatsoncode
  • 4,721
  • 1
  • 31
  • 45

4 Answers4

5

As @AurSaraf points out, there is new work coming that will allow creating a command (or use in an extension) of a built-in way to find in the current file with preset find/replace and options.

I have commented on the github issues trying to get the args to be consistent with other similar commands to no avail. Here are the current available args in a keybinding:

{
  "key": "alt+p",
  "command": "editor.actions.findWithArgs",
  "args": {

    "searchString": "howd\\d",      // double-escaped
    "replaceString": "qqqq9",
    "isRegex": true,
    // "regexOverride": 1,
    "findInSelection": false,
    "matchWholeWord": false,
    // "matchCase": false,
    // "matchCaseOverride": 0,
    "preserveCase": false,
    "isCaseSensitive": false
    // "preserveCaseOverride": 0,
    // "wholeWordOverride": 0
  }
}

The commented-out args are not available although intellisense shows that they are - so the command is still a little "rough" - and currently available only in the Insiders Build. Do not rely on the intellisense for the args keys - many of them are mis-named or non-functional at this point.

Also, note that instead of query and replace as used in the workbench.action.findInFiles and in the search.action.openEditor (open a new search editor) keybindings, this command currently uses searchString and replaceString for some reason.


For a powerful extension to do lots of predefined find/replaces or searches/replaces with all arguments, see Find and Transform (which I wrote). In particular with a lot of options for setting the files to include scope filter - like the current file or the last files found in the previous search results to narrow a search to only those files.


There is also a built-in way to do this for finding across files, I don't know if arguments were added after your question or not. In any case, I agree that it is sometimes difficult to discover which commands can take arguments.

Sometimes, intellisense within the keybindings in your command will surface them but not always.

So examining this:

{
 "key": "ctrl+shift+f",
 "command": "workbench.action.findInFiles",
 "args": {
   <cursor here>  // cursor there and type Ctrl+space
  }
}

will show those the available args as in the below example.


{
  "key": "ctrl+shift+f",
  "command": "workbench.action.findInFiles",
  "args": {

    "query": "Company(\\w+)",   // needs to be double-escaped
    "replace": "User$1",
    "triggerSearch": true,
    "isRegex": true,
  
    // "filesToExclude": "",
    // "filesToInclude": "",
    "matchWholeWord": true,
    "isCaseSensitive": true
  }
},

This will perform the search but not do the actual replacement in your files - you will have to trigger replace [all] yourself.

Mark
  • 143,421
  • 24
  • 428
  • 436
  • I like Mark's approach, `"workbench.action.findInFiles"` seems like the [best-documented command (arguments as described by Mark, and here)](https://github.com/microsoft/vscode/issues/108459#issuecomment-961541596) Please note `"workbench.action.findWithArgs"` may be an **outdated** command, in my VS Code (1.62.3; the latest as of 11/29/2021), I get an error "command 'editor.actions.findWithArgs' not found". Finally, you can use `tasks.json` to create a task to "trigger `replace [all]` yourself"; the `"search.action.replaceAll"` command worked for me (but opened a confirmation dialog) – Nate Anderson Nov 29 '21 at 22:09
  • 1
    @TheRedPea I should have made it clearer that `workbench.action.findWithArgs` is in the Insiders Build now (I mentioned it was coming). So it is likely to hit Stable soon - I don't know if it will be in this next release though. – Mark Nov 29 '21 at 22:28
  • Oops, I see you made that clear. I didn't pay attention; thanks! – Nate Anderson Nov 29 '21 at 22:33
  • I see how I may have confused "**editor**.action**s**.findWithArgs", and "**workbench**.action.findWithArgs", I need to be careful! Also same [GitHub link/thread](https://github.com/microsoft/vscode/issues/108459#issuecomment-961527537) mentions an Insider build, like Mark said -- so I look forward to the build. – Nate Anderson Nov 29 '21 at 22:51
  • I promise to stop commenting soon! I get confused between the new `editor.actions.findWithArgs`, vs `editor.action.startFindReplaceAction`; I think the former [*does* allow us to pass args](https://github.com/microsoft/vscode/blob/8e96e0b389aedf46423431487190b878d4243edb/src/vs/editor/contrib/find/findController.ts#L588) to give initial values , i.e. in Find/Replace fields; but the latter [does *not*](https://github.com/microsoft/vscode/blob/8e96e0b389aedf46423431487190b878d4243edb/src/vs/editor/contrib/find/findController.ts#L829) allow any args to initialize the state – Nate Anderson Nov 29 '21 at 22:51
  • If you are willing to use `tasks.json` to perform this task (i.e. without installing VS Code extensions), you could chain together multiple commands (i.e. `workbench.action.findInFiles`->`search.action.replaceAll`, using a task that `dependsOn` other tasks ** which run in `sequence` order**. Then again, if you're willing to use `tasks.json` to accomplish this, you have the power of your shell(s), ["(for example: bash, cmd, or PowerShell)"](https://code.visualstudio.com/docs/editor/tasks), so you have the power of Powershell or bash functions – Nate Anderson Nov 29 '21 at 23:45
3

I was looking for an API to do this as an extension writer and it seems one was added less than a month ago (which you could also presumably use to manually define a keybinding, if I understand correctly):

https://github.com/microsoft/vscode/commit/8e96e0b389aedf46423431487190b878d4243edb

Aur Saraf
  • 3,214
  • 1
  • 26
  • 15
2

Install the extension Replace Rules.

Construct a search-replace in your settings.json (Workspace or User). Read the page about the possibilities.

  "replacerules.rules": {
    "Replace User": {
      "find": "User(\d+)",
      "replace": "Player$1"
    }
  }

In keybindings.json define the following keybinding:

  {
  "key": "ctrl+shift+alt+u",
  "command": "replacerules.runRule",
  "when": "editorTextFocus",
  "args": { "ruleName": "Replace User"}
  }

If you select some text the search-replace will only be performed within the selection.

rioV8
  • 24,506
  • 3
  • 32
  • 49
  • 1
    Thanks. I will try this out. I was hoping to find built-in commands to do this (rather than an extension), but it appears that the commands are not documented well (and it's possible a built-in search and replace command just doesn't exist). Anyway I think your solution will work just fine. – drwatsoncode Sep 10 '19 at 02:52
1

If you are willing to use tasks.json; a native VS Code concept -- and you have access to a shell like bash (I use Windows with GitBash), or Powershell (builtin to Windows), you can use the power of that shell without a VS Code extension, or any new deployments -- in my case, I use sed command to make file replacements:

{
        "label": "find-replace-task-name",
        "type": "shell",
        "command": "sed -i -E \"s/Company(\\w+)/User\\1/g; s/user/User/g\" \"${file}\""
},

Advantages of using tasks.json with a shell command:

  • In my case, I want to other developers on my team to use my solution, so I like using the tasks.json because it's stored in the .vscode folder, which we do include in our version control (keybindings.json is not stored in .vscode folder)
  • I can use my solution on today's version of VSCode (I don't need Insiders build),
  • I can use my it without installing any VSCode extension.
  • Because my task relies on a shell, I get the power of a shell and any of its "builtin" commands

In my case, I could use the bash shell and the sed utility, which are powerful, expressive and easy-to-use for file manipulation (including find-replace).

A shell helps me approach this question from a different angle; i.e. "how to find-replace a file, using (bash|Powershell)..." (So you could adapt this approach to Powershell instead of bash, more on that...)

Notice:

  • I used sed to perform multiple find-replacements (which I needed, the OP of this question did not need - So I chained a replacement of "user"->"User" in my command)
  • I used the "${file}" variable replacement to pass the filepath to the currently-open-file

And I can associate with a keybinding so it's easier to run the task. Notice the keybinding only works "when":"editorTextFocus", maybe I should add a condition that there is some file open!

{
    "key": "ctrl+shift+alt+s",
    "when": "editorTextFocus",
    "command": "workbench.action.tasks.runTask",
    "args": "find-replace-task-name"
}

There are some disadvantages to my approach:

  • the sed script I write is very dense, and has multiple levels of "escape characters", so it's hard to read/interpret/troubleshoot (compared to an easy-to-read JSON snippet like {"searchString":..., "replaceString":...})
  • it operates on the file outside of VS Code, so no "Undo" operation it seems like you can "undo" the changes, specifically you would "undo" VS Code's automatic reloading of the file, (VS Code probably recognizes that sed modified the file; but VS Code still lets you "Ctrl+Z" to go back before the modifications)
  • can't work unless you have a file open
  • doesn't use the $1 for RegEx replacement, instead uses the "extended regular expressions" flag -E and the syntax \1, etc
  • etc...
Nate Anderson
  • 18,334
  • 18
  • 100
  • 135