# 機能設計書 44-ファイルテンプレート自動挿入

## 概要

本ドキュメントは、Doom Emacsにおけるファイルテンプレート自動挿入機能の設計仕様を記述する。yasnippetを基盤として、新規ファイル作成時にファイルタイプやパスに応じたテンプレートを自動展開する。

### 本機能の処理概要

**業務上の目的・背景**：ソフトウェア開発において、新しいファイルを作成する際には定型的なボイラープレートコードや構造が必要となることが多い。例えば、新しいPythonファイルにはモジュールドキュメント、HTMLファイルには基本構造、Doomモジュールファイルにはヘッダーコメントが必要である。本機能は、これらの反復的な作業を自動化し、開発者の生産性を向上させる。

**機能の利用シーン**：
- 新しいソースファイルを作成する際
- Doomモジュールの新規ファイル（config.el, packages.el等）作成時
- プロジェクト設定ファイル（Makefile, package.json等）作成時
- ライセンスファイルの挿入時

**主要な処理内容**：
1. 新規ファイル作成時のテンプレート適用判定
2. ファイルパスまたはメジャーモードに基づくルールマッチング
3. yasnippetスニペットの展開
4. カスタムトリガー関数による動的テンプレート生成
5. プロジェクト依存テンプレートのサポート

**関連システム・外部連携**：
- yasnippet: スニペット展開エンジン
- doom-project: プロジェクト検出
- doom-user-dir/doom-emacs-dir: テンプレートパス判定

**権限による制御**：特になし（全ユーザーが利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面関連なし（バックグラウンド処理） |

## 機能種別

テンプレート展開 / 自動化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| +file-templates-alist | alist | No | テンプレートルールのリスト | - |
| +file-templates-default-trigger | string | No | デフォルトトリガーキー（デフォルト: "__"） | - |
| +file-templates-dir | string | No | テンプレートディレクトリ | 存在するディレクトリ |
| +file-templates-inhibit | boolean | No | テンプレート展開の抑制フラグ | - |

### 入力データソース

- buffer-file-name: 新規ファイルのパス
- major-mode: バッファのメジャーモード
- doom-switch-buffer-hookイベント

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 展開されたテンプレート | string | バッファに挿入されるテンプレート内容 |

### 出力先

- 新規作成されたバッファ

## 処理フロー

### 処理シーケンス

```
1. doom-switch-buffer-hookトリガー
   └─ +file-templates-check-h呼び出し
2. 適用条件チェック
   ├─ +file-templates-inhibit = nil
   ├─ buffer-file-name != nil
   ├─ buffer-read-only = nil
   ├─ バッファが空（bobp and eobp）
   ├─ 特殊バッファでない
   ├─ org-captureバッファでない
   └─ 新規ファイル（file-exists-p = nil）
3. ルールマッチング
   └─ +file-templates-alistから適用ルール検索
4. テンプレート展開
   ├─ triggerが関数: 関数実行
   └─ triggerが文字列: yasnippet展開
5. Evilモード時: insert stateへ遷移
```

### フローチャート

```mermaid
flowchart TD
    A[バッファ切り替え] --> B{適用条件チェック}
    B -->|条件不一致| C[処理終了]
    B -->|条件一致| D[ルールマッチング]

    D --> E{ルール検索}
    E -->|見つからない| C
    E -->|見つかる| F{:ignore?}

    F -->|Yes| C
    F -->|No| G{:project?}

    G -->|Yes| H{プロジェクト内?}
    H -->|No| C
    H -->|Yes| I[テンプレート展開]
    G -->|No| I

    I --> J{triggerの種類}
    J -->|関数| K[関数実行]
    J -->|文字列| L[yasnippet展開]

    K --> M{Evil有効?}
    L --> M
    M -->|Yes| N[Insert Stateへ]
    M -->|No| O[処理完了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 空バッファのみ | テンプレートは空のバッファにのみ適用 | 常時 |
| BR-02 | 新規ファイルのみ | ファイルが既に存在する場合は適用しない | 常時 |
| BR-03 | 特殊バッファ除外 | "*"や" "で始まるバッファには適用しない | 常時 |
| BR-04 | org-capture除外 | org-captureバッファには適用しない | 常時 |
| BR-05 | プロジェクト限定 | :projectフラグありのルールはプロジェクト内のみ | ルール定義による |
| BR-06 | :whenによる条件 | :when関数がnilを返したらスキップ | ルール定義による |

### 計算ロジック

ルールマッチング:
```elisp
(defun +file-template-p (rule)
  (let ((pred (car rule))
        (plist (cdr rule)))
    (and (or (and (symbolp pred)
                  (eq major-mode pred))
             (and (stringp pred)
                  (stringp buffer-file-name)
                  (string-match-p pred buffer-file-name)))
         (or (not (plist-member plist :when))
             (funcall (plist-get plist :when) buffer-file-name))
         rule)))
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | user-error | モードが判定できない | エラーメッセージ表示 |
| - | error | スニペットが見つからない | 静かに失敗（テンプレート未適用） |

### リトライ仕様

リトライ処理は実装されていない。

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

トランザクション処理は不要。

## パフォーマンス要件

- テンプレート検索: 即座（リスト走査のみ）
- スニペット展開: yasnippetの性能に依存

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

- テンプレートファイルはユーザーディレクトリまたはDoomディレクトリから読み込み
- 外部からのテンプレート注入は想定していない

## 備考

- `set-file-template!`マクロで新しいルールを追加可能
- `set-file-templates!`で複数ルールを一括追加可能
- `:trigger`にシンボルや関数を指定してカスタムテンプレート生成が可能

---

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

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

### 推奨読解順序

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

テンプレートルールのデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | config.el | `modules/editor/file-templates/config.el` | +file-templates-alist変数 |

**読解のコツ**:
- **3-9行目**: 変数定義（+file-templates-dir, +file-templates-default-trigger等）
- **14-119行目**: デフォルトのテンプレートルール定義
- ルールはCAR（述語: メジャーモードまたは正規表現）とCDR（plist）で構成

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | config.el | `modules/editor/file-templates/config.el` | フック設定 |

**主要処理フロー**:
- **145-158行目**: `+file-templates-check-h`関数（バッファフックで呼ばれる）
- **180行目**: `doom-switch-buffer-hook`への登録

#### Step 3: テンプレート展開処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | autoload.el | `modules/editor/file-templates/autoload.el` | 展開処理 |

**主要処理フロー**:
- **56-84行目**: `+file-templates--expand`関数（実際の展開処理）
- **70-83行目**: yasnippetスニペット検索と展開

#### Step 4: ルール設定APIを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | autoload.el | `modules/editor/file-templates/autoload.el` | API関数 |

**主要処理フロー**:
- **11-40行目**: `set-file-template!`マクロ
- **43-49行目**: `set-file-templates!`マクロ

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

```
doom-switch-buffer-hook
    │
    └─ +file-templates-check-h
           │
           ├─ 条件チェック（+file-templates-inhibit等）
           │
           ├─ +file-templates/apply
           │      │
           │      └─ cl-find-if #'+file-template-p
           │             └─ ルールマッチング
           │
           └─ +file-templates--expand
                  │
                  ├─ (functionp trigger)
                  │      └─ funcall trigger
                  │
                  └─ (stringp trigger)
                         ├─ yas-minor-mode-on
                         ├─ yas--all-templates
                         └─ yas-expand-snippet
```

### データフロー図

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

新規ファイル作成      ┌──────────────────────┐
(find-file)    ───▶  │ doom-switch-buffer   │
                      │ -hook                │
                      └──────────────────────┘
                               │
                               ▼
                      ┌──────────────────────┐
                      │ +file-templates      │
                      │ -check-h             │
buffer-file-name ───▶│                      │
major-mode     ───▶  │ ルールマッチング      │
                      └──────────────────────┘
                               │
                               ▼
                      ┌──────────────────────┐
+file-templates ───▶  │ +file-templates      │
-alist               │ --expand             │
                      └──────────────────────┘
                               │
                               ▼
                      ┌──────────────────────┐
yasnippet      ───▶  │ yas-expand-snippet   │ ───▶ バッファ内容
スニペット            └──────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| config.el | `modules/editor/file-templates/config.el` | ソース | モジュール設定、ルール定義 |
| autoload.el | `modules/editor/file-templates/autoload.el` | ソース | API関数、展開処理 |
| packages.el | `modules/editor/file-templates/packages.el` | 設定 | 依存パッケージ（なし、yasnippetはコアで提供） |
| templates/ | `modules/editor/file-templates/templates/` | テンプレート | スニペットファイル |
