# 画面設計書 7-プレフィックス検索モード

## 概要

現在の入力をプレフィックスとして履歴を前方/後方検索するモードの設計書。一致する履歴エントリを順次表示する。

### 本画面の処理概要

本画面は、Julia REPLのプレフィックス検索モードであり、現在のプロンプト入力をプレフィックス（先頭文字列）として使用し、履歴から一致するエントリを検索して表示する。

**業務上の目的・背景**：REPLの入力中に、過去に入力した類似のコマンドを素早く呼び出すためのインタフェースである。例えば `using` と入力した状態で上矢印キーを押すと、`using` で始まる履歴エントリが順次表示される。通常の履歴ナビゲーション（入力なしでの上下キー）とは異なり、入力中のテキストをフィルタとして使用するため、関連するコマンドのみを効率的に検索できる。

**画面へのアクセス方法**：Juliaプロンプト画面で入力がある状態で上下矢印キーを押下すると本モードに遷移する。プロンプト自体は元のモード（julia>, help?>, shell>等）のまま維持される。

**主要な操作・処理内容**：
1. ユーザーがプロンプトにテキストを入力した状態で上矢印（前方検索）または下矢印（後方検索）を押下する
2. `enter_prefix_search()` が呼ばれ、現在の入力がプレフィックスとして保存される
3. `history_move_prefix()` が `startswith` ベースの前方一致で履歴を検索する
4. 一致する履歴エントリが見つかると、プロンプトのバッファがその内容で置き換えられる
5. 上下キーの連続押下で次/前の一致エントリに移動する
6. 検索が終了すると元のモードに戻る

**画面遷移**：
- 遷移元：Juliaプロンプト（入力がある状態で上下矢印キー）
- 遷移先：Juliaプロンプト（検索終了時）
- 注：プレフィックス検索中は元のプロンプト表示が維持される

**権限による表示制御**：権限による表示制御は存在しない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 102 | REPL | 主機能 | LineEdit.jlのPrefixHistoryPromptによるプレフィックスベースの履歴検索実装 |
| 30 | 文字列検索・置換 | 主機能 | startswithベースの前方一致による履歴エントリの検索 |
| 37 | ファイルI/O | 補助機能 | 履歴ファイルからの履歴エントリ読み込み |
| 36 | テキスト出力 | 補助機能 | 一致した履歴エントリのプロンプトバッファへの表示 |

## 画面種別

プレフィックス検索（履歴プレフィックスマッチ）

## URL/ルーティング

該当なし（ターミナルベースのCLIアプリケーション）

## 入出力項目

| 項目名 | 入出力 | 型 | 説明 |
|--------|--------|-----|------|
| プレフィックス | 入力 | String | 現在の入力テキスト（検索キーとして使用） |
| 方向 | 入力 | Bool | true: 前方検索（上矢印）、false: 後方検索（下矢印） |
| 一致エントリ | 出力 | String | プレフィックスに一致した履歴エントリのテキスト |

## 表示項目

| 項目名 | 表示内容 | 条件 |
|--------|----------|------|
| プロンプト | 元のモードのプロンプト（julia>, help?>等） | 常に表示（プレフィックス検索はプロンプトを変更しない） |
| 入力バッファ | 一致した履歴エントリのテキスト | 一致エントリが見つかった場合 |
| カーソル位置 | プレフィックスの末尾位置 | 一致エントリが見つかった場合（空プレフィックス時は末尾） |

## イベント仕様

### 1-前方検索（上矢印）

入力がある状態で上矢印キーを押下すると、`enter_prefix_search()` が呼ばれる。現在の入力テキストがプレフィックスとして保存され、`history_prev_prefix()` が `history_move_prefix()` を呼び出して後方（過去方向）に検索する。一致するエントリが見つかると `history_move()` でバッファが更新され、カーソルがプレフィックス位置に留まる。

### 2-後方検索（下矢印）

下矢印キー押下で `history_next_prefix()` が呼び出され、前方（新しい方向）に検索が進む。最新のエントリを超えると、元の入力（in-progress edit）が復元される。

### 3-検索終了

Enter押下またはモード遷移キー押下で検索が終了し、`accept_result()` により現在表示されている内容が入力バッファに確定される。

## データベース更新仕様

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

該当なし（データベースを使用しない）

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| - | 音声 | ビープ音 | 一致するエントリが見つからなかった場合 |

## 例外処理

| 例外 | 発生条件 | 対応 |
|------|----------|------|
| 一致なし | プレフィックスに一致する履歴が存在しない | Terminals.beep()でビープ音を鳴らし、現在の入力を維持 |

## 備考

- `PrefixHistoryPrompt` は `TextInterface` を継承し、`hp`（HistoryProvider）と `parent_prompt`（元のPrompt）を保持する
- `PrefixSearchState` が検索状態（プレフィックス、レスポンスバッファ、親プロンプト）を管理する
- 空プレフィックスの場合は全履歴を順次検索し、カーソルは末尾に移動する
- `history_move()` は異なるモードの履歴エントリも検索対象とし、mode_mappingに基づいてモード遷移が行われる
- `last_buffer` と `last_mode` で現在の編集中バッファが保存・復元される
- `accept_result_newmode()` により、選択した履歴のモードに応じて異なるプロンプトへの遷移が可能

---

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

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

### 推奨読解順序

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

プレフィックス検索の中核データ構造はPrefixHistoryPromptとPrefixSearchStateである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LineEdit.jl | `stdlib/REPL/src/LineEdit.jl` | PrefixHistoryPrompt構造体（2254-2261行）: hp, parent_prompt, complete, keymap_dictフィールド |
| 1-2 | LineEdit.jl | `stdlib/REPL/src/LineEdit.jl` | PrefixSearchState構造体（2263-2276行）: terminal, histprompt, prefix, response_bufferフィールド |

**読解のコツ**: PrefixHistoryPromptはTextInterfaceを継承し、キーマップによりプレフィックス検索固有のキーバインドを提供する。PrefixSearchStateはModeStateを継承し、検索中の状態を保持する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | LineEdit.jl | `stdlib/REPL/src/LineEdit.jl` | enter_prefix_search()関数（2392-2412行）: プレフィックス検索の開始処理 |

**主要処理フロー**:
1. **2393行**: 現在のバッファをコピー
2. **2396-2404行**: transition()で PrefixHistoryPromptに遷移。プレフィックス文字列とバッファを保存
3. **2406-2410行**: backward=trueの場合history_prev_prefix()、falseの場合history_next_prefix()を呼び出し

#### Step 3: 検索ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | REPL.jl | `stdlib/REPL/src/REPL.jl` | history_move_prefix()（1021-1059行）: startswithベースの履歴検索ロジック |
| 3-2 | REPL.jl | `stdlib/REPL/src/REPL.jl` | history_move()（909-951行）: 履歴の実際の移動（バッファ更新、モード遷移） |

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

```
上下矢印キー（入力あり状態）
    |
    +-- enter_prefix_search(s, p, backward)  [2392行]
            |
            +-- transition(s, PrefixHistoryPrompt)
            |       +-- prefix = 現在入力のプレフィックス
            |       +-- response_buffer = 現在のバッファコピー
            |
            +-- history_prev_prefix() / history_next_prefix()
                    |
                    +-- history_move_prefix(s, hist, prefix, backwards)  [1021行]
                            |
                            +-- startswith(entry.content, prefix)  [1038行]
                            +-- history_move(s, hist, idx)  [1039行]
                                    |
                                    +-- LineEdit.transition(s, mode)
                                    +-- LineEdit.replace_line(s, content)
                                    +-- seek(buffer, sizeof(prefix))
```

### データフロー図

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

上下矢印キー     ----> enter_prefix_search()      ----> PrefixSearchState
(入力あり状態)          |
                  プレフィックス保存
                        |
                  history_move_prefix()
                        |
                  startswith() で前方一致検索
                        |
                  history_move()
                        |
                  replace_line()             ----> バッファ更新
                  seek(buffer, prefix位置)   ----> カーソル位置更新
                                              ----> 画面再描画
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| LineEdit.jl | `stdlib/REPL/src/LineEdit.jl` | ソース | PrefixHistoryPrompt, PrefixSearchState, enter_prefix_search() (2254-2412行) |
| REPL.jl | `stdlib/REPL/src/REPL.jl` | ソース | history_move_prefix(), history_move(), REPLHistoryProvider (909-1063行) |
