# 機能設計書 9-互換性レイヤー

## 概要

本ドキュメントは、Doom Emacsの互換性レイヤー（doom-compat.el）の機能設計を記述する。このシステムは、新しいバージョンのEmacsで導入された関数・変数を古いバージョンにバックポートし、Emacs 27.x〜30.xの幅広いバージョンをサポートする。

### 本機能の処理概要

**業務上の目的・背景**：Doom Emacsは、最新のEmacs機能を活用しながらも、幅広いバージョンのEmacsで動作することを目指している。互換性レイヤーにより、古いバージョンのユーザーも新しいAPIを利用でき、コードの一貫性と保守性が向上する。

**機能の利用シーン**：
- 古いEmacsで新しいAPIを使用する場合
- バージョン間の差異を吸収する場合
- ポリフィルが必要な場合

**主要な処理内容**：
1. Emacs 28からのバックポート（ensure-list、file-name-concat等）
2. Emacs 29からのバックポート（with-memoization、pos-bol/pos-eol等）
3. Emacs 30からのバックポート（major-mode-remap、safe-local-variable-directories等）
4. Emacs 31+からのバックポート（static-when、static-unless）
5. ターミナルEmacs用のスタブ関数（define-fringe-bitmap、set-fontset-font）

**関連システム・外部連携**：doom.el（最初に読み込まれる）

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 内部ライブラリのため直接的な画面関連なし |

## 機能種別

互換性 / ポリフィル / バックポート

## 入力仕様

### 入力パラメータ

特になし（自動的にEmacsバージョンを検出して適用）

### 入力データソース

- emacs-major-version
- fboundp/boundp（関数・変数の存在確認）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| バックポート関数 | function | 新バージョンと同等の関数 |
| バックポート変数 | variable | 新バージョンと同等の変数 |

### 出力先

Emacsのグローバル名前空間

## バックポート一覧

### Emacs 28からのバックポート

| 関数/変数 | 説明 | 元のEmacs行 |
|----------|------|-------------|
| format-spec | フォーマット仕様関数（autoload） | 21-22行目 |
| ensure-list | オブジェクトをリスト化 | 25-31行目 |
| always | 常にtを返す | 34-39行目 |
| file-name-concat | パス結合 | 42-58行目 |
| with-environment-variables | 環境変数の一時設定 | 61-75行目 |
| file-name-with-extension | 拡張子の変更 | 78-99行目 |

### Emacs 29からのバックポート

| 関数/変数 | 説明 | 元のEmacs行 |
|----------|------|-------------|
| with-memoization | メモ化マクロ | 104-115行目 |
| pos-bol | 行頭位置 | 118行目 |
| pos-eol | 行末位置 | 119行目 |
| enable-theme-functions | テーマ有効化フック | 122-142行目 |
| disable-theme-functions | テーマ無効化フック | 130-142行目 |
| treesit-available-p | Tree-sitter利用可能判定 | 148-151行目 |

### Emacs 30からのバックポート

| 関数/変数 | 説明 | 元のEmacs行 |
|----------|------|-------------|
| major-mode-remap | メジャーモードリマップ | 166-186行目 |
| major-mode-remap-alist | リマップ設定リスト | 167行目 |
| safe-local-variable-directories | 安全なローカル変数ディレクトリ | 189-200行目 |
| static-if | コンパイル時条件分岐 | 203-213行目 |

### Emacs 31+からのバックポート

| 関数/変数 | 説明 | 元のEmacs行 |
|----------|------|-------------|
| static-when | コンパイル時条件分岐（when） | 217-229行目 |
| static-unless | コンパイル時条件分岐（unless） | 232-244行目 |

## 処理フロー

### バックポート適用

```
1. doom.elがdoom-compat.elをrequire
2. 各関数/変数について:
   └─ (unless (fboundp 'FUNC) ...) で存在確認
   └─ 存在しない場合のみ定義
3. 以降のDoomコードで新しいAPIを使用可能
```

### フローチャート

```mermaid
flowchart TD
    A[doom-compat.el読み込み] --> B{fboundp ensure-list?}
    B -->|Yes| C[スキップ]
    B -->|No| D[ensure-list定義]
    D --> E{fboundp file-name-concat?}
    E -->|Yes| F[スキップ]
    E -->|No| G[file-name-concat定義]
    G --> H[他の関数も同様に処理]
    H --> I[doom-compat提供完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 既存関数優先 | 既に関数が存在する場合は定義しない | fboundp確認 |
| BR-02 | 既存変数優先 | 既に変数が存在する場合は定義しない | boundp確認 |
| BR-03 | ターミナル対応 | GUI専用関数はターミナルでno-op | define-fringe-bitmap等 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 互換性エラー | Emacs 27未満 | doom.elでエラー |

### リトライ仕様

特になし

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

該当なし

## パフォーマンス要件

- 起動時に一度だけ評価
- fboundp/boundpチェックは軽量

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

特になし

## 備考

- このファイルはDoomの最初期に読み込まれる
- ネイティブコンパイルされたEmacsでも動作

---

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

### 推奨読解順序

#### Step 1: ターミナル対応を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | doom-compat.el | `lisp/doom-compat.el` | 13-16行目のスタブ関数 |

**スタブ関数**:
- **13-14行目**: `define-fringe-bitmap` → ignore
- **15-16行目**: `set-fontset-font` → ignore

#### Step 2: Emacs 28バックポートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | doom-compat.el | `lisp/doom-compat.el` | 19-99行目 |

**重要な関数**:
- **25-31行目**: `ensure-list` - リスト化関数
- **42-58行目**: `file-name-concat` - パス結合関数

#### Step 3: Emacs 29バックポートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | doom-compat.el | `lisp/doom-compat.el` | 102-161行目 |

**重要な関数**:
- **104-115行目**: `with-memoization` - メモ化マクロ
- **118-119行目**: `pos-bol`/`pos-eol` - 行位置関数
- **148-151行目**: `treesit-available-p` - Tree-sitter判定

#### Step 4: Emacs 30バックポートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | doom-compat.el | `lisp/doom-compat.el` | 164-213行目 |

**重要な関数**:
- **166-186行目**: `major-mode-remap` - モードリマップ
- **189-200行目**: `safe-local-variable-directories` - 安全ディレクトリ
- **203-213行目**: `static-if` - コンパイル時条件分岐

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

```
doom.el (require 'doom-compat)
    │
    └─ doom-compat.el
            │
            ├─ ターミナルスタブ定義
            │       ├─ define-fringe-bitmap
            │       └─ set-fontset-font
            │
            ├─ Emacs 28バックポート
            │       ├─ ensure-list
            │       ├─ file-name-concat
            │       └─ with-environment-variables
            │
            ├─ Emacs 29バックポート
            │       ├─ with-memoization
            │       ├─ pos-bol / pos-eol
            │       └─ enable-theme-functions
            │
            └─ Emacs 30バックポート
                    ├─ major-mode-remap
                    └─ static-if
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| doom-compat.el | `lisp/doom-compat.el` | ソース | 互換性レイヤー本体 |
| doom.el | `lisp/doom.el` | ソース | コアシステム（最初にrequire） |
