it seems my requests are simply ignored
It's not clear what requests are ignored. Your script kinda works for me, nothing seems to be ignored if I run it fresh, without tmux server already running. With tmux server already running there are problems:
- the session may already exist and someone may be (actively) using it,
- the window may already exist,
- your
split-window
commands may target some other (pre-existing) window.
It seems to me that some layouts are simply not allowed.
If your goal is to work with the layout you already have and get to the desired layout by doing something more after, then it will be difficult because you cannot easily get the desired top-right or the bottom-right pane after the whole left "33%" column is split to two "50%" panes. You need to split in a different order.
One way to learn what the order may be is to draw the layout on a piece of paper and cut it with scissors with straight cuts that go through, so each cut divides the current piece into two smaller ones. Or imagine breaking a chocolate bar.
A possible scheme for your desired layout is like this:
+---------------------+
| 1 |
|22222221 |
| 3 1 |
| 3 1#############|
| 3 1 |
|22222221 |
| 1 |
+---------------------+
The numbers indicate in what order you need to cut. The cut marked with #
represents multiple cuts in the right column, you can make them in any order after 1
, before or after 2
or 3
. These #
cuts are not important to the issue. The important thing is you need to make the two 2
cuts (in any order) after 1
and before 3
. Your script performs the 3
cut without making 2
and then there is no straightforward way to get what you want.
There is split-window -f
, it creates a new pane spanning the full window height or full window width, instead of splitting a single pane. While it brings some flexibility and allows creating panes in yet different order, it won't help you get the desired layout from your achieved layout; nor it will make more layouts possible.
For comparison, this is a truly impossible layout, I think:
+---------------------+
| # |
| # |
| ##############|
| | | |
| | | |
|---------------| |
| | |
+---------------------+
In reality you can cut it with scissors but not with tmux, because at least the first cut with scissors needs to bend to create two separate pieces of paper. An example first cut is drawn with #
characters. You can interpret it as two cuts that are not "through", so for tmux this interpretation changes nothing, it's still impossible.
This is an example script that works for me in tmux 2.3. Remarks and improvements are listed as notes below the code; please read them before you run the script.
#!/bin/sh
session="$USER"
window="$session:1"
lines="$(tput lines)"
columns="$(tput cols)"
tmux -2 new-session -d -x "$columns" -y "$lines" -s "$session" 'echo "step -1"; bash'
tmux new-window -t "$window" -n 'Logs' 'echo "step 0"; bash' || exit
tmux split-window -t "$window" -h -p 67 -d 'echo "step 1"; bash'
tmux split-window -t "$window" -v -p 10 -b -d 'echo "step 2a"; bash'
tmux split-window -t "$window" -v -p 22 -d 'echo "step 2b"; bash'
tmux split-window -t "$window" -h -p 50 'echo "step 3"; bash'
tmux split-window -t "$window.{top-right}" -v -p 55 -d
tmux split-window -t "$window.{top-right}" -v -p 64
tmux select-pane -t "$window.{bottom-right}"
tmux split-window -t "$window" -v -p 67
tmux split-window -t "$window" -v -p 50
tmux select-window -t "$window"
# Attach to session
tmux -2 attach-session -t "$session"
Notes:
- The shebang is
/bin/sh
, no need for Bash here.
- Get used to double-quoting variables. It's way better to habitually quote regardless if you need it than forget to quote when it makes a real difference.
- I used lowercase names for variables.
- I used
tput
to determine the size of the current terminal. Then new-session -d -x … -y …
uses proper values. But:
- In my initial tests this seemed unnecessary, all worked without
-x
or -y
…
- … although according to my local manual it should be necessary.
- Anyway if the session already exists, its size is determined and
new-session -d -x … -y …
will have no impact. You may experience distorted proportions in the layout after you attach and the panes get resized. There are tmux commands and options that may help (resize-window
, window-size
, default-size
), although not in my oldish tmux, so I won't elaborate.
tput
operands lines
and cols
are not required by POSIX. See this answer for alternatives.
- If window cannot be created, the script exits.
- Each
split-window
targets the right window. If the session existed or someone attached in the meantime and changed the window, the current window would not be what you assume. To be even more robust each split-window
should target a respective pane explicitly. Note that select-pane
before split-window
(or before resize-pane
as in your script) is not really robust in a general setup where many clients can interact with the same tmux server: some other client (user or script) could select another pane between these two commands.
- I do not resize panes. I create them with proper percentages in the first place. The
-p
option I use works in my oldish tmux. The documentation tells me the newer syntax is like split-window -l 20%
and resize-pane
can work with percentages as well. I don't know if the newest tmux understands split-window -p
. The documentation doesn't mention this option any more, it may be deprecated and unsupported or it may be kept for compatibility; I cannot test this (feedback or edit is welcome).
split-window
takes percentages that refer to the available space, i.e. to the old size of the pane that is about to shrink to make space for the new pane (at least this is how it works in my oldish tmux with -p
). This is why numbers like 22
appear ( 20/(20+70) ≈ 22 ). According to the documentation resize-pane
uses percentages of the window size.
- I use or don't use
-d
to stay in the current pane or make the new one current, depending on which pane I need to target with the next split-window
.
- When I need to specify/select a pane that fits a token like
{top-right}
, I use the token.
- I do not use
send-keys
to run commands. In general do not use send-keys
to run commands. Any(?) tmux command that creates a new shell inside tmux can run a shell command instead. In the example script echo "step 0"; bash
is such shell command. It includes bash
at the end, so the pane doesn't exit when the actual command (echo
) finishes. An alternative is the remain-on-exit
option. Your shell commands (watch
) can work indefinitely, so you may not need such tricks. Running a shell command with send-keys
like you do in your script makes sense if the command affects the shell it runs in and your goal is to work interactively in the shell prepared this way. E.g. the command may set variables or source a script; or you want to be able to interrupt watch
and have it in the shell history. In any other case the "right" way is to pass commands with split-window
, respawn-pane
or some similar tmux command.
Additional note:
printf '\033]60;.1:.33 .8:.16 .8:.33 1:.33 .2:1 .55:1 .7:1 .85:1 1:1\007'
smtx is still experimental. https://github.com/wrp/smtx – William Pursell Dec 23 '20 at 21:01tmux list-windows
to retrieve all layouts. If you need the layout for tmuxinator, yank everything between[layout
and] @
for to be inserted into your.tmuxinator.yml
. – Martin Braun May 29 '23 at 16:14