# space-vim コードリーディングガイドライン

## はじめに

このガイドラインは、space-vimのコードベースを効率的に理解するための手引きです。
Vim scriptに精通していないエンジニアでも、段階的に学習できるよう構成されています。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

**プロジェクト概要:**
space-vimは、spacemacsにインスパイアされたVim/NeoVim向けのディストリビューションです。レイヤーベースのプラグイン管理システムを採用し、モジュラーな設定管理を実現しています。

---

## 1. 言語基礎

> このセクションでは、Vim scriptの基本構文と概念を解説します。

### 1.1 プログラム構造

Vim scriptファイルは `.vim` 拡張子を持ち、Vimエディタによって直接解釈・実行されます。ファイルの先頭には通常、エンコーディング指定やコメントによるヘッダー情報が含まれます。

**実例:** `init.vim:17-21`
```vim
scriptencoding utf-8

let g:spacevim = get(g:, 'spacevim', {})
let g:spacevim.base = fnamemodify(resolve(expand('<sfile>:p')),':h')
let g:spacevim.version = '0.9.0'
```

**解説:**
- `scriptencoding utf-8`: ファイルのエンコーディングを指定
- `let`: 変数への代入を行うコマンド
- `g:`: グローバルスコープを示すプレフィックス
- `get(g:, 'spacevim', {})`: 変数が存在しなければデフォルト値`{}`を返す

### 1.2 データ型と変数

Vim scriptには以下の主要なデータ型があります:

| データ型 | 説明 | 例 |
|---------|------|-----|
| Number | 整数値 | `let num = 42` |
| Float | 浮動小数点数 | `let pi = 3.14` |
| String | 文字列 | `let str = 'hello'` |
| List | 配列（順序付きコレクション） | `let list = [1, 2, 3]` |
| Dictionary | 連想配列（キー・値ペア） | `let dict = {'key': 'value'}` |
| Funcref | 関数参照 | `let Func = function('call')` |

**スコーププレフィックス:**

| プレフィックス | スコープ | 説明 |
|---------------|---------|------|
| `g:` | グローバル | どこからでもアクセス可能 |
| `s:` | スクリプトローカル | 現在のスクリプト内のみ |
| `l:` | ローカル | 関数内のみ |
| `a:` | 引数 | 関数の引数 |
| `v:` | Vim定義変数 | Vimが定義する特殊変数 |

**実例:** `core/autoload/spacevim.vim:16-25`
```vim
let s:plug_options = {}
let s:dot_spacevim = $HOME.'/.spacevim'
let s:private_config = g:spacevim.base.'/private/config.vim'
let s:private_packages = g:spacevim.base.'/private/packages.vim'
let s:TYPE = {
\ 'string':  type(''),
\ 'list':    type([]),
\ 'dict':    type({}),
\ 'funcref': type(function('call'))
\ }
```

### 1.3 制御構造

**条件分岐:**

```vim
if 条件式
  " 処理
elseif 別の条件式
  " 処理
else
  " 処理
endif
```

**実例:** `core/autoload/spacevim/cache.vim:1-12`
```vim
function! spacevim#cache#init() abort
  if has('python') || has('python3')
    let s:py_exe = has('python') ? 'python' : 'python3'
    try
      call s:py_init()
    catch
      call s:init()
    endtry
  else
    call s:init()
  endif
endfunction
```

**ループ構造:**

```vim
" forループ
for item in リスト
  " 処理
endfor

" whileループ
while 条件式
  " 処理
endwhile
```

**実例:** `layers/+distributions/better-defaults/keybindings.vim:17-26`
```vim
for s:i in range(1, 9)
  " <Leader>[1-9] move to window [1-9]
  execute 'nnoremap <Leader>'.s:i ' :'.s:i.'wincmd w<CR>'

  " <Leader><leader>[1-9] move to tab [1-9]
  execute 'nnoremap <Leader><Leader>'.s:i s:i.'gt'

  " <Leader>b[1-9] move to buffer [1-9]
  execute 'nnoremap <Leader>b'.s:i ':b'.s:i.'<CR>'
endfor
unlet s:i
```

### 1.4 関数/メソッド定義

Vim scriptの関数は `function` キーワードで定義します。

**基本構文:**
```vim
function! 関数名(引数1, 引数2, ...) abort
  " 処理
  return 戻り値
endfunction
```

- `!`: 同名の関数が既に存在する場合に上書きを許可
- `abort`: エラー発生時に即座に関数を終了

**実例:** `core/autoload/spacevim.vim:27-30`
```vim
function! spacevim#bootstrap() abort
  call spacevim#begin()
  call spacevim#end()
endfunction
```

**autoload関数:**

`autoload/` ディレクトリ以下のファイルに配置された関数は、初回呼び出し時に自動的にロードされます。関数名は `ディレクトリ名#ファイル名#関数名` の形式になります。

**例:** `core/autoload/spacevim/util.vim` 内の関数
```vim
function! spacevim#util#err(msg)
  " spacevim#util#err() として呼び出し可能
endfunction
```

### 1.5 モジュール/インポート

Vim scriptでは、以下の方法でファイルを読み込みます:

**source コマンド:**
```vim
source ファイルパス
execute 'source ' . ファイルパス
```

**実例:** `layers/+distributions/better-defaults/config.vim:36`
```vim
execute 'source' fnamemodify(expand('<sfile>'), ':h') . '/keybindings.vim'
```

**runtime コマンド:**
```vim
runtime! plugin/default.vim
```
`runtimepath` からファイルを検索して実行します。

---

## 2. プロジェクト固有の概念

> このセクションでは、space-vim特有の概念を解説します。

### 2.1 レイヤーシステム

space-vimの最も重要な概念は「レイヤー」です。レイヤーは関連するプラグインと設定をグループ化したモジュールです。

**レイヤーの構成:**
各レイヤーは以下の3ファイルで構成されます:

| ファイル | 役割 |
|---------|------|
| `packages.vim` | レイヤーで使用するプラグインの宣言 |
| `config.vim` | プラグインの設定とキーバインディング |
| `README.md` | レイヤーのドキュメント |

**実例:** `layers/+tools/fzf/packages.vim:1-15`
```vim
if get(g:, 'spacevim_enable_clap', 0)
  MP 'liuchengxu/vim-clap', { 'do': ':Clap install-binary!' }
  MP 'vn-ki/coc-clap'
elseif g:spacevim.gui && !has('terminal')
  MP 'Yggdroot/LeaderF'
else
  if g:spacevim.speed_up_via_timer
    MP 'junegunn/fzf',  { 'dir': '~/.fzf', 'do': function('spacevim#VimPlugPostUpdateHook', [v:false, './install --all']), 'on': [] }
    MP 'junegunn/fzf.vim', { 'on': [] }
    call timer_start(700, 'spacevim#defer#fzf')
  else
    MP 'junegunn/fzf',  { 'dir': '~/.fzf', 'do': function('spacevim#VimPlugPostUpdateHook', [v:false, './install --all']) }
    MP 'junegunn/fzf.vim'
  endif
endif
```

### 2.2 トピックによるレイヤー分類

レイヤーは「トピック」というカテゴリで整理されています:

| トピック | 説明 | 例 |
|---------|------|-----|
| `+checkers` | 構文チェック・リンター | syntax-checking |
| `+completion` | 補完機能 | auto-completion, deoplete |
| `+distributions` | 基本設定・デフォルト | better-defaults, spacevim |
| `+fun` | エンターテインメント | emoji, games, goyo |
| `+lang` | プログラミング言語サポート | python, go, rust |
| `+programming` | プログラミング共通機能 | editing, formatting |
| `+themes` | テーマ・外観 | airline, lightline |
| `+tools` | ツール連携 | fzf, lsp, tmux |
| `+version-control` | バージョン管理 | git, github |
| `+vim` | Vim拡張機能 | which-key, better-motion |

### 2.3 ブートストラップシーケンス

space-vimの起動フローを理解することは、コードを読む上で重要です。

```
init.vim
  |
  v
spacevim#bootstrap()
  |
  +-- spacevim#begin()
  |     |
  |     +-- vim-plugの確認・ダウンロード
  |     +-- コマンド定義 (Layer, MP, LayerStatus等)
  |     +-- キャッシュ読み込み
  |     +-- .spacevimの読み込み
  |
  +-- spacevim#end()
        |
        +-- プラグイン登録 (plug#begin/plug#end)
        +-- レイヤーのconfig.vim読み込み
        +-- UserConfig()呼び出し（ユーザー定義）
        +-- ヘルプタグ生成
        +-- 不足プラグインチェック
```

**実例:** `core/autoload/spacevim.vim:27-30, 137-152`
```vim
function! spacevim#bootstrap() abort
  call spacevim#begin()
  call spacevim#end()
endfunction

function! spacevim#end() abort
  " Backward compatibility
  if exists('*Layers') | call Layers() | endif

  call s:register_plugin()
  " Make vim-better-default settings can be overrided
  silent! runtime! plugin/default.vim

  call s:config()
  if exists('*UserConfig') | call UserConfig() | endif

  call s:spacevim_helptags()

  call s:check_missing_plugins()
  silent doautocmd <nomodeline> User SpacevimAfterUserConfig
endfunction
```

### 2.4 MPコマンド（My Plugin）

`MP` コマンドは space-vim 独自のプラグイン登録コマンドです。

**実例:** `core/autoload/spacevim.vim:105-122`
```vim
" This is an only one possible extra argument: plug option, dict
function! s:my_plugin(plugin, ...) abort
  if index(g:spacevim.plugins, a:plugin) < 0
    call add(g:spacevim.plugins, a:plugin)
  endif
  if a:0 == 1
    let s:plug_options[a:plugin] = a:1
    if has_key(a:1, 'on_event')
      let l:group = 'load/'.a:plugin
      let l:name = split(a:plugin, '/')[1]
      let l:events = join(s:to_a(a:1.on_event), ',')
      let l:load = printf("call plug#load('%s')", l:name)
      execute "augroup" l:group
      autocmd!
      execute 'autocmd' l:events '*' l:load '|' 'autocmd!' l:group
      execute 'augroup END'
    endif
  endif
endfunction
```

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `+カテゴリ名/` | トピックディレクトリ | `+lang/`, `+tools/` |
| `レイヤー名/` | レイヤーディレクトリ | `fzf/`, `python/` |
| `packages.vim` | プラグイン宣言ファイル | 各レイヤーに存在 |
| `config.vim` | 設定ファイル | 各レイヤーに存在 |
| `keybindings.vim` | キーバインド定義 | 一部レイヤーに存在 |
| `autoload/spacevim/` | 自動読み込み関数群 | `spacevim#` プレフィックス |
| `ftplugin/言語名.vim` | ファイルタイプ別設定 | `python.vim`, `go.vim` |
| `ftdetect/` | ファイルタイプ検出 | `spacevim.vim` |

### 3.2 関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `spacevim#` | space-vimのautoload関数 | `spacevim#bootstrap()` |
| `spacevim#vim#` | Vim操作関連の関数 | `spacevim#vim#file#Open()` |
| `spacevim#plug#` | プラグイン連携関数 | `spacevim#plug#fzf#Rg()` |
| `spacevim#lang#` | 言語サポート関数 | `spacevim#lang#go#Init()` |
| `spacevim#map#` | マッピング関連関数 | `spacevim#map#leader#desc` |
| `g:spacevim_` | space-vim設定変数 | `g:spacevim_layers` |
| `g:spacevim.` | space-vimオブジェクト | `g:spacevim.base`, `g:spacevim.loaded` |
| `s:` | スクリプトローカル変数 | `s:plug_options` |

### 3.3 キーマッピング規則

space-vimはspacemacsのニーモニックキーバインディングを採用しています:

| プレフィックス | 意味 | 例 |
|---------------|------|-----|
| `SPC b` | Buffer関連 | `SPC b b`: バッファ一覧 |
| `SPC f` | File/Find関連 | `SPC f f`: ファイル検索 |
| `SPC g` | Git関連 | `SPC g s`: git status |
| `SPC l` | LSP関連 | `SPC l g d`: 定義へジャンプ |
| `SPC p` | Project関連 | `SPC p f`: プロジェクト内ファイル検索 |
| `SPC s` | Search関連 | `SPC s b`: バッファ内検索 |
| `SPC t` | Toggle関連 | `SPC t g`: Git表示切替 |
| `SPC w` | Window関連 | `SPC w w`: 他ウィンドウへ移動 |
| `,` (LocalLeader) | 言語固有コマンド | `,v`: クイックオープン |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
space-vim/
├── init.vim              # メインエントリーポイント
├── init.spacevim         # ユーザー設定テンプレート
├── install.sh            # インストールスクリプト（Unix系）
├── install.cmd           # インストールスクリプト（Windows）
├── uninstall.sh          # アンインストールスクリプト
├── Makefile              # ビルド・インストール自動化
├── core/                 # コア機能
│   ├── autoload/         # 自動読み込み関数
│   │   └── spacevim/     # space-vim名前空間
│   │       ├── spacevim.vim      # メインモジュール
│   │       ├── cache.vim         # キャッシュ管理
│   │       ├── layer.vim         # レイヤー管理UI
│   │       ├── util.vim          # ユーティリティ関数
│   │       ├── vim/              # Vim操作関連
│   │       ├── plug/             # プラグイン連携
│   │       ├── lang/             # 言語サポート
│   │       ├── map/              # マッピング管理
│   │       └── autocmd/          # オートコマンド
│   ├── doc/              # ヘルプドキュメント
│   ├── ftplugin/         # ファイルタイプ別設定
│   ├── ftdetect/         # ファイルタイプ検出
│   └── plugin/           # プラグイン初期化
├── layers/               # レイヤー定義
│   ├── LAYERS.md         # レイヤー一覧
│   ├── +checkers/        # 構文チェック
│   ├── +completion/      # 補完機能
│   ├── +distributions/   # 基本設定
│   │   ├── better-defaults/  # デフォルト設定
│   │   └── spacevim/         # space-vimテーマ
│   ├── +fun/             # エンターテインメント
│   ├── +lang/            # 言語サポート
│   ├── +misc/            # その他
│   ├── +programming/     # プログラミング共通
│   ├── +themes/          # テーマ
│   ├── +tools/           # ツール連携
│   ├── +version-control/ # バージョン管理
│   └── +vim/             # Vim拡張
├── private/              # プライベート設定
│   ├── packages.vim      # プライベートプラグイン
│   └── config.vim        # プライベート設定
├── assets/               # 画像等のアセット
├── ci/                   # CI/CD設定
└── .github/              # GitHub設定
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `core/` | space-vimのコアロジック | `autoload/spacevim.vim` |
| `core/autoload/` | 自動読み込み関数の格納場所 | `spacevim/*.vim` |
| `core/ftplugin/` | ファイルタイプ別の設定 | `python.vim`, `go.vim` |
| `layers/` | 全てのレイヤー定義 | 各レイヤーの`packages.vim`, `config.vim` |
| `layers/+distributions/` | 基本的なVim設定 | `better-defaults/`, `spacevim/` |
| `layers/+lang/` | 言語別サポート | `python/`, `go/`, `rust/` |
| `layers/+tools/` | ツール連携 | `fzf/`, `lsp/`, `file-manager/` |
| `private/` | ユーザーのプライベート設定 | `packages.vim`, `config.vim` |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

space-vimは「レイヤードアーキテクチャ」と「プラグインアーキテクチャ」を組み合わせた設計を採用しています。

```
┌─────────────────────────────────────────────────┐
│                  ユーザー設定                    │
│               (~/.spacevim)                      │
│  ┌──────────────┐  ┌──────────────┐             │
│  │ UserInit()   │  │ UserConfig() │             │
│  └──────────────┘  └──────────────┘             │
└─────────────────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│              レイヤーシステム                    │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐           │
│  │ +lang/  │ │ +tools/ │ │ +vim/   │  ...      │
│  └─────────┘ └─────────┘ └─────────┘           │
│      │           │           │                  │
│      ▼           ▼           ▼                  │
│  packages.vim + config.vim                      │
└─────────────────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│               コアシステム                       │
│  ┌──────────────────────────────────────┐      │
│  │          spacevim#bootstrap()         │      │
│  │  ┌─────────────┐  ┌─────────────┐    │      │
│  │  │ begin()     │  │ end()       │    │      │
│  │  └─────────────┘  └─────────────┘    │      │
│  └──────────────────────────────────────┘      │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐           │
│  │ cache   │ │ util    │ │ layer   │  ...      │
│  └─────────┘ └─────────┘ └─────────┘           │
└─────────────────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│            vim-plug（プラグインマネージャ）       │
│  ┌──────────────────────────────────────┐      │
│  │ plug#begin() / plug#end()             │      │
│  └──────────────────────────────────────┘      │
└─────────────────────────────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│              外部プラグイン群                    │
│  fzf, ale, vim-fugitive, coc.nvim, etc.        │
└─────────────────────────────────────────────────┘
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| ユーザー設定層 | ユーザー固有のカスタマイズ | `~/.spacevim`, `private/` |
| レイヤー層 | 機能モジュールの提供 | `layers/+*/*/packages.vim` |
| コア層 | ブートストラップ、基盤機能 | `core/autoload/spacevim.vim` |
| プラグイン管理層 | vim-plugによるプラグイン管理 | `plug#begin/end` |

### 5.3 データフロー

**起動時のデータフロー:**

1. `init.vim` が読み込まれる
2. `g:spacevim` オブジェクトが初期化される
3. `spacevim#bootstrap()` が呼ばれる
4. キャッシュ (`info.vim`) からレイヤー情報を読み込む
5. `.spacevim` からユーザー設定を読み込む
6. 有効レイヤーの `packages.vim` を順に読み込む
7. `plug#begin/end` でプラグインを登録
8. 有効レイヤーの `config.vim` を順に読み込む
9. `UserConfig()` でユーザーカスタマイズを適用

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

**init.vim** がspace-vimのエントリーポイントです。

**実例:** `init.vim:17-41`
```vim
scriptencoding utf-8

let g:spacevim = get(g:, 'spacevim', {})
let g:spacevim.base = fnamemodify(resolve(expand('<sfile>:p')),':h')
let g:spacevim.version = '0.9.0'

" Identify platform {
let g:spacevim.os = {}
let g:spacevim.os.mac = has('macunix')
let g:spacevim.os.linux = has('unix') && !has('macunix') && !has('win32unix')
let g:spacevim.os.windows = has('win32')
" }

" Windows Compatible {
if g:spacevim.os.windows
  set runtimepath=$HOME/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,$HOME/.vim/after
endif
" }

let &runtimepath = &runtimepath . ',' . g:spacevim.base . '/core'

call spacevim#bootstrap()
```

### 6.2 コア機能

**spacevim.vim** はコアロジックを提供します。

主要関数:
- `spacevim#bootstrap()`: 初期化の起点
- `spacevim#begin()`: 初期化前半（コマンド定義、設定読み込み）
- `spacevim#end()`: 初期化後半（プラグイン登録、設定適用）
- `spacevim#load()`: 特定レイヤーが有効か確認

**実例:** `core/autoload/spacevim.vim:237-239`
```vim
" Util for config.vim and packages.vim
function! spacevim#load(layer) abort
  return index(g:spacevim.loaded, a:layer) > -1 ? 1 : 0
endfunction
```

### 6.3 キャッシュシステム

**cache.vim** はレイヤー情報のキャッシュを管理します。

**実例:** `core/autoload/spacevim/cache.vim:14-48`
```vim
function! s:init()
  let l:topic_base = g:spacevim.base."/layers"
  let l:topics_dir = split(globpath(l:topic_base, '*'), '\n')
  let l:topics_path = filter(l:topics_dir, 'isdirectory(v:val)')

  " ... レイヤー情報の収集 ...

  let s:cache = g:spacevim.info
  call writefile([printf("let g:spacevim.topics = %s", g:spacevim.topics)], s:cache)
  call writefile([printf("let g:spacevim.manifest = %s", g:spacevim.manifest)], s:cache, "a")
endfunction
```

### 6.4 ユーティリティ/共通機能

**util.vim** は汎用ユーティリティ関数を提供します。

主要関数:
- `spacevim#util#err()`: エラーメッセージ表示
- `spacevim#util#warn()`: 警告メッセージ表示
- `spacevim#util#RootDirectory()`: プロジェクトルートの取得
- `spacevim#util#VisualSelection()`: 選択テキストの取得

**実例:** `core/autoload/spacevim/util.vim:88-97`
```vim
function! spacevim#util#RootDirectory() abort
  let root_dir = s:is_in_git_repo()
  if root_dir != ''
    return root_dir
  endif
  if exists('*FindRootDirectory')
    let root_dir = FindRootDirectory()
  endif
  return root_dir == '' ? getcwd() : root_dir
endfunction
```

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| 遅延読み込み | プラグインを必要時にのみ読み込む | 高 | `packages.vim` 全般 |
| 機能検出 | 環境・機能の有無で分岐 | 高 | `init.vim`, `packages.vim` |
| autoload | 関数の遅延定義 | 高 | `core/autoload/**/*.vim` |
| コマンド定義 | カスタムコマンドの定義 | 中 | `config.vim` 全般 |
| キーマッピング | キーバインドの設定 | 高 | `keybindings.vim`, `config.vim` |

### 各パターンの詳細

#### パターン1: 遅延読み込み (Lazy Loading)

**目的:** 起動時間を短縮するため、プラグインを必要になるまで読み込まない

**実装例:**
```vim
" ファイル: layers/+distributions/better-defaults/packages.vim:5-15
if g:spacevim.speed_up_via_timer
  MP 'kshenoy/vim-signature'        , { 'on': [] }
  MP 'tpope/vim-rsi'                , { 'on': [] }
  MP 'markonm/traces.vim'           , { 'on': [] }
  MP 'dominikduda/vim_current_word' , { 'on': [] }
  call timer_start(500, 'spacevim#defer#defaults')
else
  MP 'tpope/vim-rsi'
  MP 'kshenoy/vim-signature'
  MP 'dominikduda/vim_current_word'
endif
```

**解説:**
- `{ 'on': [] }`: プラグインを即座に読み込まない
- `timer_start()`: 一定時間後に読み込み関数を呼び出す
- `spacevim#defer#*`: 遅延読み込み専用の関数群

#### パターン2: 機能検出 (Feature Detection)

**目的:** Vim/NeoVimの機能の有無に応じて処理を分岐

**実装例:**
```vim
" ファイル: init.vim:23-28
let g:spacevim.os = {}
let g:spacevim.os.mac = has('macunix')
let g:spacevim.os.linux = has('unix') && !has('macunix') && !has('win32unix')
let g:spacevim.os.windows = has('win32')
```

```vim
" ファイル: layers/+tools/fzf/config.vim:24-47
if exists('*nvim_open_win')
  let $FZF_DEFAULT_OPTS = '--layout=reverse'
  let g:fzf_layout = { 'window': 'call spacevim#util#FloatingWin()' }
else
  " フォールバック処理
  let g:fzf_colors = { ... }
endif
```

#### パターン3: Autoload関数パターン

**目的:** 関数を初回呼び出し時のみロードし、起動を高速化

**実装例:**
```vim
" ファイル: core/autoload/spacevim/plug/fzf.vim:8-15
function! spacevim#plug#fzf#Session()
  call fzf#run({
  \ 'source':  'ls -1 ~/.vim/session',
  \ 'sink':    'SLoad',
  \ 'options': '+m --prompt="Sessions> "',
  \ 'down':    '40%'
  \})
endfunction
```

**解説:**
- ファイルパス `autoload/spacevim/plug/fzf.vim` が関数名 `spacevim#plug#fzf#*` に対応
- 初回呼び出し時にファイルが自動的に読み込まれる

#### パターン4: execute によるキーマッピング動的生成

**目的:** ループを使って複数のキーマッピングを効率的に定義

**実装例:**
```vim
" ファイル: layers/+distributions/better-defaults/keybindings.vim:17-26
for s:i in range(1, 9)
  execute 'nnoremap <Leader>'.s:i ' :'.s:i.'wincmd w<CR>'
  execute 'nnoremap <Leader><Leader>'.s:i s:i.'gt'
  execute 'nnoremap <Leader>b'.s:i ':b'.s:i.'<CR>'
endfor
unlet s:i
```

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の業務フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定
2. 処理の流れを追跡（呼び出し関係を追う）
3. データの変換を確認
4. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: レイヤー有効化フロー

**概要:** ユーザーが`.spacevim`でレイヤーを有効化してから、プラグインがロードされるまでの流れ

**処理フロー:**
```
.spacevim → spacevim#bootstrap() → packages.vim読み込み → plug#end() → config.vim読み込み
```

**詳細な追跡:**

1. **ユーザー設定の読み込み** (`core/autoload/spacevim.vim:56-65`)
   ```vim
   function! s:check_dot_spacevim() abort
     if filereadable(expand(s:dot_spacevim))
       call s:Source(s:dot_spacevim)
       call extend(g:spacevim.loaded, get(g:, 'spacevim_layers', []))
       let g:mapleader = get(g:, 'spacevim_leader', "\<Space>")
       let g:maplocalleader = get(g:, 'spacevim_localleader', ',')
     else
       call spacevim#util#err('.spacevim does not exist! Exiting...')
     endif
   endfunction
   ```

2. **レイヤーのpackages.vim読み込み** (`core/autoload/spacevim.vim:176-195`)
   ```vim
   function! s:packages() abort
     " Load Layer packages
     for l:layer in g:spacevim.loaded
       try
         let l:layer_packages = g:spacevim.manifest[l:layer].dir . '/packages.vim'
       catch
         call spacevim#cache#init()
       endtry
       call s:Source(l:layer_packages)
     endfor
     " ...
   endfunction
   ```

3. **プラグイン登録完了** (`core/autoload/spacevim.vim:173`)
   ```vim
   call plug#end()
   ```

4. **レイヤーのconfig.vim読み込み** (`core/autoload/spacevim.vim:197-208`)
   ```vim
   function! s:config() abort
     " Load Layer config
     cal map(copy(g:spacevim.loaded), 's:Source(g:spacevim.manifest[v:val].dir . "/config.vim")')
     " ...
   endfunction
   ```

#### 例2: fzfファイル検索フロー

**概要:** `SPC f f` でファイル検索が実行されるまでの流れ

**処理フロー:**
```
キー入力 → キーマッピング → spacevim#map#manager#Files() → fzf#vim#files()
```

**詳細な追跡:**

1. **キーマッピング定義** (`layers/+tools/fzf/config.vim:1`)
   ```vim
   nnoremap <silent><Leader>ff :<c-u>call spacevim#map#manager#Files()<CR>
   ```

2. **マネージャー関数呼び出し** (概念的)
   ```vim
   " spacevim#map#manager#Files() が呼ばれる
   " これはfzf, LeaderF, Clap等のどれを使うかを判定して
   " 適切な検索関数を呼び出す
   ```

3. **fzf検索実行** (`layers/+tools/fzf/config.vim:53-54`)
   ```vim
   command! -bang -nargs=? -complete=dir Files
     \ echo "\r\r" | call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)
   ```

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか
- [ ] 呼び出し関係を把握したか
- [ ] データの変換ポイントを確認したか
- [ ] エラーハンドリングを確認したか
- [ ] 最終的な出力を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` - プロジェクト概要、インストール方法
2. `layers/LAYERS.md` - 利用可能なレイヤー一覧
3. `init.vim` + `core/autoload/spacevim.vim` - ブートストラップの流れ

#### 特定機能を理解したい場合
1. `layers/+カテゴリ/レイヤー名/README.md` - レイヤーの概要
2. `layers/+カテゴリ/レイヤー名/packages.vim` - 使用プラグイン
3. `layers/+カテゴリ/レイヤー名/config.vim` - 設定とキーバインド

#### 改修作業を行う場合
1. 対象レイヤーの `README.md`
2. `core/autoload/spacevim/*.vim` - コア機能
3. 既存レイヤーの実装パターンを参照

#### 新しいレイヤーを追加したい場合
1. 既存レイヤーの構造を確認 (`layers/+tools/fzf/` など)
2. `packages.vim` の書き方を学ぶ
3. `config.vim` でキーマッピングを定義

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| `README.md` | プロジェクト全体の説明 | 最初に読む |
| `layers/LAYERS.md` | レイヤー一覧と依存プラグイン | レイヤー選択時 |
| `init.spacevim` | ユーザー設定テンプレート | カスタマイズ時 |
| `core/doc/spacevim.txt` | Vimヘルプ形式のドキュメント | `:help spacevim` |
| 各レイヤーの `README.md` | レイヤー固有の説明 | 特定機能の理解時 |
| `CHANGELOG.md` | 変更履歴 | バージョン確認時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: `MP` コマンドが見つからない
A: `MP` は `s:my_plugin` のエイリアスです。`core/autoload/spacevim.vim:49` で定義されています:
```vim
command! -nargs=+ -bar MP call s:my_plugin(<args>)
```

#### Q: `g:spacevim.loaded` にはどのレイヤーが入っているか？
A: `.spacevim` の `g:spacevim_layers` に定義されたレイヤーと、`Layer` コマンドで追加されたレイヤーが格納されます。`:echo g:spacevim.loaded` で確認できます。

#### Q: キーマッピングがどこで定義されているか分からない
A: `:verbose map <キー>` コマンドで、マッピングの定義元ファイルを確認できます。

#### Q: 特定のプラグインがロードされているか確認したい
A: `:PlugStatus` コマンドでインストール済みプラグインを確認できます。

### デバッグのヒント

1. **変数の確認:**
   ```vim
   :echo g:spacevim          " space-vimオブジェクト全体
   :echo g:spacevim.loaded   " 有効なレイヤー一覧
   :echo g:spacevim.manifest " レイヤーのパス情報
   ```

2. **関数の呼び出し元追跡:**
   ```vim
   :verbose function spacevim#util#err
   ```

3. **プロファイリング:**
   ```vim
   :call spacevim#util#ProfileStart()
   " 遅い操作を実行
   :call spacevim#util#ProfileStop()
   " profile.log を確認
   ```

4. **`:LayerStatus` コマンド:**
   有効なレイヤーを一覧表示します。

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| Layer | 関連するプラグインと設定をグループ化したモジュール |
| Topic | レイヤーのカテゴリ（`+lang`, `+tools` など） |
| MP | My Plugin - space-vim独自のプラグイン登録コマンド |
| Leader | 多くのキーバインドの起点となるキー（デフォルト: Space） |
| LocalLeader | 言語固有コマンドの起点（デフォルト: カンマ） |
| autoload | 初回呼び出し時に自動的に読み込まれる関数機構 |
| vim-plug | space-vimが使用するプラグインマネージャ |
| runtimepath | Vimがスクリプトを検索するパスのリスト |
| ftplugin | ファイルタイプ別のプラグイン設定 |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `init.vim` | エントリーポイント | 起動処理、プラットフォーム検出 |
| `init.spacevim` | 設定テンプレート | ユーザー設定の雛形 |
| `core/autoload/spacevim.vim` | コアモジュール | ブートストラップ、レイヤー管理 |
| `core/autoload/spacevim/cache.vim` | キャッシュ | レイヤー情報のキャッシュ |
| `core/autoload/spacevim/layer.vim` | レイヤーUI | `:LayerStatus` 実装 |
| `core/autoload/spacevim/util.vim` | ユーティリティ | 共通関数群 |
| `core/autoload/spacevim/plug/*.vim` | プラグイン連携 | fzf, ale等との連携 |
| `core/autoload/spacevim/lang/*.vim` | 言語サポート | LSP, 言語別設定 |
| `core/autoload/spacevim/map/*.vim` | マッピング | キーバインド定義 |
| `layers/LAYERS.md` | レイヤー一覧 | 全レイヤーとプラグイン |
| `layers/+*/*/packages.vim` | プラグイン定義 | レイヤー別プラグイン |
| `layers/+*/*/config.vim` | 設定 | レイヤー別設定 |

### C. 参考資料

- [Vim script リファレンス](https://vim-jp.org/vimdoc-ja/eval.html)
- [vim-plug ドキュメント](https://github.com/junegunn/vim-plug)
- [spacemacs ドキュメント](http://spacemacs.org/doc/DOCUMENTATION.html)
- [space-vim Wiki](https://github.com/liuchengxu/space-vim/wiki)
- [Neovim API リファレンス](https://neovim.io/doc/user/api.html)
