# 機能設計書 73-EasyMotion

## 概要

本ドキュメントは、space-vimの+vim/better-motionレイヤーが提供するEasyMotion機能について、その設計と実装を詳細に記述する。

### 本機能の処理概要

**業務上の目的・背景**：
Vimの標準的なモーション（w、b、f、/等）は効率的だが、目的位置への到達に複数のキーストロークや正確な文字数のカウントが必要となる場合がある。EasyMotionは、画面上の移動可能な位置にラベルを表示し、ユーザーが視覚的に目的地を選択できるようにする。これにより、カーソル移動の効率が大幅に向上し、特に長いファイルや複雑なコード構造でのナビゲーションが容易になる。

**機能の利用シーン**：
- 画面内の特定の単語・文字に素早くジャンプしたい場合
- 複数ウィンドウをまたいでカーソルを移動したい場合
- 行単位で素早く移動したい場合
- 特定の文字を含む位置を視覚的に選択してジャンプしたい場合

**主要な処理内容**：
1. vim-easymotionプラグインの遅延読み込み（タイマーによる600ms後のロード）
2. リーダーキー（SPC j）によるジャンプ操作のマッピング定義
3. 文字、単語、行単位でのジャンプ位置ラベル表示
4. ウィンドウをまたいだジャンプ（overwin系）のサポート

**関連システム・外部連携**：
- 外部プラグイン: easymotion/vim-easymotion（コアEasyMotion機能）
- 外部プラグイン: haya14busa/incsearch-easymotion.vim（検索との統合）
- vim-which-keyとの連携（キーバインディングヒント表示）

**権限による制御**：
本機能に権限による制御は存在しない。+vim/better-motionレイヤーを有効化することで全ユーザーが利用可能となる。

## 関連画面

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

## 機能種別

エディタ補助機能 / カーソル移動

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ジャンプ種別 | String | Yes | jj(文字)/jJ(2文字)/jl(行)/jw(単語)/jf(前方)/jb(後方) | 有効なキーシーケンス |
| 対象文字 | Char | Conditional | ジャンプ先の文字（jj/jJ使用時） | 任意の1文字または2文字 |

### 入力データソース

- ユーザーのキーボード入力（SPC j + サブコマンド）
- 現在のバッファ内容（ジャンプ候補の抽出用）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ジャンプラベル | Visual | 画面上のジャンプ可能位置に表示される文字ラベル |
| カーソル位置 | Number | ジャンプ後のカーソル行・列 |

### 出力先

- Vimエディタのバッファ画面（ジャンプラベルのオーバーレイ表示）
- カーソル位置（ジャンプ実行後）

## 処理フロー

### 処理シーケンス

```
1. ユーザーがSPC jを押下
   └─ vim-which-keyがサブコマンド一覧を表示
2. サブコマンド（j/J/l/w/f/b）を押下
   └─ 対応するEasyMotionプラグマッピングを実行
3. EasyMotionがジャンプ候補を計算
   └─ 画面内の対象位置を走査
4. ジャンプラベルを表示
   └─ 各候補位置にアルファベットラベルをオーバーレイ
5. ユーザーがラベル文字を入力
   └─ 対応する位置にカーソルをジャンプ
```

### フローチャート

```mermaid
flowchart TD
    A[SPC j 押下] --> B[Which-Keyがサブコマンド表示]
    B --> C{サブコマンド選択}
    C -->|jj| D[1文字入力待ち]
    C -->|jJ| E[2文字入力待ち]
    C -->|jl| F[行ジャンプモード]
    C -->|jw| G[単語ジャンプモード]
    D --> H[対象文字を含む位置を検索]
    E --> H
    F --> I[各行にラベル表示]
    G --> J[各単語先頭にラベル表示]
    H --> K[対象位置にラベル表示]
    I --> L[ラベル文字入力待ち]
    J --> L
    K --> L
    L --> M[選択位置にジャンプ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-73-1 | 遅延読み込み | 起動時間短縮のため600ms後にロード | speed_up_via_timer有効時 |
| BR-73-2 | プレフィックス | Leader+Leaderをeasymotionプレフィックスに設定 | 常時 |
| BR-73-3 | overwin | ウィンドウをまたいだジャンプをサポート | ノーマルモード時 |

### 計算ロジック

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ジャンプ先なし | 指定文字がバッファ内に存在しない | 別の文字を指定 |
| - | Escキャンセル | ユーザーがEscでジャンプをキャンセル | 正常終了として扱う |

### リトライ仕様

本機能にリトライ処理は存在しない。ジャンプキャンセル後は再度コマンドを実行する。

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

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

## パフォーマンス要件

- 遅延読み込みにより起動時間への影響を最小化（600ms後にバックグラウンドロード）
- ジャンプラベル表示は即座に行われる（体感的に遅延なし）

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

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

## 備考

- vim-easymotionはeasymotion組織が開発・メンテナンスしている外部プラグイン
- spacemacsのSPC jキーバインディングと互換性を持つよう設計されている

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: `g:spacevim.speed_up_via_timer`変数によって遅延読み込みの方式が切り替わる。タイマー有効時は600msで`spacevim#defer#motion`関数を呼び出す。

**主要処理フロー**:
- **1行目**: `MP 'unblevable/quick-scope'` - quick-scopeプラグイン（即時ロード）
- **3-7行目**: タイマーによる遅延読み込み設定（vim-sneak、vim-easymotion、incsearch-easymotion.vim）
- **8-21行目**: 通常ロード設定（タイマー無効時）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | config.vim | `layers/+vim/better-motion/config.vim` | EasyMotionのキーマッピング定義 |

**読解のコツ**: `<Plug>(easymotion-xxx)`はEasyMotionが提供するプラグマッピング。これをLeaderキーと組み合わせてマッピングしている。

**主要処理フロー**:
- **10行目**: `map <Leader><Leader> <Plug>(easymotion-prefix)` - Leader2回をプレフィックスに設定
- **14-15行目**: `<Leader>jj` - 1文字ジャンプ（bd-f、overwin-f）
- **18行目**: `<Leader>jJ` - 2文字ジャンプ（overwin-f2）
- **21-22行目**: `<Leader>jl` - 行ジャンプ（bd-jk、overwin-line）
- **25-26行目**: `<Leader>jw` - 単語ジャンプ（bd-w、overwin-w）
- **28-29行目**: `<Leader>jf/jb` - 前方/後方ワードジャンプ

#### Step 3: 遅延読み込み関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | defer.vim | `core/autoload/spacevim/defer.vim` | 遅延読み込みの実装 |

**読解のコツ**: `spacevim#defer#motion`関数は複数のモーション関連プラグインをまとめてロードする。

**主要処理フロー**:
- **41-43行目**: `spacevim#defer#motion`関数 - vim-sneak、vim-easymotion、incsearch-easymotion.vimをロード

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

```
~/.spacevim（ユーザー設定）
    │
    └─ Layer('+vim/better-motion')
           │
           ├─ packages.vim
           │      ├─ MP 'unblevable/quick-scope'（即時ロード）
           │      ├─ MP 'justinmk/vim-sneak'（遅延/通常）
           │      ├─ MP 'easymotion/vim-easymotion'（遅延/通常）
           │      └─ timer_start(600, 'spacevim#defer#motion')
           │
           └─ config.vim
                  ├─ <Leader><Leader> → EasyMotionプレフィックス
                  ├─ <Leader>jj → 1文字ジャンプ
                  ├─ <Leader>jJ → 2文字ジャンプ
                  ├─ <Leader>jl → 行ジャンプ
                  └─ <Leader>jw → 単語ジャンプ
```

### データフロー図

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

SPC j j + {char}   ───▶  EasyMotion検索        ───▶  ラベル表示
                                ↓
ラベル文字入力      ───▶  位置計算              ───▶  カーソルジャンプ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| packages.vim | `layers/+vim/better-motion/packages.vim` | ソース | プラグイン登録と遅延読み込み設定 |
| config.vim | `layers/+vim/better-motion/config.vim` | ソース | キーマッピング定義 |
| defer.vim | `core/autoload/spacevim/defer.vim` | ソース | 遅延読み込み実装 |
| leader.vim | `core/autoload/spacevim/map/leader.vim` | ソース | Leaderキーマッピングの説明定義 |
