mirror of
https://github.com/tmux/tmux.git
synced 2026-09-14 09:11:59 +00:00
204 lines
6.5 KiB
Bash
204 lines
6.5 KiB
Bash
#!/bin/sh
|
|
|
|
# Exercise switch-mode's session and window lists with a real attached client:
|
|
# fuzzy filtering, movement and selection, the default and custom commands,
|
|
# no-match cancellation, resize, zoom restoration, and -k mode teardown.
|
|
|
|
PATH=/bin:/usr/bin
|
|
TERM=screen
|
|
LC_ALL=C.UTF-8
|
|
export PATH TERM LC_ALL
|
|
|
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
DIR=$(mktemp -d) || exit 1
|
|
TMUX_TMPDIR=$DIR
|
|
export TMUX_TMPDIR
|
|
INNER="$TEST_TMUX -LtestI$$ -f/dev/null"
|
|
OUTER="$TEST_TMUX -LtestO$$ -f/dev/null"
|
|
|
|
fail()
|
|
{
|
|
echo "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
cleanup()
|
|
{
|
|
$OUTER kill-server 2>/dev/null
|
|
$INNER kill-server 2>/dev/null
|
|
rm -rf "$DIR"
|
|
}
|
|
trap cleanup 0 1 15
|
|
|
|
capture()
|
|
{
|
|
$OUTER capture-pane -p -t outer:0.0 2>/dev/null
|
|
}
|
|
|
|
wait_capture()
|
|
{
|
|
marker=$1
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
captured=$(capture)
|
|
printf '%s\n' "$captured" | grep -Fq "$marker" && return 0
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "timed out waiting for '$marker'"
|
|
}
|
|
|
|
wait_count()
|
|
{
|
|
marker=$1
|
|
want=$2
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
captured=$(capture)
|
|
count=$(printf '%s\n' "$captured" | grep -Fc "$marker")
|
|
[ "$count" -eq "$want" ] && return 0
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "found $count '$marker' rows, expected $want"
|
|
}
|
|
|
|
wait_format()
|
|
{
|
|
target=$1
|
|
format=$2
|
|
want=$3
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
got=$($INNER display-message -p -t "$target" "$format" \
|
|
2>/dev/null)
|
|
[ "$got" = "$want" ] && return 0
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "$target format $format is '$got', expected '$want'"
|
|
}
|
|
|
|
wait_client_session()
|
|
{
|
|
want=$1
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
got=$($INNER list-clients -F '#{client_session}' 2>/dev/null)
|
|
[ "$got" = "$want" ] && return 0
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "client session is '$got', expected '$want'"
|
|
}
|
|
|
|
# Three alphabetically ordered sessions. alpha:main has two panes so -Z can be
|
|
# observed; the two pick-* windows make a deterministic two-row window filter.
|
|
$INNER new-session -d -s alpha -n main -x60 -y15 'exec sleep 100' || exit 1
|
|
$INNER split-window -d -h -t alpha:main 'exec sleep 100' || exit 1
|
|
$INNER new-window -d -t alpha: -n pick-one 'exec sleep 100' || exit 1
|
|
$INNER new-session -d -s bravo -n pick-two -x60 -y15 \
|
|
'exec sleep 100' || exit 1
|
|
$INNER new-session -d -s charlie -n last -x60 -y15 \
|
|
'exec sleep 100' || exit 1
|
|
$INNER set-option -g status off || exit 1
|
|
$INNER set-option -g window-size manual || exit 1
|
|
$INNER select-window -t alpha:main || exit 1
|
|
|
|
$OUTER new-session -d -s outer -x60 -y15 "$INNER attach -t alpha" || exit 1
|
|
$OUTER set-option -g status off || exit 1
|
|
$OUTER set-option -g window-size manual || exit 1
|
|
wait_client_session alpha
|
|
|
|
# Session rows are sorted alpha, bravo, charlie. Up from the first row wraps to
|
|
# charlie; Enter runs a custom command with the selected session target.
|
|
$INNER set-option -g @picked '' || exit 1
|
|
$INNER switch-mode -s -t alpha:main.0 -F 'SESSION #{session_name}' \
|
|
"set-option -g @picked '%%'" || exit 1
|
|
wait_count 'SESSION ' 3
|
|
$INNER send-keys -t alpha:main.0 Up Enter || exit 1
|
|
wait_format alpha:main.0 '#{@picked}' '=charlie:'
|
|
wait_format alpha:main.0 '#{pane_in_mode}' 0
|
|
|
|
# Fuzzy filtering keeps only bravo for "brv". The default command switches the
|
|
# real client to that session and closes the mode.
|
|
$INNER switch-mode -s -t alpha:main.0 -F 'SESSION #{session_name}' || exit 1
|
|
wait_count 'SESSION ' 3
|
|
$INNER send-keys -t alpha:main.0 -l brv || exit 1
|
|
wait_count 'SESSION ' 1
|
|
printf '%s\n' "$captured" | grep -Fq 'SESSION bravo' ||
|
|
fail "fuzzy session filter did not select bravo"
|
|
$INNER send-keys -t alpha:main.0 Enter || exit 1
|
|
wait_client_session bravo
|
|
client=$($INNER list-clients -F '#{client_name}')
|
|
$INNER switch-client -c "$client" -t alpha || exit 1
|
|
wait_client_session alpha
|
|
|
|
# Window mode sees pick-one then pick-two for the "pick" filter. Down selects
|
|
# the second row, and the custom command receives its window target.
|
|
$INNER set-option -g @picked '' || exit 1
|
|
$INNER switch-mode -w -t alpha:main.0 -F \
|
|
'WINDOW #{session_name}:#{window_name}' \
|
|
"set-option -g @picked '%%'" || exit 1
|
|
wait_capture 'WINDOW '
|
|
$INNER send-keys -t alpha:main.0 -l pick || exit 1
|
|
wait_count 'WINDOW ' 2
|
|
$INNER send-keys -t alpha:main.0 Down Enter || exit 1
|
|
picked=$($INNER show-option -gv @picked)
|
|
case "$picked" in
|
|
=bravo:0.) ;;
|
|
*) fail "window selection produced '$picked', expected '=bravo:0.'" ;;
|
|
esac
|
|
|
|
# Navigation with an empty result set must be harmless, and Escape cancels
|
|
# without running the custom command.
|
|
$INNER set-option -g @picked unchanged || exit 1
|
|
$INNER switch-mode -s -t alpha:main.0 -F 'NONE #{session_name}' \
|
|
"set-option -g @picked '%%'" || exit 1
|
|
wait_capture 'NONE '
|
|
$INNER send-keys -t alpha:main.0 -l no-such-session || exit 1
|
|
wait_count 'NONE ' 0
|
|
$INNER send-keys -t alpha:main.0 Up Down PPage NPage Home End || exit 1
|
|
wait_format alpha:main.0 '#{pane_mode}' switch-mode
|
|
$INNER send-keys -t alpha:main.0 Escape || exit 1
|
|
wait_format alpha:main.0 '#{pane_in_mode}' 0
|
|
[ "$($INNER show-option -gv @picked)" = unchanged ] ||
|
|
fail "cancelled switch-mode ran its command"
|
|
|
|
# -Z temporarily zooms an unzoomed window. Resizing while the mode is open
|
|
# rebuilds and redraws it; exiting restores the original unzoomed state.
|
|
$INNER switch-mode -Zs -t alpha:main.0 -F 'RESIZE #{session_name}' || exit 1
|
|
wait_capture 'RESIZE alpha'
|
|
wait_format alpha:main.0 '#{window_zoomed_flag}' 1
|
|
$INNER resize-window -t alpha:main -x50 -y12 || exit 1
|
|
wait_format alpha:main.0 '#{window_width}x#{window_height}' 50x12
|
|
wait_format alpha:main.0 '#{pane_mode}' switch-mode
|
|
$INNER send-keys -t alpha:main.0 Escape || exit 1
|
|
wait_format alpha:main.0 '#{window_zoomed_flag}' 0
|
|
|
|
# If the window was already zoomed, leaving -Z mode must keep it zoomed.
|
|
$INNER resize-pane -Z -t alpha:main.0 || exit 1
|
|
$INNER switch-mode -Zs -t alpha:main.0 -F 'ZOOMED #{session_name}' || exit 1
|
|
wait_capture 'ZOOMED alpha'
|
|
$INNER send-keys -t alpha:main.0 Escape || exit 1
|
|
wait_format alpha:main.0 '#{window_zoomed_flag}' 1
|
|
$INNER resize-pane -Z -t alpha:main.0 || exit 1
|
|
|
|
# -k uses the shared mode teardown flag. Put it on a disposable pane and make
|
|
# sure exiting the mode removes that pane.
|
|
kill_pane=$($INNER split-window -d -P -F '#{pane_id}' -t alpha:main \
|
|
'exec sleep 100') || exit 1
|
|
$INNER switch-mode -ks -t "$kill_pane" -F 'KILL #{session_name}' || exit 1
|
|
wait_format "$kill_pane" '#{pane_mode}' switch-mode
|
|
$INNER send-keys -t "$kill_pane" Escape || exit 1
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
$INNER list-panes -s -t alpha -F '#{pane_id}' 2>/dev/null | \
|
|
grep -q -x "$kill_pane" || break
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
[ "$i" -lt 50 ] || fail "switch-mode -k did not kill its pane"
|
|
|
|
exit 0
|