From Tmux+Vim to VSCode … and back again

Over the course of my 20 year career in software development, I've used many different code editors and development environments to build everything from desktop apps to web apps. Everything from Visual Studio 6 to Xcode to Textmate to Notepad, has been installed at some point. As I started to focus on web app development, specifically using Ruby-on-Rails, my day-to-day setup involved using Tmux for everything command line, and vim for editing code files. This post is the story about how I went from a highly tuned Tmux and vim setup, to VSCode, and why I'm going back.

Tmux+Vim was probably my most productive development environment I've had the pleasure of using. using Tmux makes managing the myriad of processes required easy. I can have a window for Vim, a window for tests, another for the Rails server, etc.., and a quick key binding switch to each window. Tmux is also scriptable, and I used (Tmuxinator](https://github.com/tmuxinator/tmuxinator) is create workspaces for projects. Tmux scripting is also used by vim plugins to background various jobs like running tests from within vim without interruptions. As for Vim, well, YouTube is full of influencers telling you what latest and great plugins to install. My only advice to add is this: Use vanilla vim as much as possible, learn the basics of motions, registers and macros. Only when you find a gap in the toolset does it make sense to install a plugin. After a decade of regular vim use, only had a handful of plugins installed, many of which were very specialised, such as the ruby-text-object plugin, or Tim Popes vim-surround.

So why did I give up all of the this and switch to VSCode?

Firstly, VSCode has all the momentum when it comes to providing new features for development. Excellent Github integration and a large community of plugins and language support. If you want an instant developer environment, it's pretty hard to not go with VSCode.

Secondly, and by far my main reason, was DevContainers. From the first time I saw DevContainers in use, I knew this was the future of building web apps. Composable environments with Docker Compose, stable environments to run tests in, no need for system wide language or package management. VSCode has almost magical abilities to manage DevContainers, they're easy to setup, easy to run, and the experience is exactly the same when using Github Workspaces in your browser.

So what went wrong? Simply put, Vim is a better editor for the bulk of the work I do. So much of my time is spent on the terminal, that it makes work a lot easier when the terminal is a keystroke away, rather than in a separate window (I know VSCode has terminals but it's just not the same). This might see like a small annoyance, but it's just one of many small annoyances, and doing the same small thing lots of times really adds up quickly. In the end, I never really become comfortable with VSCode, maybe I needed to spend more time learning it, but it just wasn't fun to spend a lot of time in.

It was time to move back to Vim

A lot has changed in the Vim world during my period in exile. NeoVim is now the popular choice and it promises a few tools that will be very useful for programming, like improved rendering performance and native LSP support. I won't go into all the differences, or which trendy new plugins I'm using are. Instead, I'll focus on how I've integrated DevContainers into this workflow, which is made possible by the reference implementation of the DevContainers spec via the devcontainer CLI tool. Now, to get a DevContainer environment up and running, I can run devcontainer up --workspace-folder ., and the containers will be built and running in docker, just like in VSCode. If I want to create a new login shell, I can run devcontainer exec --workspace-folder . '/bin/bash'. The full spec, and links to the CLI are available at https://containers.dev.

Where the real magic happens, is when all of this is combined with Tmux. As a proof of concept, let's assume we're running Tmux with 2 panes. In the first pane we're running nvim and we have a ruby rspec test open. In the second pane, we just have a login shell. Now in nvim, we can run :map <CR> :! tmux send-keys -t2 "devcontainer exec --workspace-folder . rspec %" Enter <CR> to create a new keyboard shortcut that will, when "Enter"/"Return" is pressed, run the current test file, with rspec, in the app devcontainer, in the second tmux pane. This happens without losing focus from nvim, and the test output will remain visible in the second pane. This is a very crude use-case, but it demonstrates the power of having tools that can interop with each other.

About the Author

Phil Balchin is a full-time software developer at Zendesk, previously at Heroku/Salesforce, and Kyan, as well as a part-time photographer living in Guildford, Surrey, UK.

facebook.com/phil.balchin | instagram.com/maniacalrobot | last.fm/users/maniacalrobot | picfair.com/maniacalrobot | maniacalrobot.tumblr.com | twitter.com/maniacalrobot