# 機能設計書 88-履歴管理

## 概要

本ドキュメントは、Nushellの履歴管理機能の設計について記述する。この機能は、ユーザーが入力したコマンドの履歴を保存・検索・管理する機能を提供し、プレーンテキスト形式とSQLite形式の2種類の永続化方式をサポートする。

### 本機能の処理概要

履歴管理機能は、reedlineの履歴システムと連携し、コマンド履歴の永続化、検索、セッション分離などを実現する。historyコマンドによる履歴の表示・クリア、history importによる他シェルからの履歴インポート、SQLite形式での詳細メタデータ（実行時間、終了コード、CWD等）の記録をサポートする。

**業務上の目的・背景**：コマンド履歴は、過去の作業を再現したり、類似のコマンドを素早く再利用したりするために不可欠な機能である。特に複雑なコマンドやパイプラインを再入力する手間を省き、作業効率を大幅に向上させる。SQLite形式ではメタデータも記録され、高度な履歴分析が可能になる。

**機能の利用シーン**：コマンド入力中の履歴検索（Ctrl+R）、historyコマンドによる履歴一覧表示、履歴のクリア、他シェルからの履歴移行など。

**主要な処理内容**：
1. コマンド実行後の履歴エントリ追加
2. 履歴メタデータの記録（SQLite形式の場合）
3. 履歴ファイルへの永続化
4. 履歴検索と候補表示
5. セッション分離（isolation設定時）
6. 履歴同期（sync_on_enter設定時）

**関連システム・外部連携**：reedline履歴システム、SQLite（オプション）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインREPL | 補助機能 | コマンド履歴の保存・検索・同期（SQLite/テキストベース） |

## 機能種別

データ永続化 / 検索機能

## 入力仕様

### 入力パラメータ

#### history コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --clear (-c) | Switch | No | 履歴をクリア | - |
| --long (-l) | Switch | No | 詳細表示（SQLite形式のみ） | - |

### 入力データソース

- 履歴ファイル（~/.config/nushell/history.txt または history.sqlite3）
- reedline履歴システム

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| command | String | コマンド文字列 |
| index | Int | 履歴インデックス（プレーンテキスト） |
| item_id | Int | 履歴ID（SQLite、--long時） |
| start_timestamp | DateTime | 実行開始時刻（SQLite） |
| session_id | Int | セッションID（SQLite、--long時） |
| hostname | String | ホスト名（SQLite、--long時） |
| cwd | String | 実行時ディレクトリ（SQLite） |
| duration | Int | 実行時間（ミリ秒、SQLite） |
| exit_status | Int | 終了コード（SQLite） |

### 出力先

標準出力（テーブル形式）

## 処理フロー

### 処理シーケンス

```
1. 履歴設定の取得
   └─ history_config()からformat/max_size/isolation等を取得
2. 履歴ファイルパスの決定
   └─ file_path()でパスを取得
3. 履歴リーダーの作成
   └─ FileBackedHistory or SqliteBackedHistory
4. 履歴の検索/表示
   └─ SearchQuery::everything()で全件取得
5. 結果のフォーマット
   └─ テーブル形式で出力
```

### フローチャート

```mermaid
flowchart TD
    A[history呼び出し] --> B{--clear指定?}
    B -->|Yes| C[履歴ファイル削除]
    C --> D[空を返却]
    B -->|No| E{フォーマット}
    E -->|Plaintext| F[FileBackedHistory]
    E -->|SQLite| G[SqliteBackedHistory]
    F --> H[SearchQuery実行]
    G --> I{--long指定?}
    I -->|Yes| J[詳細カラム選択]
    I -->|No| K[基本カラム選択]
    J --> L[SQLiteQueryBuilder返却]
    K --> L
    H --> M[結果をテーブル化]
    M --> N[出力]
    L --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-88-01 | フォーマット選択 | Plaintext/SQLiteの2形式をサポート | 設定に応じて |
| BR-88-02 | セッション分離 | isolation設定時はセッションIDで履歴を分離 | history.isolation = true |
| BR-88-03 | 最大サイズ | max_size設定に応じて古い履歴を削除 | 常時 |
| BR-88-04 | 履歴除外 | スペースで始まるコマンドは履歴に残さない | 常時 |
| BR-88-05 | 同期 | sync_on_enter設定時は各コマンド後に同期 | history.sync_on_enter = true |

### 計算ロジック

**duration**: `cmd_execution_start_time.elapsed().as_millis()`
**exit_status**: `$env.LAST_EXIT_CODE`から取得

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

### SQLite形式時

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 履歴追加 | history | INSERT | コマンドとメタデータを挿入 |
| 履歴検索 | history | SELECT | 条件に応じた履歴取得 |
| 履歴クリア | - | DELETE FILE | ファイル自体を削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConfigDirNotFound | 設定エラー | 設定ディレクトリが見つからない | 空を返却 |
| FileNotFound | IOエラー | 履歴ファイルが存在しない | 空の履歴として処理 |
| GenericError | 一般エラー | SQLite非サポートビルド | エラーメッセージ表示 |

### リトライ仕様

該当なし

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

SQLite形式では、reedlineの履歴実装に依存

## パフォーマンス要件

- 履歴検索は即座に完了
- 大量の履歴でもUIがフリーズしないこと

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

- スペースで始まるコマンドは履歴に残さない（機密情報保護）
- 履歴ファイルは適切なパーミッションで保護

## 備考

- SQLite形式はfeature: sqliteが必要
- history importで他シェルからの移行が可能

---

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

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

### 推奨読解順序

#### Step 1: 設定構造を理解する

履歴管理の設定項目を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | config.rs | `crates/nu-protocol/src/config.rs` | HistoryConfig構造体 |

**読解のコツ**: HistoryConfigにはfile_format, max_size, sync_on_enter, isolation等の設定項目がある

#### Step 2: historyコマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | history_.rs | `crates/nu-cli/src/commands/history/history_.rs` | Historyコマンド実装 |

**主要処理フロー**:
1. **14-34行目**: シグネチャ定義
2. **61-82行目**: 履歴クリア処理
3. **88-117行目**: 履歴リーダー作成
4. **118-176行目**: フォーマット別の出力処理

#### Step 3: REPL内での履歴処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | repl.rs | `crates/nu-cli/src/repl.rs` | 履歴関連処理 |

**主要処理フロー**:
- **288-304行目**: get_line_editor内でのsetup_history呼び出し
- **1195-1217行目**: setup_history関数
- **777-799行目**: prepare_history_metadata
- **804-823行目**: fill_in_result_related_history_metadata

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

```
REPLループ
    │
    ├─ setup_history()
    │      │
    │      ├─ FileBackedHistory::with_file()
    │      └─ SqliteBackedHistory::with_file()
    │
    ├─ prepare_history_metadata() [SQLite時]
    │      └─ update_last_command_context()
    │
    └─ fill_in_result_related_history_metadata() [SQLite時]
           └─ update_last_command_context()

historyコマンド
    │
    ├─ engine_state.history_config()
    │
    └─ history_reader.search()
           └─ SearchQuery::everything()
```

### データフロー図

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

コマンド入力 ───▶ reedline ───▶ 履歴追加 ───▶ ファイル永続化
  "ls -la"         履歴追加      metadata設定    history.txt/.sqlite3

historyコマンド ───▶ 履歴読み込み ───▶ テーブル出力
                     SearchQuery       command|index|...
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| history_.rs | `crates/nu-cli/src/commands/history/history_.rs` | ソース | historyコマンド |
| history_import.rs | `crates/nu-cli/src/commands/history/history_import.rs` | ソース | history importコマンド |
| history_session.rs | `crates/nu-cli/src/commands/history/history_session.rs` | ソース | history sessionコマンド |
| fields.rs | `crates/nu-cli/src/commands/history/fields.rs` | ソース | 履歴フィールド定数 |
| mod.rs | `crates/nu-cli/src/commands/history/mod.rs` | ソース | モジュールエクスポート |
| repl.rs | `crates/nu-cli/src/repl.rs` | ソース | REPL内履歴処理 |
