Configuring VSCode as a Keyboard-Centric IDE
One of my first posts on this blog in 2020 was about my experience switching from VSCode to Emacs for all of my text/code editing work. I still agree with all of the benefits to Emacs I wrote about back then, and my posts on Obsidian show my respect for org-mode
as a format and the ecosystem around it – especially org-agenda
. However, as you might have noticed when the file extension on my posts switched from .org
back to .md
, I’ve moved on from Emacs for now. But I’m happy with how I’ve moved my good habits back to VSCode. Spending time on config gave me more confidence in my ability to configure software I use to my liking, and make software work for me rather than make me work for the software.
At work, I’m always editing code while SSH’d into a remote machine. TRAMP with lsp-mode
on a very large C++ codebase just had too much lag for me. Even accessing Emacs compiled with native-comp running on my remote machine had way too much input delay when waiting on responses from clangd or ccls, two C++ language servers. Now, it’s more than possible I was holding it wrong – I do have colleagues that work all day in Emacs. But it seems like my bad UX experience was due to the limitations of Emacs’s concurrency support – calls to language server were blocking other interactions with the UI. On the other side of the hedge, VSCode really just works. I can still type and otherwise interact with the editor while waiting for clangd to process a request. The remote SSH extension is the state of the art. The clangd integration was plug-and-play. And I’ve never experienced the lag that I was feeling every day on Emacs.
While I love the smoothness of the VSCode UI, I’m not a fan of how easy it is fall back on the mouse while navigating around the editor. My favorite part of the Doom Emacs distribution was the keybindings: it made me feel like I was playing chords on the piano when splitting panes and navigating around. While I’d configured Emacs to look and feel like VSCode in my original Emacs post, I ultimately got rid of the project explorer and visual tabs to embrace more Emacs-y buffer and project management. I found myself reaching for the mouse way more often when I moved back to VSCode, putting myself at risk for RSI and generally interrupting my flow. So I set out to make my VSCode configuration as close to my Doom Emacs setup as possible. There were only a handful of changes I needed to make:
- Installed VSCode’s Vim plugin. I’ve used vim keybindings all over the place for almost four years at this point.
- Installed VSpaceCode + WhichKey. Together, these plugins replicate the chords/leader bindings that Doom borrowed from Spacemacs really well. I’ve remapped a few bindings that were different in Doom and added a few more as well.
- Disabled Tabs. Tabs are a visual abstraction that are hard to use effectively without reaching for the mouse. I got used to Emacs’s buffer management, where I can fuzzy-search for recently opened files in a reverse-chronological list. VSCode’s analog to buffers are called Editors and are normally mapped on to Tabs; after disabling Tabs I can still navigate open Editors with the command “View: Show Editors in Active Group By Most Recently Used”, which I’ve mapped to
<leader> ,
with VSpaceCode.- I removed tabs by adding
"workbench.editor.showTabs": false
to mysettings.json
file. - The command ID for “Show Editors in Active Group” is
workbench.action.showEditorsInActiveGroup
.
- I removed tabs by adding
- Disabled the Activity Bar. I can pull up sidebar Views like
File Explorer
andFind in Files
with a shortcut, and dismiss them with cmd-B.- Add
"workbench.activityBar.visible": false
to yoursettings.json
.
- Add
The fact that VSCode can do all this is a testament to its extensability and the power of a more limited but still deep plugin API. A settings.json
file is no match for init.el
when it comes to expressiveness, but I’ve still been able to mold VSCode into an editor that I feel at home using.
I’m sure I’ll keep playing around with Emacs going forward, but the all-consuming nature of the Emacs philosophy – the idea that everything from email to web browsing to journaling should happen inside Emacs – doesn’t resonate with me in practice. I can use VSCode for most of my development, Obsidian for editing Markdown, and even PyCharm for Python/Django development (check out intellimacs for JetBrains IDEs if you’re interested in my setup there). With just a few hours of set-up, I can use the right tool for the job and still feel at home regardless.