c628c45291
A separate tmux window running any TUI, reached with a vertical swipe from any carousel screen; swiping up returns to the exact window/zoom you left. The aux window is excluded from the horizontal carousel and horizontal swipes on it are inert. Bound only when SOCKTOP_AUX_CMD is set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
122 lines
3.5 KiB
Bash
Executable File
122 lines
3.5 KiB
Bash
Executable File
#!/bin/sh
|
|
# socktop-swipe next|prev|down|up
|
|
#
|
|
# Walks a linear "zoom carousel" over the socktop session. Each tmux window is
|
|
# one group of hosts; within a group the line is the tiled overview, then each
|
|
# pane zoomed full-screen in index order; then the next window's overview:
|
|
#
|
|
# overview(g0) <-> g0.0 <-> ... <-> g0.N <-> overview(g1) <-> g1.0 <-> ...
|
|
#
|
|
# "next" moves right and stops at the last pane of the last window. "prev"
|
|
# moves back and stops at the first overview. Deliberately no wrap-around: on
|
|
# a wall display, wrapping makes it impossible to tell where you are.
|
|
#
|
|
# "down" jumps to the optional aux window (see SOCKTOP_AUX_CMD) and remembers
|
|
# where you were; "up" returns there. The aux window is not part of the
|
|
# horizontal carousel, and horizontal swipes while on it do nothing.
|
|
#
|
|
# This is tmux pane zoom, NOT extra socktop instances. All panes keep running
|
|
# and stay connected while hidden, so swiping back shows current data with no
|
|
# reconnect, and the polling load on the monitored hosts is constant.
|
|
set -eu
|
|
|
|
for c in /usr/local/etc/socktop-swipe.env "$(dirname "$0")/config.env"; do
|
|
[ -r "$c" ] && . "$c" && break
|
|
done
|
|
: "${SOCKTOP_SESSION:=socktop4}"
|
|
|
|
dir=${1:?usage: socktop-swipe next|prev|down|up}
|
|
|
|
# Ordered window ids (@N) of the carousel windows, the aux window if any, and
|
|
# the currently active window.
|
|
all=$(tmux list-windows -t "$SOCKTOP_SESSION" -F '#{window_id} #{window_name}' 2>/dev/null) || exit 0
|
|
[ -n "$all" ] || exit 0
|
|
wins= aux=
|
|
while read -r id name; do
|
|
if [ "$name" = aux ]; then aux=$id; else wins="$wins $id"; fi
|
|
done <<EOF
|
|
$all
|
|
EOF
|
|
WIN=$(tmux display-message -t "$SOCKTOP_SESSION" -p '#{window_id}') || exit 0
|
|
|
|
case "$dir" in
|
|
down)
|
|
[ -n "$aux" ] || exit 0
|
|
[ "$WIN" = "$aux" ] && exit 0
|
|
tmux set-option -t "$SOCKTOP_SESSION" @return_to "$WIN"
|
|
tmux select-window -t "$aux"
|
|
exit 0
|
|
;;
|
|
up)
|
|
[ "$WIN" = "$aux" ] || exit 0
|
|
back=$(tmux show-option -qv -t "$SOCKTOP_SESSION" @return_to)
|
|
[ -n "$back" ] && tmux has-session -t "$back" 2>/dev/null || back=${wins# }
|
|
back=${back%% *}
|
|
tmux select-window -t "$back"
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
# On the aux screen, horizontal swipes are deliberately inert.
|
|
[ "$WIN" = "$aux" ] && exit 0
|
|
|
|
prev_win= next_win= seen=no
|
|
for w in $wins; do
|
|
if [ "$seen" = yes ]; then next_win=$w; break; fi
|
|
if [ "$w" = "$WIN" ]; then seen=yes; else prev_win=$w; fi
|
|
done
|
|
|
|
state=$(tmux display-message -t "$WIN" -p '#{window_zoomed_flag} #{pane_index} #{window_panes}') || exit 0
|
|
zoomed=${state%% *}
|
|
rest=${state#* }
|
|
idx=${rest%% *}
|
|
count=${rest##* }
|
|
last=$((count - 1))
|
|
|
|
zoom_to() {
|
|
# $1 = window id, $2 = pane index.
|
|
# Selecting a different pane auto-unzooms, so zoom explicitly afterwards.
|
|
tmux select-window -t "$1"
|
|
tmux select-pane -t "$1.$2"
|
|
tmux resize-pane -Z -t "$1.$2"
|
|
}
|
|
|
|
overview() {
|
|
# Show window $1 unzoomed.
|
|
tmux select-window -t "$1"
|
|
if [ "$(tmux display-message -t "$1" -p '#{window_zoomed_flag}')" = 1 ]; then
|
|
tmux resize-pane -Z -t "$1"
|
|
fi
|
|
}
|
|
|
|
if [ "$zoomed" = 0 ]; then
|
|
case "$dir" in
|
|
next) zoom_to "$WIN" 0 ;;
|
|
prev)
|
|
# Back out of this group's overview onto the previous group's last pane.
|
|
if [ -n "$prev_win" ]; then
|
|
pl=$(tmux display-message -t "$prev_win" -p '#{window_panes}')
|
|
zoom_to "$prev_win" $((pl - 1))
|
|
fi
|
|
;;
|
|
esac
|
|
else
|
|
case "$dir" in
|
|
next)
|
|
if [ "$idx" -lt "$last" ]; then
|
|
zoom_to "$WIN" $((idx + 1))
|
|
elif [ -n "$next_win" ]; then
|
|
tmux resize-pane -Z -t "$WIN.$idx" # unzoom before leaving
|
|
overview "$next_win"
|
|
fi
|
|
;;
|
|
prev)
|
|
if [ "$idx" -gt 0 ]; then
|
|
zoom_to "$WIN" $((idx - 1))
|
|
else
|
|
tmux resize-pane -Z -t "$WIN.$idx" # unzoom -> this group's overview
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|