nekolas note
3.5 KB Raw
#!/usr/bin/env sh
# cc-tmux: tmux 連携ヘルパ(T006)。
# 参照: contracts/tmux-display.md
#
# 表示の真実は tmux per-window ユーザーオプション(@cc_state / @cc_spin / @cc_name)。
# tmux 外($TMUX 無し)では全操作を no-op にする(FR-010/042)。
#
# bin/* から `. lib/tmux.sh` で読み込まれる(POSIX sh 互換)。

# tmux 内で動作しているか(フックプロセスへ $TMUX が伝播している前提)。
cc_in_tmux() {
  [ -n "${TMUX:-}" ]
}

# 指定 pane(既定 $TMUX_PANE)から window_id(@N)を解決して出力。
# 解決できなければ exit 1。
cc_tmux_window_id() {
  _ctw_pane=${1:-${TMUX_PANE:-}}
  [ -n "$_ctw_pane" ] || return 1
  cc_in_tmux || return 1
  tmux display-message -p -t "$_ctw_pane" '#{window_id}' 2>/dev/null
}

# @cc_state を設定。 cc_tmux_set_state <window_id> <busy|idle>
cc_tmux_set_state() {
  cc_in_tmux || return 0
  [ -n "${1:-}" ] || return 1
  tmux set-option -w -t "$1" @cc_state "${2:-idle}" 2>/dev/null
}

# @cc_spin を設定(スピナー1フレーム)。 cc_tmux_set_spin <window_id> <frame>
cc_tmux_set_spin() {
  cc_in_tmux || return 0
  [ -n "${1:-}" ] || return 1
  tmux set-option -w -t "$1" @cc_spin "${2:-}" 2>/dev/null
}

# @cc_spin をクリア。 cc_tmux_clear_spin <window_id>
cc_tmux_clear_spin() {
  cc_in_tmux || return 0
  [ -n "${1:-}" ] || return 1
  tmux set-option -w -t "$1" -u @cc_spin 2>/dev/null
}

# 全状態表示をクリア(SessionEnd 用)。 cc_tmux_clear_all <window_id>
cc_tmux_clear_all() {
  cc_in_tmux || return 0
  [ -n "${1:-}" ] || return 1
  tmux set-option -w -t "$1" -u @cc_state 2>/dev/null
  tmux set-option -w -t "$1" -u @cc_spin 2>/dev/null
  return 0
}

# 即時再描画。
cc_tmux_refresh() {
  cc_in_tmux || return 0
  tmux refresh-client -S 2>/dev/null
}

# ウィンドウが「既に明示的な名前を持つ(=上書き禁止)」かを判定(FR-044)。
# automatic-rename が off で、かつ現在名が自動派生でない場合はロック扱い。
# 戻り値: 0=ロック(上書き禁止), 1=未ロック(導出名を設定して良い)。
cc_tmux_name_locked() {
  cc_in_tmux || return 0
  [ -n "${1:-}" ] || return 0
  _ctnl_auto=$(tmux show-options -w -t "$1" -v automatic-rename 2>/dev/null)
  # automatic-rename が明示的に off → ユーザー/起動側が名前を固定している → ロック。
  if [ "$_ctnl_auto" = "off" ]; then
    return 0
  fi
  return 1
}

# 未ロック時のみウィンドウ名を設定(FR-040/044)。
# cc_tmux_rename <window_id> <name>
cc_tmux_rename() {
  cc_in_tmux || return 0
  [ -n "${1:-}" ] && [ -n "${2:-}" ] || return 1
  if cc_tmux_name_locked "$1"; then
    return 0  # 既存名は尊重(上書きしない)
  fi
  tmux rename-window -t "$1" "$2" 2>/dev/null || return 1
  # 自動リネームによる即時上書きを防ぐため off にする。
  tmux set-option -w -t "$1" automatic-rename off 2>/dev/null
  return 0
}

# ロックを無視してウィンドウ名を設定(FR-041/043: 明示的なセッション名用)。
# /rename 等でユーザーが session 名を明示した場合は session 名が正(source of truth)
# であり、tmux 側の既存名(cc_tmux_rename 自身が残した automatic-rename off を含む)より優先する。
# cc_tmux_rename_force <window_id> <name>
cc_tmux_rename_force() {
  cc_in_tmux || return 0
  [ -n "${1:-}" ] && [ -n "${2:-}" ] || return 1
  tmux rename-window -t "$1" "$2" 2>/dev/null || return 1
  tmux set-option -w -t "$1" automatic-rename off 2>/dev/null
  return 0
}