# 機能設計書 9-LayerCache

## 概要

本ドキュメントは、space-vimのLayerCacheコマンドの設計について記述する。LayerCacheコマンドは、レイヤー情報を再キャッシュする機能を提供し、spacevim#cache#init()を呼び出す。

### 本機能の処理概要

LayerCacheコマンドは、layers/ディレクトリをスキャンしてレイヤーマニフェストを再生成し、キャッシュファイル（info.vim）を更新する。新しいレイヤーを追加した場合や、レイヤー構造が変更された場合にこのコマンドを実行することで、space-vimが最新のレイヤー情報を認識できるようになる。

**業務上の目的・背景**：space-vimは起動時にキャッシュファイルからレイヤー情報を読み込むことで、高速な起動を実現している。しかし、新しいレイヤーを追加したり、既存のレイヤーを削除した場合、キャッシュが古くなり実際のディレクトリ構造と不整合が生じる。LayerCacheコマンドは、この不整合を解消するために手動でキャッシュを更新する手段を提供する。

**機能の利用シーン**：
- 新しいレイヤーをlayers/ディレクトリに追加した後
- 既存のレイヤーを削除した後
- レイヤーの読み込みでエラーが発生した場合
- private/ディレクトリにプライベートレイヤーを追加した後

**主要な処理内容**：
1. spacevim#cache#init()関数の呼び出し
2. layers/ディレクトリのスキャン
3. トピック・レイヤー構造の解析
4. g:spacevim.manifestの更新
5. g:spacevim.topicsの更新
6. private/ディレクトリの処理（存在する場合）
7. info.vimファイルへの書き込み

**関連システム・外部連携**：
- ファイルシステム: ディレクトリスキャンとファイル書き込み
- Python（オプション）: 高速なキャッシュ生成

**権限による制御**：本機能に権限制御はない。ただし、キャッシュファイルへの書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面を持たないコマンド |

## 機能種別

キャッシュ更新 / システムメンテナンス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | LayerCacheコマンドは引数を取らない | - |

### 入力データソース

1. **ディレクトリ構造**: `layers/`以下のトピック・レイヤーディレクトリ
2. **プライベートレイヤー**: `private/`以下のディレクトリ（オプション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| g:spacevim.manifest | Dictionary | レイヤー名→{dir: パス}のマッピング |
| g:spacevim.topics | Dictionary | トピック名→レイヤー名リストのマッピング |
| g:spacevim.private | List | プライベートレイヤー名のリスト（オプション） |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. :LayerCacheコマンド実行
   └─ spacevim#cache#init()呼び出し

2. Python使用可否判定
   └─ has('python') || has('python3')

3. Python使用可能時
   └─ s:py_init()による高速処理

4. Python使用不可時
   └─ s:init()によるVimScript処理

5. ディレクトリスキャン
   └─ layers/以下のトピックディレクトリ列挙
   └─ 各トピック内のレイヤーディレクトリ列挙

6. データ構造更新
   └─ g:spacevim.manifest更新
   └─ g:spacevim.topics更新

7. プライベートレイヤー処理
   └─ private/ディレクトリの存在確認と処理

8. キャッシュファイル書き込み
   └─ info.vimにVimScript形式で出力
```

### フローチャート

```mermaid
flowchart TD
    A[:LayerCache] --> B[spacevim#cache#init]
    B --> C{Python使用可能?}
    C -->|Yes| D[s:py_init]
    C -->|No| E[s:init]
    D --> F[layers/スキャン]
    E --> F
    F --> G[トピック抽出]
    G --> H[レイヤー抽出]
    H --> I[manifest生成]
    I --> J[topics生成]
    J --> K{private/存在?}
    K -->|Yes| L[private処理]
    K -->|No| M[info.vim書き込み]
    L --> M
    M --> N[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | Python優先 | Python使用可能時は高速処理を使用 | has('python') || has('python3') |
| BR-02 | 完全再生成 | 既存のキャッシュを上書き | 常時 |
| BR-03 | ディレクトリのみ | ファイルはレイヤーとして認識しない | スキャン時 |
| BR-04 | VimScript形式 | キャッシュはVimScriptのlet文で保存 | 書き込み時 |

### 計算ロジック

該当なし

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Pythonエラー | Pythonでの処理中にエラー | VimScript処理にフォールバック |
| - | 書き込みエラー | info.vimへの書き込み失敗 | エラーメッセージ表示 |

### リトライ仕様

Pythonエラー時はVimScript処理にフォールバック。

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

該当なし（キャッシュファイルの一括書き込み）

## パフォーマンス要件

- キャッシュ生成: 通常数百ミリ秒以内
- Python使用時はより高速

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

- キャッシュファイルはVimScriptとして実行されるため、改ざんに注意

## 備考

- このコマンドはNo.3 キャッシュ機能と同じ処理を実行する
- 自動的にキャッシュが再生成されるケースもある（エラー発生時など）

---

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

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

### 推奨読解順序

#### Step 1: コマンド定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | spacevim.vim | `core/autoload/spacevim.vim` | LayerCacheコマンドの定義 |

**主要処理フロー**:
- **52行目**: `command! -nargs=0 -bar LayerCache call spacevim#cache#init()`

#### Step 2: キャッシュ生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cache.vim | `core/autoload/spacevim/cache.vim` | spacevim#cache#init()関数 |

**主要処理フロー**:
- **1-12行目**: spacevim#cache#init()
  - **2行目**: Python使用可否判定
  - **3行目**: 使用するPythonコマンドの選択
  - **4-8行目**: Pythonが使用可能な場合
    - **5行目**: s:py_init()を試行
    - **6-7行目**: エラー時はs:init()にフォールバック
  - **9-11行目**: Python不使用時はs:init()を直接呼び出し

#### Step 3: VimScript処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cache.vim | `core/autoload/spacevim/cache.vim` | s:init()関数 |

**主要処理フロー**:
- **14-48行目**: s:init()関数
- **15行目**: topic_base = layers/ディレクトリ
- **16-17行目**: トピックディレクトリをスキャン
- **20-33行目**: 各トピック・レイヤーの処理
- **35行目**: g:spacevim.topicsに格納
- **37-47行目**: private/処理とinfo.vim書き込み

#### Step 4: Python処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | cache.vim | `core/autoload/spacevim/cache.vim` | s:py_init()関数 |

**主要処理フロー**:
- **50-96行目**: s:py_init()関数
- **52-54行目**: Pythonモジュールのインポート
- **56-57行目**: ヘルパー関数定義
- **63-81行目**: ディレクトリスキャンとデータ構造生成
- **83-86行目**: vim.command()でVim変数に設定
- **88-93行目**: ファイル書き込み

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

```
:LayerCache  [コマンド]
    │
    └─ spacevim#cache#init()  [core/autoload/spacevim/cache.vim:1]
           │
           ├─ [Python使用可能]
           │      └─ s:py_init()  [core/autoload/spacevim/cache.vim:50]
           │             ├─ glob でディレクトリスキャン
           │             ├─ vim.command() で変数設定
           │             └─ open().write() でファイル出力
           │
           └─ [Python使用不可 or エラー]
                  └─ s:init()  [core/autoload/spacevim/cache.vim:14]
                         ├─ globpath() でディレクトリスキャン
                         ├─ g:spacevim に直接設定
                         └─ writefile() でファイル出力
```

### データフロー図

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

layers/
├─ +lang/                    spacevim#cache#init()
│   ├─ python/       ─────▶ ディレクトリスキャン ─────────▶ g:spacevim.manifest
│   └─ javascript/           │                              {'python': {'dir': '...'}}
├─ +tools/                   │
│   ├─ fzf/                  │
│   └─ ctags/                │
...                          │
                             ▼
                       トピック分類 ─────────────────────▶ g:spacevim.topics
                             │                            {'+lang': ['python', ...]}
private/                     │
└─ my-layer/         ─────▶ プライベート処理 ─────────────▶ g:spacevim.private
                             │                            ['my-layer']
                             ▼
                       writefile() ───────────────────────▶ info.vim
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cache.vim | `core/autoload/spacevim/cache.vim` | ソース | キャッシュ生成処理 |
| spacevim.vim | `core/autoload/spacevim.vim` | ソース | LayerCacheコマンド定義 |
| info.vim | `core/autoload/spacevim/info.vim` | キャッシュ | 生成されるキャッシュファイル |
| layers/ | `layers/` | ディレクトリ | スキャン対象 |
| private/ | `private/` | ディレクトリ | プライベートレイヤー格納先 |
