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