# 機能設計書 42-キーバインド設定

## 概要

本ドキュメントは、Oh My Zshのキーバインド設定機能について、その設計と実装の詳細を記載したものである。この機能は、ZSHのZLE（Zsh Line Editor）に対してemacs風のキーバインドを基本とし、各種ナビゲーションキー、編集キー、履歴検索キーを設定する。

### 本機能の処理概要

この機能は、ZSHのコマンドライン編集において、直感的で効率的なキー操作を可能にする設定を行う。ターミナルのアプリケーションモードを適切に管理し、PageUp/Down、Home/End、矢印キー、Ctrl+矢印キーなど、一般的なキーボード操作をZSHで利用可能にする。

**業務上の目的・背景**：コマンドライン作業の効率化において、キーバインドは極めて重要な役割を果たす。デフォルトのZSH設定では、多くのターミナルで期待される動作（Home/Endでの行頭/行末移動、Ctrl+矢印での単語移動など）が設定されていない。本機能により、一般的なテキストエディタと同様の操作感をZSHで実現し、ユーザーの学習コストを削減する。

**機能の利用シーン**：
- コマンドライン編集中のカーソル移動操作
- 履歴からのコマンド検索・選択操作
- 長いコマンドラインの効率的な編集作業
- 補完候補の選択操作

**主要な処理内容**：
1. ターミナルアプリケーションモードの管理（zle-line-init/finish）
2. emacs風キーバインドの基本設定（bindkey -e）
3. PageUp/PageDownキーの履歴ナビゲーション設定
4. 上下矢印キーの履歴検索機能設定
5. Home/Endキーの行頭/行末移動設定
6. Shift-Tabによる補完メニュー逆順移動設定
7. Backspace/Deleteキーの削除操作設定
8. Ctrl+矢印キーの単語移動設定
9. edit-command-lineの設定（Ctrl+X Ctrl+E）

**関連システム・外部連携**：
- ターミナルエミュレータのterminfo情報を使用
- $VISUAL/$EDITOR環境変数と連携（edit-command-line機能）

**権限による制御**：特になし。全ユーザーに同一の設定が適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は画面を持たず、シェル初期化時に自動適用される |

## 機能種別

設定処理 / キーバインド設定 / ZLE設定

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| terminfo[smkx] | terminfo値 | No | アプリケーションモード開始シーケンス | 存在確認のみ |
| terminfo[rmkx] | terminfo値 | No | アプリケーションモード終了シーケンス | 存在確認のみ |
| terminfo[kpp] | terminfo値 | No | PageUpキーシーケンス | 存在確認のみ |
| terminfo[knp] | terminfo値 | No | PageDownキーシーケンス | 存在確認のみ |
| terminfo[kcuu1] | terminfo値 | No | 上矢印キーシーケンス | 存在確認のみ |
| terminfo[kcud1] | terminfo値 | No | 下矢印キーシーケンス | 存在確認のみ |
| terminfo[khome] | terminfo値 | No | Homeキーシーケンス | 存在確認のみ |
| terminfo[kend] | terminfo値 | No | Endキーシーケンス | 存在確認のみ |
| terminfo[kcbt] | terminfo値 | No | Shift-Tabキーシーケンス | 存在確認のみ |
| terminfo[kdch1] | terminfo値 | No | Deleteキーシーケンス | 存在確認のみ |

### 入力データソース

- ターミナルのterminfo情報
- ZSHの$terminfo連想配列

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| キーバインド設定 | ZLEウィジェット | 各キーに対応する機能のバインド |
| zle-line-init | ZLEウィジェット | 行編集開始時のフック関数 |
| zle-line-finish | ZLEウィジェット | 行編集終了時のフック関数 |

### 出力先

- ZLE（Zsh Line Editor）のキーマップ
- emacs、viins、vicmdの3つのキーマップ

## 処理フロー

### 処理シーケンス

```
1. アプリケーションモード設定
   └─ terminfo[smkx]/[rmkx]が存在する場合のみ設定

2. emacsキーバインドを基本として設定
   └─ bindkey -e

3. PageUp/PageDownの履歴ナビゲーション設定
   └─ up-line-or-history / down-line-or-history

4. 上下矢印キーの履歴検索設定
   └─ up-line-or-beginning-search / down-line-or-beginning-search

5. Home/Endの行頭/行末移動設定
   └─ beginning-of-line / end-of-line

6. 編集キーの設定
   └─ Backspace、Delete、Ctrl+Delete、Ctrl+矢印など

7. その他のキーバインド設定
   └─ Esc-w、Esc-l、Ctrl-r、Space、Ctrl-X Ctrl-E、Esc-m
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{terminfo smkx/rmkx存在?}
    B -->|Yes| C[アプリケーションモード設定]
    B -->|No| D[bindkey -e emacs基本設定]
    C --> D
    D --> E{terminfo kpp/knp存在?}
    E -->|Yes| F[PageUp/Down設定]
    E -->|No| G[上下矢印設定]
    F --> G
    G --> H{terminfo khome/kend存在?}
    H -->|Yes| I[Home/End設定]
    H -->|No| J[Shift-Tab設定]
    I --> J
    J --> K[編集キー設定]
    K --> L[その他キーバインド設定]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-1 | terminfo条件付き設定 | terminfoにキー情報がある場合のみバインドを設定 | 各terminfo値の存在時 |
| BR-42-2 | マルチモード設定 | emacs、viins、vicmdの3モードすべてに設定 | 常時 |
| BR-42-3 | フォールバックシーケンス | terminfoにない場合は一般的なエスケープシーケンスを使用 | terminfo未定義時 |
| BR-42-4 | アプリケーションモード管理 | ZLE開始時にsmkx、終了時にrmkxを送信 | terminfo存在時 |

### 計算ロジック

特になし

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

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

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

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | terminfo未定義 | エラーなし、該当キー設定をスキップ |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- シェル起動時に即座に実行される軽量な処理
- 処理時間：1ms未満

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

- edit-command-line機能は$VISUAL/$EDITORを実行するため、信頼できるエディタを設定すること

## 備考

- terminfo値はターミナルエミュレータによって異なるため、互換性のためにフォールバック値を使用
- viモードユーザーにも対応するため、viins/vicmdモードにも設定を適用

---

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

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

### 推奨読解順序

#### Step 1: アプリケーションモード管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | key-bindings.zsh | `lib/key-bindings.zsh` | 1-16行目のアプリケーションモード設定 |

**主要処理フロー**:
1. **7行目**: `if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} ))` - terminfo存在チェック
2. **8-9行目**: `zle-line-init()` - 行編集開始時にアプリケーションモード開始
3. **11-13行目**: `zle-line-finish()` - 行編集終了時にアプリケーションモード終了
4. **14-15行目**: `zle -N` - ZLEウィジェットとして登録

**読解のコツ**: `echoti`はterminfoのキーシーケンスを出力するZSHビルトイン。`zle -N`でカスタム関数をZLEウィジェットとして登録する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | key-bindings.zsh | `lib/key-bindings.zsh` | 18-32行目のemacs基本設定とPageUp/Down |

**主要処理フロー**:
- **19行目**: `bindkey -e` - emacsキーマップを基本として使用
- **22-26行目**: PageUpキーの設定（3モードすべて）
- **28-32行目**: PageDownキーの設定（3モードすべて）

#### Step 3: 履歴検索キーバインドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | key-bindings.zsh | `lib/key-bindings.zsh` | 34-58行目の上下矢印キー設定 |

**主要処理フロー**:
- **35-36行目**: `autoload -U up-line-or-beginning-search` - 関数の遅延読み込みとZLE登録
- **38-45行目**: 上矢印キーのバインド（ANSIとterminfo両方）
- **47-58行目**: 下矢印キーの同様の設定

#### Step 4: ナビゲーション・編集キーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | key-bindings.zsh | `lib/key-bindings.zsh` | 60-127行目 |

**主要処理フロー**:
- **61-71行目**: Home/Endキー設定
- **73-78行目**: Shift-Tab設定
- **80-97行目**: Backspace/Delete設定
- **99-111行目**: Ctrl+Delete/Ctrl+矢印設定
- **120-123行目**: edit-command-line設定

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

```
oh-my-zsh.sh
    │
    └─ source lib/key-bindings.zsh
           │
           ├─ zle-line-init / zle-line-finish（ZLEフック）
           │
           ├─ autoload -U up-line-or-beginning-search
           │      └─ ZSHビルトイン関数の遅延読み込み
           │
           ├─ autoload -U down-line-or-beginning-search
           │      └─ ZSHビルトイン関数の遅延読み込み
           │
           ├─ autoload -U edit-command-line
           │      └─ ZSHビルトイン関数の遅延読み込み
           │
           └─ bindkey（複数回呼び出し）
                  └─ キーマップへのバインド設定
```

### データフロー図

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

$terminfo連想配列           lib/key-bindings.zsh          ZLEキーマップ
・smkx/rmkx     ───────▶  条件分岐処理  ───────▶      ・emacsマップ
・kpp/knp                  キーシーケンス判定              ・viinsマップ
・kcuu1/kcud1              bindkey呼び出し                 ・vicmdマップ
・khome/kend
・kcbt/kdch1

                                                     ZLEウィジェット
                        zle -N     ───────▶      ・zle-line-init
                                                  ・zle-line-finish
                                                  ・up-line-or-beginning-search
                                                  ・down-line-or-beginning-search
                                                  ・edit-command-line
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| key-bindings.zsh | `lib/key-bindings.zsh` | ソース | キーバインド設定の本体（146行） |
| oh-my-zsh.sh | `oh-my-zsh.sh` | ソース | OMZ初期化時にkey-bindings.zshを読み込む |
