# 機能設計書 6-Vim/NeoVim自動検出

## 概要

本ドキュメントは、space-vimのVim/NeoVim自動検出機能の設計について記述する。この機能は、インストール時にシステムにインストールされているVimまたはNeoVimを自動検出し、適切なインストール先を決定する。

### 本機能の処理概要

Vim/NeoVim自動検出機能は、インストールスクリプト実行時にユーザーのシステム環境を調査し、利用可能なエディタを検出する。両方がインストールされている場合はユーザーに選択肢を提示し、片方のみの場合は自動的にそのエディタ用にspace-vimを設定する。

**業務上の目的・背景**：VimとNeoVimは異なる設定ファイルパスを使用する（Vimは~/.vimrc、NeoVimは~/.config/nvim/init.vim）。また、vim-plugのインストール先も異なる。この検出機能により、ユーザーは自分の環境に合った正しい設定を自動的に取得でき、手動で設定パスを調整する必要がなくなる。

**機能の利用シーン**：
- install.shスクリプトでオプションを指定せずに実行した場合
- 新しいマシンでspace-vimをセットアップする場面
- VimまたはNeoVimの一方のみがインストールされている環境

**主要な処理内容**：
1. `command -v`コマンドでvimコマンドの存在確認
2. `command -v`コマンドでnvimコマンドの存在確認
3. 検出結果に基づいて適切なインストール処理を選択
4. 両方存在する場合はユーザーに対話的に選択を求める

**関連システム・外部連携**：
- シェル環境: PATH上のコマンド検索

**権限による制御**：本機能に権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ターミナル | 実行環境 | 検出結果の表示と選択入力 |

## 機能種別

環境検出 / 条件分岐処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | 本機能は引数を取らない（環境から自動検出） | - |

### 入力データソース

1. **システム環境**: PATH環境変数に含まれるコマンド
2. **ユーザー入力**: 両方存在時の選択（0, 1, 2）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 選択結果 | 処理分岐 | vim/nvim/両方のいずれかのインストール処理を実行 |

### 出力先

- install_for_vim()またはinstall_for_neovim()の呼び出し

## 処理フロー

### 処理シーケンス

```
1. infer()関数呼び出し

2. exists "vim" && exists "nvim"
   └─ 両方存在: 選択肢を表示
      └─ 0: install_for_vim()
      └─ 1: install_for_neovim()
      └─ 2: install_for_vim() + install_for_neovim()

3. exists "vim" のみ
   └─ install_for_vim()

4. exists "nvim" のみ
   └─ install_for_neovim()

5. どちらも存在しない
   └─ エラー終了
```

### フローチャート

```mermaid
flowchart TD
    A[infer関数] --> B{vim存在?}
    B -->|Yes| C{nvim存在?}
    B -->|No| D{nvim存在?}
    C -->|Yes| E[両方存在 - 選択肢表示]
    C -->|No| F[vimのみ - install_for_vim]
    D -->|Yes| G[nvimのみ - install_for_neovim]
    D -->|No| H[エラー終了]
    E --> I{ユーザー選択}
    I -->|0| F
    I -->|1| G
    I -->|2| J[install_for_vim + install_for_neovim]
    F --> K[完了]
    G --> K
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | コマンド検索 | command -v でPATH上のコマンドを検索 | 常時 |
| BR-02 | 両方検出 | vim/nvim両方存在時は選択肢を提示 | 両方インストール済み |
| BR-03 | 片方検出 | 片方のみ存在時は自動選択 | 片方のみインストール済み |
| BR-04 | 未検出エラー | どちらも存在しない場合はエラー | 未インストール |
| BR-05 | 入力検証 | 0, 1, 2以外の入力は再入力を求める | 選択時 |

### 計算ロジック

該当なし

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 前提条件エラー | vimもnvimも存在しない | エラーメッセージ表示・終了 |
| - | 入力エラー | 0, 1, 2以外の入力 | 再入力を求める |

### リトライ仕様

不正な入力に対しては再入力を求める（whileループ）

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

該当なし

## パフォーマンス要件

- コマンド検出: 即座に完了（ミリ秒オーダー）

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

- PATH環境変数を信頼して使用
- ユーザー入力は0, 1, 2のみを受け付ける

## 備考

- この機能はinstall.shスクリプトのinfer()関数で実装されている
- --vim, --neovim, --allオプションでバイパス可能

---

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

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

### 推奨読解順序

#### Step 1: コマンド存在確認の仕組みを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | install.sh | `install.sh` | exists()関数の実装 |

**読解のコツ**: exists()関数はシンプルなラッパーで、`command -v`の結果を判定する:
```bash
exists() {
  command -v "$1" >/dev/null 2>&1
}
```
- `command -v`: 指定されたコマンドのパスを返す（存在しない場合は何も返さない）
- `>/dev/null 2>&1`: 出力を破棄
- 戻り値: コマンドが存在すれば0（true）、存在しなければ1（false）

#### Step 2: 自動検出ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | install.sh | `install.sh` | infer()関数の実装 |

**主要処理フロー**:
- **157行目**: infer()関数定義開始
- **158行目**: `exists "vim" && exists "nvim"` で両方の存在確認
- **159-160行目**: 両方存在時のメッセージ表示
- **161-181行目**: ユーザー選択のwhileループ
  - **162行目**: 選択肢の表示（0:vim, 1:nvim, 2:両方）
  - **163-167行目**: 0選択時 - install_for_vim()呼び出し
  - **168-172行目**: 1選択時 - install_for_neovim()呼び出し
  - **173-177行目**: 2選択時 - 両方のインストール
  - **178-180行目**: 不正入力時 - 再入力を求める
- **182-185行目**: vimのみ存在時の処理
- **186-191行目**: nvimのみ存在時の処理
- **192-193行目**: どちらも存在しない場合のエラー

#### Step 3: 呼び出し元を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | install.sh | `install.sh` | install()関数からの呼び出し |

**主要処理フロー**:
- **196-209行目**: install()関数
- **197-200行目**: --all指定時は両方インストール
- **202-204行目**: --vim指定時はvimのみ
- **205-207行目**: --neovim指定時はnvimのみ
- **208行目**: オプション未指定時にinfer()を呼び出し

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

```
install()  [install.sh:196]
    │
    ├─ [--all] install_for_vim() + install_for_neovim()
    │
    ├─ [--vim] install_for_vim()
    │
    ├─ [--neovim] install_for_neovim()
    │
    └─ [オプションなし] infer()  [install.sh:157]
           │
           ├─ exists("vim")  [install.sh:71]
           │      └─ command -v vim
           │
           ├─ exists("nvim")  [install.sh:71]
           │      └─ command -v nvim
           │
           └─ 検出結果に応じた分岐
                  ├─ [両方存在] 選択肢表示 → ユーザー入力
                  │      ├─ 0: install_for_vim()
                  │      ├─ 1: install_for_neovim()
                  │      └─ 2: 両方インストール
                  │
                  ├─ [vimのみ] install_for_vim()
                  │
                  ├─ [nvimのみ] install_for_neovim()
                  │
                  └─ [なし] error()
```

### データフロー図

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

PATH環境変数 ─────────────────▶ command -v vim ────────────────▶ vim存在フラグ
                                    │
                                    ▼
                              command -v nvim ────────────────▶ nvim存在フラグ
                                    │
                                    ▼
存在フラグの組み合わせ ───────▶ 条件分岐 ───────────────────────▶ インストール処理選択
                                    │
                                    ├─ 両方存在: ユーザー入力待ち
                                    │      └─ read -r -p
                                    │
                                    ├─ vimのみ: install_for_vim()
                                    │
                                    ├─ nvimのみ: install_for_neovim()
                                    │
                                    └─ なし: error()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| install.sh | `install.sh` | スクリプト | 自動検出ロジック実装 |
