# 機能設計書 98-全選択

## 概要

本ドキュメントは、Ghosttyターミナルエミュレータにおける「全選択」機能の設計を記述する。本機能により、ターミナル画面の全てのテキストを一括で選択できる。

### 本機能の処理概要

全選択機能は、スクロールバック履歴を含むターミナル画面の全テキストを選択状態にする。選択されたテキストはクリップボードにコピーしたり、他の操作に利用できる。

**業務上の目的・背景**：ターミナル出力全体をコピーしたい場合、マウスでドラッグして選択するのは非効率。全選択機能により、一括でテキストを選択し、その後コピー操作で全内容を取得できる。GUIアプリケーションで一般的なCmd+A/Ctrl+A操作をターミナルでも実現する。

**機能の利用シーン**：
- ターミナル出力全体をコピーしてレポートに貼り付ける場合
- ログ全体を別のエディタに転送する場合
- 全テキストを検索対象として選択する場合

**主要な処理内容**：
1. ユーザーがselect_allアクションを実行
2. Screen.selectAll()を呼び出し
3. スクロールバック先頭から現在位置までの範囲を選択
4. 周囲の空白文字は選択範囲から除外
5. 選択範囲がセットされ、画面が再描画される

**関連システム・外部連携**：特になし

**権限による制御**：特になし。全ユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主画面 | 全選択操作が行われる画面 |

## 機能種別

UI制御 / 選択操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | select_allはパラメータなし | - |

### 入力データソース

- キーバインド設定（例: `keybind = cmd+a=select_all`）
- コマンドパレットからの選択（「Select All」）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 選択範囲 | Selection | 全テキストの選択範囲（開始位置〜終了位置） |

### 出力先

- 画面表示（選択ハイライト）
- 内部状態（Selection構造体）

## 処理フロー

### 処理シーケンス

```
1. ユーザーがselect_allアクションを実行
   └─ キーバインド経由（通常Cmd+A / Ctrl+A）
2. Surface.performBindingActionでアクションを処理
   └─ renderer_state.mutexをロック
3. Screen.selectAll()を呼び出し
   └─ 空白文字（0, ' ', '\t'）をスキップ
   └─ 先頭の非空白文字を開始位置に設定
   └─ 末尾の非空白文字を終了位置に設定
4. 選択範囲が存在する場合
   └─ setSelection(s)で選択を設定
   └─ queueRender()で再描画をキュー
5. 選択がない場合（全て空白）
   └─ 何もしない
```

### フローチャート

```mermaid
flowchart TD
    A[select_allアクション実行] --> B[renderer_state.mutex取得]
    B --> C[Screen.selectAll呼び出し]
    C --> D{選択範囲あり?}
    D -->|Yes| E[setSelectionで選択設定]
    D -->|No| F[何もしない]
    E --> G[queueRenderで再描画]
    G --> H[処理完了]
    F --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-98-1 | 空白除外 | 先頭と末尾の空白文字（0, ' ', '\t'）は選択範囲から除外 | 常時 |
| BR-98-2 | 全画面対象 | スクロールバック履歴も含めて選択対象 | 常時 |
| BR-98-3 | 空の場合 | 全て空白の場合は選択範囲なし（nullを返す） | 内容が空白のみの場合 |

### 計算ロジック

```
selectAll():
1. 先頭から末尾に向かってセルをイテレート
2. 空白以外の最初のセルを開始位置(start)とする
3. 末尾から先頭に向かってセルをイテレート
4. 空白以外の最初のセルを終了位置(end)とする
5. Selection.init(start, end, false)で選択範囲を作成
```

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | なし | 全て空白の場合 | 選択範囲なしとして処理 |

### リトライ仕様

リトライ不要

## トランザクション仕様

トランザクション不要（メモリ上の状態更新のみ）

## パフォーマンス要件

全選択操作は即座に完了すること（100ms以内）

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

特になし

## 備考

- 選択後にcopy_to_clipboardアクションでクリップボードにコピー可能
- write_selection_fileアクションで選択内容をファイルに保存可能

---

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

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

### 推奨読解順序

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

アクションと選択範囲の定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Binding.zig | `src/input/Binding.zig` | select_allアクション定義（414行目） |
| 1-2 | Selection.zig | `src/terminal/Selection.zig` | Selection構造体の定義 |

**読解のコツ**: Selectionは開始位置(start)と終了位置(end)を持つ構造体。Pinで位置を表現する。

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

Surfaceでのアクション処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Surface.zig | `src/Surface.zig` | select_all処理（5755-5764行目） |

**主要処理フロー**:
1. **5755行目**: select_allアクションのマッチング
2. **5756行目**: renderer_state.mutex.lock()でロック取得
3. **5757行目**: deferでunlock
4. **5759行目**: self.io.terminal.screens.active.selectAll()を呼び出し
5. **5760-5762行目**: 選択範囲があればsetSelectionとqueueRender

#### Step 3: Screen.selectAllを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Screen.zig | `src/terminal/Screen.zig` | selectAll関数（2679-2720行目付近） |

**主要処理フロー**:
- **2680行目**: whitespace定義（0, ' ', '\t'）
- **2682-2699行目**: 先頭から走査して開始位置を特定
- **2701-2715行目**: 末尾から走査して終了位置を特定
- **2717行目**: Selection.init(start, end, false)で選択範囲を作成

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

```
Surface.performBindingAction
    │
    └─ select_allアクションを検出
           │
           ├─ renderer_state.mutex.lock()
           │
           └─ Screen.selectAll()
                  │
                  ├─ 先頭から非空白文字を検索（開始位置）
                  │
                  ├─ 末尾から非空白文字を検索（終了位置）
                  │
                  └─ Selection.init(start, end, false)
                         │
                         └─ setSelection() / queueRender()
```

### データフロー図

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

キーバインド ───▶ Surface.performBindingAction ───▶ 選択状態
(Cmd+A等)               │
                        ▼
               Screen.selectAll()
                        │
                        ├─ 開始位置検索
                        ├─ 終了位置検索
                        └─ Selection作成 ───▶ 画面再描画
                                              （選択ハイライト）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Binding.zig | `src/input/Binding.zig` | ソース | select_allアクション定義 |
| command.zig | `src/input/command.zig` | ソース | コマンドパレット用コマンド（238-242行目） |
| Surface.zig | `src/Surface.zig` | ソース | アクション処理のエントリーポイント |
| Screen.zig | `src/terminal/Screen.zig` | ソース | selectAll関数の実装 |
| Selection.zig | `src/terminal/Selection.zig` | ソース | Selection構造体の定義 |
