# 機能設計書 78-which-key

## 概要

本ドキュメントは、space-vimの+vim/which-keyレイヤーが提供するキーバインディングヒント表示機能について、その設計と実装を詳細に記述する。

### 本機能の処理概要

**業務上の目的・背景**：
space-vimは多数のキーバインディングを提供するが、全てを記憶することは困難である。which-keyは、プレフィックスキー（SPC、,など）を押下した後に、利用可能なキーバインディングをポップアップウィンドウで表示する。これにより、ユーザーは次に押すべきキーを視覚的に確認でき、学習コストの低減と操作効率の向上が実現される。spacemacsの同名機能を模倣した、space-vimの中核的なUI機能である。

**機能の利用シーン**：
- SPCキーを押した後に、利用可能なコマンド一覧を確認したい場合
- ローカルリーダー（,）を押した後に、言語固有のコマンドを確認したい場合
- 新しいキーバインディングを学習する際のガイドとして
- 忘れたキーバインディングを思い出す際のヘルプとして

**主要な処理内容**：
1. vim-which-keyプラグインの遅延読み込み（WhichKeyコマンド実行時）
2. LeaderキーとLocalLeaderキーへのマッピング設定
3. キーバインディング辞書（leader_map）の登録
4. ポップアップウィンドウでのキー説明表示

**関連システム・外部連携**：
- 外部プラグイン: liuchengxu/vim-which-key
- core/autoload/spacevim/map/leader.vim（キーバインディング定義）
- 全レイヤーのキーバインディングとの連携

**権限による制御**：
本機能に権限による制御は存在しない。+vim/which-keyレイヤーを有効化することで全ユーザーが利用可能となる（デフォルトレイヤー）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Which-Key（キーバインド表示画面） | 主機能 | SPCキー押下後のキーバインドヒント表示 |

## 機能種別

UI/UX機能 / キーバインディングヘルプ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| プレフィックスキー | Char | Yes | SPCまたは,（ローカルリーダー） | 設定されたリーダーキー |

### 入力データソース

- ユーザーのキーボード入力（SPCキーまたは,キー）
- g:spacevim#map#leader#desc（Leaderキーバインディング辞書）
- g:spacevim#map#localleader#desc（LocalLeaderキーバインディング辞書）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ポップアップウィンドウ | UI Window | キーバインディング一覧とその説明 |

### 出力先

- Vimのポップアップウィンドウ（画面下部に表示）

## 処理フロー

### 処理シーケンス

```
1. ユーザーがSPC（または,）を押下
   └─ config.vimで定義されたマッピングがトリガー
2. WhichKeyコマンドが実行される
   └─ 初回は遅延読み込みでプラグインがロードされる
3. which_key#Init()が呼び出される
   └─ キーバインディング辞書を登録
4. ポップアップウィンドウが表示される
   └─ 利用可能なキーと説明の一覧
5. ユーザーが次のキーを押下
   └─ 対応するコマンドが実行される、またはサブメニューが表示される
```

### フローチャート

```mermaid
flowchart TD
    A[SPC/,キー押下] --> B{初回実行?}
    B -->|Yes| C[vim-which-keyロード]
    B -->|No| D[WhichKeyコマンド実行]
    C --> E[which_key#Init呼び出し]
    E --> F[キーバインディング辞書登録]
    F --> D
    D --> G[ポップアップ表示]
    G --> H[次のキー入力待ち]
    H --> I{キー種別}
    I -->|コマンド| J[コマンド実行]
    I -->|サブメニュー| K[サブメニュー表示]
    I -->|Esc| L[キャンセル]
    K --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-78-1 | 遅延読み込み | WhichKeyコマンド実行時にプラグインをロード | 初回SPC/,押下時 |
| BR-78-2 | 辞書登録 | LeaderとLocalLeader用の辞書を分離して登録 | プラグインロード時 |
| BR-78-3 | モード対応 | ノーマルモードとビジュアルモードで異なる辞書を使用可能 | 常時 |

### 計算ロジック

本機能に独自の計算ロジックは存在しない（vim-which-keyプラグインに委譲）。

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

本機能にデータベース操作は存在しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 辞書未登録 | キーバインディング辞書が存在しない | leader.vimの読み込みを確認 |
| - | キャンセル | ユーザーがEscでキャンセル | 正常終了として扱う |

### リトライ仕様

本機能にリトライ処理は存在しない。

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

本機能にトランザクション処理は存在しない。

## パフォーマンス要件

- 遅延読み込みにより起動時間への影響を最小化
- ポップアップ表示は即座に行われる

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

本機能は表示のみであり、セキュリティ上の考慮事項は特になし。

## 備考

- vim-which-keyはliuchengxu氏が開発・メンテナンスしている外部プラグイン
- spacemacsのwhich-key機能を模倣
- space-vimのデフォルトレイヤーとして含まれる

---

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

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

### 推奨読解順序

#### Step 1: パッケージ定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | packages.vim | `layers/+vim/which-key/packages.vim` | プラグイン登録と遅延読み込み条件 |

**読解のコツ**: `{ 'on': ['WhichKey', 'WhichKey!', 'WhichKeyVisual', 'WhichKeyVisual!'] }`で複数のコマンドによる遅延読み込みを設定。autocmdでプラグインロード後に初期化関数を呼び出す。

**主要処理フロー**:
- **1行目**: `MP 'liuchengxu/vim-which-key', { 'on': [...] }` - 遅延読み込み設定
- **2行目**: `autocmd! User vim-which-key call spacevim#autocmd#which_key#Init()` - 初期化関数の自動呼び出し

#### Step 2: キーバインディング設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | config.vim | `layers/+vim/which-key/config.vim` | Leader/LocalLeaderへのマッピング |

**読解のコツ**: `nnoremap`でノーマルモード、`vnoremap`でビジュアルモードのマッピングを定義。WhichKeyとWhichKeyVisualを使い分ける。

**主要処理フロー**:
- **1行目**: `nnoremap <silent> <leader> :<c-u>WhichKey '<Space>'<CR>` - SPCキーでWhichKey起動（ノーマル）
- **2行目**: `vnoremap <silent> <leader> :<c-u>WhichKeyVisual '<Space>'<CR>` - SPCキーでWhichKey起動（ビジュアル）
- **4行目**: `nnoremap <silent> <localleader> :<c-u>WhichKey ','<CR>` - ,キーでWhichKey起動（ノーマル）
- **5行目**: `vnoremap <silent> <localleader> :<c-u>WhichKeyVisual ','<CR>` - ,キーでWhichKey起動（ビジュアル）

#### Step 3: 初期化関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | which_key.vim | `core/autoload/spacevim/autocmd/which_key.vim` | 辞書登録処理 |

**読解のコツ**: `which_key#register`関数でプレフィックスキーと辞書、モードを関連付ける。

**主要処理フロー**:
- **2行目**: `which_key#register('<Space>', 'g:spacevim#map#leader#desc', 'n')` - Leaderノーマル用
- **3行目**: `which_key#register(',', 'g:spacevim#map#localleader#desc', 'n')` - LocalLeaderノーマル用
- **4行目**: `which_key#register('<Space>', 'g:spacevim#map#leader#desc_visual', 'v')` - Leaderビジュアル用
- **5行目**: `which_key#register(',', 'g:spacevim#map#localleader#desc_visual', 'v')` - LocalLeaderビジュアル用

#### Step 4: キーバインディング辞書を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | leader.vim | `core/autoload/spacevim/map/leader.vim` | キーバインディング定義 |

**読解のコツ**: `s:leader_map`辞書でキーバインディングの階層構造を定義。`'name'`キーでサブメニューの名前を指定。

**主要処理フロー**:
- **2-3行目**: ルート辞書の定義
- **5-8行目**: 数字キー（ウィンドウ移動）の定義
- **12-24行目**: タブ操作（SPC SPC）の定義
- **30-50行目**: バッファ操作（SPC b）の定義
- **93-106行目**: Git操作（SPC g）の定義
- **181-201行目**: ウィンドウ操作（SPC w）の定義

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

```
~/.spacevim（ユーザー設定）
    │
    └─ Layer('+vim/which-key')
           │
           ├─ packages.vim
           │      ├─ MP 'liuchengxu/vim-which-key'（遅延ロード）
           │      └─ autocmd User vim-which-key → which_key#Init()
           │
           └─ config.vim
                  ├─ <leader> → WhichKey '<Space>'
                  └─ <localleader> → WhichKey ','

core/autoload/spacevim/autocmd/which_key.vim
    │
    └─ spacevim#autocmd#which_key#Init()
           ├─ which_key#register('<Space>', leader#desc, 'n')
           ├─ which_key#register(',', localleader#desc, 'n')
           ├─ which_key#register('<Space>', leader#desc_visual, 'v')
           └─ which_key#register(',', localleader#desc_visual, 'v')

core/autoload/spacevim/map/leader.vim
    │
    └─ g:spacevim#map#leader#desc（辞書定義）
           ├─ 'b' → バッファ操作
           ├─ 'f' → ファイル操作
           ├─ 'g' → Git操作
           ├─ 'w' → ウィンドウ操作
           └─ ...
```

### データフロー図

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

SPCキー押下        ───▶  WhichKeyコマンド        ───▶  ポップアップ表示
                                ↓
                         辞書から候補取得
                               ↓
次のキー入力        ───▶  コマンド/サブメニュー  ───▶  実行/再表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| packages.vim | `layers/+vim/which-key/packages.vim` | ソース | プラグイン登録と遅延読み込み設定 |
| config.vim | `layers/+vim/which-key/config.vim` | ソース | キーマッピング定義 |
| which_key.vim | `core/autoload/spacevim/autocmd/which_key.vim` | ソース | 初期化と辞書登録 |
| leader.vim | `core/autoload/spacevim/map/leader.vim` | ソース | Leaderキーバインディング辞書 |
| README.md | `layers/+vim/which-key/README.md` | ドキュメント | レイヤー説明 |
