Putting the Space in Workspace April 15, 2018
I use my terminal as an IDE, largely thanks to Tmux. I spin up sessions for the API, the client front-end, and any other codebases I happen to be working in, as well as a session for tracking to do’s and ideas.
I launch a session using a script I call
zmux. If given a session name,
zmux attaches to the session. If given a directory,
zmux launches a new session and looks for a
.tmuxrc file in the directory that it can source to set up the session, allowing me to easily spin up a workspace and daemon processes for a project. This is especially useful for projects I haven’t touched in years. My typical
.tmuxrc file looks like this:
rename-session api rename-window main send "vim" C-m split-window -h resize-pane -x 80 new-window -t 8 -n tools send "vim +'tab all' .vimlocal .snippets" C-m new-window -t 9 -n daemons send "./server.sh" C-m
I created a Tmux binding to switch between sessions on partial session name matches:
unbind t; bind t command-prompt -p "session" "run-shell \"find-tmux-session %%\""
Each Tmux session has its own arrangement of windows and panes that varies by project, but I tend to arrange processes by the frequency with which I use them. Window 1 has Vim and a shell. Window 9 has server daemons. I name windows deliberately, rather than letting them auto-name based on the running process, which makes it easier to refer to them in scripts. If I spend much time in a pane that shares a window with other panes, I’ll maximize it with
prefix z. I have one window of tools that’s useful in several different projects, so I link it to multiple sessions with Tmux’s
Tmux’s hierarchy of panes, windows, and sessions evokes a sense of moving in three dimensions. Changing sessions feels like moving up and down, while windows orient left and right. Zooming panes adds another dimension.
Within a Tmux pane, I spend more time in Vim than anywhere else, and Vim adds two more navigable dimensions: splits and tabs. I use splits rarely, usually only to see code side-by-side, and then only briefly. I don’t use splits for organizing open buffers. For that, I use tabs. I often arrange tabs such that code higher in the stack is further left. Sometimes that means having multiple tabs open to different places in a single file. With tabs arranged this way, moving up and down in the stack is as easy as
gT, which can supply a small bit of sanity in tricky legacy code.
In all, I count five dimensions or degrees of freedom for organizing my view of all the code I work in on a daily basis:
- Tmux session
- Tmux window
- Tmux pane
- Vim tab
- Vim split
- Vim tab
- Tmux pane
- Tmux window
Architecting my workspace this way gives me a very kinesthetic sense of navigating code and processes. I have at least twenty different terminals going at any given moment, and it could easily feel like a confusing maze, but a few specific keystrokes take me anywhere I want, up or down, left or right, in any of the five dimensions listed above. I’ve never felt lost in what could easily be a fun-house of terminal windows that all look alike. (I’ve seen developers working solely in iTerm tabs who suddenly realize they just restarted the wrong server.) Once, a coworker told me he marveled to watch me work so quickly in so many different windows. I’d never thought about it. It felt natural.
I haven’t used IDEs or other GUI editors much, and while I’m missing some terrific features, I always feel claustrophobic having no more than splits and tabs, or having to close the current workspace to open a new one. I’ll use an IDE for a specific problem, but Tmux and Vim have become by all-purpose tools of choice.
#!/bin/bash if [ -n "$1" ] && [ -n "$(tmux list-session | cut -d':' -f1 | grep "^$1\$")" ]; then tmux -2 attach -t $1 elif cd $1; then if [ -e ".tmuxrc" ]; then tmux -2 new \; source-file `pwd`/.tmuxrc \; attach else tmux -2 new \; attach fi else echo "'$1' directory or session does not exist" exit 1 fi
#!/bin/bash session=$(tmux list-sessions | cut -d':' -f1 | grep "^$1" | head -1) tmux switch-client -t $session