# 機能設計書 2-標準ライブラリ

## 概要

本ドキュメントは、Doom Emacsの標準ライブラリ（doom-lib.el）の機能設計を記述する。このライブラリは、Doom Emacs全体で使用されるユーティリティ関数、マクロ、エラー処理、フック管理、ファイル操作、モジュール管理などの基盤機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Doom Emacsの各モジュールやユーザー設定で共通して使用される汎用的な機能を一箇所に集約することで、コードの重複を避け、保守性を向上させる。また、Emacs Lispのボイラープレートコードを削減し、開発者の生産性を高める。

**機能の利用シーン**：Doom Emacsの初期化時に読み込まれ、以降すべてのDoom機能から参照される。モジュール開発者やユーザーは、これらの関数・マクロを自身の設定やパッケージで活用できる。

**主要な処理内容**：
1. カスタムエラー型の定義（doom-error、doom-nosync-error等）
2. 文字列・リスト・シンボル操作関数
3. フック管理マクロ（add-hook!、remove-hook!、defhook!）
4. ファイル・ディレクトリ操作関数
5. プロセス実行関数（doom-call-process、doom-exec-process）
6. モジュール管理関数（doom-module-p、doom-module-depth、doom-module-list）
7. パッケージ管理ヘルパー関数
8. ログ・デバッグ機能

**関連システム・外部連携**：doom.el（コアシステム）から直接requireされ、doom-start.el、doom-cli.el、doom-modules.el等のすべてのDoomコンポーネントから使用される。

**権限による制御**：特にロールベースの権限制御はない。

## 関連画面

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

## 機能種別

ユーティリティライブラリ / 内部API

## 入力仕様

### 入力パラメータ

本ライブラリは各関数・マクロごとに個別の入力パラメータを持つ。代表的なものを以下に示す。

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| (doom-call-process) cmd | string | Yes | 実行コマンド | 存在確認 |
| (doom-call-process) args | list | No | コマンド引数 | - |
| (doom-module-p) category | keyword | Yes | モジュールカテゴリ | キーワード型 |
| (doom-module-p) module | symbol | Yes | モジュール名 | シンボル型 |
| (doom-file-read) file | string | Yes | ファイルパス | ファイル存在確認 |

### 入力データソース

- Doom Emacsの各種設定ファイル
- 環境変数
- ファイルシステム
- 外部プロセス（subprocess）

## 出力仕様

### 出力データ

各関数の戻り値は関数ごとに異なる。代表的なものを以下に示す。

| 関数名 | 戻り値型 | 説明 |
|--------|---------|------|
| doom-call-process | cons | (STATUS . OUTPUT) |
| doom-module-p | boolean | モジュールの有効/無効 |
| doom-file-read | mixed | ファイル内容（形式指定可） |
| doom-glob | list | マッチしたファイルパス一覧 |
| doom-module-list | list | モジュール一覧 |

### 出力先

関数の戻り値として呼び出し元に返される。一部の関数はログ出力も行う。

## 処理フロー

### 主要関数カテゴリ

```
doom-lib.el
├── エラー定義（6-20行目）
│   ├── doom-error
│   ├── doom-nosync-error
│   ├── doom-context-error
│   └── doom-module-error
├── ユーティリティ関数（22-350行目）
│   ├── doom-rpartial, doom-partial
│   ├── doom-unquote, doom-keyword-name
│   ├── doom-log
│   └── 文字列・リスト操作
├── フック管理（352-650行目）
│   ├── add-hook!, remove-hook!
│   ├── defhook!
│   └── doom-run-hooks
├── ファイル操作（652-900行目）
│   ├── doom-glob, doom-path
│   ├── doom-file-read, doom-file-write
│   └── doom-file-size
├── プロセス実行（902-1000行目）
│   ├── doom-call-process
│   └── doom-exec-process
├── パッケージ管理（1002-1140行目）
│   ├── doom-package-p
│   └── doom-package-pinned-alist
└── モジュール管理（1140-1818行目）
    ├── doom-module構造体
    ├── doom-module-p
    ├── doom-module-get
    └── doom-module-list
```

### フローチャート（モジュール読み込み）

```mermaid
flowchart TD
    A[doom-module-p 呼び出し] --> B{カテゴリ・モジュール指定?}
    B -->|Yes| C[doom-modules ハッシュテーブル検索]
    B -->|No| D[doom-module-contextから取得]
    C --> E{モジュール存在?}
    E -->|Yes| F[モジュール情報を返す]
    E -->|No| G[nilを返す]
    D --> H{コンテキスト存在?}
    H -->|Yes| I[現在のモジュールを返す]
    H -->|No| G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | フック登録順序 | add-hook!でdepth指定がない場合はデフォルト値0 | 常時 |
| BR-02 | モジュール深度 | :core > :user > その他の順で優先度が決まる | doom-module-depth |
| BR-03 | ファイルキャッシュ | doom-file-readでcache指定時はttl期限管理 | cache引数指定時 |
| BR-04 | エラー継承 | すべてのDoomエラーはdoom-errorから継承 | define-error使用時 |

### 計算ロジック

モジュール深度計算:
```elisp
(defun doom-module-depth (category module &optional initdepth)
  (let ((dominated (doom-module-get category module :depth)))
    (if (and dominated initdepth)
        (cond ((eq dominated t) initdepth)
              ((eq initdepth t) dominated)
              ((min dominated initdepth)))
      (or dominated initdepth))))
```

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

該当なし（インメモリデータ構造のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| doom-error | ベースエラー | Doom固有エラーの基底クラス | 派生エラーを使用 |
| doom-nosync-error | 同期エラー | doom syncが必要な状態 | doom sync実行 |
| doom-context-error | コンテキストエラー | 不正なコンテキスト使用 | doom-context確認 |
| doom-module-error | モジュールエラー | モジュール読み込み失敗 | モジュール設定確認 |

### リトライ仕様

doom-call-process: 特にリトライなし。呼び出し元で制御。

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

該当なし

## パフォーマンス要件

- doom-file-read: キャッシュ機構によるファイルI/O削減
- doom-memoize: メモ化による計算結果キャッシュ
- doom-log: 非インタラクティブ時のみ出力（オーバーヘッド削減）

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

- doom-call-process: シェル経由ではなく直接プロセス起動（インジェクション防止）
- doom-file-read: ファイル存在確認後に読み込み
- ユーザー入力のサニタイズは呼び出し元の責任

## 備考

- doom-lib.elは約1800行を超える大規模ライブラリ
- 多くのマクロはコンパイル時に展開される
- Emacs 27/28/29の互換性はdoom-compat.elで補完

---

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

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

### 推奨読解順序

#### Step 1: エラー定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | doom-lib.el | `lisp/doom-lib.el` | 6-20行目のdefine-error宣言 |

**読解のコツ**: `define-error`でカスタムエラー型を定義。親エラー型からの継承関係を把握する。

```elisp
;; 6-20行目
(define-error 'doom-error "An unexpected Doom error")
(define-error 'doom-nosync-error "Doom hasn't been initialized" 'doom-error)
(define-error 'doom-hook-error "Error in a Doom hook" 'doom-error)
(define-error 'doom-user-error "Syntax error" 'doom-error)
(define-error 'doom-context-error "Invalid context" 'doom-error)
(define-error 'doom-module-error "Error in a Doom module" 'doom-error)
(define-error 'doom-profile-error "Error in a Doom profile" 'doom-error)
(define-error 'doom-package-error "Error with a Doom package" 'doom-error)
```

#### Step 2: ユーティリティ関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | doom-lib.el | `lisp/doom-lib.el` | 22-80行目の基本関数 |

**主要関数**:
- **22-31行目**: `doom-rpartial` - 関数の部分適用（右から）
- **34-43行目**: `doom-partial` - 関数の部分適用（左から）
- **46-52行目**: `doom-unquote` - クォート解除
- **54-56行目**: `doom-keyword-name` - キーワードから文字列抽出

#### Step 3: フック管理マクロを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | doom-lib.el | `lisp/doom-lib.el` | 352-550行目のフックマクロ |

**主要マクロ**:
- **352-450行目**: `add-hook!` - 拡張フック登録
- **452-480行目**: `remove-hook!` - フック削除
- **482-520行目**: `defhook!` - 名前付きフック定義
- **522-550行目**: `doom-run-hooks` - フック実行

**読解のコツ**: `add-hook!`は標準の`add-hook`を拡張し、複数フックへの同時登録、ローカルフック、depth指定などをサポート。

#### Step 4: ファイル操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | doom-lib.el | `lisp/doom-lib.el` | 652-900行目のファイル関数 |

**主要関数**:
- **652-680行目**: `doom-glob` - パターンマッチングでファイル検索
- **682-710行目**: `doom-path` - パス結合
- **712-800行目**: `doom-file-read` - ファイル読み込み（キャッシュ対応）
- **802-850行目**: `doom-file-write` - ファイル書き込み
- **852-870行目**: `doom-file-size` - ファイルサイズ取得

#### Step 5: モジュール管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | doom-lib.el | `lisp/doom-lib.el` | 1140-1818行目のモジュール管理 |

**主要な構造体・関数**:
- **1140-1158行目**: `doom-module`構造体
- **1160-1162行目**: `doom-module-context`構造体
- **1200-1250行目**: `doom-module-p` - モジュール存在確認
- **1252-1300行目**: `doom-module-get` - モジュール情報取得
- **1400-1450行目**: `doom-module-list` - モジュール一覧

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

```
doom.el
    │
    └─ doom-lib.el (require)
           │
           ├─ エラー定義 (define-error)
           │
           ├─ ユーティリティ関数群
           │       ├─ doom-partial, doom-rpartial
           │       ├─ doom-unquote
           │       └─ doom-log
           │
           ├─ フック管理マクロ
           │       ├─ add-hook!
           │       │       └─ add-hook (標準関数)
           │       ├─ remove-hook!
           │       │       └─ remove-hook (標準関数)
           │       └─ doom-run-hooks
           │               └─ run-hook-with-args (標準関数)
           │
           ├─ ファイル操作関数
           │       ├─ doom-file-read
           │       │       ├─ insert-file-contents (標準関数)
           │       │       └─ doom-file-cookie-p
           │       └─ doom-file-write
           │               └─ write-region (標準関数)
           │
           ├─ プロセス実行関数
           │       └─ doom-call-process
           │               └─ call-process (標準関数)
           │
           └─ モジュール管理関数
                   ├─ doom-module-p
                   │       └─ gethash (doom-modules)
                   ├─ doom-module-get
                   │       └─ doom-module-p
                   └─ doom-module-list
                           └─ hash-table-keys (doom-modules)
```

### データフロー図

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

(add-hook!) ──────────▶ マクロ展開 ─────────────────▶ フック登録
  hook-name               │
  function                └─ add-hook呼び出し

doom-module-p ────────▶ ハッシュテーブル検索 ───────▶ boolean
  :category               │
  'module                 └─ doom-modules参照

doom-file-read ───────▶ キャッシュ確認 ─────────────▶ ファイル内容
  file-path               │
  :by, :cache             ├─ HIT: キャッシュ返却
                          └─ MISS: ファイル読込→キャッシュ保存

doom-call-process ────▶ プロセス生成 ───────────────▶ (status . output)
  command                 │
  args                    └─ call-process実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| doom-lib.el | `lisp/doom-lib.el` | ソース | 標準ライブラリ本体 |
| doom.el | `lisp/doom.el` | ソース | doom-lib.elを読み込むコアシステム |
| doom-compat.el | `lisp/doom-compat.el` | ソース | Emacsバージョン互換性レイヤー |
| doom-modules.el | `lisp/doom-modules.el` | ソース | モジュールシステム実装 |
