diff --git a/dot_functions b/dot_functions index 0f2f5db332..63f9fd7c71 100644 --- a/dot_functions +++ b/dot_functions @@ -2231,6 +2231,19 @@ function git-doctor() { print -r -- "configs: $(command git config --list --show-origin --name-only 2>/dev/null | command awk -F'\t' '$1 ~ /^file:/ {print substr($1, 6)}' | command awk '!seen[$0]++' | command paste -sd, - | command sed 's/,/, /g')"; } +# Set this tab's row in iTerm2's Session Status panel: +# tabstatus [detail] [--dot-color '#rrggbb' --text-color …] +# `tabstatus` alone clears it. Goes through `it2 set-status` (the API), not the +# OSC 21337 escape, because the escape needs the tab's tty and neither Claude +# Code's Bash tool nor its hooks have one. iTerm2's own cc-status hook rewrites +# the row on the next Claude Code event, so inside a session this lasts a turn. +function tabstatus() { + [[ -n $ITERM_SESSION_ID ]] || { print -ru2 -- "tabstatus: not inside an iTerm2 session"; return 1; } + local st=${1-} detail=${2-}; + (( $# )) && shift; (( $# )) && shift; + command it2 set-status --session "${ITERM_SESSION_ID#*:}" --status "$st" --detail "$detail" "$@" >/dev/null; +} + # Where iTerm2 is installed, or nothing. $ITERM2_APP names a non-standard # location and, when set, is used *exclusively* — an override that quietly # fell back to /Applications would make every answer below a lie about a diff --git a/tests/tabstatus.bats b/tests/tabstatus.bats new file mode 100644 index 0000000000..0e6b5288e3 --- /dev/null +++ b/tests/tabstatus.bats @@ -0,0 +1,32 @@ +#!/usr/bin/env bats + +# tabstatus in dot_functions fills in the session id `it2 set-status` demands. +# it2 is stubbed to record its argv; no test touches a real iTerm2. + +setup() { + STUB="$BATS_TEST_TMPDIR/bin" + mkdir -p "$STUB" + printf '#!/bin/sh\nprintf "%%s\\n" "$@" > "%s/argv"\n' "$BATS_TEST_TMPDIR" > "$STUB/it2" + chmod +x "$STUB/it2" + PATH="$STUB:$PATH" + DOTFUNCTIONS="$BATS_TEST_DIRNAME/../dot_functions" +} + +@test "tabstatus: passes the session uuid, status, detail and extra flags" { + run zsh -c "ITERM_SESSION_ID=w0t1p0:ABC-123; source '$DOTFUNCTIONS'; tabstatus 'reviewing PR' 'on CI' --dot-color '#66cccc'" + [ "$status" -eq 0 ] + [ "$(paste -sd'|' "$BATS_TEST_TMPDIR/argv")" = "set-status|--session|ABC-123|--status|reviewing PR|--detail|on CI|--dot-color|#66cccc" ] +} + +@test "tabstatus: no arguments clears status and detail" { + run zsh -c "ITERM_SESSION_ID=w0t1p0:ABC-123; source '$DOTFUNCTIONS'; tabstatus" + [ "$status" -eq 0 ] + [ "$(paste -sd'|' "$BATS_TEST_TMPDIR/argv")" = "set-status|--session|ABC-123|--status||--detail|" ] +} + +@test "tabstatus: outside iTerm2 is an error and never calls it2" { + run zsh -c "unset ITERM_SESSION_ID; source '$DOTFUNCTIONS'; tabstatus working" + [ "$status" -eq 1 ] + [[ "$output" == *"not inside an iTerm2 session"* ]] + [ ! -e "$BATS_TEST_TMPDIR/argv" ] +}