# 機能設計書 51-自動ペア挿入・インデント

## 概要

本ドキュメントは、Doom Emacsの`emacs/electric`モジュールが提供する自動ペア挿入・インデント機能の設計仕様を記述する。括弧やクォートなどのペア文字の自動挿入と、キーワードベースの電気インデント機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：プログラミングにおいて、括弧や引用符などのペア文字の入力は頻繁に発生する。これらを自動的に補完することで、入力効率の向上とペアの不一致によるエラーを防止する。また、特定のキーワード入力後に自動的にインデントを調整することで、コードの可読性を維持しながら効率的な入力を可能にする。

**機能の利用シーン**：
- プログラミング中に開き括弧を入力した際、対応する閉じ括弧を自動挿入
- 言語固有のキーワード（`end`, `fi`, `done`等）を入力した際の自動インデント調整
- Org-modeなどでの引用符の自動変換処理

**主要な処理内容**：
1. `electric-indent-mode`の拡張による、キーワードベースの自動インデント
2. `set-electric!`マクロによるモード単位での電気インデント設定
3. `electric-quote-mode`とsmartparensの競合解決
4. 行末でのキーワード検出と再インデントの実行

**関連システム・外部連携**：
- Emacs組み込みの`electric.el`パッケージ
- smartparensパッケージ（ペア文字挿入）
- 各メジャーモード固有のインデント設定

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

本機能は画面機能マッピングに定義された直接的な画面との関連を持たない。エディタバッファ全般で動作するバックグラウンド機能である。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全エディタバッファ | 主画面 | テキスト入力時のペア文字挿入・インデント調整 |

## 機能種別

テキスト編集支援 / 自動補完処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| modes | symbol または list | Yes | 電気インデントを有効にするメジャーモード | シンボルまたはシンボルのリスト |
| :words | list of strings | No | インデントをトリガーする単語リスト | 文字列のリスト |
| :chars | list of chars | No | インデントをトリガーする文字リスト | 文字のリスト |

### 入力データソース

- ユーザーのキーボード入力
- メジャーモードのフック設定
- `+electric-indent-words`バッファローカル変数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| インデント済みテキスト | string | 自動調整されたインデントを持つテキスト |
| ペア文字 | char | 自動挿入された対応する閉じ文字 |

### 出力先

- 現在のエディタバッファ

## 処理フロー

### 処理シーケンス

```
1. ユーザーが文字を入力
   └─ electric-indent-functions フックが呼び出される
2. +electric-indent-char-fn が実行
   └─ 行末かつ +electric-indent-words が設定されているかチェック
3. キーワードマッチング
   └─ backward-word で前の単語を取得し、+electric-indent-words とマッチング
4. マッチした場合、インデントを再計算
   └─ indent-according-to-mode を実行
```

### フローチャート

```mermaid
flowchart TD
    A[文字入力] --> B{行末か?}
    B -->|No| E[通常処理]
    B -->|Yes| C{+electric-indent-words設定あり?}
    C -->|No| E
    C -->|Yes| D{前の単語がキーワードか?}
    D -->|No| E
    D -->|Yes| F[インデント再計算]
    F --> G[バッファ更新]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-51-01 | キーワードインデント | 指定キーワード入力後に自動インデント | 行末で+electric-indent-wordsに含まれる単語を入力時 |
| BR-51-02 | デフォルト電気文字 | 改行と削除で電気インデント発動 | electric-indent-modeが有効時 |
| BR-51-03 | electric-quote順序 | smartparensより先にelectric-quoteを処理 | electric-quote-modeが有効時 |

### 計算ロジック

- キーワードマッチング: `(looking-at-p (concat "\\<" (regexp-opt +electric-indent-words)))`
- 前の単語への移動: `backward-word`

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 設定エラー | 無効なモードシンボルを指定 | エラーメッセージを表示し、設定をスキップ |

### リトライ仕様

リトライ処理は不要。

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

トランザクション処理は不要（単一バッファ操作）。

## パフォーマンス要件

- キー入力に対するレスポンス: 即時（体感遅延なし）
- キーワードマッチング: O(n) where n = キーワードリストの長さ

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

特になし。ローカルバッファ内のテキスト操作のみ。

## 備考

- Org-modeのソースブロック内では`electric-quote-inhibit-functions`を考慮
- smartparensとの競合を避けるため、`post-self-insert-hook`の優先度を調整

---

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

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

### 推奨読解順序

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

まず、電気インデントで使用されるキーとなる変数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | config.el | `modules/emacs/electric/config.el` | `+electric-indent-words`変数の定義（5-7行目） |

**読解のコツ**: `defvar-local`はバッファローカル変数を定義するEmacs Lispの特殊形式。各バッファで独立した値を持つ。

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

処理の起点となるフック設定を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | config.el | `modules/emacs/electric/config.el` | `after! electric`ブロック（10-27行目） |

**主要処理フロー**:
1. **11行目**: デフォルトの電気インデント文字を改行(`?\n`)と削除(`?\^?`)に設定
2. **13-18行目**: `+electric-indent-char-fn`をフックに追加
3. **23-27行目**: `electric-quote-mode`のフック順序を調整

#### Step 3: 設定API（set-electric!）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | autoload.el | `modules/emacs/electric/autoload.el` | `set-electric!`関数の定義（4-26行目） |

**主要処理フロー**:
- **12行目**: モードをリスト化して処理
- **13-14行目**: モード用のフック名と関数名を生成
- **15-17行目**: plistがnilの場合はフックを削除
- **18-25行目**: フック関数を定義し、電気インデントを有効化

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

```
set-electric! (autoload.el)
    │
    ├─ ensure-list (modes)
    │
    ├─ fset (+electric--init-MODE-h)
    │      │
    │      ├─ electric-indent-local-mode
    │      ├─ setq-local electric-indent-chars
    │      └─ setq +electric-indent-words
    │
    └─ add-hook (MODE-hook)

+electric-indent-char-fn (config.el)
    │
    ├─ eolp (行末チェック)
    │
    ├─ backward-word
    │
    └─ looking-at-p (regexp-opt +electric-indent-words)
```

### データフロー図

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

キー入力 ───▶ electric-indent-functions ───▶ インデント調整
                      │
                      ▼
              +electric-indent-char-fn
                      │
                      ▼
              キーワードマッチング
                      │
                      ▼
              indent-according-to-mode
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| config.el | `modules/emacs/electric/config.el` | ソース | メイン設定ファイル、フック定義 |
| autoload.el | `modules/emacs/electric/autoload.el` | ソース | `set-electric!`マクロの定義 |
