# 機能設計書 85-リテラシー設定（Orgから設定読み込み）

## 概要

本ドキュメントは、Doom Emacsにおけるリテラシー設定機能（`modules/config/literate/`）の設計を記述する。この機能は、org-modeファイル（config.org）からEmacs Lisp設定を抽出（tangle）し、ドキュメント駆動型の設定管理を実現する。

### 本機能の処理概要

**業務上の目的・背景**：Emacsの設定は複雑になりがちであり、設定の意図や背景を記録しておくことが重要である。本機能は、org-modeのリテラシープログラミング機能を活用し、設定コードとその説明を同一ファイルに記述できるようにする。これにより、設定の可読性、保守性、共有性が大幅に向上する。Knuthが提唱したリテラシープログラミングの思想をEmacs設定に適用している。

**機能の利用シーン**：
- config.orgにEmacs設定を記述し、説明文とともに管理
- `doom sync`実行時に自動的にconfig.elを生成
- config.org編集後の保存時に自動再tangle
- 設定の見出しへの素早いジャンプ

**主要な処理内容**：
1. config.orgファイルからEmacs Lispソースブロックを抽出（org-babel-tangle）
2. doom-module-config-file（config.el）への出力
3. doom sync実行前の自動tangle
4. org-mode保存時の非同期tangle
5. imenuを使用した見出しナビゲーション

**関連システム・外部連携**：
- org-mode: org-babel-tangleによるソースブロック抽出
- org-babel: ソースブロック評価・抽出機能
- straight.el: 正しいバージョンのorgを使用するためのパス設定

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | org-mode編集画面 | 主画面 | config.orgの編集とtangle |

## 機能種別

設定管理 / ビルドプロセス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| +literate-config-file | string | No | リテラシー設定ファイルパス（デフォルト: doom-user-dir/config.org） | 存在するファイルパス |

### 入力データソース

- config.org: ユーザーのリテラシー設定ファイル
- org-modeソースブロック: `#+begin_src emacs-lisp` または `#+begin_src elisp`

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| config.el | file | tangleされたEmacs Lisp設定ファイル |

### 出力先

- doom-module-config-file: ユーザーのconfig.elファイル

## 処理フロー

### 処理シーケンス

```
1. doom sync 実行
   └─ doom-before-sync-hook が発火
2. +literate-tangle-h 呼び出し
   └─ 非インタラクティブ時: +literate-tangle--sync
   └─ インタラクティブ時: +literate-tangle--async
3. config.org の存在確認
   └─ 存在しなければスキップ
4. ソースブロックの存在確認
   └─ emacs-lisp/elispブロックがなければスキップ
5. org-babel-tangle-file 実行
   └─ config.org → config.el
6. 完了通知
   └─ tangleされたファイル数を表示
```

### フローチャート

```mermaid
flowchart TD
    A[doom sync 実行] --> B[doom-before-sync-hook]
    B --> C[+literate-tangle-h]
    C --> D{__NOTANGLE環境変数?}
    D -->|Yes| E[スキップ]
    D -->|No| F{インタラクティブ?}
    F -->|Yes| G[+literate-tangle--async]
    F -->|No| H[+literate-tangle--sync]
    G --> I[非同期Emacsプロセス起動]
    H --> J[+literate-tangle]
    I --> K[org-babel-tangle-file実行]
    J --> K
    K --> L{config.org存在?}
    L -->|No| M[警告表示、スキップ]
    L -->|Yes| N{ソースブロック存在?}
    N -->|No| O[警告表示、スキップ]
    N -->|Yes| P[tangle実行]
    P --> Q[config.el生成]
    Q --> R[完了通知]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 自動tangle | doom sync前に自動的にtangleを実行 | doom-before-sync-hook |
| BR-02 | 非同期処理 | インタラクティブ時は非同期でtangle | インタラクティブセッション |
| BR-03 | 環境変数スキップ | __NOTANGLE=1で tangle をスキップ | 環境変数設定時 |
| BR-04 | ファイル不在スキップ | config.orgが存在しない場合は警告してスキップ | ファイル不在時 |
| BR-05 | ブロック不在スキップ | emacs-lisp/elispソースブロックがない場合は警告してスキップ | ブロック不在時 |
| BR-06 | 保存時再tangle | config.org保存時に自動再tangle | org-mode-hook経由 |

### 計算ロジック

特になし

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

### 操作別データベース影響一覧

本機能はデータベースを操作しない。ファイルシステム操作のみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | ファイル不在 | config.orgが見つからない | doom-user-dirにconfig.orgを作成 |
| N/A | ソースブロック不在 | tangleすべきブロックがない | emacs-lispブロックを追加 |
| N/A | tangleエラー | org-babel-tangleが失敗 | ソースブロックの文法を確認 |
| exit 3 | 非インタラクティブエラー | 同期tangleが失敗 | ログを確認、手動で修正 |

### リトライ仕様

非同期プロセスが既に実行中の場合、古いプロセスをkillして新しいプロセスを起動する。

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

org-babel-tangleは一括処理で、部分的なtangleは行わない。

## パフォーマンス要件

- 同期tangle: 数秒（ファイルサイズ依存）
- 非同期tangle: バックグラウンド実行、メインEmacsに影響なし

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

- org-confirm-babel-evaluateをnilに設定し、tangle時のコード評価を許可
- これはセキュリティリスクだが、ユーザーの設定ファイルなので信頼される想定
- 信頼できないconfig.orgをtangleしないこと

## 備考

- __NOTANGLE=1で環境変数を設定すると、doom syncで再帰的なtangleを防止
- straight.elでインストールされたorgを使用するためのload-path設定が含まれる
- +literate/find-headingでconfig.org内の見出しに素早くジャンプ可能
- Vertico使用時はconsult-outlineが使われる

---

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

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

### 推奨読解順序

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

設定変数を理解し、機能のカスタマイズポイントを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | autoload.el | `modules/config/literate/autoload.el` | defvar定義（5-12行目） |

**読解のコツ**:
- `+literate-config-file`: リテラシー設定ファイルのパス
- `+literate-tangle--async-proc`: 非同期プロセスの追跡用変数
- `+literate-tangle--async-proc-start-time`: プロセス開始時刻

#### Step 2: メインtangle関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | autoload.el | `modules/config/literate/autoload.el` | +literate-tangle関数（14-56行目） |

**主要処理フロー**:
1. **14行目**: 関数定義、TARGET（元ファイル）とDEST（出力先）を受け取る
2. **16-17行目**: ox, ob-tangleをrequire
3. **18-20行目**: パス展開
4. **21行目**: "Tangling your literate config..."メッセージ表示
5. **23-36行目**: org-mode関連変数の一時設定（高速化のため）
6. **44-46行目**: ファイル不在チェック
7. **47-52行目**: ソースブロック存在チェック（正規表現検索）
8. **53-56行目**: org-babel-tangle-file実行

#### Step 3: 同期/非同期tangleを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | autoload.el | `modules/config/literate/autoload.el` | +literate-tangle--sync（58-65行目） |
| 3-2 | autoload.el | `modules/config/literate/autoload.el` | +literate-tangle--async（67-96行目） |
| 3-3 | autoload.el | `modules/config/literate/autoload.el` | +literate-tangle--async-sentinel（98-109行目） |

**主要処理フロー**:
- **58-65行目**: 同期tangle、__NOTANGLE環境変数チェック
- **67-96行目**: 非同期tangle、start-processでバッチEmacsを起動
- **98-109行目**: 非同期プロセスの終了処理、成功/失敗メッセージ表示

#### Step 4: 見出しナビゲーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | autoload.el | `modules/config/literate/autoload.el` | +literate--flatten-imenu-index（118-127行目） |
| 4-2 | autoload.el | `modules/config/literate/autoload.el` | +literate/find-heading（131-151行目） |

**主要処理フロー**:
- **118-127行目**: org-modeのimenu-indexをフラットリストに変換
- **131-151行目**: config.org内の見出しにジャンプするコマンド
- **145-149行目**: Vertico使用時はconsult-outline、それ以外はcompleting-read

#### Step 5: フック関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | autoload.el | `modules/config/literate/autoload.el` | +literate-tangle-h（158-165行目） |
| 5-2 | autoload.el | `modules/config/literate/autoload.el` | +literate-enable-recompile-h（176-178行目） |
| 5-3 | autoload.el | `modules/config/literate/autoload.el` | +literate-recompile-maybe-h（181-189行目） |

**主要処理フロー**:
- **158-165行目**: メインフック、インタラクティブ/非インタラクティブで分岐
- **176-178行目**: org-mode-hookからafter-save-hookにフックを追加
- **181-189行目**: 保存時に再tangleを実行（ディレクトリチェック付き）

#### Step 6: CLI連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | cli.el | `modules/config/literate/cli.el` | フック登録（1-19行目） |

**主要処理フロー**:
- **3行目**: autoload.elの読み込み
- **5-15行目**: straight.elでインストールされたorgをload-pathに追加
- **18行目**: doom-before-sync-hookに+literate-tangle-hを追加
- **19行目**: org load-path設定フックを追加

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

```
doom sync
    │
    └─ doom-before-sync-hook
           │
           ├─ +literate-add-installed-org-to-load-path-h
           │      └─ add-to-list 'load-path
           │
           └─ +literate-tangle-h
                  │
                  ├─ (非インタラクティブ) +literate-tangle--sync
                  │      └─ +literate-tangle
                  │             └─ org-babel-tangle-file
                  │
                  └─ (インタラクティブ) +literate-tangle--async
                         └─ start-process "emacs" "--batch"
                                └─ +literate-tangle

org-mode保存
    │
    └─ +literate-enable-recompile-h (org-mode-hook)
           │
           └─ after-save-hook
                  └─ +literate-recompile-maybe-h
                         └─ +literate-tangle-h
```

### データフロー図

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

config.org ────────────────▶ org-babel-tangle-file ────────▶ config.el
                                    │
                                    ├─ require 'ox
                                    ├─ require 'ob-tangle
                                    └─ ソースブロック抽出

                                    [環境変数]
__NOTANGLE=1 ─────────────────────▶ tangle スキップ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| autoload.el | `modules/config/literate/autoload.el` | ソース | メイン機能とフック定義 |
| cli.el | `modules/config/literate/cli.el` | ソース | CLI連携とフック登録 |
