VS Code: bind one key to multiple commands without an extension

People wanting to assign multiple commands to a single keybinding in VS Code typically use an extension, such as multi-command or macros. However, there is another, lesser known method to achieve this using built-in functionality of VS Code — user level tasks.

The user level tasks method has its disadvantages:

  • needs a workspace folder, i.e. the task won’t run if you’re editing a single file;
  • doesn’t work for inserting text.

User level tasks is a new feature in VS Code available since version 1.42 (January 2020):

Tasks declared in tasks.json are now supported at the User Settings level. If you have a build script that you use across many projects, or if you don’t want your tasks in a project folder, you can add your tasks in the user tasks.json file. Run the Tasks: Open User Tasks command to create user level tasks and these tasks will be available across all folders and workspaces. Only the shell and process task types are supported here.

Let’s say you want to bind “save file” + “build” commands to Cmd+R using this method.

Step 1. Run “Tasks: Open User Tasks” command to create or open a user level tasks file. If it asks for a template, choose “Others”.

Step 2. Declare the tasks, like so:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "cmdR-1",
            "command": "${command:workbench.action.files.save}"
        },
        {
            "label": "cmdR-2",
            "command": "${command:workbench.action.tasks.build}"
        },
        {
            "label": "cmdR-All",
            "dependsOrder": "sequence",
            "dependsOn": [
                "cmdR-1",
                "cmdR-2"
            ],
            "problemMatcher": []
        }
    ]
}

Note: task labels can be anything. I use “cmdR-…” format for my own convenience.

Step 3. Add a keybinding to your keybindings.json:

{
    "key": "cmd+r",
    "command": "workbench.action.tasks.runTask",
    "args": "cmdR-All"
}

Press Cmd+R to see if it works.

It should work with other types of commands too. For example, comment out a line + move the cursor down:

{
    "label": "cmdR-1",
    "command": "${command:editor.action.commentLine}"
},
{
    "label": "cmdR-2",
    "command": "${command:cursorDown}"
},
...

You can chain as many commands as you want. Each command has to be declared as a separate task. Don’t forget to add the labels of your tasks to the dependsOn property of the “aggregate” task (“cmdR-All” in my example above).

The ${command:command-ID} format is called a command variable and, as far as I know, it doesn’t support arguments.

You can find and copy command IDs if open Preferences > Keyboard Shortcuts:

I hope you get the idea.

* * *

I’d like to take an opportunity to promote my extension for VS Code — Refresh Browser (macOS only), which lets you refresh browser with a keybinding without losing focus on VS Code. Here’s how you can use the refresh browser command in your tasks: ${command:extension.refreshBrowser}.

This entry was posted in How to’s and tagged . Bookmark the permalink.

6 Responses to VS Code: bind one key to multiple commands without an extension

  1. anonymous says:

    Add this to remove the 2 second delay from keypress to execution of the tasks:

    “typescript.tsc.autoDetect”: “off”,

  2. Ashark says:

    Thanks for the article. I have found a way how to pass arguments to the task command. It can be done with ${input:something} variable. See example here: stackoverflow.com/a/72202313/7869636

  3. jose says:

    very useful, thanks

Leave a Reply

Your email address will not be published. Required fields are marked *