Make tmux alert parsing and focus more robust

Session names can contain pipes but never colons, so split fields on
colons instead. Remember refreshes that arrive while the indicator is
already polling, and jump to the most recently used tmux client rather
than an arbitrary one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-07-23 17:40:47 -07:00
co-authored by Claude Fable 5
parent a382be2645
commit 5b130c1063
3 changed files with 28 additions and 16 deletions
+14 -9
View File
@@ -6,8 +6,9 @@
set -e
# Window names can contain the separator, so they always come last when parsed.
WINDOW_FORMAT='#{window_bell_flag}#{window_activity_flag}#{window_silence_flag}|#{session_name}|#{window_index}|#{window_name}'
# Session names cannot contain colons, and window names can, so they always
# come last when parsed.
WINDOW_FORMAT='#{window_bell_flag}#{window_activity_flag}#{window_silence_flag}:#{session_name}:#{window_index}:#{window_name}'
usage() {
echo "Usage: omarchy-tmux-alert <show [--json]|focus>" >&2
@@ -20,9 +21,9 @@ alerted_windows() {
local flags session index name
tmux list-windows -a -F "$WINDOW_FORMAT" 2>/dev/null |
while IFS='|' read -r flags session index name; do
while IFS=':' read -r flags session index name; do
if [[ $flags == *1* ]]; then
printf '%s|%s|%s\n' "$session" "$index" "$name"
printf '%s:%s:%s\n' "$session" "$index" "$name"
fi
done
}
@@ -33,7 +34,7 @@ show() {
readarray -t windows < <(alerted_windows)
for window in "${windows[@]}"; do
IFS='|' read -r session index name <<<"$window"
IFS=':' read -r session index name <<<"$window"
[[ -n $description ]] && description+=", "
description+="$name ($session:$index)"
done
@@ -68,23 +69,27 @@ focus_terminal_window() {
hyprctl dispatch focuswindow "address:$address" >/dev/null
}
most_recent_client() {
tmux list-clients "$@" -F '#{client_activity}:#{client_tty}:#{client_pid}' 2>/dev/null | sort -rn | head -n1
}
focus() {
local target session index client tty pid
target=$(alerted_windows | head -n1)
[[ -n $target ]] || return 0
IFS='|' read -r session index _ <<<"$target"
IFS=':' read -r session index _ <<<"$target"
client=$(tmux list-clients -t "$session" -F '#{client_tty}|#{client_pid}' 2>/dev/null | head -n1)
[[ -n $client ]] || client=$(tmux list-clients -F '#{client_tty}|#{client_pid}' 2>/dev/null | head -n1)
client=$(most_recent_client -t "$session")
[[ -n $client ]] || client=$(most_recent_client)
if [[ -z $client ]]; then
tmux select-window -t "$session:$index"
exec omarchy-launch-terminal tmux attach -t "$session"
fi
IFS='|' read -r tty pid <<<"$client"
IFS=':' read -r _ tty pid <<<"$client"
tmux switch-client -c "$tty" -t "$session:$index"
omarchy-shell -q omarchy.indicators refresh
focus_terminal_window "$pid"
+8 -1
View File
@@ -8,6 +8,7 @@ BarIndicator {
property int waitingCount: 0
property string tooltip: ""
property bool refreshPending: false
active: waitingCount > 0
activeText: "󰆍"
@@ -16,7 +17,8 @@ BarIndicator {
inactiveTooltipText: "No terminal is waiting"
function refresh() {
if (!statusProc.running) statusProc.running = true
if (statusProc.running) refreshPending = true
else statusProc.running = true
}
function update(raw) {
@@ -54,6 +56,11 @@ BarIndicator {
root.waitingCount = 0
root.tooltip = ""
}
if (root.refreshPending) {
root.refreshPending = false
root.refresh()
}
}
}
+6 -6
View File
@@ -22,22 +22,22 @@ export TMUX_STUB_WINDOWS="$test_dir/windows"
export PATH="$test_dir:$PATH"
cat >"$TMUX_STUB_WINDOWS" <<'WINDOWS'
000|Work|1|editor
100|Work|2|claude
001|Side|1|server|with|pipes
000:Work:1:editor
100:Work:2:claude
001:Side|Gig:1:server: still going
WINDOWS
output=$("$ROOT/bin/omarchy-tmux-alert" show --json)
expected='{"count":2,"tooltip":"claude (Work:2), server|with|pipes (Side:1)"}'
expected='{"count":2,"tooltip":"claude (Work:2), server: still going (Side|Gig:1)"}'
[[ $output == "$expected" ]] || fail "tmux alert reports alerted windows" "expected: $expected"$'\n'"actual: $output"
pass "tmux alert reports alerted windows"
output=$("$ROOT/bin/omarchy-tmux-alert" show)
[[ $output == "claude (Work:2), server|with|pipes (Side:1)" ]] || fail "tmux alert describes alerted windows" "$output"
[[ $output == "claude (Work:2), server: still going (Side|Gig:1)" ]] || fail "tmux alert describes alerted windows" "$output"
pass "tmux alert describes alerted windows"
cat >"$TMUX_STUB_WINDOWS" <<'WINDOWS'
000|Work|1|editor
000:Work:1:editor
WINDOWS
output=$("$ROOT/bin/omarchy-tmux-alert" show --json)