Introduction
One of the first tmux plugins that changed my brain was Chris Toomey’s vim-tmux-navigator. Sure it makes things more convenient, but the core idea is that switching between sections of a terminal window should feel natural and consistent. It shouldn’t matter whether those sections are tmux panes or vim splits:
It’s an idea that seems obvious in retrospect. In this post, we’ll walk through a couple ways to apply that mindset to VS Code keybindings.
Terminal Muscle Memory in a GUI World
VS Code’s customizable keybindings and extensions gallery provide lots of opportunities to make your terminal sensibilities feel at home. Installing the VSCodeVim extension is a great start! But if you feel at home at the terminal, you’ll probably be missing a few of your favorite shortcuts.
To keep this post manageable, I’ll focus on a few key bindings I use so often in tmux that not having them in VS Code makes my fingers cry:
-
Ctrl-(h|j|k|l)
- Bounce around between panes
-
Ctrl-a
|
- Create a vertical split
-
Ctrl-a
-
- Create a horizontal split
-
Ctrl-a
x
- Close a pane
Keybindings for Navigation
At a glance, this seems like a simple request.
Ctrl
plus a vim direction key should take my focus in that direction. So I can add a few key bindings:
{
"key": "ctrl+k",
"command": "workbench.action.navigateUp"
},
{
"key": "ctrl+j",
"command": "workbench.action.navigateDown"
},
{
"key": "ctrl+h",
"command": "workbench.action.navigateLeft"
},
{
"key": "ctrl+l",
"command": "workbench.action.navigateRight"
}
And… done, right? Except I’m picky, so that doesn’t quite cover it. When my focus is in the panel below my open editors, I want
Ctrl-(h|l)
to move left/right between panel tabs. Fortunately, we can cover that by taking advantage of “when” clause contexts:
{
"key": "ctrl+h",
"command": "workbench.action.previousPanelView",
"when": "panelFocus"
},
{
"key": "ctrl+l",
"command": "workbench.action.nextPanelView",
"when": "panelFocus"
}
VS Code will use that “when” context to find the most specific matching key binding. So if my focus is in the panel,
Ctrl-h
will move to the previous panel tab. Otherwise, it will navigate left by one view. Ah… much better, feeling more comfy all the time.
But there’s still a tiny thing bugging me. If I move focus into the sidebar when I’ve got the Explorer viewlet visible, I want to use
Ctrl-(j|k)
to move between the file explorer and open editors view. If I’m being honest, this isn’t even something I really need! I just want it because I noticed it’s not there, and it felt like bumping into an invisible wall in a video game.
Again, “when” clause contexts can satisfy even this silly requirement:
{
"key": "ctrl+k",
"command": "workbench.files.action.focusOpenEditorsView",
"when": "sideBarFocus && explorerViewletVisible"
},
{
"key": "ctrl+j",
"command": "workbench.files.action.focusFilesExplorer",
"when": "sideBarFocus && explorerViewletVisible && !filesExplorerFocus"
}
The “when” clause is a little more complex in this case, but the core concept is the same. Things can get progressively more wild and powerful, combining out-of-the-box contexts with additional contexts from extensions. But that’s a story for another day, for the purposes of this post my fingers are happy!
Watch it Work
With these keybindings in place, I can hop around VS Code in a way that maps nicely to my tmux expectations:
Terminal-lovers, I doubt that your preferences will exactly match mine. Still, I hope that some of the examples in this post will help you tweak VS Code to suit you.
Note: For the record, the codebase I have open there is VisiData. That’s not an entirely random choice - if you’re happy in the terminal, you’ll probably find some handy uses for VisiData. I’ll dig into that more in a separate post…
Update (2020-Oct): Here’s a separate post :).
In the meantime, thanks for reading! Criticism, comments and questions are all welcome. So fire away in the comments!
References
- Tmux and Vim - even better together: I’m pretty sure this is the first place I saw the idea to rebind keys for horizontal/vertical splits using
|
and-
. It seemed so obvious in retrospect, I made the change immediately and never looked back. - What are your favorite VS Code extensions and why?: There are lots of VS Code extension posts around, it can be overwhelming. Your projects and personal preference will guide this though, so linking to a discussion post seems fitting.
- Chronicler: I used this VS Code extension to record my session, after a few other methods yielded unreasonably large files and/or messed up colors. Chronicler was less work for better results, nice!