# 機能設計書 14-doom env

## 概要

本ドキュメントは、Doom Emacsの環境変数管理コマンド「doom env」の機能設計を定義する。このコマンドは、シェル環境から環境変数をキャプチャし、Emacs起動時にロードできるファイルを生成する。

### 本機能の処理概要

doom envは、現在のシェル環境から環境変数を抽出し、Emacsが起動時にロードできる形式のファイルを生成するコマンドである。

**業務上の目的・背景**：Emacsは様々な方法で起動される可能性がある（ターミナルから、デスクトップランチャーから、デーモンとして等）。特にMacOSやLinuxのアプリランチャーから起動した場合、シェルの環境変数（特にPATHやSHELL）が正しく設定されないことがある。doom envはこの問題を解決するため、ユーザーのシェル環境をファイルにキャプチャし、Emacs起動時に確実に環境変数を復元する。これにより、どの方法でEmacsを起動しても一貫した環境が得られる。

**exec-path-from-shellとの違い**：
1. exec-path-from-shellは起動時にシェルを起動して環境をスクレイピングするため、起動が遅くなる
2. exec-path-from-shellは一部の環境変数のみをコピーするが、doom envは完全な環境をキャプチャ
3. doom envは事前にファイルを生成するため、起動時のオーバーヘッドがない

**機能の利用シーン**：
- MacOSでEmacsをアプリランチャーから起動する場合
- Linuxのデスクトップ環境でEmacsを起動する場合
- pyenv、nvm等の環境を確実に反映させたい場合
- doom syncで自動的に再生成される

**主要な処理内容**：
1. 現在のシェル環境から環境変数を取得
2. 許可リスト（allow）と拒否リスト（deny）によるフィルタリング
3. UTF-8エンコードでelispフォーマットのファイルを生成
4. doom-env-fileに出力（デフォルト）または指定パスに出力

**関連システム・外部連携**：
- シェル環境（$SHELL）
- process-environment変数

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

## 関連画面

本機能はCLIコマンドであり、GUIの画面は持たない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ターミナル | 主画面 | コマンドライン実行 |

## 機能種別

設定生成 / 環境管理 / ファイル出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --allow-all | フラグ | No | allowリストのみを使用（denyを無視） | - |
| --deny-all | フラグ | No | denyリストのみを使用（allowを無視） | - |
| -o | パス | No | 出力ファイルパスを指定 | 有効なファイルパス |
| -a, --allow | 正規表現 | No | 指定した環境変数を許可（複数指定可） | 有効な正規表現 |
| -d, --deny | 正規表現 | No | 指定した環境変数を拒否（複数指定可） | 有効な正規表現 |

### 入力データソース

- process-environment: Emacsが起動時に継承した環境変数のリスト
- doom-env-deny: デフォルトの拒否リスト（正規表現のリスト）
- doom-env-allow: デフォルトの許可リスト（正規表現のリスト）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| envvarファイル | ファイル | 環境変数のkey=value形式をelispリストで保存 |

### 出力先

- doom-env-file（デフォルト）または-oオプションで指定したパス

### 出力ファイル形式

```elisp
;; -*- mode: lisp-interaction; coding: utf-8-unix; -*-
;; ---------------------------------------------------------------------------
;; This file was auto-generated by `doom env'. ...
;;
("VARIABLE1=value1"
 "VARIABLE2=value2"
 ...)
```

## 処理フロー

### 処理シーケンス

```
1. 出力ファイルパスの決定
   └─ -oオプションがあれば使用、なければdoom-env-file

2. 拒否・許可リストの構築
   └─ デフォルトリスト + コマンドライン引数
   └─ --allow-all/--deny-allによる調整

3. 環境変数のフィルタリング
   └─ process-environmentから各変数を取得
   └─ 拒否リストにマッチするか確認
   └─ 許可リストにマッチすれば拒否を上書き

4. ファイル生成
   └─ ヘッダーコメントの出力
   └─ フィルタリングされた環境変数をelispリストとして出力
   └─ UTF-8エンコーディングで保存
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[出力パス決定]
    B --> C[リスト構築]
    C --> D[ヘッダー出力]
    D --> E[環境変数ループ開始]
    E --> F{拒否リストに<br>マッチ?}
    F -->|Yes| G{許可リストに<br>マッチ?}
    F -->|No| H[変数を出力]
    G -->|Yes| I[ログ: allow]
    G -->|No| J[ログ: deny]
    I --> H
    J --> K{次の変数あり?}
    H --> K
    K -->|Yes| E
    K -->|No| L[リスト閉じ]
    L --> M[成功メッセージ]
    M --> N[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルト拒否 | doom-env-denyにマッチする変数は除外 | 常時 |
| BR-02 | 許可による上書き | doom-env-allowにマッチすれば拒否を上書き | 常時 |
| BR-03 | 安全な編集ファイル | -oで指定したファイルは手動編集可能 | -oオプション使用時 |
| BR-04 | 自動再生成 | doom syncでenvファイルが存在すれば自動再生成 | doom sync実行時 |

### デフォルト拒否リスト（doom-env-deny）

```elisp
'(;; Unix/shell state
  "^HOME$" "^\\(OLD\\)?PWD$" "^SHLVL$" "^PS1$" "^R?PROMPT$" "^TERM\\(CAP\\)?$"
  "^USER$" "^GIT_CONFIG" "^INSIDE_EMACS$"
  ;; X server, Wayland
  "^\\(WAYLAND_\\)?DISPLAY$" "^DBUS_SESSION_BUS_ADDRESS$" "^XAUTHORITY$"
  ;; Windows+WSL
  "^WSL_INTEROP$"
  ;; XDG variables
  "^XDG_CURRENT_DESKTOP$" "^XDG_RUNTIME_DIR$"
  "^XDG_\\(VTNR$\\|SEAT$\\|BACKEND$\\|SESSION_\\)"
  ;; Sockets
  "SOCK\\(ET\\)?$"
  ;; SSH/GPG
  "^SSH_\\(AUTH_SOCK\\|AGENT_PID\\)$" "^\\(SSH\\|GPG\\)_TTY$"
  "^GPG_AGENT_INFO$"
  ;; Internal Doom envvars
  "^DEBUG$" "^INSECURE$" "^\\(EMACS\\|DOOM\\(LOCAL\\)?\\)DIR$"
  "^DOOM\\(PATH\\|PROFILE\\)$" "^__")
```

### 計算ロジック

なし

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ユーザーエラー | envファイルが存在しない（clearコマンド） | envファイルを生成してから削除 |

### リトライ仕様

特になし。

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

ファイル出力はwith-temp-fileで行われるため、アトミックな書き込みとなる。

## パフォーマンス要件

- 環境変数の数に応じた処理時間
- 通常は瞬時に完了

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

- 機密性の高い環境変数（SSHキー、GPGトークン等）はデフォルトで除外される
- シークレットを含む可能性のある環境変数は自分でdoom-env-denyに追加する
- envファイルは適切なパーミッションで保存すること

## 備考

- doom env clearサブコマンドでenvファイルを削除可能
- -oで指定したファイルは手動で`(doom-load-envvars-file "path")`でロード可能

---

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

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

### 推奨読解順序

#### Step 1: 変数定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | env.el | `lisp/cli/env.el` | 19-47行目の変数定義 |

**読解のコツ**: `doom-env-deny`はデフォルトで除外する環境変数のパターンリスト。正規表現で定義されており、セキュリティやセッション固有の変数を除外する。`doom-env-allow`は空リストだが、ユーザーがカスタマイズ可能。

**主要処理フロー**:
- **19-41行目**: doom-env-deny - 除外する環境変数の正規表現リスト
- **43-47行目**: doom-env-allow - 許可する環境変数のリスト（デフォルト空）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | env.el | `lisp/cli/env.el` | 53-138行目のdefcli!定義 |

**主要処理フロー**:
- **53-59行目**: コマンド定義と引数パース
- **90行目**: 出力ファイルパスの決定
- **91-92行目**: エンコーディング設定（UTF-8）
- **99-114行目**: ヘッダーコメントの生成
- **119-136行目**: 環境変数のフィルタリングと出力

#### Step 3: フィルタリングロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | env.el | `lisp/cli/env.el` | 119-136行目のフィルタリング処理 |

**主要処理フロー**:
- **119-124行目**: denylist/allowlistの構築
- **126行目**: 環境変数ループ開始
- **127-135行目**: 各変数のフィルタリング判定
- **130-134行目**: deny/allowの判定とログ出力

#### Step 4: clearサブコマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | env.el | `lisp/cli/env.el` | 140-146行目のclearコマンド |

**主要処理フロー**:
- **140行目**: `(defcli! (env (clear c)) ()` - clearコマンド定義
- **143-145行目**: ファイル存在確認と削除

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

```
doom env (defcli!)
    │
    ├─ doom-path (出力パス決定)
    │
    ├─ with-temp-file
    │      │
    │      ├─ insert (ヘッダーコメント)
    │      │
    │      └─ dolist (process-environment)
    │             │
    │             ├─ split-string (変数名抽出)
    │             │
    │             ├─ seq-find (denylist)
    │             │
    │             ├─ seq-find (allowlist)
    │             │
    │             └─ prin1-to-string (出力)
    │
    └─ print! (成功メッセージ)

doom env clear (defcli!)
    │
    ├─ file-exists-p
    │
    └─ delete-file
```

### データフロー図

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

process-environment   ───▶  変数名抽出    ───▶  フィルタリング
(initial-value)                │
                               │
doom-env-deny         ───▶  拒否判定      ───▶  除外
(正規表現リスト)               │
                               │
doom-env-allow        ───▶  許可判定      ───▶  上書き許可
(正規表現リスト)               │
                               │
コマンド引数          ───▶  リスト追加    ───▶  doom-env-file
(-a, -d)                                         (elisp形式)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| env.el | `lisp/cli/env.el` | ソース | envコマンドの主実装 |
| doom-cli.el | `lisp/doom-cli.el` | ソース | CLIフレームワーク |
| doom-lib.el | `lisp/doom-lib.el` | ソース | doom-load-envvars-file関数 |
| sync.el | `lisp/cli/sync.el` | ソース | doom sync時のenv呼び出し |
