Which Key is an editor feature to help you navigate a tree of customisable keyboard shortcuts with a lens on accessible sub-branches:
Which Key for Emacs and Which Key for Neovim are both popular, and the Helix editor ships with the feature by default, where it’s bound to the space key:
It works well to orient new users but it’s great for power users too, who can grow a personal tree of shortcuts instead of putting up with default keybindings.
Shortcut chords in VS Code
VS Code already supports shortcut “chords” — a chain of keypress actions that trigger a command when you complete the sequence. By default on macOS ⌘K followed by ⌘C will comment out the current line in the editor, and like Emacs you keep ⌘ held down; no need to lift command between pressing k and c, hence “chord”.
There are 46 chorded options after ⌘K by default. But VS Code won’t give you hints about what they are (despite a 2016 feature request). You have to discover and remember the sequence you care about, like learning the church organ or studying Tekken combos.
When you press ⌘K in VS Code it assumes you know what to press next, which — speaking for myself — is far too generous:
Which Key for VS Code
With Which Key for VS Code it doesn’t have to be this way. The extension helps VS Code users grow their own shortcut trees of mini menus with built-in hints.
I press ⌘L (for ‘list’) in VS Code to summon my root Which Key menu:
I release ⌘L and press “g” to show my git commands submenu:
Helpful git commands are one more keypress away. They use mnemonic sequences that make sense to me, because it was me who chose them and not Microsoft (‘git init’ → ⌘L g i, ‘GitHub’ → ⌘L g h, and so on).
An option for the impatient
If you like the look of this stuff but don’t want to spend time configuring custom commands and shortcuts, you could install the VSpaceCode extension. It comes with a bunch of shortcuts that someone who probably isn’t you configured.
The VSpaceCode defaults are fine and they’ll be faster to start using. But you’ll end up with menu items you don’t care about, missing commands from your daily workflow, as well as mnemonics that are pretty good but perhaps not what you would have picked, simply through the gift and curse of not sharing a brain with the plugin’s authors.
An option for the dedicated
For me it’s better to grow your own tree of shortcuts from scratch with the commands you really want. To build custom trees like this you don’t need VSpaceCode, just Which Key (from the same lovely authors):
-
Install the Which Key extension. (Press ⌘P and type
ext install VSpaceCode.whichkey
.) -
Open VS Code’s Command Palette (⇧⌘P) and type enough of “Preferences: Open User Settings (JSON)” that the option appears, then select it and press enter.
The file that opens should be named
settings.json
. (If it’s namedkeybindings.json
ordefaultSettings.json
orSettings
without the.json
or anything else, close it and look for “User Settings (JSON)” from the menu again.)Configure your Which Key bindings tree with JSON. Some pointers:
-
For the ‘name’ values, I try to use the convention of appending ‘…’ if the action will open another prompt or submenu. The absence of the ellipsis tells me I’m about to run a command straight away instead of triggering another prompt or menu.
-
For the ‘key’ values, it’s best to use a bare key like ‘f’ over a combo like ‘cmd+f’. The latter won’t work because it conflicts with “find in file”.
-
I’ve omitted my full config to encourage you to make your own instead of copying mine.
"whichkey.bindings": [ { "key": "g", "name": "git…", "type": "bindings", "bindings": [ { "key": "i", "name": "init", "type": "command", "command": "git.init" }, { "key": "g", "name": "status", "type": "command", "command": "workbench.view.scm" }, { "key": "c", "name": "checkout…", "type": "command", "command": "git.checkout" }, { "key": "P", "name": "push", "type": "command", "command": "git.push" }, { "key": "F", "name": "pull", "type": "command", "command": "git.pull" }, { "key": "f", "name": "fetch", "type": "command", "command": "git.fetch" }, { "key": "s", "name": "stage", "type": "command", "command": "git.stage" }, { "key": "S", "name": "stage selected", "type": "command", "command": "git.stageSelectedRanges" }, { "key": "u", "name": "unstage", "type": "command", "command": "git.unstage" }, { "key": "U", "name": "unstage selected", "type": "command", "command": "git.unstageSelectedRanges" }, ] }, { "key": "p", "name": "project…", "type": "bindings", "bindings": [ { "key": "o", "name": "open", "type": "command", "command": "workbench.action.openRecent" } ] }, ],
To get the command ID strings like
workbench.action.openRecent
:i. Find the command in the command palette (⇧⌘P) and click the Configure Keybinding icon:
ii. Copy the command ID by second-clicking the command name (or copying the text after
@command:
in the search filter at the top):This works for commands from installed extensions too.
-
-
Finally, bind a key to open the root Which Key menu in VS Code’s
keybindings.json
.This is separate to the
settings.json
config you’ve just been editing. Open it with ⇧⌘P via the command called “Preferences: Open Keyboard Shortcuts (JSON)”.I use ⌘L to show Which Key:
{ "key": "cmd+l", "command": "whichkey.show" },
The shortcut works even if focus is in a non-editor pane. You get quick access to your Which Key menu throughout VS Code.