# 機能設計書 66-テキスト検索

## 概要

本ドキュメントは、Ghosttyターミナルエミュレータにおけるスクロールバック内テキスト検索機能の設計を記述する。

### 本機能の処理概要

テキスト検索機能は、端末のスクロールバックバッファ内でユーザーが指定した文字列を検索し、マッチした箇所をハイライト表示する機能である。専用の検索スレッドを使用して大容量のスクロールバックでも高速に検索を実行し、リアルタイムで結果を更新する。

**業務上の目的・背景**：ターミナル作業では、過去のコマンド出力やログを検索することが頻繁に発生する。長時間のセッションでは大量の出力が蓄積されるため、効率的な検索機能は作業効率に直結する。テキスト検索機能により、ユーザーは過去の出力から必要な情報を素早く見つけることができる。

**機能の利用シーン**：
- ログ出力から特定のエラーメッセージを探す場合
- 過去に実行したコマンドの出力を確認する場合
- 設定ファイルの内容やビルド結果から特定の文字列を探す場合

**主要な処理内容**：
1. 検索オーバーレイUI表示と検索文字列の入力受付
2. 専用検索スレッドでの非同期検索処理
3. スライディングウィンドウアルゴリズムによるPageList検索
4. アクティブ領域とスクロールバック履歴の同時検索
5. マッチ結果のハイライト表示
6. 検索結果間のナビゲーション

**関連システム・外部連携**：
- レンダラー: ハイライト表示
- PageList: 端末出力データの検索対象

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | 検索オーバーレイ | 主機能 | 検索UI表示、検索文字列入力 |
| 1 | メインターミナルウィンドウ | 主機能 | 検索結果のハイライト表示 |

## 機能種別

検索処理 / UI連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| needle | []const u8 | Yes | 検索文字列 | 空文字列不可 |

### 入力データソース

- 検索オーバーレイUI: ユーザー入力
- キーバインドアクション: start_search、end_search、search_selection

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| FlattenedHighlight | struct | マッチ位置情報（ページノード、開始/終了行、X座標） |
| total_matches | usize | 総マッチ数 |
| selected_match | usize | 現在選択中のマッチ番号 |

### 出力先

- レンダラー: ハイライト描画
- 検索オーバーレイUI: マッチ数表示

## 処理フロー

### 処理シーケンス

```
1. 検索開始
   └─ start_searchアクションまたはCtrl+F
   └─ 検索オーバーレイ表示
   └─ 検索スレッド起動

2. 検索文字列入力
   └─ キーストロークごとにneedle更新
   └─ 検索スレッドにneedle送信

3. 検索処理（検索スレッド）
   └─ SlidingWindow初期化
   └─ ビューポート検索（現在表示領域優先）
   └─ アクティブ領域検索
   └─ PageList検索（スクロールバック全体）

4. 結果通知
   └─ マッチごとにFlattenedHighlightを生成
   └─ レンダラーに通知

5. ナビゲーション
   └─ search_up/search_downでマッチ間移動
   └─ ビューポートをマッチ位置にスクロール

6. 検索終了
   └─ end_searchアクションまたはEsc
   └─ 検索スレッド停止
   └─ オーバーレイ非表示
```

### フローチャート

```mermaid
flowchart TD
    A[start_search] --> B[検索オーバーレイ表示]
    B --> C[検索スレッド起動]
    C --> D[検索文字列入力]
    D --> E{needle変更?}
    E -->|Yes| F[検索スレッドにneedle送信]
    E -->|No| G{ナビゲーション?}
    F --> H[SlidingWindow初期化]
    H --> I[ビューポート検索]
    I --> J[アクティブ領域検索]
    J --> K[PageList検索]
    K --> L[マッチ結果ハイライト]
    L --> G
    G -->|search_up| M[前のマッチへ移動]
    G -->|search_down| N[次のマッチへ移動]
    G -->|end_search| O[検索終了]
    M --> P[ビューポートスクロール]
    N --> P
    O --> Q[スレッド停止]
    Q --> R[オーバーレイ非表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-66-01 | 大文字小文字無視 | ASCII文字の検索は大文字小文字を区別しない | 常時 |
| BR-66-02 | ビューポート優先 | 現在表示中の領域を最初に検索する | 常時 |
| BR-66-03 | 逆方向検索 | PageList検索は新しい出力から古い出力へ向かう | 常時 |
| BR-66-04 | リフレッシュ | 端末内容の変更を24ms間隔で検出し再検索 | 検索中 |

### 計算ロジック

マッチ検出は`std.ascii.indexOfIgnoreCase`を使用してASCII文字の大文字小文字を無視して行われる。

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

該当なし（本機能はデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | メモリ不足 | SlidingWindow拡張時 | エラーログ出力、検索継続 |
| - | ページ無効化 | 検索中にスクロールバックがプルーン | 検索再開、結果更新 |

### リトライ仕様

ページがガベージ化された場合、検索は自動的に中断され次のリフレッシュで再開される。

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

- PageList/Screenアクセス時にミューテックスロックを取得
- ロック時間を最小化するため、データを検索スレッドにコピー

## パフォーマンス要件

- 検索スレッドは専用スレッドで動作し、メインスレッドをブロックしない
- リフレッシュ間隔は24ms（約40FPS）で端末変更を検出
- SlidingWindowで最小限のメモリ使用量を維持

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

該当なし

## 備考

- 検索はインクリメンタルで、キーストロークごとに結果が更新される
- ページ境界をまたぐマッチにも対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sliding_window.zig | `src/terminal/search/sliding_window.zig` | SlidingWindow構造体（38-633行目） |
| 1-2 | highlight.zig | `src/terminal/highlight.zig` | FlattenedHighlight構造体 |

**読解のコツ**: SlidingWindowはCircularBufferを使用してデータを効率的に管理し、needle（検索文字列）を逆方向で保持して逆方向検索を高速化している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Thread.zig | `src/terminal/search/Thread.zig` | 検索スレッド管理（1-100行目） |
| 2-2 | Surface.zig | `src/Surface.zig` | 検索状態管理（166行目、190-200行目） |

**主要処理フロー**:
1. **Thread.zig 44行目**: REFRESH_INTERVAL定数（24ms）
2. **Thread.zig 74行目**: search状態（needle受信時に初期化）
3. **Thread.zig 82-100行目**: スレッド初期化

#### Step 3: 検索アルゴリズムを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | active.zig | `src/terminal/search/active.zig` | アクティブ領域検索 |
| 3-2 | pagelist.zig | `src/terminal/search/pagelist.zig` | PageList検索 |

**主要処理フロー**:
- **active.zig 20-33行目**: ActiveSearch構造体定義とinit
- **active.zig 52-95行目**: update関数（アクティブ領域データ取得）
- **pagelist.zig 30-135行目**: PageListSearch（履歴検索）

#### Step 4: マッチ検索を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sliding_window.zig | `src/terminal/search/sliding_window.zig` | next関数（166-283行目） |

**主要処理フロー**:
- **179-184行目**: 最初のスライスでのneedle検索
- **187-216行目**: オーバーラップバッファでの境界検索
- **219-224行目**: 2番目のスライスでの検索
- **296-517行目**: highlight関数（マッチ位置からFlattenedHighlight生成）

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

```
start_searchアクション
    │
    └─ Surface
           │
           ├─ 検索オーバーレイ表示
           │
           └─ search.Thread.init
                  │
                  └─ 検索スレッド起動
                         │
                         ├─ SlidingWindow.init
                         │
                         ├─ ViewportSearch（ビューポート検索）
                         │
                         ├─ ActiveSearch（アクティブ領域検索）
                         │      └─ update（PageListからデータコピー）
                         │      └─ next（マッチ検索）
                         │
                         └─ PageListSearch（スクロールバック検索）
                                └─ init（開始位置設定）
                                └─ feed（ページ追加読み込み）
                                └─ next（マッチ検索）
```

### データフロー図

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

検索文字列 ────────────▶ SlidingWindow.init
(needle)                       │
                               ▼
PageList ──────────────▶ PageListSearch.init
                               │
                               ├── ページ走査
                               │       │
                               ▼       ▼
                        SlidingWindow.append ───▶ データ蓄積
                               │
                               ▼
                        SlidingWindow.next ───▶ マッチ検出
                               │
                               ▼
                        highlight関数 ───▶ FlattenedHighlight
                               │
                               ▼
                        レンダラー通知 ───▶ ハイライト表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Thread.zig | `src/terminal/search/Thread.zig` | ソース | 検索スレッド管理 |
| sliding_window.zig | `src/terminal/search/sliding_window.zig` | ソース | スライディングウィンドウ検索 |
| active.zig | `src/terminal/search/active.zig` | ソース | アクティブ領域検索 |
| pagelist.zig | `src/terminal/search/pagelist.zig` | ソース | PageList検索 |
| viewport.zig | `src/terminal/search/viewport.zig` | ソース | ビューポート検索 |
| screen.zig | `src/terminal/search/screen.zig` | ソース | スクリーン検索 |
| Surface.zig | `src/Surface.zig` | ソース | 検索状態管理 |
