# 機能設計書 2-ブートストラップ

## 概要

本ドキュメントは、space-vimの初期化処理（ブートストラップ）機能の設計について記述する。ブートストラップ機能は、vim-plugのダウンロード、設定ファイルの読み込み、プラグイン登録を一連の流れで実行するspace-vimのコア機能である。

### 本機能の処理概要

ブートストラップ機能は、Vim起動時にspace-vimのすべてのコンポーネントを正しい順序で初期化する役割を担う。プラグインマネージャの準備からユーザー設定の適用まで、space-vimが完全に動作するために必要なすべての初期化処理を実行する。

**業務上の目的・背景**：Vimの設定は複雑になりがちであり、プラグインの依存関係や読み込み順序を正しく管理することは難しい。ブートストラップ機能は、この複雑さをユーザーから隠蔽し、`spacevim#bootstrap()`という単一の関数呼び出しでspace-vimのすべての機能を正しく初期化できるようにする。これにより、ユーザーは内部の複雑な処理を意識することなく、space-vimを利用開始できる。

**機能の利用シーン**：
- Vimの起動時に`init.vim`から自動的に呼び出される
- ユーザーが手動でVimの設定をリロードする場面（通常は不要）
- 初回インストール後の初めてのVim起動時

**主要な処理内容**：
1. vim-plugプラグインマネージャの存在確認とダウンロード
2. space-vimコマンド（Layer, MP, LayerStatus等）の定義
3. キャッシュファイルの読み込みまたは生成
4. ユーザー設定ファイル（.spacevim）の読み込みとレイヤー有効化
5. vim-plugによるプラグイン登録（plug#begin/plug#end）
6. 各レイヤーのpackages.vimとconfig.vimの読み込み
7. UserInit()およびUserConfig()関数の呼び出し
8. 不足プラグインの検出とインストール促進

**関連システム・外部連携**：
- vim-plug: プラグイン管理システム。存在しない場合はGitHubから自動ダウンロード
- curl: vim-plugのダウンロードに使用

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面を持たない内部処理機能 |

## 機能種別

初期化処理 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | spacevim#bootstrap()は引数を取らない | - |

### 入力データソース

1. **ユーザー設定ファイル**: `~/.spacevim` - レイヤー設定、リーダーキー設定等
2. **キャッシュファイル**: `core/autoload/spacevim/info.vim` - レイヤーマニフェスト
3. **レイヤーディレクトリ**: `layers/`以下の各レイヤー
4. **プライベート設定**: `private/config.vim`, `private/packages.vim`

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| g:spacevim | Dictionary | space-vim設定オブジェクト（完全初期化済み） |
| g:mapleader | String | リーダーキー設定（デフォルト: Space） |
| g:maplocalleader | String | ローカルリーダーキー設定（デフォルト: ,） |
| g:plugs | Dictionary | vim-plugによるプラグイン管理情報 |

### 出力先

- グローバル変数
- Vimランタイム設定

## 処理フロー

### 処理シーケンス

```
1. init.vimからspacevim#bootstrap()呼び出し
   └─ g:spacevimオブジェクトは既にinit.vimで初期化済み

2. spacevim#begin()実行
   └─ vim-plug存在確認
   └─ 不在の場合はcurlでダウンロード
   └─ s:define_command()でコマンド定義
   └─ s:cache()でキャッシュ読み込み/生成
   └─ s:check_dot_spacevim()で.spacevim読み込み
       └─ g:spacevim_layersをg:spacevim.loadedに追加
       └─ g:mapleader, g:maplocalleader設定

3. spacevim#end()実行
   └─ Layers()関数呼び出し（存在する場合、後方互換性）
   └─ s:register_plugin()でプラグイン登録
       └─ plug#begin()呼び出し
       └─ s:packages()で各レイヤーのpackages.vim読み込み
       └─ UserInit()呼び出し（存在する場合）
       └─ plug#end()呼び出し
   └─ plugin/default.vim読み込み（vim-better-default）
   └─ s:config()で各レイヤーのconfig.vim読み込み
   └─ UserConfig()呼び出し（存在する場合）
   └─ ヘルプタグ生成
   └─ 不足プラグイン確認とインストール促進
```

### フローチャート

```mermaid
flowchart TD
    A[init.vim] --> B[g:spacevim初期化]
    B --> C[spacevim#bootstrap]
    C --> D[spacevim#begin]
    D --> E{vim-plug存在?}
    E -->|No| F[vim-plugダウンロード]
    E -->|Yes| G[コマンド定義]
    F --> G
    G --> H{キャッシュ存在?}
    H -->|No| I[キャッシュ生成]
    H -->|Yes| J[キャッシュ読み込み]
    I --> K[.spacevim読み込み]
    J --> K
    K --> L[spacevim#end]
    L --> M[plug#begin]
    M --> N[packages.vim読み込み]
    N --> O[UserInit]
    O --> P[plug#end]
    P --> Q[default.vim読み込み]
    Q --> R[config.vim読み込み]
    R --> S[UserConfig]
    S --> T[ヘルプタグ生成]
    T --> U{不足プラグイン?}
    U -->|Yes| V[インストール促進]
    U -->|No| W[完了]
    V --> W
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | vim-plug自動取得 | vim-plugが存在しない場合、自動でダウンロード | 非Windows環境 |
| BR-02 | キャッシュ自動生成 | キャッシュファイルが存在しない場合、自動生成 | 常時 |
| BR-03 | .spacevim必須 | .spacevimファイルが存在しない場合、エラー表示 | 常時 |
| BR-04 | 読み込み順序 | packages.vim → UserInit → config.vim → UserConfig の順で実行 | 常時 |
| BR-05 | 不足プラグイン確認 | 起動後一定時間（1.5秒）後に不足プラグインを確認 | timer機能が有効な場合 |

### 計算ロジック

該当なし

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 設定エラー | .spacevimファイルが存在しない | エラーメッセージ表示して終了 |
| - | ネットワークエラー | vim-plugのダウンロードに失敗 | エラーメッセージ表示 |
| - | キャッシュエラー | マニフェストにレイヤーが存在しない | キャッシュを再生成 |
| - | Source エラー | 設定ファイルの読み込みに失敗 | 例外をキャッチしてキャッシュ再生成 |

### リトライ仕様

- Sourceエラー時は自動的にキャッシュを再生成して復旧を試みる

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

該当なし

## パフォーマンス要件

- Vim起動時間への影響を最小限に抑える
- キャッシュ機構によりレイヤースキャンを省略
- timer機能を使用して不足プラグイン確認を遅延実行（1.5秒後）

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

- vim-plugはHTTPSでダウンロード
- .spacevimファイルは任意のVimScriptを実行可能なため、信頼できる内容のみ記述すること

## 備考

- `spacevim#bootstrap()`は`init.vim`から1回だけ呼び出される
- Windows環境ではvim-plugの自動ダウンロードは行われない

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ブートストラップ処理で使用・生成されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | init.vim | `init.vim` | g:spacevimオブジェクトの初期構造（base, version, os, nvim, vim8, timer, gui, tmux） |

**読解のコツ**: `init.vim`の19-28行目でg:spacevimオブジェクトが初期化される。この時点でのキーは以下の通り:
- `base`: space-vimのインストールディレクトリパス
- `version`: バージョン文字列
- `os`: OSの種類（mac, linux, windows）
- `nvim`, `vim8`, `timer`, `gui`, `tmux`: 環境フラグ

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | init.vim | `init.vim` | spacevim#bootstrap()の呼び出しまでの流れ |

**主要処理フロー**:
1. **19行目**: g:spacevimオブジェクト初期化
2. **20行目**: baseパスの設定（シンボリックリンク解決済み）
3. **33-35行目**: Windows環境でのruntimepath設定
4. **38行目**: coreディレクトリをruntimepathに追加
5. **40行目**: spacevim#bootstrap()呼び出し

#### Step 3: ブートストラップ処理本体を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | spacevim.vim | `core/autoload/spacevim.vim` | spacevim#bootstrap(), spacevim#begin(), spacevim#end() |

**主要処理フロー**:
- **27-30行目**: spacevim#bootstrap()はbegin()とend()を順次呼び出す単純なラッパー
- **32-40行目**: spacevim#begin()
  - **34-36行目**: 非Windows環境でvim-plugの存在確認
  - **37行目**: コマンド定義
  - **38行目**: キャッシュ処理
  - **39行目**: .spacevim読み込み
- **137-152行目**: spacevim#end()
  - **139行目**: Layers()関数呼び出し（後方互換性）
  - **141行目**: プラグイン登録
  - **143行目**: vim-better-default読み込み
  - **145行目**: レイヤー設定読み込み
  - **146行目**: UserConfig()呼び出し
  - **148行目**: ヘルプタグ生成
  - **150行目**: 不足プラグイン確認

#### Step 4: vim-plugダウンロード処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | plug.vim | `core/autoload/spacevim/vim/plug.vim` | vim-plugダウンロード処理 |

**主要処理フロー**:
- **1-5行目**: spacevim#vim#plug#download()でcurlによるダウンロード
- **16-36行目**: spacevim#vim#plug#check()で不足プラグインの確認とインストール促進

#### Step 5: プラグイン登録処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | spacevim.vim | `core/autoload/spacevim.vim` | s:register_plugin(), s:packages(), s:config() |

**主要処理フロー**:
- **155-174行目**: s:register_plugin()
  - **157-158行目**: plug#begin()でプラグインホームディレクトリ指定
  - **159行目**: s:packages()呼び出し
  - **161-169行目**: 除外されていないプラグインを登録
  - **172行目**: UserInit()呼び出し
  - **173行目**: plug#end()
- **176-195行目**: s:packages()で各レイヤーのpackages.vimをSource
- **197-208行目**: s:config()で各レイヤーのconfig.vimをSource

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

```
init.vim
    │
    └─ spacevim#bootstrap()  [core/autoload/spacevim.vim:27]
           │
           ├─ spacevim#begin()  [core/autoload/spacevim.vim:32]
           │      │
           │      ├─ s:check_vim_plug()  [core/autoload/spacevim.vim:42]
           │      │      └─ spacevim#vim#plug#download()  [core/autoload/spacevim/vim/plug.vim:1]
           │      │
           │      ├─ s:define_command()  [core/autoload/spacevim.vim:47]
           │      │
           │      ├─ s:cache()  [core/autoload/spacevim.vim:67]
           │      │      └─ spacevim#cache#init()  [core/autoload/spacevim/cache.vim:1]
           │      │
           │      └─ s:check_dot_spacevim()  [core/autoload/spacevim.vim:56]
           │
           └─ spacevim#end()  [core/autoload/spacevim.vim:137]
                  │
                  ├─ Layers()  [~/.spacevim（オプション）]
                  │
                  ├─ s:register_plugin()  [core/autoload/spacevim.vim:155]
                  │      ├─ plug#begin()
                  │      ├─ s:packages()  [core/autoload/spacevim.vim:176]
                  │      │      └─ 各レイヤー packages.vim
                  │      ├─ UserInit()  [~/.spacevim]
                  │      └─ plug#end()
                  │
                  ├─ runtime plugin/default.vim
                  │
                  ├─ s:config()  [core/autoload/spacevim.vim:197]
                  │      └─ 各レイヤー config.vim
                  │
                  ├─ UserConfig()  [~/.spacevim]
                  │
                  ├─ s:spacevim_helptags()  [core/autoload/spacevim.vim:210]
                  │
                  └─ s:check_missing_plugins()  [core/autoload/spacevim.vim:225]
                         └─ spacevim#vim#plug#check()  [core/autoload/spacevim/vim/plug.vim:16]
```

### データフロー図

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

vim-plug (GitHub) ─────────▶ s:check_vim_plug() ────────────▶ ~/.vim/autoload/plug.vim
                                   │
                                   ▼
~/.spacevim ───────────────▶ s:check_dot_spacevim() ────────▶ g:spacevim.loaded
(g:spacevim_layers)                │                          g:mapleader
                                   │                          g:maplocalleader
                                   ▼
info.vim (キャッシュ) ──────▶ s:cache() ────────────────────▶ g:spacevim.manifest
                                   │                          g:spacevim.topics
                                   ▼
layers/*/packages.vim ──────▶ s:packages() ─────────────────▶ g:spacevim.plugins
                                   │                               │
                                   ▼                               ▼
                             plug#begin/end ────────────────▶ g:plugs (vim-plug)
                                   │
                                   ▼
layers/*/config.vim ────────▶ s:config() ───────────────────▶ Vim設定
                                   │
                                   ▼
UserInit/UserConfig ────────▶ ユーザーカスタマイズ適用 ──────▶ 最終Vim設定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| init.vim | `init.vim` | ソース | エントリーポイント、g:spacevim初期化 |
| spacevim.vim | `core/autoload/spacevim.vim` | ソース | ブートストラップ処理本体 |
| plug.vim | `core/autoload/spacevim/vim/plug.vim` | ソース | vim-plugダウンロード・チェック |
| cache.vim | `core/autoload/spacevim/cache.vim` | ソース | キャッシュ生成 |
| info.vim | `core/autoload/spacevim/info.vim` | キャッシュ | レイヤーマニフェスト |
| init.spacevim | `init.spacevim` | テンプレート | .spacevimテンプレート |
| default.vim | `vim-better-default/plugin/default.vim` | ソース | デフォルト設定（外部プラグイン） |
| packages.vim | `layers/*/packages.vim` | ソース | 各レイヤーのプラグイン定義 |
| config.vim | `layers/*/config.vim` | ソース | 各レイヤーの設定 |
