# 機能設計書 59-コードスニペット

## 概要

本ドキュメントは、space-vimにおけるコードスニペット機能の設計を定義する。UltiSnipsとvim-snippetsを利用したスニペット展開・編集機能を提供する。

### 本機能の処理概要

コーディング効率を向上させるため、よく使用するコードパターンをスニペットとして定義し、トリガーキーで展開する機能を提供する。

**業務上の目的・背景**：ソフトウェア開発においては、関数定義、クラス宣言、ループ構造など繰り返し記述するコードパターンが多数存在する。これらをスニペットとして定義し、短いトリガー文字列から展開できるようにすることで、タイピング量を削減し、コーディング速度を大幅に向上させる。

**機能の利用シーン**：任意のプログラミング言語でコードを記述する際に利用される。挿入モードでスニペットのトリガー文字列を入力し、展開キーを押すことでコードブロックが挿入される。プレースホルダー間をタブキーで移動しながら値を入力できる。

**主要な処理内容**：
1. スニペットの定義読み込み（UltiSnips）
2. トリガー文字列からのスニペット展開
3. プレースホルダー間のジャンプナビゲーション
4. 補完プラグイン（ncm2）との連携
5. カスタムスニペットの追加サポート

**関連システム・外部連携**：UltiSnipsスニペットエンジン、vim-snippetsスニペット集、ncm2補完フレームワークとの連携。

**権限による制御**：特になし。レイヤー有効化によりすべての機能が利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | 補完ポップアップ | 補助機能 | UltiSnipsによるスニペット候補の補完連携 |
| 19 | UltiSnips（スニペット展開） | 主機能 | UltiSnipsによるスニペット展開・編集 |

## 機能種別

コード生成 / 開発支援 / テンプレート展開

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| g:UltiSnipsSnippetDirectories | List | No | スニペットディレクトリ | 配列 |
| g:UltiSnipsSnippetsDir | String | No | カスタムスニペット保存先 | パス |
| g:UltiSnipsExpandTrigger | String | No | 展開トリガーキー | キーマッピング |
| g:UltiSnipsJumpForwardTrigger | String | No | 次のプレースホルダーへジャンプ | キーマッピング |
| g:UltiSnipsJumpBackwardTrigger | String | No | 前のプレースホルダーへジャンプ | キーマッピング |

### 入力データソース

- スニペット定義ファイル（.snippets）
- トリガー文字列（ユーザー入力）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 展開コード | テキスト | スニペットから生成されたコード |
| プレースホルダー | テキスト | 入力待ちのフィールド |

### 出力先

- Vimエディタ画面（バッファ）

## 処理フロー

### 処理シーケンス

```
1. レイヤー読み込み
   └─ +programming/code-snippetsレイヤーが有効化される
2. プラグイン読み込み
   └─ ultisnipsとvim-snippetsがvim-plugにより読み込まれる（遅延読み込み）
3. 設定適用
   └─ config.vimの設定が適用される
4. 挿入モード開始
   └─ InsertEnterイベントでプラグインがロードされる
5. スニペット展開
   └─ トリガー文字列入力後、展開キーでコード挿入
6. プレースホルダーナビゲーション
   └─ C-j/C-kでプレースホルダー間を移動
```

### フローチャート

```mermaid
flowchart TD
    A[Vim起動] --> B{code-snippetsレイヤー有効?}
    B -->|Yes| C[プラグイン登録（遅延）]
    B -->|No| Z[終了]
    C --> D[設定適用]
    D --> E{挿入モード開始?}
    E -->|Yes| F[ultisnips/vim-snippetsロード]
    E -->|No| G[待機]
    G --> E
    F --> H[スニペット定義読み込み]
    H --> I[編集可能状態]
    I --> J{トリガー文字列入力?}
    J -->|Yes| K[展開キー押下?]
    J -->|No| I
    K -->|Yes| L[スニペット展開]
    K -->|No| I
    L --> M[プレースホルダーにカーソル]
    M --> N{C-j/C-k?}
    N -->|C-j| O[次のプレースホルダー]
    N -->|C-k| P[前のプレースホルダー]
    N -->|No| Q[入力継続]
    O --> M
    P --> M
    Q --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-01 | レイヤー依存 | +programming/code-snippetsレイヤーの有効化が必要 | .spacevimファイルでレイヤー指定時 |
| BR-59-02 | 遅延読み込み | InsertEnterイベントでプラグインロード | on_event: 'InsertEnter' |
| BR-59-03 | ジャンプキー | C-jで次、C-kで前のプレースホルダー | デフォルト設定 |
| BR-59-04 | 展開トリガー | ncm2連携時はPlug、単独時はC-e | ncm2-ultisnipsプラグインの有無 |
| BR-59-05 | カスタムスニペット | ~/.vim/UltiSnipsに保存 | g:UltiSnipsSnippetsDir設定 |

### 計算ロジック

特になし

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

### 操作別データベース影響一覧

該当なし（データベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | プラグイン未インストール | vim-plugによるインストール未完了 | :PlugInstall実行 |
| - | Python未インストール | UltiSnipsはPython必須 | Pythonのインストール |
| - | スニペット構文エラー | .snippetsファイルに構文エラー | エラーメッセージ確認・修正 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- スニペット展開：50ms以下
- プレースホルダージャンプ：即時

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

- スニペット定義にはPythonコードを埋め込み可能
- 信頼できるスニペットのみ使用すること

## 備考

- vim-snippetsには多数の言語向けスニペットが同梱
- :UltiSnipsEditでファイルタイプ別スニペット編集
- ncm2との連携で補完候補としてスニペットを表示可能

---

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

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

### 推奨読解順序

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

コードスニペットレイヤーは設定ファイルとプラグイン登録で構成される。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | config.vim | `layers/+programming/code-snippets/config.vim` | UltiSnips設定変数の確認 |

**読解のコツ**: `g:UltiSnips*`変数はUltiSnips固有の設定。`has_key(g:plugs, 'ncm2-ultisnips')`でncm2連携の有無を判定。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | packages.vim | `layers/+programming/code-snippets/packages.vim` | MPマクロによるプラグイン登録 |

**主要処理フロー**:
1. **3行目**: `MP 'SirVer/ultisnips', { 'on': [], 'on_event': 'InsertEnter' }` - UltiSnips登録（InsertEnterで遅延読み込み）
2. **4行目**: `MP 'honza/vim-snippets', { 'on': [], 'on_event': 'InsertEnter' }` - vim-snippets登録（InsertEnterで遅延読み込み）

#### Step 3: 設定ファイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | config.vim | `layers/+programming/code-snippets/config.vim` | UltiSnips詳細設定 |

**主要処理フロー**:
- **5行目**: `g:UltiSnipsSnippetDirectories=['UltiSnips']` - スニペットディレクトリ設定
- **6行目**: runtimepathにprivate/UltiSnipsを追加
- **7行目**: `g:UltiSnipsSnippetsDir = '~/.vim/UltiSnips'` - カスタムスニペット保存先
- **10行目**: `g:UltiSnipsJumpForwardTrigger = "<c-j>"` - 次のプレースホルダーへC-j
- **11行目**: `g:UltiSnipsJumpBackwardTrigger = "<c-k>"` - 前のプレースホルダーへC-k
- **13-22行目**: ncm2-ultisnips連携時の特別設定
  - CRキーでスニペット展開
  - C-uで展開トリガー
  - `g:UltiSnipsExpandTrigger = "<Plug>(ultisnips_expand)"`

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

```
.spacevim (ユーザー設定)
    │
    └─ Layer '+programming/code-snippets' 有効化
           │
           ├─ packages.vim
           │      ├─ MP 'SirVer/ultisnips' (遅延読み込み)
           │      └─ MP 'honza/vim-snippets' (遅延読み込み)
           │
           └─ config.vim
                  ├─ スニペットディレクトリ設定
                  ├─ ジャンプキー設定 (C-j/C-k)
                  │
                  └─ ncm2連携判定
                         │
                         ├─ ncm2あり: Plug trigger + CR展開
                         └─ ncm2なし: C-e展開
```

### データフロー図

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

.spacevim ───▶ レイヤーシステム ───▶ プラグイン登録
                     │
                     ▼
InsertEnter ───▶ ultisnips/vim-snippetsロード
                     │
                     ▼
.snippets ───▶ スニペット定義読み込み
                     │
                     ▼
トリガー文字列 ───▶ UltiSnips ───▶ 展開コード挿入
                     │
                     ▼
C-j/C-k ───▶ プレースホルダージャンプ ───▶ カーソル移動
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| packages.vim | `layers/+programming/code-snippets/packages.vim` | 設定 | UltiSnips、vim-snippets登録 |
| config.vim | `layers/+programming/code-snippets/config.vim` | 設定 | UltiSnips詳細設定 |
| LAYERS.md | `layers/LAYERS.md` | ドキュメント | レイヤー一覧とプラグイン情報 |
