# 機能設計書 83-RSSリーダー

## 概要

本ドキュメントは、Doom EmacsにおけるRSSリーダー機能（`modules/app/rss/`）の設計を記述する。この機能は、elfeedパッケージを使用してEmacs内でRSS/Atomフィードの購読・閲覧機能を提供し、org-mode連携、YouTube対応、快適な閲覧UIを実現する。

### 本機能の処理概要

**業務上の目的・背景**：情報収集はナレッジワーカーの重要な日常業務である。本機能は、Emacsから離れることなくRSSフィードを閲覧でき、技術ブログ、ニュース、プロジェクト更新情報などを効率的にキャッチアップできる環境を提供する。ReederやReadkitなどのmacOSアプリにインスパイアされたワークフローを実現している。

**機能の利用シーン**：
- 朝のニュースチェック・技術ブログ巡回
- GitHubリポジトリのリリース情報追跡
- YouTube技術チャンネルの新着動画確認（+youtube flag使用時）
- org-modeでフィードを管理したい場合（+org flag使用時）

**主要な処理内容**：
1. `=rss`コマンドによる専用ワークスペースでのRSSリーダー起動
2. フィード一覧の取得とエントリー検索・フィルタリング
3. エントリーの既読/未読管理
4. 記事内容の表示（HTMLレンダリング）
5. 画像のスライス表示（長い画像の分割表示）
6. フィードデータベースの永続化とコンパクション
7. org-modeファイルでのフィード管理（elfeed-org）
8. YouTubeフィードの字幕・トランスクリプト連携（elfeed-tube）

**関連システム・外部連携**：
- RSS/Atomフィード: HTTP(S)経由でのフィード取得
- org-mode: elfeed.orgファイルでのフィード定義
- YouTube: elfeed-tube経由でのトランスクリプト取得
- MPV: 動画再生連携（elfeed-tube-mpv）

**権限による制御**：特になし。フィードURLへのアクセス権限のみ。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 16 | RSS Reader | 主画面 | elfeedによるRSSフィード読み取り |

## 機能種別

情報取得・表示 / データ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| +rss-split-direction | symbol | No | エントリー表示の分割方向（デフォルト: 'below） | 'below または 'right |
| +rss-enable-sliced-images | boolean | No | 画像のスライス表示（デフォルト: t） | t または nil |
| +rss-workspace-name | string | No | RSS専用ワークスペース名（デフォルト: "*rss*"） | 文字列 |
| rmh-elfeed-org-files | list | No | フィード定義orgファイルリスト（デフォルト: ("elfeed.org")） | ファイルパスリスト |

### 入力データソース

- RSS/Atomフィード（HTTP/HTTPS URL）
- elfeed.orgファイル（+org flag使用時）
- elfeed-feeds変数（直接設定時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 検索バッファ | buffer | フィードエントリー一覧表示 |
| エントリーバッファ | buffer | 選択したエントリーの内容表示 |
| elfeed-db | directory | フィードデータベース（永続化） |

### 出力先

- *elfeed-search*バッファ: フィード一覧・検索
- *elfeed-entry*バッファ: 記事内容表示（ポップアップ、75%サイズ）
- elfeed-db-directory: `doom-profile-data-dir/elfeed/db/`
- enclosures: `doom-profile-data-dir/elfeed/enclosures/`

## 処理フロー

### 処理シーケンス

```
1. =rss コマンド実行
   └─ ワークスペースモジュールの有無を確認
2. ワークスペース切り替え/作成（*rss*）
   └─ 既存elfeedバッファがあれば選択
3. elfeed起動
   └─ elfeed-search-mode有効化
4. フィード更新確認
   └─ @2-week-agoフィルタでデフォルト表示
5. エントリー選択
   └─ RET または +rss/open でエントリー表示
6. エントリー閲覧
   └─ next-buffer/previous-buffer で前後移動
7. セッション終了時
   └─ kill-buffer-hookで+rss-cleanup-h呼び出し
   └─ elfeed-db-compact実行
```

### フローチャート

```mermaid
flowchart TD
    A[=rss 実行] --> B{workspaces有効?}
    B -->|Yes| C[*rss*ワークスペースに切り替え]
    B -->|No| D[ウィンドウ設定を保存]
    C --> E{elfeedバッファ存在?}
    D --> F[他ウィンドウを削除]
    E -->|Yes| G[既存バッファ表示]
    E -->|No| H[スクラッチバッファに切り替え]
    F --> H
    G --> I[ワークスペース表示]
    H --> J[elfeed起動]
    J --> K[フィード一覧表示]
    K --> L{エントリー選択?}
    L -->|Yes| M[+rss/open でエントリー表示]
    L -->|No| N[更新/フィルタ操作]
    M --> O[記事内容レンダリング]
    O --> P{次/前エントリー?}
    P -->|Yes| Q[+rss/next or +rss/previous]
    P -->|No| R[閲覧継続]
    Q --> O
    N --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルトフィルタ | 2週間以内のエントリーのみ表示（@2-week-ago） | 初期表示時 |
| BR-02 | 自動既読 | エントリー表示時に自動的にunreadタグを削除 | +rss/open実行時 |
| BR-03 | ポップアップ表示 | エントリーは下部75%領域にポップアップ表示 | 常時 |
| BR-04 | 画像スライス | 長い画像は20分割してスライス表示 | +rss-enable-sliced-images有効時 |
| BR-05 | セッションクリーンアップ | RSS終了時にelfeed関連バッファをすべて削除 | kill-buffer-hook実行時 |
| BR-06 | DBコンパクション | Emacs終了時にelfeed-db-compactを実行 | kill-emacs-hook |

### 計算ロジック

画像スライス分割数の計算：
```elisp
(max 1 (/ height 20.0))
;; 高さを20で割った値（最小1）
```

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

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

| 操作 | 対象 | 操作種別 | 概要 |
|-----|------|---------|------|
| フィード更新 | elfeed-db | INSERT/UPDATE | 新規エントリーの追加、既存エントリーの更新 |
| 既読/未読変更 | elfeed-db | UPDATE | エントリーのタグ変更 |
| DBコンパクション | elfeed-db | DELETE | 古いエントリーの削除と最適化 |

### データベース詳細

elfeedはファイルベースのデータベースを使用。`elfeed-db-directory`以下に保存される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | フィード取得エラー | フィードURLにアクセスできない | ネットワーク接続確認、URL確認 |
| N/A | パースエラー | フィード形式が不正 | フィードの有効性を確認 |
| N/A | orgファイル読み込みエラー | elfeed.orgが見つからない | org-directory内にファイル作成 |

### リトライ仕様

elfeedの標準フィード更新は再試行機能を内蔵。`r`キーで強制更新可能。

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

elfeed-db-compactはEmacsプロセス終了時に実行され、データベースの整合性を保証する。

## パフォーマンス要件

- フィード一覧表示: 即時（ローカルDB参照）
- エントリー内容表示: HTMLレンダリングに依存（shr使用）
- フィード更新: ネットワーク速度に依存

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

- HTTPSフィードの使用を推奨
- 外部画像の読み込みはshrの設定に依存
- elfeed-enclosure-default-dirに保存されるファイルの管理に注意

## 備考

- elfeed-goodiesによりUI機能が強化される
- +youtube flagでYouTubeフィードのトランスクリプト取得が可能
- +org flagでorgファイルによるフィード管理が可能（elfeed-org）
- projectile-enable-cachingを一時無効化してDBコンパクション高速化

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | config.el | `modules/app/rss/config.el` | defvar定義（7-15行目） |

**読解のコツ**:
- `+rss-split-direction`は分割方向を制御（'belowがデフォルト）
- `+rss-enable-sliced-images`は大きな画像の分割表示を制御
- `+rss-workspace-name`はワークスペース名

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | autoload.el | `modules/app/rss/autoload.el` | =rss関数（6-23行目） |

**主要処理フロー**:
1. **9行目**: workspacesモジュール有効時の分岐
2. **11-12行目**: ワークスペース切り替えと既存バッファ確認
3. **17-18行目**: 既存elfeedバッファがあればfallbackバッファに切り替え
4. **18行目**: elfeed起動

#### Step 3: elfeed設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | config.el | `modules/app/rss/config.el` | elfeed use-package設定（21-67行目） |

**主要処理フロー**:
- **24-25行目**: データディレクトリ設定
- **27行目**: デフォルト検索フィルタ（@2-week-ago）
- **28-30行目**: エントリー表示とポップアップ設定
- **32-34行目**: ポップアップルール（75%サイズ、下部表示）
- **39-41行目**: リアルバッファ判定関数の追加
- **44-46行目**: 終了時クリーンアップフック設定
- **50-53行目**: 画像スライス設定

#### Step 4: エントリー操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | autoload.el | `modules/app/rss/autoload.el` | +rss/open（36-42行目） |
| 4-2 | autoload.el | `modules/app/rss/autoload.el` | +rss/next, +rss/previous（45-60行目） |
| 4-3 | autoload.el | `modules/app/rss/autoload.el` | +rss/delete-pane（26-33行目） |

**主要処理フロー**:
- **36-42行目**: エントリー選択と既読化、表示
- **45-51行目**: 次エントリーへの移動
- **54-60行目**: 前エントリーへの移動
- **26-33行目**: エントリーペインの削除

#### Step 5: クリーンアップ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | autoload.el | `modules/app/rss/autoload.el` | +rss-cleanup-h（92-116行目） |
| 5-2 | autoload.el | `modules/app/rss/autoload.el` | +rss--cleanup-on-kill-h（84-89行目） |

**主要処理フロー**:
- **84-89行目**: elfeed-db-compactの実行（projectile cache無効化）
- **92-116行目**: バッファクリーンアップとワークスペース削除

#### Step 6: オプション機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | config.el | `modules/app/rss/config.el` | elfeed-org設定（71-85行目） |
| 6-2 | config.el | `modules/app/rss/config.el` | elfeed-tube設定（94-105行目） |

**主要処理フロー**:
- **71-85行目**: +org flag時のelfeed-org設定
- **78-85行目**: org-directory相対パスの解決
- **94-105行目**: +youtube flag時のelfeed-tube設定とキーバインド

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

```
=rss
    │
    ├─ +workspace-switch (ui/workspaces)
    │      └─ persp-switch
    │
    ├─ doom/switch-to-scratch-buffer
    │
    └─ elfeed (外部パッケージ)
           │
           ├─ elfeed-search-mode
           │      └─ elfeed-search-update
           │
           └─ elfeed-show-entry
                  └─ shr-render-buffer

+rss/open
    │
    ├─ elfeed-search-selected
    ├─ elfeed-untag 'unread
    ├─ elfeed-search-update-entry
    └─ elfeed-show-entry

+rss-cleanup-h
    │
    ├─ doom-buffers-in-mode
    ├─ kill-buffer (各elfeedバッファ)
    └─ +workspace/kill
```

### データフロー図

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

RSS/Atom URL ─────────────┐
                          │
elfeed.org (opt) ─────────┼──▶ elfeed-update ─────────▶ elfeed-db
                          │           │
                          │           └──▶ elfeed-search-mode ──▶ *elfeed-search*
                          │                      │
YouTube feeds (opt) ──────┘                      └──▶ elfeed-show-entry ──▶ *elfeed-entry*
                                                              │
                                                              └──▶ shr-render ──▶ HTML表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| config.el | `modules/app/rss/config.el` | ソース | パッケージ設定とキーバインド定義 |
| autoload.el | `modules/app/rss/autoload.el` | ソース | 自動ロード関数定義 |
| doctor.el | `modules/app/rss/doctor.el` | ソース | 設定診断 |
| packages.el | `modules/app/rss/packages.el` | 設定 | 依存パッケージの宣言 |
