10

Is it possible to run multiple commands from a single keybinding/shortcut, just like a macro operates, in VS Code but without an extension?

I know there are some extensions that can do this but is there a built-in way to do it? Something like:

{
  "command": "<run a few commands in sequence>"
  "key": "alt+r",
  "args": [  // some keybinding
    "editor.action.clipboardCopyAction",   // command ids from the Keyboard Shortcuts editors
    "workbench.action.files.newUntitledFile",  
    "editor.action.clipboardPasteAction",
  ]
}

And do such options support having a delay between each command?

1 Answer 1

20

Available now in the Stable Build v1.77 there is a new built-in command

  • runCommands // run one or more commands in sequence

which can run a single command or multiple commands - just like a macro extension can. See Test: new command to run multiple commands - runCommands. Here are a couple of example keybindings (put into your keybindings.json):

{
  "command": "runCommands",
  "key": "alt+r",                // whatever keybinding you want
  "args": {
    "commands": [

        "editor.action.clipboardCopyAction",

        "workbench.action.files.newUntitledFile",  
        "editor.action.clipboardPasteAction",

        // prompt for save immediately?
        "workbench.action.files.saveAs"
    ]
  },
  "when": "editorTextFocus"  // can use context keys
}

The above would copy the selected text, open a new file, paste the copied text into it and then prompt to save that file.

{
  "command": "runCommands",
  "key": "alt+r",                // whatever keybinding you want
  "args": {
    "commands": [

      "editor.action.copyLinesDownAction",
      "cursorUp",
      "editor.action.addCommentLine",
      "cursorDown"
    ]
  }
}

The above would copy the current line, comment it, and add the same line below (uncommented).

{
  "command": "runCommands",
  "key": "alt+r",                // whatever keybinding you want
  "args": {
    "commands": [

      {                                            // use commands that take args
        "command": "editor.actions.findWithArgs",
        "args": {
          "searchString": "trouble",
          // "regexp": true,
        }
      },
      "editor.action.selectAllMatches",
      "editor.action.commentLine"
    ]
  }
}

The above finds all matches of trouble in the file and comments those lines.

This new runCommands command can not currently replace existing macro extensions, including my favorite multi-command, because some of those have a delay or interval option to add some time between running the commands. I have found it necessary to have that ability in some cases and it isn't an option with runCommands.

But in most cases with runCommands an interval between commands is not needed.


I have filed an issue suggesting that this "macro" operate in an atomic way - that is, when undoing Ctrl+Z it, all the steps/commands should be undone at once, not just one command at a time. Please upvote the github issue if would like to see that behaviour: Consider making runCommands "atomic"


For extension developers, the runCommands command can be run like this:

const commandArray =  [
  "editor.action.copyLinesDownAction",
  "cursorUp",
  "editor.action.addCommentLine",
  "cursorDown"
];

await vscode.commands.executeCommand('runCommands', { commands: commandArray });

or to use commands which take arguments:

const commandArray = [
  { 
    "command": "workbench.action.files.newUntitledFile",
      "args": {
        "languageId": "typescript",
       }
  },
  {
    "command": "type",
      "args": {
        "text": "/* add some text here */"
      }
  }
];

await vscode.commands.executeCommand('runCommands', { commands: commandArray });

Not the answer you're looking for? Browse other questions tagged or ask your own question.