mirror of
https://github.com/tmux/tmux.git
synced 2026-10-16 16:44:30 +00:00
Side status line regress tests.
This commit is contained in:
143
regress/side-status-clamp.sh
Normal file
143
regress/side-status-clamp.sh
Normal file
@@ -0,0 +1,143 @@
|
||||
#!/bin/sh
|
||||
|
||||
# With side-status left, a client narrower than the window must clamp pane
|
||||
# output to its visible part without killing the server or drawing over the
|
||||
# side status line. Each inner client runs in an outer pane of its size.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
DIR=$(mktemp -d) || exit 1
|
||||
TRIGGER=$DIR/trigger
|
||||
CAPTURE=$DIR/capture
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
rm -f "$TRIGGER" "$CAPTURE"
|
||||
rmdir "$DIR"
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
[ -s "$CAPTURE" ] && cat "$CAPTURE" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Start the inner server with one pane running $1, then attach a big and a
|
||||
# small client from outer panes of sizes $2 and $3 (WxH).
|
||||
start()
|
||||
{
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
rm -f "$TRIGGER"
|
||||
|
||||
$TMUX new-session -d -s inner -x 200 -y 50 "$1" || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g automatic-rename off || exit 1
|
||||
$TMUX set -g window-size largest || exit 1
|
||||
$TMUX set -g side-status left || exit 1
|
||||
}
|
||||
attach()
|
||||
{
|
||||
$TMUX2 new-session -d -s big -x "${1%x*}" -y "${1#*x}" 'sleep 100' ||
|
||||
exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 set -g window-size manual || exit 1
|
||||
$TMUX2 new-session -d -s small -x "${2%x*}" -y "${2#*x}" 'sleep 100' ||
|
||||
exit 1
|
||||
$TMUX2 respawn-pane -k -t big:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 0.5
|
||||
$TMUX2 respawn-pane -k -t small:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
$TMUX has-session 2>/dev/null || fail "server exited on attach"
|
||||
SMALL=$($TMUX list-clients -F '#{client_width} #{client_name}' |
|
||||
sort -n | head -n 1 | cut -d' ' -f2)
|
||||
}
|
||||
alive()
|
||||
{
|
||||
$TMUX has-session 2>/dev/null || fail "server exited: $1"
|
||||
}
|
||||
|
||||
# A clear below the cursor in a pane wider than the small client's view.
|
||||
start "sh -c 'while [ ! -e $TRIGGER ]; do sleep 0.1; done
|
||||
printf \"\\033[J\"; exec sleep 100'"
|
||||
$TMUX set -g side-status-width 31 || exit 1
|
||||
attach 167x49 40x12
|
||||
: >"$TRIGGER"
|
||||
sleep 1
|
||||
alive "clear in a pane wider than the client"
|
||||
|
||||
# The same clear with the small client panned right, so the pane is cut off
|
||||
# on both sides. The side status line keeps the window on its first row.
|
||||
start "sh -c 'while [ ! -e $TRIGGER ]; do sleep 0.1; done
|
||||
printf \"\\033[J\"; exec sleep 100'"
|
||||
$TMUX rename-window -t inner:0 work || exit 1
|
||||
$TMUX set -g side-status-width 31 || exit 1
|
||||
attach 167x49 40x12
|
||||
$TMUX refresh-client -t "$SMALL" -R 5 || exit 1
|
||||
sleep 0.5
|
||||
: >"$TRIGGER"
|
||||
sleep 1
|
||||
alive "clear in a pane cut off on both sides"
|
||||
$TMUX2 capture-pane -p -t small:0.0 >"$CAPTURE" || exit 1
|
||||
case "$(head -n 1 "$CAPTURE")" in
|
||||
0:work*) ;;
|
||||
*) fail "side status first row cleared" ;;
|
||||
esac
|
||||
|
||||
# Output in the right pane of a split, cut off on the right.
|
||||
start 'sleep 100'
|
||||
$TMUX split-window -h -d "sh -c 'while [ ! -e $TRIGGER ]; do sleep 0.1; done
|
||||
printf ab; exec sleep 100'" || exit 1
|
||||
attach 120x30 80x30
|
||||
: >"$TRIGGER"
|
||||
sleep 1
|
||||
alive "output in a pane cut off on the right"
|
||||
|
||||
# Panned right by less than the side status width, the left pane is cut off
|
||||
# on the left. Its output is drawn after the side status line, not over it.
|
||||
start "sh -c 'while [ ! -e $TRIGGER ]; do sleep 0.1; done
|
||||
printf \"%053d\" 0 | tr 0 X; exec sleep 100'"
|
||||
$TMUX split-window -h -d 'sleep 100' || exit 1
|
||||
attach 120x30 80x30
|
||||
$TMUX refresh-client -t "$SMALL" -R 10 || exit 1
|
||||
sleep 0.5
|
||||
: >"$TRIGGER"
|
||||
sleep 1
|
||||
alive "output in a pane cut off on the left"
|
||||
$TMUX2 capture-pane -p -t small:0.0 >"$CAPTURE" || exit 1
|
||||
row=$(head -n 1 "$CAPTURE")
|
||||
case "$row" in
|
||||
?????????????│XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX│*) ;;
|
||||
*) fail "row is '$row', expected the side status then 43 X" ;;
|
||||
esac
|
||||
|
||||
# Panned into the middle of the right pane, which is cut off on both sides.
|
||||
# The visible columns of the pane are drawn, counted from the pane's left.
|
||||
start 'sleep 100'
|
||||
$TMUX split-window -h -d -l 100 "sh -c 'while [ ! -e $TRIGGER ]; do sleep 0.1; done
|
||||
printf \"%010d\" 0 | sed s/0/0123456789/g; exec sleep 100'" || exit 1
|
||||
attach 214x30 40x30
|
||||
$TMUX refresh-client -t "$SMALL" -R 120 || exit 1
|
||||
sleep 0.5
|
||||
: >"$TRIGGER"
|
||||
sleep 1
|
||||
alive "output in a pane cut off on both sides"
|
||||
$TMUX2 capture-pane -p -t small:0.0 >"$CAPTURE" || exit 1
|
||||
row=$(head -n 1 "$CAPTURE")
|
||||
case "$row" in
|
||||
?????????????│01234567890123456789012345) ;;
|
||||
*) fail "row is '$row', expected the side status then pane columns 20-45" ;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
77
regress/side-status-click.sh
Normal file
77
regress/side-status-click.sh
Normal file
@@ -0,0 +1,77 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Clicking a window on the side status line, including the current window,
|
||||
# dispatches the Status binding with that window.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Click row $1 of the side status line and check the binding got $2.
|
||||
click()
|
||||
{
|
||||
$TMUX set -g @click none || exit 1
|
||||
seq=$(printf '\033[<0;3;%sM\033[<0;3;%sm' "$1" "$1")
|
||||
$TMUX2 send-keys -t outer:0.0 -l "$seq" || fail "send mouse failed"
|
||||
sleep 1
|
||||
got=$($TMUX show -gv @click)
|
||||
[ "$got" = "$2" ] || fail "row $1: got '$got', expected '$2'"
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s inner -n zero -x 60 -y 20 'sleep 100' || exit 1
|
||||
$TMUX new-window -d -n one 'sleep 100' || exit 1
|
||||
$TMUX new-window -d -n two 'sleep 100' || exit 1
|
||||
$TMUX set -g mouse on || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g side-status left || exit 1
|
||||
$TMUX bind -n MouseDown1Status \
|
||||
set -gF @click '#{mouse_status_range} #{window_name}' || exit 1
|
||||
$TMUX bind -n MouseDown1StatusDefault set -g @click default || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 60 -y 20 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
# The current window is first, then in the middle of the list.
|
||||
click 1 'window zero'
|
||||
click 2 'window one'
|
||||
click 4 default
|
||||
$TMUX select-window -t inner:1 || exit 1
|
||||
sleep 0.5
|
||||
click 1 'window zero'
|
||||
click 2 'window one'
|
||||
click 3 'window two'
|
||||
|
||||
# A range closed in the same style as the line break ends on its own row.
|
||||
$TMUX set -g side-status-format '#[range=user|foo]one#[norange,nl]two' ||
|
||||
exit 1
|
||||
sleep 0.5
|
||||
click 1 'foo one'
|
||||
click 2 default
|
||||
|
||||
# A range still open at a line break carries on to the next row.
|
||||
$TMUX set -g side-status-format '#[range=user|foo]one#[nl]two#[norange]' ||
|
||||
exit 1
|
||||
sleep 0.5
|
||||
click 1 'foo one'
|
||||
click 2 'foo one'
|
||||
|
||||
exit 0
|
||||
90
regress/side-status-drag.sh
Normal file
90
regress/side-status-drag.sh
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/bin/sh
|
||||
|
||||
# A Ctrl-drag starting on the side status line must not create a floating
|
||||
# pane, and must still dispatch Status bindings. Ctrl-clicking a window on the
|
||||
# side status line swaps windows, so panes are compared across the session.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
export PATH TERM
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
mouse()
|
||||
{
|
||||
seq=$(printf '\033[<%s;%s;%s%s' "$1" "$2" "$3" "$4")
|
||||
$TMUX2 send-keys -t outer:0.0 -l "$seq" || fail "send mouse failed"
|
||||
sleep 0.2
|
||||
}
|
||||
|
||||
check_drag()
|
||||
{
|
||||
sx=$1
|
||||
sy=$2
|
||||
ex=$3
|
||||
ey=$4
|
||||
|
||||
# First move along the side status line, then into the pane.
|
||||
mouse 16 "$sx" "$sy" M
|
||||
mouse 48 "$sx" $((sy + 1)) M
|
||||
mouse 48 "$ex" "$ey" M
|
||||
mouse 48 $((ex + 2)) "$ey" M
|
||||
mouse 16 $((ex + 2)) "$ey" m
|
||||
|
||||
panes=$($TMUX list-panes -s -F '#{pane_id}') || fail "server exited"
|
||||
panes=$(echo "$panes" | sort)
|
||||
[ "$panes" = "$BASE" ] ||
|
||||
fail "side status drag from $sx,$sy created a pane: $panes"
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s inner -x 60 -y 20 'sleep 100' || exit 1
|
||||
$TMUX new-window -d 'sleep 100' || exit 1
|
||||
$TMUX set -g mouse on || exit 1
|
||||
$TMUX set -g default-command 'sleep 100' || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g side-status left || exit 1
|
||||
BASE=$($TMUX list-panes -s -F '#{pane_id}') || exit 1
|
||||
BASE=$(echo "$BASE" | sort)
|
||||
$TMUX2 new-session -d -s outer -x 60 -y 20 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
# Blank rows and the window list on the left.
|
||||
check_drag 3 10 30 12
|
||||
check_drag 2 1 30 12
|
||||
check_drag 2 2 30 12
|
||||
|
||||
$TMUX set -g side-status right || exit 1
|
||||
sleep 0.5
|
||||
check_drag 55 10 20 12
|
||||
|
||||
# The horizontal status line takes the bottom row below the side status.
|
||||
$TMUX set -g side-status left || exit 1
|
||||
$TMUX set -g status on || exit 1
|
||||
sleep 0.5
|
||||
check_drag 3 10 30 12
|
||||
|
||||
# A drag starting on a window range dispatches the Status binding.
|
||||
$TMUX bind -n C-MouseDrag1Status set -g @status-drag status || exit 1
|
||||
$TMUX set -g @status-drag '' || exit 1
|
||||
check_drag 2 2 30 12
|
||||
got=$($TMUX show -gv @status-drag)
|
||||
[ "$got" = status ] || fail "got drag '$got', expected 'status'"
|
||||
|
||||
exit 0
|
||||
139
regress/side-status-format.sh
Normal file
139
regress/side-status-format.sh
Normal file
@@ -0,0 +1,139 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Split formats into lines, preserve headers and footers while scrolling,
|
||||
# and clip wide or combining characters at the side status boundary.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
DIR=$(mktemp -d) || exit 1
|
||||
HEIGHT=8
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
rm -f "$DIR/actual" "$DIR/expected"
|
||||
rmdir "$DIR"
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
check()
|
||||
{
|
||||
format=$1
|
||||
shift
|
||||
$TMUX set -g side-status-format "$format" || exit 1
|
||||
: >"$DIR/expected"
|
||||
n=0
|
||||
for line in "$@"; do
|
||||
printf '%s\n' "$line" >>"$DIR/expected"
|
||||
n=$((n + 1))
|
||||
done
|
||||
while [ "$n" -lt "$HEIGHT" ]; do
|
||||
printf ' │\n' >>"$DIR/expected"
|
||||
n=$((n + 1))
|
||||
done
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
$TMUX2 capture-pane -p -t outer:0.0 >"$DIR/actual" || exit 1
|
||||
cmp -s "$DIR/actual" "$DIR/expected" && return
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
echo "format '$format' at height $HEIGHT differs:" >&2
|
||||
diff -u "$DIR/expected" "$DIR/actual" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
resize()
|
||||
{
|
||||
HEIGHT=$1
|
||||
$TMUX2 resize-window -t outer:0 -y "$HEIGHT" || exit 1
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s inner -x 40 -y 8 'sleep 100' || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g side-status left || exit 1
|
||||
$TMUX set -g side-status-width 8 || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 40 -y 8 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 set -g window-size manual || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
# Empty, consecutive, leading and trailing breaks, with both spellings.
|
||||
check ''
|
||||
check 'one#[nl]#[nl]three#[nl]' 'one │' ' │' 'three │'
|
||||
check '
|
||||
|
||||
three
|
||||
' ' │' ' │' 'three │'
|
||||
check 'one
|
||||
two' 'one │' 'two │'
|
||||
|
||||
# Escaped hashes must not turn literal text into a line break.
|
||||
check '##[nl]#[nl]two' '#[nl] │' 'two │'
|
||||
check '####[nl]#[nl]two' '##[nl] │' 'two │'
|
||||
check '###[nl]two' '# │' 'two │'
|
||||
check 'one##' 'one# │'
|
||||
|
||||
# Invalid or unfinished styles do not consume the following valid lines.
|
||||
check 'one#[invalid-style]two#[nl]three' 'onetwo │' 'three │'
|
||||
check 'one#[unfinished' 'one │'
|
||||
check '#[ignore]A#[nl]B
|
||||
C' 'A#[nl]B│' 'C │'
|
||||
|
||||
# Alignment carries over a break, as do character widths.
|
||||
check '#[align=centre]X#[nl]Y' ' X │' ' Y │'
|
||||
check '#[align=absolute-centre]X#[nl]Y' ' X │' ' Y │'
|
||||
check 'abcde界#[nl]abcdef界#[nl]abcdeéf' \
|
||||
'abcde界│' 'abcdef │' 'abcdeéf│'
|
||||
|
||||
format='H1#[nl]H2#[nl]#[list=on]L0#[nl]L1#[nl]'
|
||||
format=$format'#[list=focus]L2#[nl]#[list=on]L3#[nl]L4#[nl]'
|
||||
format=$format'#[nolist]F1#[nl]F2'
|
||||
check "$format" 'H1 │' 'H2 │' 'L0 │' 'L1 │' \
|
||||
'L2 │' 'L3 │' 'F1 │' 'F2 │'
|
||||
resize 6
|
||||
check "$format" 'H1 │' 'H2 │' 'L1 │' 'L2 │' \
|
||||
'F1 │' 'F2 │'
|
||||
resize 4
|
||||
check "$format" 'H1 │' 'H2 │' 'F1 │' 'F2 │'
|
||||
resize 3
|
||||
check "$format" 'H1 │' 'H2 │' 'F1 │'
|
||||
resize 1
|
||||
check "$format" 'H1 │'
|
||||
|
||||
# Markers consume only list lines and cannot replace the focused line.
|
||||
format='H#[nl]#[list=on]#[list=left-marker]^#[nl]'
|
||||
format=$format'#[list=right-marker]v#[nl]#[list=on]L0#[nl]L1#[nl]'
|
||||
format=$format'#[list=focus]L2#[nl]#[list=on]L3#[nl]L4#[nl]'
|
||||
format=$format'#[nolist]F'
|
||||
resize 5
|
||||
check "$format" 'H │' '^ │' 'L2 │' 'v │' 'F │'
|
||||
resize 3
|
||||
check "$format" 'H │' 'L2 │' 'F │'
|
||||
resize 2
|
||||
check "$format" 'H │' 'F │'
|
||||
|
||||
# A large logical list does not require a tall terminal.
|
||||
format=$(awk 'BEGIN {
|
||||
printf "H#[nl]#[list=on]"
|
||||
for (i = 0; i < 1000; i++) {
|
||||
if (i == 800)
|
||||
printf "#[list=focus]"
|
||||
if (i == 801)
|
||||
printf "#[list=on]"
|
||||
printf "L%d#[nl]", i
|
||||
}
|
||||
printf "#[nolist]F"
|
||||
}')
|
||||
resize 3
|
||||
check "$format" 'H │' 'L800 │' 'F │'
|
||||
|
||||
exit 0
|
||||
78
regress/side-status-image.sh
Normal file
78
regress/side-status-image.sh
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Images are drawn and erased in the pane's columns with either side status
|
||||
# position and with the horizontal status off, above or below the window.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
export TERM
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
|
||||
python3 -B - "$TEST_TMUX" <<'PY'
|
||||
import sys
|
||||
from image_test import image_test, sixel
|
||||
from image_terminal import Terminal
|
||||
|
||||
side = 14
|
||||
w, h = 16, 32
|
||||
wire = sixel(w, h, [(100, 0, 0)], [0] * (w * h))
|
||||
|
||||
def placed(cx, cy):
|
||||
return {(cx * 8 + x, cy * 16 + y): (255, 0, 0)
|
||||
for y in range(h) for x in range(w)}
|
||||
|
||||
def side_cells(terminal, xoff, yoff, height):
|
||||
return {(x, y): terminal.cells.get((x, y))
|
||||
for y in range(yoff, yoff + height)
|
||||
for x in range(xoff, xoff + side)}
|
||||
|
||||
def check(position, status):
|
||||
with image_test(sys.argv[1]) as test:
|
||||
test.run("set-option", "-g", "side-status", position)
|
||||
test.run("set-option", "-g", "side-status-width", str(side))
|
||||
if status != "off":
|
||||
test.run("set-option", "-g", "status", "2")
|
||||
test.run("set-option", "-g", "status-position", status)
|
||||
xoff = side if position == "left" else 0
|
||||
yoff = 2 if status == "top" else 0
|
||||
height = 16 if status == "off" else 14
|
||||
side_x = 0 if position == "left" else 40 - side
|
||||
separator = side - 1 if position == "left" else side_x
|
||||
client = test.attach()
|
||||
test.emit(b'\033[3;3H' + wire)
|
||||
|
||||
# A full redraw.
|
||||
test.redraw()
|
||||
terminal = Terminal()
|
||||
terminal.feed(client.data)
|
||||
terminal.check(placed(xoff + 2, yoff + 2))
|
||||
cells = side_cells(terminal, side_x, yoff, height)
|
||||
assert all(cells[separator, y] not in (None, ' ')
|
||||
for y in range(yoff, yoff + height)), \
|
||||
(position, status, 'side status line not drawn')
|
||||
|
||||
# Inserting a line above the image redraws the damaged area.
|
||||
test.emit(b'\033[3;1H\033[L')
|
||||
terminal.feed(client.data)
|
||||
terminal.check(placed(xoff + 2, yoff + 3))
|
||||
assert side_cells(terminal, side_x, yoff, height) == cells, \
|
||||
(position, status, 'side status erased by damage')
|
||||
|
||||
# Leaving copy mode redraws only the pane.
|
||||
client.clear()
|
||||
test.run("copy-mode")
|
||||
test.wait(lambda: test.run("display-message", "-p",
|
||||
"#{pane_in_mode}") == "1")
|
||||
test.run("send-keys", "-X", "cancel")
|
||||
test.wait(lambda: test.run("display-message", "-p",
|
||||
"#{pane_in_mode}") == "0")
|
||||
client.read(0.2)
|
||||
terminal.feed(client.data)
|
||||
terminal.check(placed(xoff + 2, yoff + 3))
|
||||
assert side_cells(terminal, side_x, yoff, height) == cells, \
|
||||
(position, status, 'side status erased by pane redraw')
|
||||
|
||||
for position in ("left", "right"):
|
||||
for status in ("off", "top", "bottom"):
|
||||
check(position, status)
|
||||
PY
|
||||
72
regress/side-status-margins.sh
Normal file
72
regress/side-status-margins.sh
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
|
||||
# On a terminal with left and right margins, scrolling a pane beside the side
|
||||
# status line sets the margins to the pane's columns. The inner client is
|
||||
# told the terminal has margins and its output is recorded raw from the outer
|
||||
# pane, where ESC [ left ; right s sets the margins (1-based).
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
DIR=$(mktemp -d) || exit 1
|
||||
TRIGGER=$DIR/trigger
|
||||
OUT=$DIR/out
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
rm -f "$TRIGGER" "$OUT"
|
||||
rmdir "$DIR"
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Scroll a full width pane with the side status line on side $1 and check the
|
||||
# margins sent are $2.
|
||||
check()
|
||||
{
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
rm -f "$TRIGGER" "$OUT"
|
||||
|
||||
$TMUX new-session -d -s inner -x 60 -y 10 "sh -c '
|
||||
while [ ! -e $TRIGGER ]; do sleep 0.1; done
|
||||
i=0
|
||||
while [ \$i -lt 15 ]; do i=\$((i + 1)); echo line\$i; done
|
||||
exec sleep 100'" || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g side-status "$1" || exit 1
|
||||
$TMUX set -as terminal-features ',*:margins' || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 60 -y 10 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
$TMUX2 pipe-pane -t outer:0.0 "cat >$OUT" || exit 1
|
||||
sleep 0.5
|
||||
: >"$TRIGGER"
|
||||
sleep 1
|
||||
|
||||
got=$(tr '\033' E <"$OUT" | grep -o 'E\[[0-9]*;[0-9]*s' | sort -u |
|
||||
tr -d 'E[s' | tr '\n' ' ')
|
||||
[ "$got" = "$2 " ] || fail "side-status $1: margins '$got', expected '$2'"
|
||||
}
|
||||
|
||||
# Pane in columns 15 to 60 after a left side status line of width 14.
|
||||
check left '15;60'
|
||||
|
||||
# Pane in columns 1 to 46 before a right side status line.
|
||||
check right '1;46'
|
||||
|
||||
exit 0
|
||||
109
regress/side-status-mouse.sh
Normal file
109
regress/side-status-mouse.sh
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Status coordinates and session/window targets on either side, with the
|
||||
# horizontal status off, above or below the window.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
click()
|
||||
{
|
||||
expected="$3|$(($1 - 1))|$(($2 - 1))"
|
||||
$TMUX set -g @mouse none || exit 1
|
||||
seq=$(printf '\033[<0;%s;%sM\033[<0;%s;%sm' "$1" "$2" "$1" "$2")
|
||||
$TMUX2 send-keys -t outer:0.0 -l "$seq" || exit 1
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
got=$($TMUX show -gv @mouse)
|
||||
[ "$got" = "$expected" ] && break
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
[ "$got" = "$expected" ] || {
|
||||
echo "$side/$status at $1,$2: '$got', expected '$expected'" >&2
|
||||
exit 1
|
||||
}
|
||||
sleep 0.5
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s inner -n zero -x 80 -y 20 'sleep 100' || exit 1
|
||||
$TMUX new-window -d -n one 'sleep 100' || exit 1
|
||||
$TMUX new-session -d -s beta -n other -x 100 -y 30 'sleep 100' || exit 1
|
||||
$TMUX set -g mouse on || exit 1
|
||||
$TMUX set -g automatic-rename off || exit 1
|
||||
$TMUX set -g side-status-width 14 || exit 1
|
||||
[ "$($TMUX display -p '#{mouse_absolute_x}|#{mouse_absolute_y}')" = '|' ] ||
|
||||
exit 1
|
||||
$TMUX set -g 'status-format[0]' \
|
||||
'#[range=window|1]window#[norange]' || exit 1
|
||||
$TMUX set -g 'status-format[1]' 'second' || exit 1
|
||||
format='#{mouse_status_range}|#{mouse_status_line}|#{mouse_x}|#{mouse_y}'
|
||||
format=$format'|#{session_name}|#{window_name}'
|
||||
format=$format'|#{mouse_absolute_x}|#{mouse_absolute_y}'
|
||||
for key in MouseDown1Status MouseDown1StatusDefault MouseDown1StatusBorder \
|
||||
MouseDown1Pane; do
|
||||
$TMUX bind -n "$key" set -gF @mouse "$format" || exit 1
|
||||
done
|
||||
$TMUX2 new-session -d -s outer -x 80 -y 20 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
for side in left right; do
|
||||
$TMUX set -g side-status "$side" || exit 1
|
||||
if [ "$side" = left ]; then
|
||||
column=3
|
||||
separator=14
|
||||
pane_column=17
|
||||
separator_x=13
|
||||
else
|
||||
column=69
|
||||
separator=67
|
||||
pane_column=3
|
||||
separator_x=0
|
||||
fi
|
||||
for status in off top bottom; do
|
||||
offset=0
|
||||
if [ "$status" = off ]; then
|
||||
$TMUX set -g status off || exit 1
|
||||
else
|
||||
$TMUX set -g status 2 || exit 1
|
||||
$TMUX set -g status-position "$status" || exit 1
|
||||
[ "$status" = top ] && offset=2
|
||||
fi
|
||||
sleep 0.5
|
||||
|
||||
# The current session's windows are between the session headers.
|
||||
click "$column" "$((offset + 1))" 'session|0|2|0|inner|zero'
|
||||
click "$((column + 3))" "$((offset + 3))" \
|
||||
'window|2|5|2|inner|one'
|
||||
click "$column" "$((offset + 4))" 'session|3|2|3|beta|other'
|
||||
click "$separator" "$((offset + 6))" \
|
||||
"|5|$separator_x|5|inner|zero"
|
||||
click "$pane_column" "$((offset + 7))" '||2|6|inner|zero'
|
||||
|
||||
# Horizontal status coordinates are relative to its first line,
|
||||
# even if the clicked window's pane extends behind the status.
|
||||
if [ "$status" != off ]; then
|
||||
line=1
|
||||
[ "$status" = bottom ] && line=19
|
||||
click 3 "$line" 'window|0|2|0|inner|one'
|
||||
click 3 "$((line + 1))" '|1|2|1|inner|zero'
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
exit 0
|
||||
55
regress/side-status-off-redraw.sh
Normal file
55
regress/side-status-off-redraw.sh
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
|
||||
# With the side status line off, a full redraw after changing window still
|
||||
# draws pane border status lines that have not changed.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
check()
|
||||
{
|
||||
got=$($TMUX2 capture-pane -p -t outer:0.0 | head -n 1)
|
||||
[ "$got" = "$2" ] || fail "$1: top row is '$got', expected '$2'"
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s inner -x 40 -y 10 'sleep 100' || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g pane-border-status top || exit 1
|
||||
$TMUX set -g pane-border-format ' #{pane_index} ' || exit 1
|
||||
$TMUX split-window -h 'sleep 100' || exit 1
|
||||
$TMUX new-window 'sleep 100' || exit 1
|
||||
$TMUX select-window -t:0 || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 40 -y 10 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
SPLIT='── 0 ───────────────┬── 1 ──────────────'
|
||||
check attach "$SPLIT"
|
||||
|
||||
$TMUX select-window -t:1 || exit 1
|
||||
sleep 0.5
|
||||
$TMUX select-window -t:0 || exit 1
|
||||
sleep 0.5
|
||||
check "after select-window" "$SPLIT"
|
||||
|
||||
exit 0
|
||||
113
regress/side-status-pane-drag.sh
Normal file
113
regress/side-status-pane-drag.sh
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Creating, moving and resizing panes must use window coordinates with a
|
||||
# side status line, including when the horizontal status is at the top.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
export PATH TERM
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$side/$status: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Send window coordinates as one-based terminal coordinates.
|
||||
mouse()
|
||||
{
|
||||
seq=$(printf '\033[<%s;%s;%s%s' "$1" \
|
||||
"$(( $2 + xoff + 1 ))" "$(( $3 + yoff + 1 ))" "$4")
|
||||
$TMUX2 send-keys -t outer:0.0 -l "$seq" || fail "send mouse failed"
|
||||
sleep 0.2
|
||||
}
|
||||
|
||||
drag()
|
||||
{
|
||||
mouse "$1" "$2" "$3" M
|
||||
mouse "$(( $1 + 32 ))" "$4" "$5" M
|
||||
mouse "$1" "$4" "$5" m
|
||||
}
|
||||
|
||||
check()
|
||||
{
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
got=$($TMUX display -p -t "$1" \
|
||||
'#{pane_left},#{pane_top},#{pane_width},#{pane_height}')
|
||||
[ "$got" = "$2" ] && return
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
fail "pane $1: got '$got', expected '$2'"
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s inner -x 80 -y 24 'sleep 100' || exit 1
|
||||
$TMUX set -g mouse on || exit 1
|
||||
$TMUX set -g default-command 'sleep 100' || exit 1
|
||||
$TMUX set -g side-status-width 14 || exit 1
|
||||
BASE=$($TMUX display -p '#{pane_id}') || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 80 -y 24 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
for side in left right; do
|
||||
$TMUX set -g side-status "$side" || exit 1
|
||||
xoff=0
|
||||
[ "$side" = left ] && xoff=14
|
||||
for status in off top bottom; do
|
||||
yoff=0
|
||||
if [ "$status" = off ]; then
|
||||
$TMUX set -g status off || exit 1
|
||||
else
|
||||
$TMUX set -g status 2 || exit 1
|
||||
$TMUX set -g status-position "$status" || exit 1
|
||||
[ "$status" = top ] && yoff=2
|
||||
fi
|
||||
sleep 0.5
|
||||
|
||||
# Ctrl-drag creates a floating pane inside the rectangle.
|
||||
drag 16 2 1 10 5
|
||||
id=$($TMUX list-panes -F \
|
||||
'#{?pane_floating_flag,#{pane_id},}' | tail -1)
|
||||
[ -n "$id" ] || fail "drag did not create a floating pane"
|
||||
check "$id" '3,2,7,3'
|
||||
$TMUX kill-pane -t "$id" || exit 1
|
||||
|
||||
# Alt-drag moves a floating pane without changing its size.
|
||||
id=$($TMUX new-pane -dPF '#{pane_id}' \
|
||||
-x 14 -y 7 -X 5 -Y 3 'sleep 100') || exit 1
|
||||
check "$id" '6,4,12,5'
|
||||
drag 8 8 5 12 7
|
||||
check "$id" '10,6,12,5'
|
||||
|
||||
# Dragging the bottom right border resizes both dimensions.
|
||||
drag 0 22 11 25 13
|
||||
check "$id" '10,6,15,7'
|
||||
$TMUX kill-pane -t "$id" || exit 1
|
||||
|
||||
# The same terminal offsets apply to tiled pane borders.
|
||||
id=$($TMUX split-window -dhPF '#{pane_id}' \
|
||||
-t "$BASE" 'sleep 100') || exit 1
|
||||
width=$($TMUX display -p -t "$BASE" '#{pane_width}')
|
||||
drag 0 "$width" 5 "$((width + 4))" 5
|
||||
got=$($TMUX display -p -t "$BASE" '#{pane_width}')
|
||||
[ "$got" = "$((width + 4))" ] ||
|
||||
fail "tiled width: got '$got', expected '$((width + 4))'"
|
||||
$TMUX kill-pane -t "$id" || exit 1
|
||||
done
|
||||
done
|
||||
|
||||
exit 0
|
||||
83
regress/side-status-prompt.sh
Normal file
83
regress/side-status-prompt.sh
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/bin/sh
|
||||
|
||||
# A pane prompt redrawn after the pane scrolls stays beside the side status
|
||||
# line. With side-status left the pane is not full width, so scrolling is
|
||||
# redrawn as damage, which draws the prompt again over the pane.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
DIR=$(mktemp -d) || exit 1
|
||||
TRIGGER=$DIR/trigger
|
||||
CAPTURE=$DIR/capture
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
rm -rf "$DIR"
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
[ -s "$CAPTURE" ] && cat "$CAPTURE" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
wait_outer_has()
|
||||
{
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
$TMUX2 capture-pane -p -t outer:0.0 >"$CAPTURE" 2>/dev/null
|
||||
grep -q "$1" "$CAPTURE" && return 0
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
fail "outer client did not show $1"
|
||||
}
|
||||
|
||||
# The pane waits for the trigger, then prints enough lines to scroll.
|
||||
$TMUX new-session -d -s inner -n work -x 60 -y 20 "sh -c '
|
||||
while [ ! -e $TRIGGER ]; do sleep 0.1; done
|
||||
i=0
|
||||
while [ \$i -lt 40 ]; do i=\$((i + 1)); echo line\$i; done
|
||||
exec sleep 100'" || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g automatic-rename off || exit 1
|
||||
$TMUX set -g side-status left || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 60 -y 20 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
CLIENT=$($TMUX list-clients -F '#{client_name}' 2>/dev/null)
|
||||
[ -n "$CLIENT" ] && break
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
[ -n "$CLIENT" ] || fail "inner client did not attach"
|
||||
|
||||
$TMUX command-prompt -b -P -t "$CLIENT" -p PROMPTX 'display -p %%' ||
|
||||
exit 1
|
||||
wait_outer_has PROMPTX
|
||||
|
||||
: >"$TRIGGER"
|
||||
wait_outer_has line40
|
||||
sleep 0.5
|
||||
|
||||
# The bottom row is the side status line followed by the prompt.
|
||||
$TMUX2 capture-pane -p -t outer:0.0 >"$CAPTURE" || exit 1
|
||||
want="$(printf '%13s' '')│PROMPTX"
|
||||
got=$(tail -n 1 "$CAPTURE")
|
||||
[ "$got" = "$want" ] || fail "bottom row is '$got', expected '$want'"
|
||||
|
||||
exit 0
|
||||
78
regress/side-status-refresh.sh
Normal file
78
regress/side-status-refresh.sh
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
# The side status line must refresh every status-interval seconds on its own,
|
||||
# whether or not the horizontal status line is on, and whether it was on when
|
||||
# the client attached or turned on afterwards. The client status timer drives
|
||||
# both lines, so this checks it is armed in both cases with status off.
|
||||
#
|
||||
# The side status line is rendered by an inner tmux attached inside an outer
|
||||
# tmux pane. Its format is a #() command which appends a byte to a file each
|
||||
# time it runs, and a #() command is run again only when the format is
|
||||
# expanded in a later second, so the file grows once per refresh. Nothing in
|
||||
# the test asks for a redraw between the two counts, so growth means the
|
||||
# timer refreshed the side status line by itself.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
COUNT1=$(mktemp)
|
||||
COUNT2=$(mktemp)
|
||||
trap "rm -f $COUNT1 $COUNT2; $TMUX kill-server 2>/dev/null; \
|
||||
$TMUX2 kill-server 2>/dev/null" 0 1 15
|
||||
|
||||
fail() {
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
count() {
|
||||
wc -c <"$1" | tr -d ' '
|
||||
}
|
||||
|
||||
# Attach the inner server in an outer pane, then wait for the first draw.
|
||||
attach() {
|
||||
$TMUX new -d -x30 -y8 "$TMUX2 attach" || exit 1
|
||||
sleep 1
|
||||
}
|
||||
|
||||
# Check the side status line refreshed at least twice in three seconds.
|
||||
refreshes() {
|
||||
before=$(count "$1")
|
||||
sleep 3
|
||||
after=$(count "$1")
|
||||
[ $((after - before)) -ge 2 ] ||
|
||||
fail "$2: side status ran $before then $after times, did not refresh"
|
||||
}
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
# Side status on before the client attaches, with status off.
|
||||
$TMUX2 new -d -x30 -y8 "sh -c 'exec sleep 100'" || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 set -g status-interval 1 || exit 1
|
||||
$TMUX2 set -g side-status left || exit 1
|
||||
$TMUX2 set -g side-status-format "#(printf x >>$COUNT1)" || exit 1
|
||||
attach
|
||||
refreshes "$COUNT1" "on at attach"
|
||||
|
||||
# Side status turned on after the client attached, with status off. A new
|
||||
# inner server so the client timer starts from nothing.
|
||||
$TMUX2 kill-server || exit 1
|
||||
sleep 1
|
||||
$TMUX2 new -d -x30 -y8 "sh -c 'exec sleep 100'" || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 set -g status-interval 1 || exit 1
|
||||
$TMUX2 set -g side-status-format "#(printf x >>$COUNT2)" || exit 1
|
||||
attach
|
||||
$TMUX2 set -g side-status left || exit 1
|
||||
sleep 1
|
||||
refreshes "$COUNT2" "on after attach"
|
||||
|
||||
exit 0
|
||||
197
regress/side-status-resize.sh
Normal file
197
regress/side-status-resize.sh
Normal file
@@ -0,0 +1,197 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Drag the separator on either side, including across the moving boundary and
|
||||
# horizontal status. Check limits, release, text bindings and a second client.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$side/$status: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
mouse()
|
||||
{
|
||||
seq=$(printf '\033[<%s;%s;%s%s' "$1" "$2" "$3" "$4")
|
||||
$TMUX2 send-keys -t outer:0.0 -l "$seq" || fail "send mouse failed"
|
||||
sleep 0.1
|
||||
}
|
||||
|
||||
check()
|
||||
{
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
width=$($TMUX show -Av -t inner side-status-width)
|
||||
window=$($TMUX display -p -t inner '#{window_width}')
|
||||
if [ "$width" = "$1" ] && [ "$window" = "$((80 - $1))" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
[ "$width,$window" = "$1,$((80 - $1))" ] ||
|
||||
fail "side/window widths $width/$window, expected $1/$((80 - $1))"
|
||||
column=$1
|
||||
[ "$side" = right ] && column=$((81 - $1))
|
||||
padding=$(printf '%*s' "$((column - 1))" '')
|
||||
for target in outer other; do
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
row=$($TMUX2 capture-pane -p -t "$target:0.0" |
|
||||
sed -n "$((offset + 2))p")
|
||||
case "$row" in
|
||||
"$padding│"*) break ;;
|
||||
esac
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
[ "$i" -lt 50 ] || fail "$target: wrong separator column: $row"
|
||||
done
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s inner -n zero -x 80 -y 20 'sleep 180' || exit 1
|
||||
$TMUX set -g mouse on || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g side-status-format \
|
||||
'#[range=window|0]window#[norange]' || exit 1
|
||||
$TMUX bind -n MouseDrag1Status set -g @text-drag yes || exit 1
|
||||
$TMUX bind -n MouseDrag1StatusDefault set -g @blank-drag yes || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 80 -y 20 'sleep 180' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 new-session -d -s other -x 80 -y 20 'sleep 180' || exit 1
|
||||
for target in outer other; do
|
||||
$TMUX2 respawn-pane -k -t "$target:0.0" \
|
||||
"$TMUX attach -t inner" || exit 1
|
||||
done
|
||||
sleep 1
|
||||
|
||||
for side in left right; do
|
||||
$TMUX set -t inner side-status "$side" || exit 1
|
||||
for status in off top bottom; do
|
||||
offset=0
|
||||
if [ "$status" = off ]; then
|
||||
$TMUX set -t inner status off || exit 1
|
||||
else
|
||||
$TMUX set -t inner status 2 || exit 1
|
||||
$TMUX set -t inner status-position "$status" || exit 1
|
||||
[ "$status" = top ] && offset=2
|
||||
fi
|
||||
$TMUX set -t inner side-status-width 14 || exit 1
|
||||
check 14
|
||||
if [ "$side" = left ]; then
|
||||
start=14 grow=20 shrink=10 smallest=1 largest=80
|
||||
else
|
||||
start=67 grow=61 shrink=71 smallest=80 largest=1
|
||||
fi
|
||||
|
||||
# Grow into the window, then shrink past the starting point.
|
||||
mouse 0 "$start" "$((offset + 6))" M
|
||||
mouse 32 "$grow" "$((offset + 6))" M
|
||||
check 20
|
||||
mouse 32 "$shrink" 1 M
|
||||
check 10
|
||||
mouse 32 "$largest" "$((offset + 6))" M
|
||||
check 79
|
||||
mouse 32 "$smallest" "$((offset + 6))" M
|
||||
check 2
|
||||
mouse 0 "$smallest" "$((offset + 6))" m
|
||||
|
||||
# Motion after release must not resize, and the separator stays
|
||||
# draggable at the minimum width.
|
||||
mouse 35 "$grow" "$((offset + 6))" M
|
||||
check 2
|
||||
sleep 0.5
|
||||
start=2
|
||||
[ "$side" = right ] && start=79
|
||||
mouse 0 "$start" "$((offset + 6))" M
|
||||
mouse 32 "$grow" "$((offset + 6))" M
|
||||
check 20
|
||||
mouse 0 "$grow" "$((offset + 6))" m
|
||||
sleep 0.5
|
||||
|
||||
# Dragging text or blank content dispatches its usual binding.
|
||||
text=2
|
||||
[ "$side" = right ] && text=63
|
||||
$TMUX set -g @text-drag no || exit 1
|
||||
mouse 0 "$text" "$((offset + 1))" M
|
||||
mouse 32 "$((text + 1))" "$((offset + 1))" M
|
||||
mouse 32 40 "$((offset + 6))" M
|
||||
mouse 0 40 "$((offset + 6))" m
|
||||
got=$($TMUX show -gv @text-drag)
|
||||
[ "$got" = yes ] || fail "text drag binding did not fire"
|
||||
check 20
|
||||
sleep 0.5
|
||||
$TMUX set -g @blank-drag no || exit 1
|
||||
mouse 0 "$text" "$((offset + 8))" M
|
||||
mouse 32 40 "$((offset + 8))" M
|
||||
mouse 0 40 "$((offset + 8))" m
|
||||
got=$($TMUX show -gv @blank-drag)
|
||||
[ "$got" = yes ] || fail "blank drag binding did not fire"
|
||||
check 20
|
||||
|
||||
# A modified drag on the separator does not resize it.
|
||||
mouse 16 "$grow" "$((offset + 6))" M
|
||||
mouse 48 40 "$((offset + 6))" M
|
||||
mouse 16 40 "$((offset + 6))" m
|
||||
check 20
|
||||
if [ "$status" != off ]; then
|
||||
line=1
|
||||
[ "$status" = bottom ] && line=19
|
||||
mouse 0 "$grow" "$line" M
|
||||
mouse 32 40 "$((offset + 6))" M
|
||||
mouse 0 40 "$((offset + 6))" m
|
||||
check 20
|
||||
fi
|
||||
[ "$($TMUX show -gv side-status-width)" = 14 ] ||
|
||||
fail "drag changed the global width"
|
||||
|
||||
# Double-click removes the local width and inherits the default.
|
||||
sleep 0.5
|
||||
seq=$(printf '\033[<0;%s;%sM\033[<0;%s;%sm' \
|
||||
"$grow" "$((offset + 6))" "$grow" "$((offset + 6))")
|
||||
$TMUX2 send-keys -t outer:0.0 -l "$seq$seq" || exit 1
|
||||
check 14
|
||||
[ -z "$($TMUX show -v -q -t inner side-status-width)" ] ||
|
||||
fail "double-click did not remove the local width"
|
||||
done
|
||||
done
|
||||
|
||||
# The resize action is an ordinary binding and can be replaced or removed.
|
||||
$TMUX set -t inner side-status-width 20 || exit 1
|
||||
check 20
|
||||
$TMUX set -g @border-drag no || exit 1
|
||||
$TMUX set -g @border-end no || exit 1
|
||||
$TMUX bind -n MouseDrag1StatusBorder \
|
||||
set -gF @border-drag '#{mouse_absolute_x},#{mouse_absolute_y}' || exit 1
|
||||
$TMUX bind -n MouseDragEnd1StatusBorder set -g @border-end yes || exit 1
|
||||
mouse 0 61 6 M
|
||||
mouse 32 40 6 M
|
||||
mouse 32 42 6 M
|
||||
mouse 0 42 6 m
|
||||
check 20
|
||||
[ "$($TMUX show -gv @border-drag)" = 41,5 ] ||
|
||||
fail "custom border binding did not get the terminal coordinates"
|
||||
[ "$($TMUX show -gv @border-end)" = yes ] ||
|
||||
fail "border drag end binding did not fire"
|
||||
$TMUX unbind -n MouseDrag1StatusBorder || exit 1
|
||||
mouse 0 61 6 M
|
||||
mouse 32 40 6 M
|
||||
mouse 0 40 6 m
|
||||
check 20
|
||||
|
||||
exit 0
|
||||
24
regress/side-status-results/side-left-floating.result
Normal file
24
regress/side-status-results/side-left-floating.result
Normal file
@@ -0,0 +1,24 @@
|
||||
0:editor │┌──────────┐
|
||||
1:server* ││FLOAT │
|
||||
2:logs- ││ │
|
||||
│└──────────┘
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
24
regress/side-status-results/side-left.result
Normal file
24
regress/side-status-results/side-left.result
Normal file
@@ -0,0 +1,24 @@
|
||||
0:editor │SERVER
|
||||
1:server* │
|
||||
2:logs- │
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
24
regress/side-status-results/side-off.result
Normal file
24
regress/side-status-results/side-off.result
Normal file
@@ -0,0 +1,24 @@
|
||||
SERVER
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[test]0:editor 1:server* 2:logs-
|
||||
24
regress/side-status-results/side-right-narrow.result
Normal file
24
regress/side-status-results/side-right-narrow.result
Normal file
@@ -0,0 +1,24 @@
|
||||
SERVER │0:editor
|
||||
│1:server*
|
||||
│2:logs-
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
[test]0:editor 1:server* 2:logs-
|
||||
24
regress/side-status-results/side-right-status.result
Normal file
24
regress/side-status-results/side-right-status.result
Normal file
@@ -0,0 +1,24 @@
|
||||
SERVER │0:editor
|
||||
│1:server*
|
||||
│2:logs-
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
[test]0:editor 1:server* 2:logs-
|
||||
24
regress/side-status-results/side-right.result
Normal file
24
regress/side-status-results/side-right.result
Normal file
@@ -0,0 +1,24 @@
|
||||
SERVER │0:editor
|
||||
│1:server*
|
||||
│2:logs-
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
24
regress/side-status-results/side-sessions.result
Normal file
24
regress/side-status-results/side-sessions.result
Normal file
@@ -0,0 +1,24 @@
|
||||
work │SERVER
|
||||
├─→ 0:editor │
|
||||
├─→ 1:server* │
|
||||
└─→ 2:logs- │
|
||||
beta │
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
148
regress/side-status-scroll.sh
Normal file
148
regress/side-status-scroll.sh
Normal file
@@ -0,0 +1,148 @@
|
||||
#!/bin/sh
|
||||
|
||||
# With more windows than rows, the default side status format scrolls the
|
||||
# window list to keep the current window visible and replaces the first and
|
||||
# last visible rows with up and down markers.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
TMP=$(mktemp) || exit 1
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
rm -f "$TMP"
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
$TMUX new-session -d -s inner -n w0 -x 60 -y 10 'sleep 100' || exit 1
|
||||
i=1
|
||||
while [ "$i" -lt 15 ]; do
|
||||
$TMUX new-window -d -n "w$i" 'sleep 100' || exit 1
|
||||
i=$((i + 1))
|
||||
done
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g side-status left || exit 1
|
||||
$TMUX select-window -t inner:7 || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 60 -y 10 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
# Compare the outer pane with the expected rows on standard input.
|
||||
compare()
|
||||
{
|
||||
$TMUX2 capture-pane -p -t outer:0.0 >"$TMP" || exit 1
|
||||
if ! cmp -s - "$TMP"; then
|
||||
echo "$1 differs:" >&2
|
||||
cat "$TMP" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
compare "scrolled side status" <<EOF
|
||||
↑ │
|
||||
3:w3 │
|
||||
4:w4 │
|
||||
5:w5 │
|
||||
6:w6 │
|
||||
7:w7* │
|
||||
8:w8 │
|
||||
9:w9 │
|
||||
10:w10 │
|
||||
↓ │
|
||||
EOF
|
||||
|
||||
# A long current window name in the first row is cut on the right like the
|
||||
# other rows.
|
||||
$TMUX rename-window -t inner:0 dotfiles-repo || exit 1
|
||||
$TMUX select-window -t inner:0 || exit 1
|
||||
sleep 1
|
||||
compare "first row" <<EOF
|
||||
0:dotfiles-re│
|
||||
1:w1 │
|
||||
2:w2 │
|
||||
3:w3 │
|
||||
4:w4 │
|
||||
5:w5 │
|
||||
6:w6 │
|
||||
7:w7- │
|
||||
8:w8 │
|
||||
↓ │
|
||||
EOF
|
||||
|
||||
# A format with its list styles in the same order as on the status line, with
|
||||
# list=on before the markers, draws the same rows.
|
||||
$TMUX set -g side-status-format '#[list=on]#[list=left-marker]^#[nl]'\
|
||||
'#[list=right-marker]v#[nl]'\
|
||||
'#{W:#[range=window|#{window_index}]#I:#W#[norange]#[nl],'\
|
||||
'#[range=window|#{window_index} list=focus]#I:#W*#[norange list=on]#[nl]}' ||
|
||||
exit 1
|
||||
$TMUX rename-window -t inner:0 w0 || exit 1
|
||||
$TMUX select-window -t inner:7 || exit 1
|
||||
sleep 1
|
||||
compare "status line order" <<EOF
|
||||
^ │
|
||||
3:w3 │
|
||||
4:w4 │
|
||||
5:w5 │
|
||||
6:w6 │
|
||||
7:w7* │
|
||||
8:w8 │
|
||||
9:w9 │
|
||||
10:w10 │
|
||||
v │
|
||||
EOF
|
||||
|
||||
# With list=on at the start of each window row and the focus closed in the
|
||||
# current row, a long current window name is still cut on the right.
|
||||
$TMUX set -g side-status-format \
|
||||
'#{W:#[list=on]#I:#W#[nl],#[list=on]#[list=focus]#I:#W*#[list=on]#[nl]}' ||
|
||||
exit 1
|
||||
$TMUX rename-window -t inner:0 dotfiles-repo || exit 1
|
||||
$TMUX select-window -t inner:0 || exit 1
|
||||
sleep 1
|
||||
compare "list=on rows" <<EOF
|
||||
0:dotfiles-re│
|
||||
1:w1 │
|
||||
2:w2 │
|
||||
3:w3 │
|
||||
4:w4 │
|
||||
5:w5 │
|
||||
6:w6 │
|
||||
7:w7 │
|
||||
8:w8 │
|
||||
9:w9 │
|
||||
EOF
|
||||
|
||||
# With only one or two rows, a marker is not drawn over the current window.
|
||||
$TMUX set -gu side-status-format || exit 1
|
||||
$TMUX rename-window -t inner:0 w0 || exit 1
|
||||
$TMUX select-window -t inner:7 || exit 1
|
||||
$TMUX2 resize-window -t outer -y 2 || exit 1
|
||||
sleep 1
|
||||
compare "two rows" <<EOF
|
||||
↑ │
|
||||
7:w7* │
|
||||
EOF
|
||||
$TMUX select-window -t inner:1 || exit 1
|
||||
sleep 1
|
||||
compare "two rows at the top" <<EOF
|
||||
0:w0 │
|
||||
1:w1* │
|
||||
EOF
|
||||
$TMUX select-window -t inner:7 || exit 1
|
||||
$TMUX2 resize-window -t outer -y 1 || exit 1
|
||||
sleep 1
|
||||
compare "one row" <<EOF
|
||||
7:w7* │
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
81
regress/side-status-style.sh
Normal file
81
regress/side-status-style.sh
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/bin/sh
|
||||
|
||||
# The style at the end of a side status row carries over to the next row, as
|
||||
# if the rows were one line: attributes removed from side-status-style stay
|
||||
# removed, a pushed or set default stays in place, and the alignment, fill and
|
||||
# hyperlink carry on. The inner client runs in an outer pane which is captured
|
||||
# with its attributes.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check the second side status row starts with $2.
|
||||
row2()
|
||||
{
|
||||
got=$($TMUX2 capture-pane -ep -t outer:0.0 | sed -n 2p)
|
||||
case "$got" in
|
||||
"$2"*) ;;
|
||||
*) fail "$1: row 2 is '$got'" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s inner -x 40 -y 10 'sleep 100' || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX set -g side-status left || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 40 -y 10 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
ESC=$(printf '\033')
|
||||
|
||||
$TMUX set -g side-status-style bold || exit 1
|
||||
$TMUX set -g side-status-format '#[nobold]one#[nl]two' || exit 1
|
||||
sleep 1
|
||||
row2 "nobold" "two"
|
||||
|
||||
$TMUX set -g side-status-style default || exit 1
|
||||
$TMUX set -g side-status-format \
|
||||
'#[fg=red]#[push-default]one#[nl]#[fg=blue]#[default]two' || exit 1
|
||||
sleep 1
|
||||
row2 "push-default" "$ESC[31mtwo"
|
||||
|
||||
$TMUX set -g side-status-format \
|
||||
'#[fg=red]#[set-default]#[fg=blue]#[push-default]one#[nl]'\
|
||||
'#[pop-default]#[default]two' || exit 1
|
||||
sleep 1
|
||||
row2 "set-default" "$ESC[31mtwo"
|
||||
|
||||
$TMUX set -g side-status-format '#[align=right]one#[nl]two' || exit 1
|
||||
sleep 1
|
||||
row2 "align" " two"
|
||||
|
||||
$TMUX set -g side-status-format '#[fill=red]one#[nl]two' || exit 1
|
||||
sleep 1
|
||||
row2 "fill" "two$ESC[41m"
|
||||
|
||||
$TMUX set -g side-status-format '#[link=https://example.com/]one#[nl]two' ||
|
||||
exit 1
|
||||
sleep 1
|
||||
row2 "link" "$ESC]8;"
|
||||
|
||||
exit 0
|
||||
89
regress/side-status.sh
Normal file
89
regress/side-status.sh
Normal file
@@ -0,0 +1,89 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Side status line rendering: geometry on the left and right, a floating pane
|
||||
# against the window edge, coexistence with the horizontal status line, width
|
||||
# changes and turning it off. Scenes are rendered in an inner tmux attached
|
||||
# inside an outer tmux pane; the outer pane is captured and compared with
|
||||
# goldens in side-status-results/.
|
||||
#
|
||||
# Run with GENERATE=1 to (re)create the golden files.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
RESULTS=side-status-results
|
||||
|
||||
TMP=$(mktemp)
|
||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null" \
|
||||
0 1 15
|
||||
|
||||
fail() {
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
compare() {
|
||||
sleep 1
|
||||
$TMUX capturep -p >$TMP || exit 1
|
||||
if [ -n "$GENERATE" ]; then
|
||||
cp $TMP "$RESULTS/$1.result" || exit 1
|
||||
else
|
||||
cmp -s $TMP "$RESULTS/$1.result" ||
|
||||
fail "scene $1 differs from $RESULTS/$1.result"
|
||||
fi
|
||||
}
|
||||
|
||||
mkdir -p "$RESULTS"
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
$TMUX new-session -d -x 80 -y 24 || exit 1
|
||||
|
||||
# Inner server with fixed pane content so captures are stable.
|
||||
$TMUX2 new-session -d -s work -n editor "sh -c 'printf EDITOR; exec sleep 100'"
|
||||
$TMUX2 new-window -n server "sh -c 'printf SERVER; exec sleep 100'"
|
||||
$TMUX2 new-window -n logs "sh -c 'printf LOGS; exec sleep 100'"
|
||||
$TMUX2 select-window -t:1
|
||||
$TMUX2 set -g status off
|
||||
$TMUX2 set -g status-left "[test]"
|
||||
$TMUX2 set -g status-right ""
|
||||
$TMUX2 set -g side-status left
|
||||
|
||||
$TMUX send-keys "exec $TEST_TMUX -LtestB$$ -f/dev/null attach" Enter
|
||||
sleep 1
|
||||
compare side-left
|
||||
|
||||
# A floating pane at the window's top left corner sits beside the side status
|
||||
# line, not over it.
|
||||
id=$($TMUX2 new-pane -dPF '#{pane_id}' -x 12 -y 4 -X 0 -Y 0 \
|
||||
"sh -c 'printf FLOAT; exec sleep 100'") || exit 1
|
||||
compare side-left-floating
|
||||
$TMUX2 kill-pane -t "$id" || exit 1
|
||||
|
||||
$TMUX2 set -g side-status right
|
||||
compare side-right
|
||||
|
||||
$TMUX2 set -g status on
|
||||
compare side-right-status
|
||||
|
||||
$TMUX2 set -g side-status-width 12
|
||||
compare side-right-narrow
|
||||
|
||||
$TMUX2 set -g side-status off
|
||||
compare side-off
|
||||
|
||||
# A second session collapses the bar into session rows with the current
|
||||
# session's windows indented below its row.
|
||||
$TMUX2 set -g side-status left
|
||||
$TMUX2 set -g side-status-width 24
|
||||
$TMUX2 set -g status off
|
||||
$TMUX2 new-session -d -s beta -n shell "sh -c 'printf SHELL; exec sleep 100'"
|
||||
$TMUX2 refresh-client -S
|
||||
compare side-sessions
|
||||
|
||||
exit 0
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# A client attached with ignore-size that is shorter than the status line
|
||||
# must have it turned off rather than kill the server.
|
||||
# A client attached with ignore-size that is too small for the status line or
|
||||
# the side status line must have them turned off rather than kill the server.
|
||||
# Each inner client runs in an outer pane of its size.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
@@ -51,4 +51,10 @@ $TMUX set -g status 5 || exit 1
|
||||
attach 80x24 80x4
|
||||
$TMUX has-session 2>/dev/null || fail "server exited: status line too tall"
|
||||
|
||||
# A side status line wider than the client.
|
||||
$TMUX set -g status on || exit 1
|
||||
$TMUX set -g side-status left || exit 1
|
||||
attach 80x24 13x24
|
||||
$TMUX has-session 2>/dev/null || fail "server exited: side status too wide"
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Status menus are displayed in the visible window and their commands
|
||||
# target the clicked window, including when it is not current.
|
||||
# Status menus are displayed in the visible window, target the clicked
|
||||
# window, and are placed beside the clicked row on either side status line.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
@@ -29,6 +29,7 @@ fail()
|
||||
}
|
||||
|
||||
# Right-button press at column $1, row $2 (1-based), targeting window $3.
|
||||
# If supplied, $4 is the expected row and column of the first menu item's text.
|
||||
check_menu()
|
||||
{
|
||||
seq=$(printf '\033[<2;%s;%sM' "$1" "$2")
|
||||
@@ -42,6 +43,14 @@ check_menu()
|
||||
done
|
||||
grep -q 'Swap Left' "$CAPTURE" || fail "window $3 menu not visible"
|
||||
grep -q "─$3:" "$CAPTURE" || fail "window $3 title missing"
|
||||
if [ -n "$4" ]; then
|
||||
got=$(awk '{
|
||||
gsub(/│/, "|")
|
||||
if (index($0, "Swap Left"))
|
||||
print NR, index($0, "Swap Left")
|
||||
}' "$CAPTURE")
|
||||
[ "$got" = "$4" ] || fail "menu at '$got', expected '$4'"
|
||||
fi
|
||||
|
||||
# Mark acts on the clicked window without selecting it. Other windows
|
||||
# exercise dragging into the menu and releasing the right button.
|
||||
@@ -81,15 +90,49 @@ $TMUX new-window -d -n one 'sleep 100' || exit 1
|
||||
$TMUX new-window -d -n two 'sleep 100' || exit 1
|
||||
$TMUX set -g mouse on || exit 1
|
||||
$TMUX set -g automatic-rename off || exit 1
|
||||
$TMUX set -g status 2 || exit 1
|
||||
$TMUX set -g 'status-format[0]' \
|
||||
'#[range=window|0]0:zero#[norange] #[range=window|1]1:one#[norange]' || \
|
||||
exit 1
|
||||
$TMUX set -g side-status-width 14 || exit 1
|
||||
$TMUX2 new-session -d -s outer -x 80 -y 24 'sleep 100' || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 respawn-pane -k -t outer:0.0 "$TMUX attach -t inner" || exit 1
|
||||
sleep 1
|
||||
|
||||
for side in left right; do
|
||||
$TMUX set -g side-status "$side" || exit 1
|
||||
if [ "$side" = left ]; then
|
||||
column=3
|
||||
text_column=17
|
||||
else
|
||||
column=69
|
||||
text_column=51
|
||||
fi
|
||||
for status in off bottom top; do
|
||||
offset=0
|
||||
if [ "$status" = off ]; then
|
||||
$TMUX set -g status off || exit 1
|
||||
else
|
||||
$TMUX set -g status 2 || exit 1
|
||||
$TMUX set -g status-position "$status" || exit 1
|
||||
[ "$status" = top ] && offset=2
|
||||
fi
|
||||
sleep 0.5
|
||||
for window in 0 1; do
|
||||
row=$((window + offset + 1))
|
||||
check_menu "$column" "$row" "$window" \
|
||||
"$((row + 1)) $text_column"
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
# A noncurrent window's dimensions must not constrain the visible menu.
|
||||
$TMUX resize-window -t inner:1 -x 10 -y 5 || exit 1
|
||||
check_menu 69 4 1 '5 51'
|
||||
|
||||
# The same target/display distinction applies to the horizontal status line.
|
||||
$TMUX set -g side-status off || exit 1
|
||||
$TMUX set -g status 2 || exit 1
|
||||
$TMUX set -g 'status-format[0]' \
|
||||
'#[range=window|0]0:zero#[norange] #[range=window|1]1:one#[norange]' || \
|
||||
exit 1
|
||||
for position in top bottom; do
|
||||
$TMUX set -g status-position "$position" || exit 1
|
||||
if [ "$position" = top ]; then
|
||||
@@ -98,12 +141,8 @@ for position in top bottom; do
|
||||
row=23
|
||||
fi
|
||||
sleep 0.5
|
||||
check_menu 2 "$row" 0
|
||||
check_menu 9 "$row" 1
|
||||
check_menu 2 "$row" 0 ''
|
||||
check_menu 9 "$row" 1 ''
|
||||
done
|
||||
|
||||
# A noncurrent window's dimensions must not constrain the visible menu.
|
||||
$TMUX resize-window -t inner:1 -x 10 -y 5 || exit 1
|
||||
check_menu 9 23 1
|
||||
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user