nekolas note
1.9 KB Raw
#!/usr/bin/env bash
# cc-tmux: スピナー更新ループ(T015)。
# 参照: contracts/tmux-display.md
#
#   cc-tmux-spinner <session_id> <window_id>
#
# @cc_state==busy の間、ブレイルのフレームを進めて @cc_spin を更新し refresh-client。
# state が idle になったら(または state ディレクトリが消えたら)@cc_spin をクリアして終了。
# 多重起動は pidfile で防止。実効更新は tmux スロットルにより ~1fps。
set -u

CC_DIR=$(cd "$(dirname "$0")/.." && pwd)
# shellcheck source=../lib/state.sh
. "$CC_DIR/lib/state.sh"
# shellcheck source=../lib/tmux.sh
. "$CC_DIR/lib/tmux.sh"

SID=${1:-}
WIN=${2:-}
[ -n "$SID" ] && [ -n "$WIN" ] || exit 1
cc_in_tmux || exit 0

DIR=$(cc_state_dir "$SID")
PIDF="$DIR/spinner.pid"

# 既に稼働中なら多重起動しない。
if [ -f "$PIDF" ]; then
  _p=$(cat "$PIDF" 2>/dev/null)
  if [ -n "$_p" ] && kill -0 "$_p" 2>/dev/null; then
    exit 0
  fi
fi
mkdir -p "$DIR" 2>/dev/null
printf '%s' "$$" > "$PIDF"

# 終了時に pidfile と @cc_spin を後始末。
cleanup() {
  cc_tmux_clear_spin "$WIN"
  cc_tmux_refresh
  # 自分の pidfile のみ削除。
  if [ -f "$PIDF" ]; then
    _owner=$(cat "$PIDF" 2>/dev/null)
    [ "$_owner" = "$$" ] && rm -f "$PIDF" 2>/dev/null
  fi
}
trap cleanup EXIT INT TERM

# ブレイル 10 フレーム。
FRAMES='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
# 文字数(マルチバイト対応)。
NFR=$(printf '%s' "$FRAMES" | awk '{print length($0)}')
i=0

while :; do
  st=$(state_get "$SID" 2>/dev/null) || st=""
  # busy でなくなったら終了(idle/未知/ディレクトリ消滅)。
  [ "$st" = "busy" ] || break

  # i 番目のフレーム1文字を取り出す。
  frame=$(printf '%s' "$FRAMES" | awk -v n=$((i+1)) '{print substr($0,n,1)}')
  cc_tmux_set_spin "$WIN" "$frame"
  cc_tmux_refresh

  i=$(( (i + 1) % NFR ))
  # ~0.1s 間隔で回す(見た目は tmux スロットルで ~1fps)。
  sleep 0.1
done

exit 0