# 機能設計書 1-レイヤーシステム

## 概要

本ドキュメントは、space-vimにおけるレイヤーシステム機能の設計について記述する。レイヤーシステムはspacemacsのレイヤー概念を模倣し、モジュール化されたプラグインの有効化・無効化を管理する仕組みを提供する。

### 本機能の処理概要

レイヤーシステムは、Vimプラグインを機能単位でグループ化し、ユーザーが必要な機能だけを選択的に有効化できる仕組みを提供する。これにより、Vim設定の複雑さを軽減し、プラグイン管理を容易にする。

**業務上の目的・背景**：Vimには多数のプラグインが存在するが、それらを個別に管理することは煩雑である。レイヤーシステムは、関連するプラグインを「レイヤー」という単位でグループ化し、ユーザーが簡単に機能セットを有効化・無効化できるようにすることで、Vim設定の管理を大幅に簡素化する。spacemacsの成功したレイヤー概念をVimに導入することで、Emacsユーザーにも馴染みやすい設定方式を提供する。

**機能の利用シーン**：
- 新規ユーザーがspace-vimをインストールし、必要な機能（言語サポート、補完機能など）を選択する場面
- 既存ユーザーが新しいプログラミング言語の開発を始め、対応するレイヤーを追加する場面
- 不要になった機能を無効化してVimの起動時間を短縮したい場面
- 特定のプラグインを除外しつつレイヤーの他の機能は維持したい場面

**主要な処理内容**：
1. レイヤーディレクトリのスキャンとマニフェスト生成（トピック別にレイヤーを分類）
2. `.spacevim`ファイルからユーザー指定のレイヤー一覧を読み込み
3. `Layer`コマンドによる動的なレイヤー追加と除外オプションの処理
4. 有効化されたレイヤーのpackages.vimをロードしてプラグインを登録
5. 有効化されたレイヤーのconfig.vimをロードして設定を適用
6. レイヤーの状態（有効/無効）の表示機能を提供

**関連システム・外部連携**：
- vim-plug: プラグイン管理システムとしてvim-plugを使用し、レイヤーで定義されたプラグインを実際にインストール・ロードする
- キャッシュシステム: レイヤー情報をキャッシュしてロード時間を最適化

**権限による制御**：本機能に権限制御はない。すべてのユーザーが全レイヤーを有効化・無効化できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | LayerStatus表示画面 | 結果表示画面 | 有効化されているレイヤーの一覧を表示する |

## 機能種別

設定管理 / データ構造管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | レイヤー名（Layer コマンドの第1引数） | マニフェストに存在するレイヤー名であること |
| options | Dictionary | No | レイヤーオプション（excludeキーでプラグイン除外可能） | 'exclude'キーのみ許可 |

### 入力データソース

1. **ユーザー設定ファイル**: `~/.spacevim` - `g:spacevim_layers`変数でレイヤー一覧を定義
2. **レイヤーディレクトリ**: `layers/`以下の各レイヤーディレクトリ
3. **プライベートレイヤー**: `private/`以下のユーザー独自レイヤー

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| g:spacevim.loaded | List | 有効化されたレイヤー名のリスト |
| g:spacevim.excluded | List | 除外されたプラグイン名のリスト |
| g:spacevim.plugins | List | 登録されたプラグイン名のリスト |
| g:spacevim.manifest | Dictionary | レイヤー名をキー、ディレクトリ情報を値とするマニフェスト |
| g:spacevim.topics | Dictionary | トピック名をキー、レイヤー名リストを値とする分類情報 |

### 出力先

- グローバル変数（`g:spacevim`オブジェクト）
- キャッシュファイル（`core/autoload/spacevim/info.vim`）

## 処理フロー

### 処理シーケンス

```
1. spacevim#bootstrap()呼び出し
   └─ spacevim#begin()とspacevim#end()を順次実行

2. spacevim#begin()
   └─ vim-plugの存在確認とダウンロード
   └─ コマンド定義（Layer, MP, LayerStatus等）
   └─ キャッシュファイルの読み込みまたは再生成
   └─ .spacevimファイルの読み込みとレイヤー追加

3. .spacevim処理
   └─ g:spacevim_layersをg:spacevim.loadedに追加
   └─ Layers()関数の呼び出し（存在する場合）

4. spacevim#end()
   └─ s:register_plugin()でプラグイン登録
   └─ s:packages()で各レイヤーのpackages.vimをロード
   └─ s:config()で各レイヤーのconfig.vimをロード
   └─ UserInit()とUserConfig()の呼び出し（存在する場合）
```

### フローチャート

```mermaid
flowchart TD
    A[spacevim#bootstrap] --> B[spacevim#begin]
    B --> C{vim-plug存在?}
    C -->|No| D[vim-plugダウンロード]
    C -->|Yes| E[コマンド定義]
    D --> E
    E --> F{キャッシュ存在?}
    F -->|Yes| G[キャッシュ読み込み]
    F -->|No| H[spacevim#cache#init]
    G --> I[.spacevim読み込み]
    H --> I
    I --> J[spacevim#end]
    J --> K[レイヤーpackages.vim読み込み]
    K --> L[plug#begin/end]
    L --> M[レイヤーconfig.vim読み込み]
    M --> N[UserConfig呼び出し]
    N --> O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトレイヤー | 'spacevim'レイヤーはデフォルトで常に有効 | 常時 |
| BR-02 | 重複防止 | 同一レイヤーは一度のみ登録される | Layer呼び出し時 |
| BR-03 | 除外処理 | excludeオプションで指定したプラグインはインストールされない | プラグイン登録時 |
| BR-04 | プライベートレイヤー優先 | private/以下のレイヤーも通常レイヤーと同様に処理される | レイヤー読み込み時 |

### 計算ロジック

該当なし

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 引数エラー | Layer関数に無効な引数数が渡された場合 | エラーメッセージ表示 |
| - | 型エラー | Layerオプションがdictionary以外の場合 | 例外をスロー |
| - | キャッシュエラー | マニフェストにレイヤーが存在しない場合 | キャッシュを再生成 |

### リトライ仕様

キャッシュ読み込みエラー時は自動的にキャッシュを再生成する。

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

該当なし（ファイルシステム操作のみ）

## パフォーマンス要件

- キャッシュ使用時のVim起動時間への影響: 最小限（キャッシュファイル読み込みのみ）
- Python使用時は高速なキャッシュ生成が可能

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

- レイヤーのpackages.vimおよびconfig.vimは任意のVimScriptを実行可能
- 信頼できないソースからのレイヤー追加には注意が必要

## 備考

- spacemacsのレイヤー概念を参考にしている
- レイヤーはトピック（+lang, +tools, +themes等）でカテゴリ分けされている

---

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

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

### 推奨読解順序

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

まず、レイヤーシステムで管理されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | spacevim.vim | `core/autoload/spacevim.vim` | g:spacevimオブジェクトの構造（loaded, excluded, plugins, manifest, topics） |
| 1-2 | info.vim | `core/autoload/spacevim/info.vim` | キャッシュされるデータ形式（動的生成ファイル） |

**読解のコツ**: `g:spacevim`はDictionary型で、以下のキーを持つ:
- `loaded`: 有効化されたレイヤー名のList
- `excluded`: 除外されたプラグイン名のList
- `plugins`: 登録されたプラグイン名のList
- `manifest`: レイヤー名→ディレクトリパスのマッピング
- `topics`: トピック名→レイヤー名リストのマッピング

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

処理の起点となるファイル・関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | init.vim | `init.vim` | g:spacevimオブジェクトの初期化とspacevim#bootstrap()呼び出し |

**主要処理フロー**:
1. **19-27行目**: g:spacevimオブジェクトの初期化（base, version, os情報）
2. **38行目**: runtimepathへのcore追加
3. **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()でvim-plug確認、コマンド定義、キャッシュ処理、.spacevim読み込み
- **47-54行目**: s:define_command()でLayer, MP, SpaceInfo, LayerCache, LayerStatusコマンドを定義
- **76-85行目**: s:layer()関数でレイヤーをg:spacevim.loadedに追加
- **137-152行目**: spacevim#end()でプラグイン登録と設定読み込み

#### Step 4: キャッシュシステムを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | cache.vim | `core/autoload/spacevim/cache.vim` | レイヤーディレクトリのスキャンとマニフェスト生成 |

**主要処理フロー**:
- **1-12行目**: spacevim#cache#init()でPython使用可否を判定
- **14-48行目**: s:init()でVimScriptによるキャッシュ生成（ディレクトリスキャン）
- **50-96行目**: s:py_init()でPythonによる高速キャッシュ生成

#### Step 5: レイヤー状態表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | layer.vim | `core/autoload/spacevim/layer.vim` | LayerStatusコマンドの実装 |

**主要処理フロー**:
- **26-51行目**: spacevim#layer#status()で有効レイヤー一覧を新規ウィンドウに表示
- **53-92行目**: s:syntax()でレイヤー表示用のシンタックスハイライト定義

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

```
init.vim
    │
    ├─ spacevim#bootstrap()  [core/autoload/spacevim.vim:27]
    │      │
    │      ├─ spacevim#begin()  [core/autoload/spacevim.vim:32]
    │      │      ├─ s:check_vim_plug()
    │      │      ├─ s:define_command()
    │      │      ├─ s:cache()
    │      │      │      └─ spacevim#cache#init()  [core/autoload/spacevim/cache.vim:1]
    │      │      └─ s:check_dot_spacevim()
    │      │
    │      └─ spacevim#end()  [core/autoload/spacevim.vim:137]
    │             ├─ s:register_plugin()
    │             │      └─ s:packages()
    │             │             └─ 各レイヤーのpackages.vim読み込み
    │             ├─ s:config()
    │             │      └─ 各レイヤーのconfig.vim読み込み
    │             └─ UserConfig()（存在する場合）
    │
    └─ :LayerStatus
           └─ spacevim#layer#status()  [core/autoload/spacevim/layer.vim:26]
```

### データフロー図

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

~/.spacevim ──────────▶ s:check_dot_spacevim() ──────────▶ g:spacevim.loaded
(g:spacevim_layers)        │
                           ▼
layers/*/packages.vim ──▶ s:packages() ──────────────────▶ g:spacevim.plugins
                           │                                    │
                           ▼                                    ▼
                      plug#begin/end ────────────────────▶ vim-plugによる
                           │                              プラグイン登録
                           ▼
layers/*/config.vim ────▶ s:config() ────────────────────▶ Vim設定適用
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| init.vim | `init.vim` | ソース | エントリーポイント、g:spacevim初期化 |
| spacevim.vim | `core/autoload/spacevim.vim` | ソース | ブートストラップ処理、レイヤー登録 |
| cache.vim | `core/autoload/spacevim/cache.vim` | ソース | レイヤーキャッシュ生成 |
| layer.vim | `core/autoload/spacevim/layer.vim` | ソース | レイヤー状態表示 |
| info.vim | `core/autoload/spacevim/info.vim` | キャッシュ | マニフェスト・トピック情報のキャッシュ |
| init.spacevim | `init.spacevim` | テンプレート | .spacevimのテンプレート |
| LAYERS.md | `layers/LAYERS.md` | ドキュメント | 利用可能なレイヤー一覧 |
| packages.vim | `layers/*/packages.vim` | ソース | 各レイヤーのプラグイン定義 |
| config.vim | `layers/*/config.vim` | ソース | 各レイヤーの設定 |
