Resize tmux main panes by percentage
As of tmux 2.6, by default, main-pane-horizontal and main-pane-vertical layouts require some extra legwork to stay proportional. This article shows a script that can set dimensions of this type of layout through percentages. Note: By default the even-vertical, even-horizontal, and tiled layouts should always stay even.
This has been mentioned before on the tmux issue tracker at tmux/tmux#888. There is a need to create a script that's flexible enough to resize main pane widths and heights based on the size of the client. This is subject to change as the user's terminal size changes (due to switching monitors, maximizing, tiling window managers, adjusting font size, screen resolutions, and so on).
The only way to get a comfortable proportion set almost every time is to use a percentage.
We could use run-shell
, which allows us to do some variable
interpolation and kung-fu. I have tried this in my own config for a few
weeks and for some reason, the options wouldn't stick. Invoking a shell
script would be more reliable.
Since we're there, though, user's may have different preferences for what proportions they want. For instance, I want main-vertical at 66%. Other users want a different ratio. And also, some users may prefer main-horizontal. So let's use script arguments and conditionals to handle these cases.
Second, let's try to make is POSIX-compliant as possible so it can work on systems like FreeBSD and OpenBSD which don't include Bash/Zsh by default.
Third, let's give the user some feedback if they don't enter an argument, such as the percentage, the right way.
Forth, let's allow the user to specify a target window, optionally.
The latest script can be found in it's entirety at resize-adaptable.sh, or below:
lflag=
pflag=
tflag=
while getopts l:p:t: name;
do
case $name in
l) lflag=1
layout_name=$OPTARG;;
p) pflag=1
percentage="$OPTARG";;
t) tflag=1
target="$OPTARG";;
?) printf "Usage: %s: [-l layout-name] [-p percentage] [-t target-window]\n" $0
exit 2;;
esac
done
if [ ! -z "$pflag" ]; then
if ! [ "$percentage" -eq "$percentage" ] 2> /dev/null; then
printf "Percentage (-p) must be an integer" >&2
exit 1
fi
fi
if [ ! -z "$lflag" ]; then
if [ $layout_name != 'main-horizontal' ] && [ $layout_name != 'main-vertical' ] ; then
printf "layout name must be main-horizontal or main-vertical" >&2
exit 1
fi
fi
if [ "$layout_name" = "main-vertical" ]; then
MAIN_PANE_SIZE=$(expr $(tmux display -p '#{window_width}') \* $percentage \/ 100)
MAIN_SIZE_OPTION='main-pane-width'
fi
if [ "$layout_name" = "main-horizontal" ]; then
MAIN_PANE_SIZE=$(expr $(tmux display -p '#{window_height}') \* $percentage \/ 100)
MAIN_SIZE_OPTION='main-pane-height'
fi
if [ ! -z "$target" ]; then
tmux setw -t $target $MAIN_SIZE_OPTION $MAIN_PANE_SIZE; tmux select-layout -t $target $layout_name
else
tmux setw $MAIN_SIZE_OPTION $MAIN_PANE_SIZE; tmux select-layout $layout_name
fi
exit 0
I placed the script in ~/.tmux/scripts/resize-adaptable.sh
.
In order to make this available as a keybinding, let's do this in our
~/.tmux.conf
:
# set to main-horizontal, 66% height for main pane
bind m run-shell "~/.tmux/scripts/resize-adaptable.sh -l main-horizontal -p 66"
# Same thing for verical layouts
bind M run-shell "~/.tmux/scripts/resize-adaptable.sh -l main-vertical -p 50"
Above, create a keybinding, in this case, we picked m, you can switch
m with anything. You can use prefix,:
to open the prompt and
so ~/.tmux.conf
return
to reload the config.
Try prefix,m
. Your panes should resize to be 2/3 the height of your
client's window size, something like this:
Main horitontal
.___________.
| |
| | < main pane 66% height
|-----------|
| | | | < other panes, split left to right
|___|___|___|
prefix,M
will set the main pane on the left side at half the client's
width, stacking other panes on the right, from top to bottom. It looks
like:
Main vertical
/----------- main pane half width
.___________.
| | |
| |_____|
| | | < < other panes on the right, split top to bottom
| |_____|
| | |
|_____|_____|
Example usage:
Case 1: Resize to a main-horizontal, main pane 66% of client height:
$ ./scripts/resize-adaptable.sh -p 66 -l main-horizontal
Case 2: Same as Case 1, target "devel" window:
$ ./scripts/resize-adaptable.sh -p 66 -l main-horizontal -t devel
Case 3: Resize to a main-horizontal, main pane half width:
$ ./scripts/resize-adaptable.sh -p 50 -l main-vertical
Case 4: Same as Case 3, target "mywindow":
$ ./scripts/resize-adaptable.sh -p 50 -l main-vertical -t mywindow