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>
110 lines
2.9 KiB
Bash
Executable File
110 lines
2.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Show or jump to tmux windows waiting for attention
|
|
# omarchy:args=<show [--json]|focus>
|
|
# omarchy:examples=omarchy tmux alert show | omarchy tmux alert focus
|
|
|
|
set -e
|
|
|
|
# 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
|
|
exit 1
|
|
}
|
|
|
|
# Windows tmux has flagged with a bell, activity, or silence alert, which is the
|
|
# same state that highlights the window in the tmux status bar.
|
|
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
|
|
if [[ $flags == *1* ]]; then
|
|
printf '%s:%s:%s\n' "$session" "$index" "$name"
|
|
fi
|
|
done
|
|
}
|
|
|
|
show() {
|
|
local windows=() window session index name description=""
|
|
|
|
readarray -t windows < <(alerted_windows)
|
|
|
|
for window in "${windows[@]}"; do
|
|
IFS=':' read -r session index name <<<"$window"
|
|
[[ -n $description ]] && description+=", "
|
|
description+="$name ($session:$index)"
|
|
done
|
|
|
|
if [[ ${1:-} == "--json" ]]; then
|
|
jq -nc --argjson count "${#windows[@]}" --arg tooltip "$description" '{count: $count, tooltip: $tooltip}'
|
|
elif [[ -n $description ]]; then
|
|
echo "$description"
|
|
fi
|
|
}
|
|
|
|
focus_terminal_window() {
|
|
local pid=$1 address="" window_pid window_address
|
|
local -A windows=()
|
|
|
|
while read -r window_pid window_address; do
|
|
windows[$window_pid]=$window_address
|
|
done < <(hyprctl clients -j | jq -r '.[] | "\(.pid) \(.address)"')
|
|
|
|
# The tmux client runs somewhere below the terminal that owns the window.
|
|
while [[ -n $pid ]] && (( pid > 1 )); do
|
|
if [[ -n ${windows[$pid]:-} ]]; then
|
|
address=${windows[$pid]}
|
|
break
|
|
fi
|
|
pid=$(awk '/^PPid:/ { print $2 }' "/proc/$pid/status" 2>/dev/null)
|
|
done
|
|
|
|
[[ -n $address ]] || return 1
|
|
|
|
hyprctl dispatch "hl.dsp.focus({ window = \"address:$address\" })" >/dev/null 2>&1 ||
|
|
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"
|
|
|
|
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"
|
|
tmux switch-client -c "$tty" -t "$session:$index"
|
|
omarchy-shell -q omarchy.indicators refresh
|
|
focus_terminal_window "$pid"
|
|
}
|
|
|
|
case "${1:-}" in
|
|
show)
|
|
shift
|
|
show "$@"
|
|
;;
|
|
focus)
|
|
focus
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|