# 機能設計書 46-コードフォーマッタ統合

## 概要

本ドキュメントは、Doom Emacsにおけるコードフォーマッタ統合機能の設計仕様を記述する。apheleia.elを基盤として、各プログラミング言語に対応したフォーマッタ（prettier, black, gofmt等）を統一的なインターフェースで呼び出し、保存時の自動フォーマットやリージョンフォーマットを実現する。

### 本機能の処理概要

**業務上の目的・背景**：ソフトウェア開発において、コードスタイルの一貫性を保つことは可読性とメンテナンス性の向上に直結する。各言語には標準的なフォーマッタ（Go: gofmt、Python: black/ruff、JavaScript: prettier等）が存在し、これらを統一的に利用できることが望ましい。本機能は、言語ごとのフォーマッタを透過的に呼び出し、開発者がコードスタイルに気を取られることなく本来の開発に集中できる環境を提供する。

**機能の利用シーン**：
- ファイル保存時の自動フォーマット
- 手動でのバッファ/リージョンフォーマット
- LSPサーバーによるフォーマット
- プロジェクト固有のフォーマッタ設定適用

**主要な処理内容**：
1. 保存時の自動フォーマット（+onsaveフラグ有効時）
2. バッファ全体のフォーマット（+format/buffer）
3. 選択リージョンのフォーマット（+format/region）
4. LSPサーバーを使用したフォーマット（+lspフラグ有効時）
5. フォーマッタの自動検出と設定

**関連システム・外部連携**：
- apheleia: 非同期フォーマットエンジン
- lsp-mode: LSPフォーマット連携
- eglot: LSPフォーマット連携（代替）
- 各種フォーマッタ: prettier, black, gofmt, clang-format等

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面関連なし（エディタ機能） |

## 機能種別

コードフォーマット / 自動化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| +format-on-save-disabled-modes | list | No | 自動フォーマット無効モードのリスト | シンボルのリスト |
| +format-with (apheleia-formatter) | symbol | No | 使用するフォーマッタ | - |
| beg | integer | Yes(region) | リージョン開始位置 | バッファ内位置 |
| end | integer | Yes(region) | リージョン終了位置 | バッファ内位置 |

### 入力データソース

- バッファ内容
- ユーザー設定（init.el/config.el）
- プロジェクト設定ファイル（.prettierrc, pyproject.toml等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| フォーマット済みコード | string | フォーマッタが出力した整形済みコード |

### 出力先

- バッファ（フォーマット結果で置換）

## 処理フロー

### 処理シーケンス

```
1. フォーマットコマンド呼び出し or 保存フック
   └─ apheleia-format-buffer (バッファ) / +format-region (リージョン)
2. フォーマッタ決定
   ├─ +format-with が設定されていれば使用
   └─ apheleia-mode-alist からメジャーモードで検索
3. フォーマッタプロセス起動
   └─ 非同期でフォーマッタを実行
4. 結果の適用
   └─ diff計算により最小限の変更でバッファ更新
5. フック実行
   └─ apheleia-post-format-hook (vc-gutter更新等)
```

### フローチャート

```mermaid
flowchart TD
    A[フォーマット要求] --> B{要求種別}
    B -->|保存時| C{自動フォーマット有効?}
    B -->|手動| D[フォーマッタ決定]

    C -->|無効モード| E[フォーマットスキップ]
    C -->|有効| D

    D --> F{+format-with設定?}
    F -->|Yes| G[指定フォーマッタ使用]
    F -->|No| H[apheleia-mode-alistから検索]

    G --> I[フォーマッタプロセス起動]
    H --> I

    I --> J[非同期実行]
    J --> K[結果受信]
    K --> L[diff計算]
    L --> M[バッファ更新]
    M --> N[post-format-hook]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 無効モード | +format-on-save-disabled-modesのモードでは自動フォーマットしない | 常時 |
| BR-02 | プレフィックス引数 | save-bufferにプレフィックス引数を付けると自動フォーマットをスキップ | 常時 |
| BR-03 | インデント尊重 | プロジェクト設定がない場合、Emacsのインデント設定を使用 | prettier, clang-format |
| BR-04 | LSP優先 | +lspフラグ有効時、LSPサーバーのフォーマット機能を優先 | lsp-mode/eglot有効時 |

### 計算ロジック

フォーマット無効判定:
```elisp
(defun +format-maybe-inhibit-h ()
  (or (eq major-mode 'fundamental-mode)
      (string-blank-p (buffer-name))
      (eq +format-on-save-disabled-modes t)
      (not (null (memq major-mode +format-on-save-disabled-modes)))))
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | error | フォーマッタが見つからない | エラーメッセージ表示、フォーマットスキップ |
| - | error | フォーマッタがエラーを返した | エラーログ出力、元のバッファ内容を維持 |

### リトライ仕様

リトライ処理は実装されていない。フォーマットに失敗した場合は元のバッファ内容を維持。

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

トランザクション処理は不要。フォーマット結果はdiffベースで適用され、失敗時は元の状態を維持。

## パフォーマンス要件

- フォーマット処理: 非同期実行のためUIブロックなし
- 結果適用: diff計算により最小限の変更

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

- フォーマッタは外部プロセスとして実行
- プロジェクト設定ファイルからの設定読み込みに注意

## 備考

- `apheleia-log-debug-info`を有効にするとデバッグ情報を出力
- `+format-with`でバッファローカルにフォーマッタを指定可能
- LSPフォーマットは`+format-with 'lsp`で明示的に指定可能

---

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

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

### 推奨読解順序

#### Step 1: 設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | config.el | `modules/editor/format/config.el` | apheleia設定、フォーマッタ定義 |

**読解のコツ**:
- **3-13行目**: `+format-on-save-disabled-modes`変数
- **16-17行目**: `+format-with`, `+format-inhibit`のエイリアス定義
- **23-130行目**: apheleia設定（use-package!ブロック）

#### Step 2: コマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | format.el | `modules/editor/format/autoload/format.el` | コマンド定義 |

**主要処理フロー**:
- **20-68行目**: `+format-region`関数（リージョンフォーマット）
- **75行目**: `+format/buffer`（apheleia-format-bufferのエイリアス）
- **78-92行目**: `+format/region`コマンド
- **95-101行目**: `+format/region-or-buffer`

#### Step 3: カスタムフォーマッタを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | config.el | `modules/editor/format/config.el` | カスタムフォーマッタ設定 |

**主要処理フロー**:
- **72行目**: sh-mode → shfmt
- **78行目**: lspフォーマッタ定義
- **81-87行目**: cuda/protobuf → clang-format
- **91-99行目**: clang-formatのインデント設定

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

```
+format/buffer (ユーザーコマンド)
    │
    └─ apheleia-format-buffer
           │
           ├─ apheleia--get-formatters
           │      └─ apheleia-mode-alist検索
           │
           ├─ apheleia--run-formatter
           │      └─ 外部プロセス起動
           │
           └─ apheleia--apply-rcs-patch
                  └─ バッファ更新

+format/region (ユーザーコマンド)
    │
    └─ +format-region
           │
           ├─ apheleia--get-formatters
           │
           ├─ バッファローカル変数コピー
           │
           ├─ インデント調整
           │
           └─ apheleia-format-buffer
                  └─ replace-region-contents
```

### データフロー図

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

バッファ内容          ┌──────────────────────┐
     ───────────────▶│ apheleia             │
                      │ フォーマッタ選択     │
                      └──────────────────────┘
                               │
                               ▼
                      ┌──────────────────────┐
                      │ 外部フォーマッタ      │
                      │ (prettier, black等)  │
                      └──────────────────────┘
                               │
                               ▼
                      ┌──────────────────────┐
フォーマット済み ◀──── │ diff計算・適用       │
コード                 └──────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| config.el | `modules/editor/format/config.el` | ソース | apheleia設定、フォーマッタ定義 |
| format.el | `modules/editor/format/autoload/format.el` | ソース | コマンド定義 |
| settings.el | `modules/editor/format/autoload/settings.el` | ソース | 設定ヘルパー |
| lsp.el | `modules/editor/format/autoload/lsp.el` | ソース | LSPフォーマット連携 |
| evil.el | `modules/editor/format/autoload/evil.el` | ソース | Evilオペレータ |
| org.el | `modules/editor/format/autoload/org.el` | ソース | Org-mode対応 |
| packages.el | `modules/editor/format/packages.el` | 設定 | 依存パッケージ（apheleia） |
