Saving time with a preset tmux setup
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.
- Maybe a todo list / notes
- Log output
- Watch output e.g.
npm run watch
- Test output e.g.
- File ops e.g.
- Reference material
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.
No problem, take a look at this script
#!/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 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.
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
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
figlet with the string "Ready!", piped into lolcat in true colour mode )
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:
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.