mirror of
https://github.com/tmux/tmux.git
synced 2026-07-10 03:19:31 +00:00
292 lines
9.2 KiB
Bash
292 lines
9.2 KiB
Bash
#!/bin/sh
|
|
|
|
# monitor-activity, monitor-bell and monitor-silence: both the
|
|
# alert-activity, alert-bell and alert-silence hooks and the winlink alert
|
|
# flags (window_activity_flag, window_bell_flag, window_silence_flag and
|
|
# the #, !, ~ characters in window_flags). The sessions are detached so
|
|
# alert flags are set even on the current window; the *-action options
|
|
# still decide whether the hooks fire. Panes run cat: activity is
|
|
# generated by the tty echo of send-keys and a bell by sending a BEL and
|
|
# newline for cat to write back.
|
|
|
|
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
|
|
}
|
|
|
|
wait_for_fmt()
|
|
{
|
|
target=$1
|
|
fmt=$2
|
|
expected=$3
|
|
i=0
|
|
|
|
while [ $i -lt 30 ]; do
|
|
value=$($TMUX display -pt "$target" "$fmt" 2>/dev/null || true)
|
|
[ "$value" = "$expected" ] && return 0
|
|
i=$((i + 1))
|
|
sleep 0.2
|
|
done
|
|
fail "expected $fmt for $target to be '$expected' but got '$value'"
|
|
}
|
|
|
|
assert_fmt_unchanged()
|
|
{
|
|
target=$1
|
|
fmt=$2
|
|
expected=$3
|
|
i=0
|
|
|
|
while [ $i -lt 10 ]; do
|
|
value=$($TMUX display -pt "$target" "$fmt" 2>/dev/null || true)
|
|
[ "$value" = "$expected" ] || \
|
|
fail "expected $fmt for $target to remain '$expected' but got '$value'"
|
|
i=$((i + 1))
|
|
sleep 0.2
|
|
done
|
|
}
|
|
|
|
flags_have()
|
|
{
|
|
target=$1
|
|
char=$2
|
|
|
|
flags=$($TMUX display -pt "$target" '#{window_flags}') ||
|
|
fail "display window_flags failed"
|
|
case "$flags" in
|
|
*"$char"*) ;;
|
|
*) fail "expected '$char' in window_flags for $target: '$flags'" ;;
|
|
esac
|
|
}
|
|
|
|
flags_lack()
|
|
{
|
|
target=$1
|
|
char=$2
|
|
|
|
flags=$($TMUX display -pt "$target" '#{window_flags}') ||
|
|
fail "display window_flags failed"
|
|
case "$flags" in
|
|
*"$char"*) fail "unexpected '$char' in window_flags for $target: '$flags'" ;;
|
|
esac
|
|
}
|
|
|
|
bell()
|
|
{
|
|
$TMUX send-keys -t "$1" -H 07 0a || fail "send-keys bell failed"
|
|
}
|
|
|
|
activity()
|
|
{
|
|
$TMUX send-keys -t "$1" -l x || fail "send-keys activity failed"
|
|
}
|
|
|
|
$TMUX new -d -s mon -n w0 cat || fail "new-session mon failed"
|
|
|
|
$TMUX set -g @log '' || fail "set @log failed"
|
|
$TMUX set-hook -g alert-bell \
|
|
'set -gF @log "#{@log}|alert-bell:#{hook_session_name}:#{hook_window_name}"' ||
|
|
fail "set-hook alert-bell failed"
|
|
$TMUX set-hook -g alert-activity \
|
|
'set -gF @log "#{@log}|alert-activity:#{hook_session_name}:#{hook_window_name}"' ||
|
|
fail "set-hook alert-activity failed"
|
|
$TMUX set-hook -g alert-silence \
|
|
'set -gF @log "#{@log}|alert-silence:#{hook_session_name}:#{hook_window_name}"' ||
|
|
fail "set-hook alert-silence failed"
|
|
|
|
# A bell in a non-current window (monitor-bell defaults to on) fires
|
|
# alert-bell and sets the bell flag, shown as ! in window_flags.
|
|
$TMUX neww -d -t mon: -n bellw cat || fail "new-window bellw failed"
|
|
assert_fmt_unchanged mon:bellw '#{window_bell_flag}' 0
|
|
flags_lack mon:bellw '!'
|
|
bell mon:bellw
|
|
wait_for @log '|alert-bell:mon:bellw'
|
|
wait_for_fmt mon:bellw '#{window_bell_flag}' 1
|
|
flags_have mon:bellw '!'
|
|
|
|
# Bells are not deduplicated: a second bell fires the hook again even
|
|
# though the flag is still set.
|
|
bell mon:bellw
|
|
wait_for @log '|alert-bell:mon:bellw|alert-bell:mon:bellw'
|
|
|
|
# Selecting the window clears the alert flags.
|
|
$TMUX selectw -t mon:bellw || fail "select-window bellw failed"
|
|
wait_for_fmt mon:bellw '#{window_bell_flag}' 0
|
|
flags_lack mon:bellw '!'
|
|
$TMUX selectw -t mon:w0 || fail "select-window w0 failed"
|
|
|
|
# A bell in the current window of a detached session still sets the flag
|
|
# and bell-action any (the default) fires the hook for the current window.
|
|
$TMUX set -g @log '' || fail "reset @log failed"
|
|
bell mon:w0
|
|
wait_for @log '|alert-bell:mon:w0'
|
|
wait_for_fmt mon:w0 '#{window_bell_flag}' 1
|
|
$TMUX selectw -t mon:bellw || fail "select-window bellw failed"
|
|
$TMUX selectw -t mon:w0 || fail "select-window w0 failed"
|
|
wait_for_fmt mon:w0 '#{window_bell_flag}' 0
|
|
|
|
# bell-action none: the flag is still set but the hook does not fire.
|
|
$TMUX set -t mon bell-action none || fail "set bell-action none failed"
|
|
$TMUX set -g @log '' || fail "reset @log failed"
|
|
bell mon:bellw
|
|
wait_for_fmt mon:bellw '#{window_bell_flag}' 1
|
|
assert_unchanged @log ''
|
|
$TMUX set -ut mon bell-action || fail "unset bell-action failed"
|
|
$TMUX selectw -t mon:bellw || fail "select-window bellw failed"
|
|
$TMUX selectw -t mon:w0 || fail "select-window w0 failed"
|
|
|
|
# monitor-bell off: neither the flag nor the hook.
|
|
$TMUX set -wt mon:bellw monitor-bell off || fail "set monitor-bell failed"
|
|
$TMUX set -g @log '' || fail "reset @log failed"
|
|
bell mon:bellw
|
|
assert_fmt_unchanged mon:bellw '#{window_bell_flag}' 0
|
|
assert_unchanged @log ''
|
|
|
|
# monitor-activity defaults to off: output sets neither flag nor hook.
|
|
$TMUX neww -d -t mon: -n actw cat || fail "new-window actw failed"
|
|
$TMUX set -g @log '' || fail "reset @log failed"
|
|
activity mon:actw
|
|
assert_fmt_unchanged mon:actw '#{window_activity_flag}' 0
|
|
assert_unchanged @log ''
|
|
|
|
# With monitor-activity on, output fires alert-activity and sets the
|
|
# activity flag, shown as # in window_flags.
|
|
$TMUX set -wt mon:actw monitor-activity on ||
|
|
fail "set monitor-activity failed"
|
|
activity mon:actw
|
|
wait_for @log '|alert-activity:mon:actw'
|
|
wait_for_fmt mon:actw '#{window_activity_flag}' 1
|
|
flags_have mon:actw '#'
|
|
|
|
# While the flag is set further activity does not fire the hook again.
|
|
$TMUX set -g @log '' || fail "reset @log failed"
|
|
activity mon:actw
|
|
assert_unchanged @log ''
|
|
|
|
# On a detached session selecting the window does not clear the activity
|
|
# flag: session_set_current treats the selection itself as activity and
|
|
# the flag is raised again at once because the session is not attached.
|
|
# No hook fires as activity-action other does not apply to the current
|
|
# window.
|
|
$TMUX selectw -t mon:actw || fail "select-window actw failed"
|
|
assert_fmt_unchanged mon:actw '#{window_activity_flag}' 1
|
|
$TMUX selectw -t mon:w0 || fail "select-window w0 failed"
|
|
assert_fmt_unchanged mon:actw '#{window_activity_flag}' 1
|
|
assert_unchanged @log ''
|
|
|
|
# With a client attached, selecting the window does clear the activity
|
|
# flag and it stays clear for the current window.
|
|
mkfifo "$OUT/fifo" || fail "mkfifo failed"
|
|
$TMUX -C attach -t mon <"$OUT/fifo" >"$OUT/control.out" 2>&1 &
|
|
exec 3>"$OUT/fifo"
|
|
wait_for_fmt mon: '#{session_attached}' 1
|
|
$TMUX selectw -t mon:actw || fail "select-window actw failed"
|
|
wait_for_fmt mon:actw '#{window_activity_flag}' 0
|
|
flags_lack mon:actw '#'
|
|
$TMUX selectw -t mon:w0 || fail "select-window w0 failed"
|
|
exec 3>&-
|
|
wait_for_fmt mon: '#{session_attached}' 0
|
|
|
|
# Once the flag is clear the alert is re-armed.
|
|
activity mon:actw
|
|
wait_for @log '|alert-activity:mon:actw'
|
|
|
|
# Activity in the current window of a detached session sets the flag but
|
|
# activity-action other (the default) does not fire the hook.
|
|
$TMUX set -wt mon:w0 monitor-activity on ||
|
|
fail "set monitor-activity w0 failed"
|
|
$TMUX set -g @log '' || fail "reset @log failed"
|
|
activity mon:w0
|
|
wait_for_fmt mon:w0 '#{window_activity_flag}' 1
|
|
assert_unchanged @log ''
|
|
$TMUX set -wut mon:w0 monitor-activity ||
|
|
fail "unset monitor-activity w0 failed"
|
|
|
|
# monitor-silence: a quiet window fires alert-silence after the interval
|
|
# and sets the silence flag, shown as ~ in window_flags. The hook fires
|
|
# only once while the flag remains set even though the timer keeps
|
|
# running.
|
|
$TMUX neww -d -t mon: -n silw cat || fail "new-window silw failed"
|
|
assert_fmt_unchanged mon:silw '#{window_silence_flag}' 0
|
|
$TMUX set -g @log '' || fail "reset @log failed"
|
|
$TMUX set -wt mon:silw monitor-silence 1 || fail "set monitor-silence failed"
|
|
wait_for @log '|alert-silence:mon:silw'
|
|
wait_for_fmt mon:silw '#{window_silence_flag}' 1
|
|
flags_have mon:silw '~'
|
|
assert_unchanged @log '|alert-silence:mon:silw'
|
|
$TMUX set -wt mon:silw monitor-silence 0 ||
|
|
fail "reset monitor-silence failed"
|
|
$TMUX selectw -t mon:silw || fail "select-window silw failed"
|
|
wait_for_fmt mon:silw '#{window_silence_flag}' 0
|
|
flags_lack mon:silw '~'
|
|
$TMUX selectw -t mon:w0 || fail "select-window w0 failed"
|
|
|
|
# A window linked into two sessions: the hook fires once per winlink and
|
|
# the flag is set in both sessions. Selecting the window in one session
|
|
# clears the flags on every winlink.
|
|
$TMUX new -d -s mon2 || fail "new-session mon2 failed"
|
|
$TMUX neww -d -t mon: -n shw cat || fail "new-window shw failed"
|
|
$TMUX link-window -d -s mon:shw -t mon2:5 || fail "link-window failed"
|
|
$TMUX set -g @log '' || fail "reset @log failed"
|
|
bell mon:shw
|
|
wait_for @log '|alert-bell:mon:shw|alert-bell:mon2:shw'
|
|
wait_for_fmt mon:shw '#{window_bell_flag}' 1
|
|
wait_for_fmt mon2:5 '#{window_bell_flag}' 1
|
|
$TMUX selectw -t mon2:5 || fail "select-window mon2:5 failed"
|
|
wait_for_fmt mon2:5 '#{window_bell_flag}' 0
|
|
wait_for_fmt mon:shw '#{window_bell_flag}' 0
|
|
|
|
exit 0
|