# 通知設計書 5-print!マクロ

## 概要

本ドキュメントは、Doom Emacsにおける`print!`マクロによる出力機能の設計を記載する。このマクロは、カラー対応のフォーマット済みメッセージを標準出力に出力する機能である。

### 本通知の処理概要

print!マクロは、Doom Emacsのメッセージ出力システムの中核を担う。ANSIカラーコードまたはテキストプロパティを使用して、視認性の高いフォーマット済みメッセージを出力する。

**業務上の目的・背景**：Doom EmacsのCLIツールやスクリプトは、ユーザーに対して多くの情報を出力する必要がある。単純な`message`関数では、色付けやフォーマットが限定的である。print!マクロは、成功・警告・エラーなどの状態を視覚的に区別しやすい形式で出力することで、ユーザー体験を向上させる。

**通知の送信タイミング**：`print!`マクロが呼び出された時点で即座に出力が行われる。出力は`doom-print-minimum-level`で設定されたレベル以上の場合にのみ実行される。

**通知の受信者**：CLIモードでは標準出力/標準エラー出力に、対話モードではエコーエリア/ミニバッファに出力される。

**通知内容の概要**：フォーマット済みテキスト。色（bold, green, red, yellow等）やスタイル（success, warn, error, item等）を適用可能。

**期待されるアクション**：ユーザーは出力を確認して、処理の進捗や結果を把握する。

## 通知種別

アプリ内通知（標準出力 / エコーエリア）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 可変（doom-print-level） |
| リトライ | 無 |

### 送信先決定ロジック

`doom-print-backend`変数に基づいて出力形式を決定：
- `ansi`: ANSIエスケープコードを使用（CLIモード）
- `text-properties`: Emacsテキストプロパティを使用（対話モード）
- `nil`: スタイルなしのプレーンテキスト

## 通知テンプレート

### メッセージ出力の場合

| 項目 | 内容 |
|-----|------|
| 表示先 | standard-output / doom-print-stream |
| 形式 | カラー対応フォーマット済みテキスト |

### 本文テンプレート

```lisp
(print! MESSAGE ARGS...)
(print! (success "Operation completed: %s" result))
(print! (warn "Warning: %s" message))
(print! (error "Error: %s" error-message))
(print! (item "Processing %s..." filename))
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| doom-print-backend | 出力バックエンド（ansi/text-properties/nil） | グローバル変数 | Yes |
| doom-print-level | 現在の出力レベル | グローバル変数 | Yes |
| doom-print-minimum-level | 最低出力レベル | グローバル変数 | Yes |
| doom-print-indent | インデントレベル | グローバル変数 | No |
| doom-print-stream | 出力先ストリーム | グローバル変数 | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| マクロ呼び出し | (print! MESSAGE ARGS) | level >= doom-print-minimum-level | 通常の出力 |
| マクロ呼び出し | print-group!内でのprint! | グループ設定に従う | インデント付き出力 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| doom-print-level < doom-print-minimum-level | 出力レベル不足時は抑止 |
| 出力内容がnilまたは空文字列 | 内容がない場合は抑止 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[print!マクロ呼び出し] --> B[format!でメッセージ整形]
    B --> C[doom-print関数呼び出し]
    C --> D{出力レベルチェック}
    D -->|OK| E{doom-print-format?}
    D -->|NG| F[出力なし]
    E -->|Yes| G[doom-print--formatでインデント適用]
    E -->|No| H[そのまま出力]
    G --> I[princで出力]
    H --> I
    I --> J{newline?}
    J -->|Yes| K[terpriで改行]
    J -->|No| L[終了]
    K --> L
    F --> L
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（Emacs Lisp変数のみ使用）

### 変数参照詳細

| 変数名 | 用途 | 取得条件 |
|--------|------|---------|
| doom-print-ansi-alist | ANSIカラーコードマッピング | 常時参照可能 |
| doom-print-class-alist | クラス変換関数マッピング | 常時参照可能 |
| doom-print-indent | インデントレベル | 常時参照可能 |
| doom-print-indent-increment | インデント増分 | 常時参照可能 |
| doom-print-backend | 出力バックエンド | 常時参照可能 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Invalid print style | doom-print-ansi-alistに存在しないスタイル指定 | エラーシグナル |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限なし | 呼び出しごとに出力 |

### 配信時間帯

制限なし

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

- 出力内容はユーザーが指定するため、機密情報が含まれる可能性がある
- ローカル出力のみで外部送信はない
- ANSIエスケープコードは信頼できるコード内でのみ使用される

## 備考

- print!はマクロとして実装されており、format!マクロと連携する
- print-group!マクロで階層的なインデント出力が可能
- doom-print関数は直接呼び出しも可能

---

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

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

### 推奨読解順序

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

出力システムの変数定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | print.el | `lisp/lib/print.el` | doom-print-ansi-alist（18-51行目）を確認 |
| 1-2 | print.el | `lisp/lib/print.el` | doom-print-class-alist（53-108行目）を確認 |
| 1-3 | print.el | `lisp/lib/print.el` | doom-print-backend他の変数（110-141行目）を確認 |

**読解のコツ**: `doom-print-ansi-alist`はANSIカラーコードのマッピング、`doom-print-class-alist`は出力クラス（success, warn等）と変換関数のマッピング。

#### Step 2: エントリーポイントを理解する

print!マクロの定義を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | print.el | `lisp/lib/print.el` | print!マクロ（203-215行目）を確認 |
| 2-2 | print.el | `lisp/lib/print.el` | format!マクロ（178-180行目）を確認 |

**主要処理フロー**:
1. **203行目**: `defmacro print!`でマクロ定義開始
2. **215行目**: `doom-print`関数呼び出しを生成
3. **178行目**: `format!`マクロでスタイル適用

#### Step 3: 出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | print.el | `lisp/lib/print.el` | doom-print関数（147-175行目）を確認 |
| 3-2 | print.el | `lisp/lib/print.el` | doom-print--style関数（468-485行目）を確認 |

**主要処理フロー**:
- **163-170行目**: 出力レベルのチェック
- **171-172行目**: フォーマット適用
- **173行目**: `princ`で出力
- **174行目**: 改行処理

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

```
print! (マクロ)
    |
    +-- format! (メッセージ整形マクロ)
    |       |
    |       +-- doom-print--apply (スタイル変換)
    |
    +-- doom-print (出力関数)
            |
            +-- doom-print--format (インデント適用)
            |
            +-- princ (出力)
            |
            +-- terpri (改行)
```

### データフロー図

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

MESSAGE ───────────────┐
                       │
ARGS ──────────────────┼──▶ print! ──▶ format! ──▶ doom-print
                       │                                │
doom-print-backend ────┘                                │
                                                        ▼
doom-print-ansi-alist ──▶ doom-print--style ──▶ カラーコード適用
                                                        │
                                                        ▼
                                                standard-output
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| print.el | `lisp/lib/print.el` | ソース | print!/format!/doom-printの定義 |
| doom-lib.el | `lisp/doom-lib.el` | ソース | doom-log等で内部的に使用 |
