Files
tmux/regress/cmd-invoke-deferred.sh
Nicholas Marriott 115002748b Add some tests.
2026-07-01 07:35:55 +01:00

103 lines
3.9 KiB
Bash
Executable File

#!/bin/sh
# Deferred command callbacks.
#
# Several commands store a parsed tree and invoke it later through
# cmd_invoke_get: if-shell (then/else, sync and background), run-shell -C, and -
# once a key is pressed by an attached client - a key binding, confirm-before and
# command-prompt. The headless cases run directly on the inner server; the
# client cases use the nested-tmux pattern from prompt-mechanics.sh: an outer
# server hosts the inner client in a pane and keys are injected with send-keys.
PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
OUT="$TEST_TMUX -Ltest -f/dev/null"
IN="$TEST_TMUX -Ltest2 -f/dev/null"
$OUT kill-server 2>/dev/null
$IN kill-server 2>/dev/null
trap "$OUT kill-server 2>/dev/null; $IN kill-server 2>/dev/null" 0 1 15
fail() { echo "[FAIL] $1" >&2; exit 1; }
settle() { sleep 0.5; }
CONF=$(mktemp)
trap "rm -f $CONF; $OUT kill-server 2>/dev/null; $IN kill-server 2>/dev/null" 0 1 15
# --- Headless deferred callbacks: no client needed. ------------------------
$IN new -d -x80 -y23 -nbase "sh -c 'exec sleep 1000'" || exit 1
$IN set -g status on || exit 1
$IN set -g status-keys emacs || exit 1
$IN set -g window-size manual || exit 1
$IN if-shell true 'set -g @t then' 'set -g @t else' || exit 1
[ "$($IN show -gv @t)" = then ] || fail "if-shell true ran wrong branch"
$IN if-shell false 'set -g @f then' 'set -g @f else' || exit 1
[ "$($IN show -gv @f)" = else ] || fail "if-shell false ran wrong branch"
# Background (-b) if-shell evaluates its condition in a shell asynchronously.
$IN if-shell -b 'true' 'set -g @b yes' 'set -g @b no' || exit 1
settle
[ "$($IN show -gv @b)" = yes ] || fail "background if-shell ran wrong branch"
# A multi-command then-body runs both commands.
$IN if-shell true 'new-window -dn IF1 ; new-window -dn IF2' '' || exit 1
$IN list-windows -F '#{window_name}' | grep -qx IF1 || fail "if-shell body cmd1 missing"
$IN list-windows -F '#{window_name}' | grep -qx IF2 || fail "if-shell body cmd2 missing"
# run-shell -C invokes its argument as tmux commands.
$IN run-shell -C 'set -g @rc ran' || exit 1
[ "$($IN show -gv @rc)" = ran ] || fail "run-shell -C did not run command"
# --- Client deferred callbacks: key binding, confirm-before, command-prompt. -
$IN bind -n M-c confirm-before -p '(ok) ' 'set -g @cb confirmed' || exit 1
$IN bind -n M-d command-prompt -I pre -p '(cmd) ' 'set -g @cp %%' || exit 1
# A brace body must come through the lexer, so bind it from a config.
cat <<'EOF' >$CONF
bind -n M-k { new-window -dn K1 ; new-window -dn K2 }
EOF
$IN source-file $CONF || exit 1
$OUT new -d -x80 -y24 || exit 1
$OUT set -g status off || exit 1
$OUT set -g window-size manual || exit 1
$OUT send-keys -l "$IN attach" || exit 1
$OUT send-keys Enter || exit 1
sleep 1
# Key binding with a stored multi-command body fires on keypress.
$OUT send-keys M-k || exit 1
settle
$IN list-windows -F '#{window_name}' | grep -qx K1 || fail "key binding body cmd1 missing"
$IN list-windows -F '#{window_name}' | grep -qx K2 || fail "key binding body cmd2 missing"
# confirm-before runs its command only when confirmed.
$IN set -g @cb none || exit 1
$OUT send-keys M-c || exit 1
settle
$OUT capture-pane -p | tail -1 | grep -qF '(ok)' || fail "confirm-before prompt not shown"
$OUT send-keys n || exit 1
settle
[ "$($IN show -gv @cb)" = none ] || fail "confirm-before ran command after 'n'"
$OUT send-keys M-c || exit 1
settle
$OUT send-keys y || exit 1
settle
[ "$($IN show -gv @cb)" = confirmed ] || fail "confirm-before did not run command after 'y'"
# command-prompt feeds the typed line (with -I prefill) into its template.
$IN set -g @cp none || exit 1
$OUT send-keys M-d || exit 1
settle
$OUT capture-pane -p | tail -1 | grep -qF '(cmd)' || fail "command-prompt not shown"
$OUT send-keys -l X || exit 1
$OUT send-keys Enter || exit 1
settle
[ "$($IN show -gv @cp)" = preX ] || fail "command-prompt recovered '$($IN show -gv @cp)'"
$OUT kill-server 2>/dev/null
$IN kill-server 2>/dev/null
exit 0