Files
tmux/regress/hooks.sh
2026-07-06 11:50:58 +01:00

156 lines
4.8 KiB
Bash

#!/bin/sh
PATH=/bin:/usr/bin
TERM=screen
LC_ALL=C.UTF-8
LANG=C.UTF-8
export TERM LC_ALL LANG
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
OUT=$(mktemp -d)
TMUX_TMPDIR="$OUT"
export TMUX_TMPDIR
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
fail()
{
echo "$*" >&2
$TMUX kill-server 2>/dev/null || true
rm -rf "$OUT"
exit 1
}
cleanup()
{
$TMUX kill-server 2>/dev/null || true
rm -rf "$OUT"
}
trap cleanup EXIT
wait_for()
{
option=$1
expected=$2
i=0
while [ $i -lt 30 ]; do
value=$($TMUX show -gqv "$option" 2>/dev/null || true)
[ "$value" = "$expected" ] && return 0
i=$((i + 1))
sleep 0.2
done
fail "expected $option to be '$expected' but got '$value'"
}
assert_unchanged()
{
option=$1
expected=$2
i=0
while [ $i -lt 10 ]; do
value=$($TMUX show -gqv "$option" 2>/dev/null || true)
[ "$value" = "$expected" ] || \
fail "expected $option to remain '$expected' but got '$value'"
i=$((i + 1))
sleep 0.2
done
}
$TMUX new -d -s one || fail "new-session one failed"
# A global hook fires and sees the hook formats.
$TMUX set -g @created 0 || fail "set @created failed"
$TMUX set-hook -g session-created \
'set -gF @created "#{hook}:#{hook_session_name}"' ||
fail "set-hook -g session-created failed"
$TMUX new -d -s two || fail "new-session two failed"
wait_for @created 'session-created:two'
# Hooks are arrays: an appended command runs after the first.
$TMUX set -g @second 0 || fail "set @second failed"
$TMUX set-hook -ga session-created \
'set -gF @second "#{@created}+second"' ||
fail "set-hook -ga session-created failed"
$TMUX new -d -s three || fail "new-session three failed"
wait_for @created 'session-created:three'
wait_for @second 'session-created:three+second'
# show-hooks lists both commands.
shown=$($TMUX show-hooks -g session-created) ||
fail "show-hooks -g failed"
[ "$(echo "$shown" | wc -l)" -eq 2 ] ||
fail "unexpected show-hooks output: $shown"
echo "$shown" | grep -q '^session-created\[0\]' ||
fail "missing first array item: $shown"
echo "$shown" | grep -q '^session-created\[1\]' ||
fail "missing second array item: $shown"
# Unsetting removes the whole hook.
$TMUX set-hook -gu session-created || fail "set-hook -gu failed"
shown=$($TMUX show-hooks -g session-created) ||
fail "show-hooks -g after unset failed"
if echo "$shown" | grep -q '\['; then
fail "show-hooks showed removed hook: $shown"
fi
$TMUX set -g @created 0 || fail "reset @created failed"
$TMUX new -d -s four || fail "new-session four failed"
assert_unchanged @created 0
# An unknown hook name is rejected.
if $TMUX set-hook -g no-such-hook 'display x' 2>/dev/null; then
fail "unknown hook name was accepted"
fi
# A session hook only fires for events in that session.
$TMUX set -g @renamed 0 || fail "set @renamed failed"
$TMUX set-hook -t one window-renamed \
'set -gF @renamed "#{hook}:#{hook_window_name}"' ||
fail "set-hook -t one window-renamed failed"
$TMUX rename-window -t two:0 twoname || fail "rename-window two failed"
assert_unchanged @renamed 0
$TMUX rename-window -t one:0 onename || fail "rename-window one failed"
wait_for @renamed 'window-renamed:onename'
$TMUX set-hook -u -t one window-renamed || fail "set-hook -u failed"
# A pane hook only fires for events in that pane.
pane2=$($TMUX splitw -d -t one:0 -P -F '#{pane_id}') ||
fail "split-window failed"
$TMUX set -g @mode 0 || fail "set @mode failed"
$TMUX set-hook -p -t "$pane2" pane-mode-changed \
'set -gF @mode "#{hook}:#{hook_pane}"' ||
fail "set-hook -p pane-mode-changed failed"
$TMUX copy-mode -t one:0.0 || fail "copy-mode pane 0 failed"
assert_unchanged @mode 0
$TMUX copy-mode -t "$pane2" || fail "copy-mode pane 1 failed"
wait_for @mode "pane-mode-changed:$pane2"
$TMUX send-keys -t "$pane2" -X cancel || fail "cancel failed"
$TMUX set-hook -pu -t "$pane2" pane-mode-changed ||
fail "set-hook -pu failed"
# A window hook only fires for events in that window.
$TMUX set -g @wmode 0 || fail "set @wmode failed"
$TMUX set-hook -w -t two:0 pane-mode-changed \
'set -gF @wmode "#{hook}:#{hook_window_name}"' ||
fail "set-hook -w pane-mode-changed failed"
$TMUX copy-mode -t three:0.0 || fail "copy-mode three failed"
assert_unchanged @wmode 0
$TMUX copy-mode -t two:0.0 || fail "copy-mode two failed"
wait_for @wmode 'pane-mode-changed:twoname'
$TMUX set-hook -wu -t two:0 pane-mode-changed ||
fail "set-hook -wu failed"
# Commands run from a hook do not fire hooks again.
$TMUX set -g @renames '' || fail "set @renames failed"
$TMUX set-hook -g window-renamed \
'set -gF @renames "#{@renames}x" ; rename-window -t three:0 inner' ||
fail "set-hook -g window-renamed failed"
$TMUX rename-window -t three:0 outer || fail "rename-window outer failed"
wait_for @renames 'x'
assert_unchanged @renames 'x'
name=$($TMUX display -pt three:0 '#{window_name}') ||
fail "display window_name failed"
[ "$name" = inner ] || fail "expected window name inner but got $name"
exit 0