# 通知設計書 15-タブタイトル設定

## 概要

本ドキュメントは、Oh My Zshのターミナルサポート機能における、ターミナルタブのタイトルを現在のディレクトリに自動設定する通知の設計を記載する。

### 本通知の処理概要

この通知は、ANSIエスケープシーケンス（OSC 1）を使用して、ターミナルタブのタイトルを動的に更新する機能である。ウィンドウタイトル（OSC 2）と同時に設定され、タブに表示される短いタイトルを提供する。

**業務上の目的・背景**：タブ付きターミナルエミュレータでは、複数のタブを同時に使用することが一般的である。各タブに作業中のディレクトリ名を表示することで、タブ間の切り替え時に目的のタブを素早く特定できる。タブはウィンドウよりも表示領域が狭いため、15文字に切り詰めた短いタイトルが適している。

**通知の送信タイミング**：precmdフック（プロンプト表示前）では現在のディレクトリ名を15文字以内で設定し、preexecフック（コマンド実行前）では実行中のコマンド名を設定する。

**通知の受信者**：ターミナルエミュレータ。OSC 1エスケープシーケンスを解釈してタブタイトルを更新する。

**通知内容の概要**：アイドル時は「%15<..<%~%<<」形式（例：「..oject/src」のように15文字に左切り詰め）、コマンド実行時はコマンド名（例：「git」）がタブタイトルとして設定される。

**期待されるアクション**：ターミナルエミュレータがエスケープシーケンスを解釈し、タブタイトルを更新する。ユーザーはタブ一覧で現在の作業ディレクトリやコマンドを確認できる。

## 通知種別

ターミナルエスケープシーケンス（OSC 1）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（フック実行時に即座に送信） |
| 優先度 | 低（表示最適化のための補助機能） |
| リトライ | なし |

### 送信先決定ロジック

現在のターミナルセッションに対してエスケープシーケンスを出力する。ターミナルエミュレータが対応していない場合は無視される。

## 通知テンプレート

### エスケープシーケンス形式

| 項目 | 内容 |
|-----|------|
| 送信元 | termsupport.zsh |
| エスケープシーケンス | `\e]1;${title}\a` |
| 対応ターミナル | xterm, putty, rxvt, konsole, mlterm, alacritty, st, foot, contour, wezterm, iTerm2 |

### 本文テンプレート

#### アイドル時（precmd）

```
\e]1;%15<..<%~%<<\a
```

展開例：`\e]1;~/project/src\a`（15文字以内）
展開例：`\e]1;..cts/my-project\a`（15文字で左切り詰め）

#### コマンド実行時（preexec）

```
\e]1;${CMD}\a
```

展開例：`\e]1;git\a`

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | エスケープシーケンスのため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| %~ | カレントディレクトリ（~展開） | $PWD | Yes |
| ZSH_THEME_TERM_TAB_TITLE_IDLE | アイドル時タブタイトルフォーマット | 設定/デフォルト | No |
| CMD | コマンド名（sudo/ssh等を除く） | preexecの第1引数から抽出 | No（preexecのみ） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| フック | precmd | DISABLE_AUTO_TITLE != true | プロンプト表示前 |
| フック | preexec | DISABLE_AUTO_TITLE != true | コマンド実行前 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| DISABLE_AUTO_TITLE=true | タイトル自動設定を無効化 |
| INSIDE_EMACS != "" && != vterm | Emacs内（vtermを除く）では設定しない |
| 非対応ターミナル | $TERMが対応ターミナルでない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[precmd/preexecフック実行] --> B{DISABLE_AUTO_TITLE?}
    B -->|true| C[処理終了]
    B -->|false| D{INSIDE_EMACS?}
    D -->|Yes かつ != vterm| C
    D -->|No または vterm| E[title関数呼び出し]
    E --> F{$TERM判定}
    F -->|xterm等| G[OSC 1でタブタイトル設定]
    F -->|screen/tmux| H[screen hardstatusのみ設定]
    F -->|その他| I{$TERM_PROGRAM?}
    I -->|iTerm.app| G
    I -->|その他| C
    G --> J[OSC 2でウィンドウタイトルも設定]
    H --> K[終了]
    J --> K
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | データベースは使用しない |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | データベースは使用しない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ターミナル非対応 | OSC 1を解釈できないターミナル | エスケープシーケンスは無視される（害はない） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限なし | フックごとに1回のみ実行 |

### 配信時間帯

制限なし（フック実行時に即座に送信）

## セキュリティ考慮事項

- タイトルにはディレクトリパスが含まれる
- 機密性の高いディレクトリ名が表示される可能性がある
- `${1:q}`によるクォート処理でエスケープシーケンスインジェクションを防止

## 備考

- ZSH_THEME_TERM_TAB_TITLE_IDLE変数でアイドル時のタブタイトルフォーマットをカスタマイズ可能
- デフォルトは15文字で左切り詰め（`%15<..<%~%<<`）
- コマンド実行時のCMDはsudo、ssh、mosh、rake、環境変数設定、オプションを除いた実際のコマンド名

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、タブタイトルフォーマットの設定変数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | termsupport.zsh | `lib/termsupport.zsh` | タブタイトルフォーマット変数の定義（41行目） |

**読解のコツ**: `%15<..<%~%<<`はzshのプロンプト展開形式で、15文字を超える場合は左側を「..」で置き換える。

#### Step 2: エントリーポイントを理解する

処理の起点となるtitle関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | termsupport.zsh | `lib/termsupport.zsh` | title関数（9-39行目） |

**主要処理フロー**:
1. **17行目**: 第2引数が未指定の場合、第1引数をデフォルト値として使用
2. **22行目**: `print -Pn "\e]1;${1:q}\a"` でタブタイトル設定（OSC 1）
3. **21行目**: 同時にウィンドウタイトルも設定（OSC 2）

#### Step 3: コマンド名抽出ロジックを理解する

preexecでのコマンド名抽出を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | termsupport.zsh | `lib/termsupport.zsh` | omz_termsupport_preexec関数（55-103行目） |

**主要処理フロー**:
- **99行目**: `local CMD="${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%}"`
  - `(wr)`：ワード単位で最初のマッチを取得
  - `^(...)`：指定パターン以外にマッチ
  - `*=*`：環境変数設定を除外
  - `sudo|ssh|mosh|rake`：ラッパーコマンドを除外
  - `-*`：オプションを除外

### プログラム呼び出し階層図

```
シェル起動
    │
    └─ lib/termsupport.zsh (source)
           │
           ├─ add-zsh-hook precmd omz_termsupport_precmd (108行目)
           │      │
           │      └─ omz_termsupport_precmd (49-52行目)
           │             └─ title "$ZSH_THEME_TERM_TAB_TITLE_IDLE" ...
           │                    └─ print -Pn "\e]1;${1:q}\a" (22行目)
           │
           └─ add-zsh-hook preexec omz_termsupport_preexec (109行目)
                  │
                  └─ omz_termsupport_preexec (55-103行目)
                         │
                         ├─ CMD抽出 (99行目)
                         │      └─ sudo/ssh等を除外
                         │
                         └─ title "$CMD" ...
                                └─ print -Pn "\e]1;${1:q}\a" (22行目)
```

### データフロー図

```
[入力]               [処理]                    [出力]

$PWD ────────────▶ ZSH_THEME_TERM_TAB_TITLE_IDLE ───▶ title関数
                          │                              │
                          ▼                              ▼
                   プロンプト展開               \e]1;..project/src\a
                   (%15<..<%~%<<)                        │
                                                        ▼
                                               ターミナルタブタイトル

---

コマンドライン ───▶ CMD抽出 ───────────────────▶ title関数
                   │ sudo/ssh除外                    │
                   │ 環境変数除外                    ▼
                   │ オプション除外          \e]1;git\a
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| termsupport.zsh | `lib/termsupport.zsh` | ソース | ターミナルタイトル設定のメイン実装 |
