# 機能設計書 45-edit-command-line

## 概要

本ドキュメントは、Oh My Zshのedit-command-line機能について、その設計と実装の詳細を記載したものである。この機能は、Ctrl+X Ctrl+Eのキーバインドで、現在のコマンドラインを外部エディタ（$VISUAL、$EDITOR、またはvi）で編集できるようにする。

### 本機能の処理概要

この機能は、ZSHのZLE（Zsh Line Editor）ウィジェットとして実装され、複雑なコマンドや複数行のコマンドを外部エディタで編集できる機能を提供する。コマンドラインでの入力に限界がある長いコマンドや、複雑な構文を含むコマンドを、使い慣れたエディタで快適に編集できる。

**業務上の目的・背景**：コマンドライン上での長いコマンドの編集は困難を伴うことがある。特に、複数行にわたるスクリプトや、複雑なパイプライン、ヒアドキュメントを含むコマンドなどは、コマンドライン上で直接編集するより、フル機能のテキストエディタで編集した方が効率的である。本機能により、ユーザーは馴染みのあるエディタを使用してコマンドを編集できる。

**機能の利用シーン**：
- 長く複雑なコマンドを入力する場面
- 複数行のコマンドやスクリプトを編集する場面
- 構文エラーを含むコマンドを修正したい場面
- パイプラインや条件分岐を含む複雑なワンライナーを作成する場面
- 既存の履歴コマンドを大幅に修正したい場面

**主要な処理内容**：
1. Ctrl+X Ctrl+Eのキー入力を検出
2. 現在のコマンドラインバッファを一時ファイルに保存
3. $VISUAL、$EDITOR、または vi でその一時ファイルを開く
4. エディタ終了後、編集内容をコマンドラインバッファに読み込む
5. 一時ファイルを削除

**関連システム・外部連携**：
- 環境変数 $VISUAL（優先）
- 環境変数 $EDITOR
- デフォルトエディタ vi
- 一時ファイルシステム

**権限による制御**：特になし。全ユーザーが利用可能（ただし、エディタへのアクセス権が必要）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は外部エディタを起動し、画面はエディタに依存 |

## 機能種別

外部連携処理 / ZLEウィジェット / エディタ連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| BUFFER | ZLE変数 | Yes | 現在のコマンドラインバッファ | なし |
| VISUAL | 環境変数 | No | 優先エディタコマンド | 存在確認 |
| EDITOR | 環境変数 | No | フォールバックエディタコマンド | 存在確認 |

### 入力データソース

- ZLEのコマンドラインバッファ
- 環境変数 $VISUAL、$EDITOR

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| BUFFER | ZLE変数 | エディタで編集後のコマンド内容 |
| CURSOR | ZLE変数 | 更新されたカーソル位置（行末） |

### 出力先

- ZLEコマンドラインバッファ（画面上のコマンドライン）

## 処理フロー

### 処理シーケンス

```
1. キー入力の検出
   └─ Ctrl+X Ctrl+E (\C-x\C-e) の入力を検出

2. 一時ファイルの作成
   └─ コマンドラインバッファを一時ファイルに書き出し

3. エディタの選択と起動
   └─ $VISUAL > $EDITOR > vi の優先順位でエディタを決定
   └─ 選択したエディタで一時ファイルを開く

4. 編集完了を待機
   └─ エディタの終了を待つ

5. 編集結果の読み込み
   └─ 一時ファイルの内容をバッファに読み込み

6. クリーンアップ
   └─ 一時ファイルを削除
```

### フローチャート

```mermaid
flowchart TD
    A[Ctrl+X Ctrl+E押下] --> B[バッファを一時ファイルに保存]
    B --> C{$VISUALが設定?}
    C -->|Yes| D[$VISUALでファイルを開く]
    C -->|No| E{$EDITORが設定?}
    E -->|Yes| F[$EDITORでファイルを開く]
    E -->|No| G[viでファイルを開く]
    D --> H[エディタ終了を待機]
    F --> H
    G --> H
    H --> I[編集結果をバッファに読み込み]
    I --> J[一時ファイルを削除]
    J --> K[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-45-1 | エディタ優先順位 | $VISUAL > $EDITOR > vi の順でエディタを選択 | 常時 |
| BR-45-2 | 編集反映 | エディタを正常終了した場合のみ編集結果を反映 | エディタ正常終了時 |
| BR-45-3 | 一時ファイル管理 | 編集完了後に一時ファイルを削除 | 常時 |
| BR-45-4 | 複数行対応 | 複数行のコマンドも編集可能 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | 本機能はデータベースを使用しない |

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | エディタ異常終了 | エディタが非0で終了 | 編集結果を反映しない |
| - | エディタ未発見 | 指定エディタが存在しない | デフォルトviを使用 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- キー入力後、即座にエディタを起動
- エディタ終了後、即座に編集結果を反映

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

- エディタとして任意のコマンドが実行されるため、$VISUAL/$EDITORには信頼できるエディタを設定すること
- 一時ファイルには適切なパーミッションを設定

## 備考

- Bashの同様の機能（Ctrl+X Ctrl+E）と互換性がある
- edit-command-lineはZSHビルトインの関数で、autoloadで遅延読み込みされる

---

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

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

### 推奨読解順序

#### Step 1: キーバインド設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | key-bindings.zsh | `lib/key-bindings.zsh` | 120-123行目のedit-command-line設定 |

**主要処理フロー**:
1. **120行目**: コメント - `Edit the current command line in $VISUAL (or $EDITOR / 'vi' if not set)`
2. **121行目**: `autoload -U edit-command-line` - ZSHビルトイン関数の遅延読み込み
3. **122行目**: `zle -N edit-command-line` - ZLEウィジェットとして登録
4. **123行目**: `bindkey '\C-x\C-e' edit-command-line` - Ctrl+X Ctrl+Eにバインド

**読解のコツ**:
- `\C-x\C-e`はCtrl+X Ctrl+Eのキーシーケンス
- この機能はemacsキーマップにのみバインドされている（emacs風のキーバインドのため）

#### Step 2: 関数の動作原理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ZSH内部 | ZSHビルトイン | edit-command-lineはZSHビルトインウィジェット |

**読解のコツ**:
- edit-command-lineはZSH標準のZLEウィジェット
- 動作は以下の通り：
  1. $BUFFERを一時ファイルに書き出し
  2. ${VISUAL:-${EDITOR:-vi}}でエディタを決定
  3. エディタで一時ファイルを編集
  4. 編集結果を$BUFFERに読み込み

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

```
lib/key-bindings.zsh
    │
    ├─ autoload -U edit-command-line
    │      └─ ZSH/share/zsh/functions/Zle/edit-command-line
    │
    └─ zle -N edit-command-line
           │
           └─ ZLEウィジェット登録
                  │
                  └─ bindkey '\C-x\C-e' でバインド
                         │
                         └─ Ctrl+X Ctrl+E 押下時
                                │
                                ├─ 一時ファイル作成
                                │
                                ├─ エディタ起動
                                │    │
                                │    └─ $VISUAL / $EDITOR / vi
                                │
                                └─ 編集結果読み込み
```

### データフロー図

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

Ctrl+X Ctrl+E               edit-command-line             コマンドライン更新
     │                            │                            │
     ▼                            ▼                            ▼
BUFFER ───────────────▶  一時ファイルに保存 ───▶  エディタで編集
                                  │
                                  ▼
$VISUAL / $EDITOR / vi ──▶  エディタ起動
                                  │
                                  ▼
編集結果 ───────────────▶  BUFFERに読み込み ───▶  コマンドライン表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| key-bindings.zsh | `lib/key-bindings.zsh` | ソース | キーバインド設定とautoload |
| edit-command-line | ZSHビルトイン | ZSH関数 | 実際のエディタ連携処理を実行 |
