#!/bin/bash # omarchy:summary=Show or jump to tmux windows waiting for attention # omarchy:args= # 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_id}:#{window_bell_flag}#{window_activity_flag}#{window_silence_flag}:#{window_activity}:#{@omarchy_unfocused_activity}:#{session_name}:#{window_index}:#{window_name}' CLIENT_FORMAT='#{client_flags}:#{window_id}' usage() { echo "Usage: omarchy-tmux-alert " >&2 exit 1 } # Include tmux alert flags plus output newer than the last focus transition for # selected windows whose attached terminals are all unfocused. alerted_windows() { local client_flags window_id flags activity seen_activity session index name local waiting local -A attached_windows=() local -A focused_windows=() while IFS=':' read -r client_flags window_id; do [[ -n $window_id ]] || continue attached_windows[$window_id]=1 if [[ ,$client_flags, == *",focused,"* ]]; then focused_windows[$window_id]=1 fi done < <(tmux list-clients -F "$CLIENT_FORMAT" 2>/dev/null) while IFS=':' read -r window_id flags activity seen_activity session index name; do waiting=0 [[ $flags == *1* ]] && waiting=1 if [[ ${attached_windows[$window_id]:-} == "1" && ${focused_windows[$window_id]:-} != "1" && $activity =~ ^[0-9]+$ && $seen_activity =~ ^[0-9]+$ ]] && ((activity > seen_activity)); then waiting=1 fi ((waiting)) && printf '%s:%s:%s\n' "$session" "$index" "$name" done < <(tmux list-windows -a -F "$WINDOW_FORMAT" 2>/dev/null) } 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 } track() { local window=${1:-} activity=${2:-} [[ $window =~ ^@[0-9]+$ && $activity =~ ^[0-9]+$ ]] || return 0 tmux set-option -wq -t "$window" @omarchy_unfocused_activity "$activity" 2>/dev/null || return 0 omarchy-shell -q omarchy.indicators refresh } 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 ;; track) shift track "$@" ;; *) usage ;; esac