About a year ago, I decided to make the switch from VSCode to a terminal based solution and landed on Tmux & Neovim. There wasn’t really anything wrong with VSCode, but I had heard some great things about these tools and wanted to challenge myself to get comfortable with something new. Fast-forward to today, and I have a hard time using any other editor.
Truthfully, it was pretty painful initially, with lots of small bumps and inconveniences along the way. Most of the friction came down to breaking old habits, but some problems required configuring the tools to meet my needs. I’ve been doing just that for about a year now, and have a pretty customized experience at this point. For me, it wasn’t always straightforward setting things up, so I thought I’d share my setup in case anyone finds it helpful or interesting.
Tmux is a pretty neat tool for multiplexing. For a primer on how it works, you can check out the Tmux wiki. I use it primarily to organize and persist workspaces for different projects. You can find my Tmux config file in Github. I should note that Tmux commands all begin with
Ctrl-b, but I’ve remapped this to
Ctrl-a in my config for convenience. So in the remainder of this post, I’ll use
Ctrl-a but just know out of the box this will be different. In any case, here are my favorite uses of Tmux.
Panes and Windows
Tmux works as a sort of hierarchy, with panes and windows being at the bottom. Despite that, they are primarily how you will interact with, and are my favorite part of using Tmux. Panes allow you to split your terminal window into sections, each serving as its own shell. In my config, I’ve remapped the commands for adding new horizontal panes to
Ctrl-a + _ and new vertical panes to
Ctrl-a + |. I’ve also remapped resizing these panes to
Option + k,
Option + j,
Option + l, and
Option + h (up, down, left, right) so I am able to quickly add and resize them however I see fit.
Windows are the next level of the hierarchy and they allow you to create separate tabs of workspaces, each with its own set of panes. So for instance, I usually have one window with three panes open to the current project I am working on. One large pane serves as my editor space, while the other two serve as shells for running project commands or running build scripts. But I also need a space for running my development server, or monitoring logs. Tmux windows allow me to create all of these spaces and easily swap back and forth. You can do this easily by using the built-in shortcut
Ctrl-a + [number], where
number corresponds to the numbered window.
After panes and windows, we have sessions, which allow you to organize groupings of windows and easily switch between them. To give a real-life example, I typically work on a local WordPress dev site served with valet. When working in this environment, I like to have a number of seperate windows open. One for each of the following:
- Neovim + shell
- General purpose shell for modify config files or other system related tasks
But I also often work on projects that are a bit more complex and require me to run some additional things like middleware servers or docker. In these cases I like to have additional windows for:
- Server or other project files
That’s a lot of windows! I could stick to a core set of windows and add/remove as I go, but with Tmux I am able to create a session for each project I work on, with the exact number of windows/panes I want for each project:
Awesome right! What’s even more awesome is having this all set itself up on startup. I use tux-resurrect and tux-continuum to do just that. So now, when I start my day, all I have to do is open my terminal, select the session I need, and I’m all set.
It took me a long time to get Neovim to a state where I felt fully comfortable. And honestly, there is still work to be done. But in any case, I’m very happy with where I’ve landed thus far. You can also find my Neovim config in Github. There are a ton of resources out there on how to use vim/Neovim or why you should give it a try, so I won’t say too much about this other than making the change has increased my productivity after taking the time to learn. I love that I never find myself touching my mouse anymore. (Sometimes, I almost forget it exists!) And, at the very least, since making the change coding has become so much more fun. 🤓
Instead for the remainder of this post, I’ll just share some of my favorite plugins that enhance my Neovim experience.
Vim-surround is one that I use everyday without even thinking about it. It lets you quickly modify the surroundings of text with quick key strokes. And that’s it. Super simple, but super practical. I use this a lot to quickly change things like single quotes to double or vice versa when
eslint yells at me. For example, in JSON files, I need to use double quotes to surround keys but often forget or paste in keys with single quotes. With vim-surround, I just move my cursor over the key in question and type
While I’ve seen many vim/Neovim proponents shun the idea of adding Modern code editor functionality, I personally really missed some of the features VSCode came with when I made the switch. One of these being fuzzy finding and search. Denite solves this problem for me. With it, I can quickly search my project by file, string, or buffer. I’ve remapped these commands to make this super easy. So for example, if I want to search my project for any files containing the string ‘shipping_methods’, I type
Ctrl-g shipping_method and I’m presented with a list of files containing this string, along with previews of these lines. If I want to quickly find where a function is defined, I can move my cursor to the function name and type
gd, and I’m taken to the file and line where the function is defined. There are lots of other really cool features, so I encourage you to check out the plugin repo.
I like using NERDTree over Neovim’s default explorer. Mostly because it offers some super useful commands. To start, I remapped the command to quickly show or hide the explorer to
,n since I usually only need the it open for short intervals of time. NERDTree also allows you to quickly create, move, or delete files and directories. For example, I often find myself wanting to duplicate a file as a starting place for whatever I’m about to work on. With NERDTree, I just hover over the file in the explorer, type
c, then type in the new filename, and viola the file is copied. Finally, the bookmark feature is also super convenient. Again, I just have to hover over a file and type
,b (This is a remapping of
:Bookmark), then type in a name for my bookmark, and the file is stored so I can easily access it anytime.
Conquer of Completion
CoC adds completion to Neovim, which was something I sorely missed when I first made the switch. It offers full language server support, and is surprisingly snappy. In addition to completion, I also use CoC for linting files as I type.
There are a handful of other plugins I use which can be found in my config, but in truth I try to keep my usage of plugins as minimal as possible and stick to what Neovim offers natively. I encourage you to check out the Neovim site as well as some of the other resources linked in this post. As a disclaimer, I’m far from an expert user, but I have put a lot of effort into my configuration, so hopefully it can be useful to somebody out there.
I hope you’ve enjoyed reading, thanks for sticking with me til the end 🙇♂️