# 機能設計書 84-REPL

## 概要

本ドキュメントは、NushellのREPL（Read-Eval-Print Loop）機能の設計について記述する。REPLは対話型シェル環境の中核であり、ユーザーからの入力を受け取り、評価し、結果を表示するループ処理を提供する。

### 本機能の処理概要

NushellのREPLは、reedlineライブラリを基盤とした対話型シェル環境を提供する。コマンド入力、構文解析、実行、結果表示のサイクルを繰り返し、シェル統合（OSC sequences）、ヒント表示、履歴管理、キーバインディング等の高度な機能を統合している。

**業務上の目的・背景**：シェルの本質的な機能として、ユーザーとの対話的なインターフェースを提供することは不可欠である。REPLはNushellの「顔」であり、ユーザー体験の中心となる。高機能な行編集、豊富なキーバインディング、VSCodeターミナル統合などの現代的な機能を提供することで、開発者の生産性向上に貢献する。

**機能の利用シーン**：シェルの起動から終了まで、常にREPLが動作している。コマンド入力、タブ補完、履歴検索、複数行入力、外部エディタでの編集など、対話的なシェル操作のすべてがREPLを通じて行われる。

**主要な処理内容**：
1. reedlineラインエディタの初期化と設定
2. プロンプト表示とユーザー入力の受け取り
3. 入力のパース（auto-cd検出、コマンド解析）
4. フック処理（pre_prompt, pre_execution, env_change）
5. コマンド実行とエラーハンドリング
6. シェル統合シーケンスの出力（OSC 2/7/9;9/133/633）
7. 履歴メタデータの更新
8. 次のイテレーションへの状態引き継ぎ

**関連システム・外部連携**：reedlineライブラリ、ターミナルエミュレータ（OSC sequences）、VSCode統合

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインREPL | 主機能 | reedlineライブラリを使用した対話型シェル環境の提供 |

## 機能種別

対話処理 / イベントループ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| engine_state | EngineState | Yes | エンジン状態（変更可能） | - |
| stack | Stack | Yes | 実行スタック | - |
| prerun_command | Option<Spanned<String>> | No | 起動時に実行するコマンド | - |
| load_std_lib | Option<Spanned<String>> | No | 標準ライブラリのロード指定 | - |
| entire_start_time | Instant | Yes | 起動時刻 | - |

### 入力データソース

- 標準入力（TTY接続必須）
- EngineState（設定、環境変数、定義済みコマンド）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (標準出力) | - | コマンド実行結果 |
| (シェル統合) | - | OSCエスケープシーケンス |
| (Result) | Result<()> | 成功/エラー |

### 出力先

- 標準出力
- 標準エラー出力
- ターミナル制御シーケンス

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ reedline作成、履歴設定、環境変数設定
2. プロンプト前処理
   └─ pre_promptフック実行、プロンプト更新
3. ラインエディタ設定
   └─ ハイライター、バリデーター、コンプリーター設定
4. ユーザー入力受付
   └─ line_editor.read_line()
5. 入力処理
   └─ auto-cd検出 or コマンド実行
6. 後処理
   └─ OSCシーケンス出力、履歴更新
7. ループ継続
   └─ Ctrl+Dで終了
```

### フローチャート

```mermaid
flowchart TD
    A[evaluate_repl開始] --> B[ラインエディタ初期化]
    B --> C[履歴設定]
    C --> D[メインループ開始]
    D --> E[env_changeフック]
    E --> F[pre_promptフック]
    F --> G[プロンプト更新]
    G --> H[ラインエディタ設定]
    H --> I[read_line]
    I --> J{シグナル種別}
    J -->|Success| K[入力パース]
    J -->|CtrlC| L[プロンプト再表示]
    J -->|CtrlD| M[終了処理]
    K --> N{auto-cd?}
    N -->|Yes| O[ディレクトリ変更]
    N -->|No| P[コマンド実行]
    O --> Q[OSCシーケンス出力]
    P --> Q
    Q --> R[CMD_DURATION_MS設定]
    R --> L
    L --> D
    M --> S[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-84-01 | TTY必須 | 標準入力がTTYでない場合はエラー | REPL起動時 |
| BR-84-02 | auto-cd | パスのみの入力はディレクトリ変更として処理 | パス形式の入力時 |
| BR-84-03 | 空行スキップ | 空文字列は処理しない | 入力が空の場合 |
| BR-84-04 | 履歴スペース除外 | スペースで始まるコマンドは履歴に残さない | 入力がスペース開始時 |
| BR-84-05 | パニック回復 | ループ内パニックから回復してREPL継続 | パニック発生時 |

### 計算ロジック

**CMD_DURATION_MS**: `cmd_execution_start_time.elapsed().as_millis()`

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

該当なし（履歴はファイル/SQLiteで別途管理）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NotFound | IO | 標準入力がTTYでない | TTY付きで起動 |
| ShellError | シェルエラー | コマンド実行時エラー | エラー表示して継続 |
| Io | IO | ディレクトリ変更失敗 | エラー表示して継続 |

### リトライ仕様

パニック発生時はcatch_unwindで捕捉し、ラインエディタを再作成してループ継続

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

該当なし

## パフォーマンス要件

- プロンプト表示は即座に行う
- キー入力応答は体感できない遅延（<100ms）
- 大きな出力のストリーミング表示

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

- スペースで始まるコマンドは履歴に残さない（機密情報保護）
- 環境変数の適切な分離

## 備考

- reedlineライブラリに強く依存
- キーボードプロトコル（kitty protocol）のサポート
- ブラケットペーストの対応

---

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

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

### 推奨読解順序

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

REPLで使用する主要な構造体とコンテキストを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | repl.rs | `crates/nu-cli/src/repl.rs` | LoopContext構造体とReplOperation列挙型 |

**読解のコツ**:
- **306-315行目**: LoopContext構造体でループに必要なコンテキストを保持
- **826-840行目**: ReplOperation列挙型でauto-cd/実行/何もしないを表現

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | repl.rs | `crates/nu-cli/src/repl.rs` | evaluate_repl関数 |

**主要処理フロー**:
1. **70-249行目**: evaluate_repl関数のメイン処理
2. **82-103行目**: 初期化処理（スタック、プロンプト、環境変数）
3. **104-106行目**: ラインエディタ取得
4. **119-149行目**: シェル統合の初期設定
5. **187-246行目**: メインループ（catch_unwindでパニック保護）

#### Step 3: ループイテレーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | repl.rs | `crates/nu-cli/src/repl.rs` | loop_iteration関数 |

**主要処理フロー**:
- **320-772行目**: loop_iteration関数の全体
- **339-371行目**: フック処理（env_change, pre_prompt）
- **394-436行目**: ラインエディタ設定（ハイライター、コンプリーター）
- **500-514行目**: プロンプト更新と入力受付
- **546-758行目**: 入力シグナル処理（Success/CtrlC/CtrlD/Error）
- **633-669行目**: コマンド実行（do_run_cmd呼び出し）

#### Step 4: auto-cdとコマンド実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | repl.rs | `crates/nu-cli/src/repl.rs` | parse_operation, do_auto_cd, do_run_cmd関数 |

**主要処理フロー**:
- **849-877行目**: parse_operation - 入力解析とReplOperation決定
- **882-958行目**: do_auto_cd - ディレクトリ変更処理
- **964-1021行目**: do_run_cmd - コマンド実行

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

```
evaluate_repl()
    │
    ├─ get_line_editor()
    │      └─ Reedline::create() + setup_history()
    │
    └─ loop (catch_unwind)
           │
           └─ loop_iteration(LoopContext)
                  │
                  ├─ hook::eval_env_change_hook()
                  ├─ hook::eval_hooks() [pre_prompt]
                  │
                  ├─ NuHighlighter::new()
                  ├─ NuValidator::new()
                  ├─ NuCompleter::new()
                  │
                  ├─ prompt_update::update_prompt()
                  ├─ line_editor.read_line()
                  │
                  └─ match input
                         ├─ Signal::Success
                         │      ├─ parse_operation()
                         │      │      └─ ReplOperation::{AutoCd, RunCommand, DoNothing}
                         │      ├─ do_auto_cd() / do_run_cmd()
                         │      └─ run_shell_integration_*()
                         ├─ Signal::CtrlC → 継続
                         └─ Signal::CtrlD → cleanup_exit()
```

### データフロー図

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

ユーザー入力 ───▶ read_line() ───▶ parse_operation() ───▶ コマンド結果
  "ls -la"          Signal::Success     RunCommand           テーブル表示
  "../"             Signal::Success     AutoCd               ディレクトリ変更
  Ctrl+C            Signal::CtrlC       -                    プロンプト再表示
  Ctrl+D            Signal::CtrlD       -                    終了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| repl.rs | `crates/nu-cli/src/repl.rs` | ソース | REPLメインループ |
| prompt_update.rs | `crates/nu-cli/src/prompt_update.rs` | ソース | プロンプト更新処理 |
| prompt.rs | `crates/nu-cli/src/prompt.rs` | ソース | NushellPrompt構造体 |
| reedline_config.rs | `crates/nu-cli/src/reedline_config.rs` | ソース | キーバインディング設定 |
| syntax_highlight.rs | `crates/nu-cli/src/syntax_highlight.rs` | ソース | 構文ハイライト |
| completions/completer.rs | `crates/nu-cli/src/completions/completer.rs` | ソース | 補完処理 |
| validation.rs | `crates/nu-cli/src/validation.rs` | ソース | 入力バリデーション |
| util.rs | `crates/nu-cli/src/util.rs` | ソース | eval_sourceなどのユーティリティ |
