Programming is all about doing the same thing... over and over again, ad nauseam. No, not the computer, the poor programmer as they work on similar projects bouncing around all the different tools.
For example, let's take Drupal development - usually once you are in the midst of it, you may be accessing:
- An editor (Vim, naturally)
- A terminal for running system commands e.g.
drush cr
,drush cedit
,drupal generate:module
etc. - Maybe a todo list / notes
- Log output
- Watch output e.g.
npm run watch
- Test output e.g.
phpunit
,codeception
etc. - File ops e.g.
ranger
- Reference material
- etc.
That may end up looking a bit like this:
Note the Tmux status, bottom left, where it shows that I am in the first window of three.
As this is typical, wouldn't it be nice if, I don't know, you could run a command such as tmd <name of session>
and it would set everything up just so. Also, over time, we could then refine this setup and get all the benefits of finessing it - or have multiple scripts depending on the type of project.
The script
No problem, take a look at this script drupal.sh
:
#!/bin/zsh
# Note that this assumes base index of 1
# check for existence of required things
# $1 is the name of the window
# we are in the directory of the drupal project
if [ $# -eq 0 ]
then
echo "No arguments supplied, requires name of window."
exit 1
fi
CWD=$(pwd)
SESSION_NAME="$1"
# detach from a tmux session if in one
tmux detach > /dev/null
# Create a new session, -d means detached itself
set -- $(stty size) # $1 = rows $2 = columns
tmux new-session -d -s $SESSION_NAME -x "$2" -y "$(($1 - 1))"
tmux new-window -t $SESSION_NAME:1 -n 'code'
tmux new-window -t $SESSION_NAME:2 -n 'logs'
tmux new-window -t $SESSION_NAME:3 -n 'zsh'
## Logs window
tmux select-window -t $SESSION_NAME:2
# Start up the logs listener
tmux send-keys "vbin/tail -f /var/log/apache2/error.log | clog drupal" C-m
## Zsh window
tmux select-window -t $SESSION_NAME:3
tmux rename-window 'Zsh'
## Main Window
tmux select-window -t $SESSION_NAME:1
tmux rename-window 'code'
# Split into left and right
tmux split-window -h -p30
# Right ready for taking commands / tests.
tmux select-pane -t 2
tmux send-keys "figlet -f roman Ready! | lolcat -t" C-m
# Left for neovim.
tmux select-pane -t 1
tmux send-keys "v" C-m
# Finally attach to it
tmux attach -t $SESSION_NAME
How it works
The process can be broken down as follows:
- Creating a new session
- Creating windows
- Creating panes
- Sending commands to the panes / windows
Creating a new session
Creating a new session is as simple as tmux new-session -s <name-of-session>
. In the example script I have a bit more going on:
# Create a new session, -d means detached itself
set -- $(stty size) # $1 = rows $2 = columns
tmux new-session -d -s $SESSION_NAME -x "$2" -y "$(($1 - 1))"
What I am doing here is getting the current screen resolution and then creating a detached session of that size - the reason being that if you don't specify a size using the -x
parameter then if you try to specify window split sizes it will wig out since it has no point of reference for "size".
Creating windows
Creating a window can be accomplished via tmux new-window -n <name-of-window>
. In the example we have:
tmux new-window -t $SESSION_NAME:1 -n 'code'
tmux new-window -t $SESSION_NAME:2 -n 'logs'
tmux new-window -t $SESSION_NAME:3 -n 'zsh'
Here we create three windows - the -t
flag is so that we can specify the target of the windows, which in this case is the session that we just created and the index of where they should appear.
We can then target windows with tmux select-window -t <name-of-session>:<index>
for further commands.
Creating panes
Often you will want to split up a window into multiple panes. This can be done with something like tmux split-window -h -p<percentage>
where -h
signifies a horizontal split (guess how a vertical split is specified?) and -p
signifies a percentage split. In the example I create a 30 percent split but you can of course specify by pixel if that is your jam.
Once you have created one or more splits, you can target panes with tmux select-pane -t <index-of-pane>
for more commands.
Sending commands to the panes / windows
Lastly, once we have our windows and panes ready, we can send them further commands to start things up. Some examples from the above:
tmux send-keys "vbin/tail -f /var/log/apache2/error.log | clog drupal" C-m
(run the tail
command in watch mode against the apache error log, piped into clog - the C-m
is used to send an <Enter>
to a pane or window)
tmux send-keys "figlet -f roman Ready! | lolcat -t" C-m
(run figlet
with the string "Ready!", piped into lolcat in true colour mode )
Finishing up
Rounding out the script we have a call to tmux attach -t <name-of-session>
which makes it visible. In the script, the name of the session is passed in as a parameter. For extra convenience I have the following alias in my .zshrc
to run this script:
alias tmd='~/.config/tmux/drupal.sh'
Obviously you don't have to attach to a Tmux session - if you had the need, your script could start up all kinds of processes and then you could attach only to check it whilst doing other things (or not!). Tmux also supports multiple people attaching to a session, sending commands to specific sessions, saving sessions (via plugins) etc. The possibilities runneth over.
This article originally appeared on michaelwelford.blog
Top comments (8)
Love tmux but it can have a steep learning curve imo. These links helped me a lot:
github.com/rothgar/awesome-tmux
leanpub.com/the-tao-of-tmux/read
rushiagr.com/blog/2016/06/16/every...
Thanks for the links!
Agreed - thankfully I feel like the curve eventually tapers off (more so than Vim, for example).
Great post Michael! I've been using tmux for a while now, and its really a great addon to boost one's productivity, especially when one spends a lot of time in the terminal (vim is my primary editor).
Do you screencast your vim/tmux workflows?
Thanks Francis, appreciate it.
Re screencasts: I literally bought a bunch of gear (probably unnecessarily) and then haven't followed through on recording anything.
I pledge to do at least one by end of next month :)
This is really neat, thanks for taking the time to write about this! I'm running an almost identical setup so this was just perfect.
I actually followed this explanation, read the Tao of Tmux, made a few of my own scripts for different projects, and actually saved time and became more productive.
I use tmuxp that brings a lot of simplicity to tmux' sessions.
Great post !
Fab - I also tried
tmuxinator
but it wouldn't quite do what I wanted it to do and then of course the tinkering impulse kicked in...