From 504e1fb0e8455f0f87d8e0aa2183b0c18aff97ad Mon Sep 17 00:00:00 2001 From: David Chen Date: Fri, 1 May 2026 11:43:05 -0700 Subject: [PATCH] tmux watch update --- .tmux.conf | 14 +++++++------- tmux/scripts/watch_pane.sh | 15 +++++++++++++++ tmux/tmux-status/left.sh | 8 +++++++- tmux/tmux-status/window_task_icon.sh | 5 +++++ 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/.tmux.conf b/.tmux.conf index 16a661e..7a31628 100644 --- a/.tmux.conf +++ b/.tmux.conf @@ -48,7 +48,7 @@ set-hook -gu pane-focus-in set-hook -g pane-focus-in "run -b 'bash ~/.config/tmux/fzf_panes.tmux update_mru_pane_ids'" set-hook -ag pane-focus-in 'run -b "test -x ~/.config/agent-tracker/bin/agent && ~/.config/agent-tracker/bin/agent tmux on-focus --session #{q:session_id} --window #{q:window_id} --pane #{q:pane_id} || true"' set-hook -ag pane-focus-in 'run -b "test -x ~/.config/agent-tracker/bin/agent && ~/.config/agent-tracker/bin/agent tracker command acknowledge --client #{q:client_tty} --session-id #{q:session_id} --window-id #{q:window_id} --pane #{q:pane_id} || true"' -set-hook -ag pane-focus-in 'run -b "tmux set -wu -t #{window_id} @unread 2>/dev/null || true"' +set-hook -ag pane-focus-in 'run -b "tmux set -wu -t #{window_id} @unread 2>/dev/null || true; tmux set -wu -t #{window_id} @watch_failed 2>/dev/null || true"' set-hook -ag pane-focus-in 'run -b "tmux refresh-client -S"' set-hook -gu pane-died @@ -60,7 +60,7 @@ set-hook -gu after-select-window set-hook -g after-select-window 'run-shell "~/.config/tmux/scripts/check_and_run_on_activate.sh \"#{pane_current_path}\""' set-hook -ag after-select-window 'run -b "test -x ~/.config/agent-tracker/bin/agent && ~/.config/agent-tracker/bin/agent tmux on-focus --session #{q:session_id} --window #{q:window_id} --pane #{q:pane_id} || true"' set-hook -ag after-select-window 'run -b "test -x ~/.config/agent-tracker/bin/agent && ~/.config/agent-tracker/bin/agent tracker command acknowledge --client #{q:client_tty} --session-id #{q:session_id} --window-id #{q:window_id} --pane #{q:pane_id} || true"' -set-hook -ag after-select-window 'run -b "tmux set -wu -t #{window_id} @unread 2>/dev/null || true"' +set-hook -ag after-select-window 'run -b "tmux set -wu -t #{window_id} @unread 2>/dev/null || true; tmux set -wu -t #{window_id} @watch_failed 2>/dev/null || true"' set-hook -ag after-select-window 'run -b "tmux refresh-client -S"' # set-hook -ag window-linked 'run -b "tmux refresh-client -S"' @@ -72,7 +72,7 @@ set-hook -ag after-select-window 'run -b "tmux refresh-client -S"' set-hook -gu client-session-changed set-hook -g client-session-changed 'run -b "test -x ~/.config/agent-tracker/bin/agent && ~/.config/agent-tracker/bin/agent tmux on-focus --session #{q:session_id} --window #{q:window_id} --pane #{q:pane_id} || true"' set-hook -ag client-session-changed 'run -b "test -x ~/.config/agent-tracker/bin/agent && ~/.config/agent-tracker/bin/agent tracker command acknowledge --client #{q:client_tty} --session-id #{q:session_id} --window-id #{q:window_id} --pane #{q:pane_id} || true"' -set-hook -ag client-session-changed 'run -b "tmux set -wu -t #{window_id} @unread 2>/dev/null || true"' +set-hook -ag client-session-changed 'run -b "tmux set -wu -t #{window_id} @unread 2>/dev/null || true; tmux set -wu -t #{window_id} @watch_failed 2>/dev/null || true"' set-hook -ag client-session-changed 'run -b "tmux refresh-client -S"' set-hook -gu session-created @@ -195,8 +195,8 @@ bind -n M-r run-shell 'pane=$(bash ~/.config/tmux/scripts/focus_pane_by_position bind > swap-pane -D bind < swap-pane -U bind | swap-pane -bind -n M-b run-shell 'val=$(tmux show -wv @unread 2>/dev/null); if [ "$val" = "1" ]; then tmux set -wu @unread; else tmux set -w @unread 1; fi; tmux refresh-client -S' -bind -n M-w run-shell -b 'val=$(tmux show -wv @watching 2>/dev/null); if [ "$val" = "1" ]; then tmux set -wu @watching; tmux refresh-client -S; else ~/.config/tmux/scripts/watch_pane.sh "#{pane_id}" "#{window_id}"; fi' +bind -n M-b run-shell 'val=$(tmux show -wv @unread 2>/dev/null); if [ "$val" = "1" ]; then tmux set -wu @unread; tmux set -wu @watch_failed; else tmux set -w @unread 1; tmux set -wu @watch_failed; fi; tmux refresh-client -S' +bind -n M-w run-shell -b 'val=$(tmux show -wv @watching 2>/dev/null); if [ "$val" = "1" ]; then tmux set -wu @watching; tmux set -wu @watch_failed; tmux refresh-client -S; else ~/.config/tmux/scripts/watch_pane.sh "#{pane_id}" "#{window_id}"; fi' bind -n M-m run-shell "test -f ~/.config/agent-tracker/scripts/focus_latest_notified.sh && bash ~/.config/agent-tracker/scripts/focus_latest_notified.sh || true" bind -n M-M run-shell "test -f ~/.config/agent-tracker/scripts/focus_last_origin.sh && bash ~/.config/agent-tracker/scripts/focus_last_origin.sh || true" unbind -nq M-p @@ -287,8 +287,8 @@ set -g status-bg black #set -g status-left '#[fg=brightyellow] #{?client_prefix,⌨ , } #[fg=magenta,bold] %Y-%m-%d %H:%M ' #set -g status-right '#(rainbarf --battery --remaining --bolt --tmux --rgb)' #set -g status-left "#[fg=magenta,bold] %Y-%m-%d %H:%M | #[fg=brightblue]#(curl icanhazip.com) #(ifconfig en0 | grep 'inet ' | awk '{print \"en0 \" $2}') #(ifconfig en1 | grep 'inet ' | awk '{print \"en1 \" $2}') #(ifconfig en3 | grep 'inet ' | awk '{print \"en3 \" $2}') #(ifconfig tun0 | grep 'inet ' | awk '{print \"vpn \" $2}') " -setw -g window-status-format '#[fg=#c5c8c6] #W#(~/.config/tmux/tmux-status/window_task_icon.sh "#{window_id}" "#{@unread}" "#{@watching}") ' -setw -g window-status-current-format '#[fg=#{@theme_color},bold] #W#(~/.config/tmux/tmux-status/window_task_icon.sh "#{window_id}" "#{@unread}" "#{@watching}") ' +setw -g window-status-format '#[fg=#c5c8c6] #W#(~/.config/tmux/tmux-status/window_task_icon.sh "#{window_id}" "#{@unread}" "#{@watching}" "#{@watch_failed}") ' +setw -g window-status-current-format '#[fg=#{@theme_color},bold] #W#(~/.config/tmux/tmux-status/window_task_icon.sh "#{window_id}" "#{@unread}" "#{@watching}" "#{@watch_failed}") ' setw -g window-status-activity-style bg=black setw -g window-status-bell-style bg=black #set-window-option -g window-status-current-format "#[fg=colour235, bg=colour27]⮀#[fg=colour255, bg=colour27] #I ⮁ #W #[fg=colour27, bg=colour235]⮀" diff --git a/tmux/scripts/watch_pane.sh b/tmux/scripts/watch_pane.sh index f069f96..839c8f2 100755 --- a/tmux/scripts/watch_pane.sh +++ b/tmux/scripts/watch_pane.sh @@ -17,6 +17,8 @@ current_cmd=$(tmux display-message -p -t "$pane_id" '#{pane_current_command}' 2> clear_pane_watch() { tmux set-option -p -u -t "$pane_id" @pane_watching 2>/dev/null || true + tmux set-option -p -u -t "$pane_id" @pane_watch_done 2>/dev/null || true + tmux set-option -p -u -t "$pane_id" @pane_watch_exit_status 2>/dev/null || true } trap clear_pane_watch EXIT @@ -33,21 +35,34 @@ if [[ "$current_cmd" == "$pane_shell" ]]; then exit 0 fi +tmux set -wu -t "$window_id" @unread 2>/dev/null || true +tmux set -wu -t "$window_id" @watch_failed 2>/dev/null || true tmux set -w -t "$window_id" @watching 1 2>/dev/null || true tmux set-option -p -t "$pane_id" @pane_watching 1 2>/dev/null || true +tmux set-option -p -t "$pane_id" @pane_watch_done 0 2>/dev/null || true +tmux set-option -p -u -t "$pane_id" @pane_watch_exit_status 2>/dev/null || true tmux refresh-client -S while true; do sleep 1 watching=$(tmux show -wv -t "$window_id" @watching 2>/dev/null || true) [[ "$watching" != "1" ]] && exit 0 + watch_done=$(tmux show-options -pv -t "$pane_id" @pane_watch_done 2>/dev/null || true) + [[ "$watch_done" == "1" ]] && break cmd=$(tmux display-message -p -t "$pane_id" '#{pane_current_command}' 2>/dev/null || true) if [[ -z "$cmd" || "$cmd" == "$pane_shell" ]]; then break fi done +exit_status=$(tmux show-options -pv -t "$pane_id" @pane_watch_exit_status 2>/dev/null || true) + tmux set -wu -t "$window_id" @watching 2>/dev/null || true +if [[ "$exit_status" =~ ^[0-9]+$ && "$exit_status" != "0" ]]; then + tmux set -w -t "$window_id" @watch_failed 1 2>/dev/null || true +else + tmux set -wu -t "$window_id" @watch_failed 2>/dev/null || true +fi tmux set -w -t "$window_id" @unread 1 2>/dev/null || true tmux refresh-client -S notify_completion diff --git a/tmux/tmux-status/left.sh b/tmux/tmux-status/left.sh index 9c60bc9..c8c3e46 100755 --- a/tmux/tmux-status/left.sh +++ b/tmux/tmux-status/left.sh @@ -65,7 +65,7 @@ question_state=$(tmux list-panes -a -F '#{session_id}::#{@op_question_pending}' get_session_icon() { local sid="$1" - local has_question=0 has_bell=0 has_watch=0 + local has_question=0 has_bell=0 has_watch=0 has_fail=0 local question_pane question_pane=$(grep -F -m1 -x "${sid}::1" <<< "$question_state" || true) @@ -75,6 +75,10 @@ get_session_icon() { unread_win=$(tmux list-windows -t "$sid" -F '#{@unread}' 2>/dev/null | grep -m1 '^1$' || true) [[ -n "$unread_win" ]] && has_bell=1 + local failed_win + failed_win=$(tmux list-windows -t "$sid" -F '#{@unread}:#{@watch_failed}' 2>/dev/null | grep -m1 '^1:1$' || true) + [[ -n "$failed_win" ]] && has_fail=1 + local watching_win watching_win=$(tmux list-windows -t "$sid" -F '#{@watching}' 2>/dev/null | grep -m1 '^1$' || true) [[ -n "$watching_win" ]] && has_watch=1 @@ -95,6 +99,8 @@ get_session_icon() { if (( has_question )); then printf '❓' + elif (( has_fail )); then + printf '❌' elif (( has_bell )); then printf '🔔' elif (( has_watch )); then diff --git a/tmux/tmux-status/window_task_icon.sh b/tmux/tmux-status/window_task_icon.sh index ce89b06..1588288 100755 --- a/tmux/tmux-status/window_task_icon.sh +++ b/tmux/tmux-status/window_task_icon.sh @@ -4,13 +4,16 @@ set -euo pipefail window_id="${1:-}" unread="${2:-0}" watching="${3:-0}" +watch_failed="${4:-0}" [[ -z "$window_id" ]] && exit 0 has_bell=0 has_watch=0 has_question=0 +has_fail=0 [[ "$unread" == "1" ]] && has_bell=1 +[[ "$unread" == "1" && "$watch_failed" == "1" ]] && has_fail=1 [[ "$watching" == "1" ]] && has_watch=1 @@ -36,6 +39,8 @@ fi if (( has_question )); then printf '❓' +elif (( has_fail )); then + printf '❌' elif (( has_bell )); then printf '🔔' elif (( has_watch )); then