# 機能設計書 21 --watch オプション

## 概要

本ドキュメントは、CoffeeScript CLIツールの `--watch` (`-w`) オプションの機能設計を記述する。このオプションは、ソースファイルの変更を監視し、変更検出時に自動で再コンパイルを実行する機能を提供する。

### 本機能の処理概要

`--watch` オプションは、CoffeeScriptファイルの開発効率を向上させるファイル監視機能を提供する。開発者がソースコードを編集・保存するたびに、手動でコンパイルコマンドを実行する必要なく、自動的にJavaScriptへのコンパイルが行われる。

**業務上の目的・背景**：CoffeeScriptの開発において、コード変更のたびに手動でコンパイルコマンドを実行するのは非効率的である。`--watch` オプションにより、開発者はコードの編集に集中でき、コンパイル処理はバックグラウンドで自動的に行われる。これにより開発サイクルが高速化され、即座にコンパイル結果やエラーを確認できるようになる。

**機能の利用シーン**：
- 開発中にCoffeeScriptファイルをリアルタイムでJavaScriptに変換したい場合
- 複数ファイルを含むプロジェクトで継続的にビルドを行いたい場合
- テスト駆動開発（TDD）において、コード変更後すぐにテストを実行したい場合

**主要な処理内容**：
1. Node.js の `fs.watch` API を使用してファイルシステムの変更を監視する
2. ファイルの変更検出時に25msのデバウンス処理を行い、連続した変更をまとめる
3. ファイルのサイズと更新時刻をチェックし、実際に変更があった場合のみ再コンパイルする
4. ディレクトリを監視し、新規ファイルの追加にも対応する
5. コンパイルエラーが発生しても監視を継続し、ベル文字（\x07）でエラーを通知する

**関連システム・外部連携**：Node.js ファイルシステムAPI（`fs.watch`, `fs.stat`, `fs.readFile`）

**権限による制御**：特になし。ただし、監視対象ファイル/ディレクトリへの読み取り権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 18 | Annotated Source - Command | 補助機能 | ファイル監視オプションの解説を含む |
| 33 | Annotated Source - Command | 補助機能 | ファイル監視オプションの解説を含む（v2） |

## 機能種別

ファイル監視 / イベント駆動処理 / 自動コンパイル

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --watch / -w | boolean | No | ファイル監視モードを有効にする | オプションの有無で判定 |
| source | string | Yes | 監視対象のCoffeeScriptファイルまたはディレクトリパス | ファイル/ディレクトリが存在すること |

### 入力データソース

- コマンドライン引数
- ファイルシステム（監視対象ファイル/ディレクトリ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| compiled file | file | コンパイルされたJavaScriptファイル（`--compile` 併用時） |
| console output | string | コンパイル結果またはエラーメッセージの標準出力 |
| timestamp log | string | コンパイル完了時刻のログメッセージ |

### 出力先

- ファイルシステム（`.js` ファイル、`--compile` 併用時）
- 標準出力（`--print` 併用時）
- 標準エラー出力（エラー発生時）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数をパース
   └─ --watch オプションが指定されているか確認

2. 監視対象パスの解析
   └─ ファイルかディレクトリかを判定

3. ファイル監視の開始
   └─ fs.watch() でファイルシステムイベントをリッスン

4. 変更検出時の処理
   └─ 25msのデバウンス後にファイル状態をチェック

5. 再コンパイルの実行
   └─ ファイルサイズ/更新時刻が変更されていれば再コンパイル

6. 結果の出力
   └─ タイムスタンプ付きでログを出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始: coffee --watch source.coffee] --> B[引数パース]
    B --> C{--watch 指定?}
    C -->|No| D[通常コンパイル]
    C -->|Yes| E{ディレクトリ?}
    E -->|Yes| F[watchDir: ディレクトリ監視開始]
    E -->|No| G[watch: ファイル監視開始]
    F --> H[fs.watch でイベント待機]
    G --> H
    H --> I{変更イベント検出}
    I --> J[25ms デバウンス]
    J --> K[fs.stat でファイル状態取得]
    K --> L{サイズ/時刻変更?}
    L -->|No| H
    L -->|Yes| M[fs.readFile でファイル読み込み]
    M --> N[compileScript 実行]
    N --> O{コンパイル成功?}
    O -->|Yes| P[タイムスタンプ付きログ出力]
    O -->|No| Q[エラー出力 + ベル文字]
    P --> R[rewatch: 監視再開]
    Q --> R
    R --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | デバウンス処理 | 変更検出から25ms待機してから処理を開始する | ファイル変更イベント検出時 |
| BR-21-02 | 実質変更チェック | ファイルサイズと更新時刻が前回と同じ場合は再コンパイルしない | デバウンス後 |
| BR-21-03 | エラー時継続 | コンパイルエラーが発生しても監視を継続する | コンパイルエラー発生時 |
| BR-21-04 | node_modules除外 | node_modules ディレクトリは監視対象から除外する | ディレクトリ監視時 |
| BR-21-05 | 隠しファイル除外 | `.` で始まるファイルや `~` で終わるファイルは除外する | ファイル監視時 |

### 計算ロジック

特になし

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ENOENT | ファイル不存在 | 監視対象ファイルが削除された | ソースリストから削除し、出力ファイルも削除 |
| EPERM | 権限エラー | ファイルへのアクセス権限がない | 監視を停止しソースリストから削除 |
| SyntaxError | 構文エラー | CoffeeScriptの文法エラー | エラーメッセージ + ベル文字を出力し監視継続 |

### リトライ仕様

- `ENOENT` エラー発生時は `rewatch()` で監視を再開し再度コンパイルを試みる
- それでも失敗する場合はソースリストから削除

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

本機能はトランザクション処理を使用しない。

## パフォーマンス要件

- デバウンス間隔: 25ms（連続した変更をまとめる）
- ディレクトリ再読み込み間隔: 25ms

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

- 監視対象はコマンドライン引数で指定されたパスに限定される
- シンボリックリンクの循環参照に注意が必要

## 備考

- `--compile` オプションと併用することでファイル出力が可能
- `--print` オプションと併用することで標準出力への出力が可能
- `--join` オプションと併用することで複数ファイルの結合コンパイルが可能（非推奨）

---

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

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

### 推奨読解順序

#### Step 1: オプション定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | command.coffee | `src/command.coffee` | SWITCHESの `--watch` 定義（55行目）を確認 |

**読解のコツ**: CoffeeScriptでは配列リテラルが `[]` で定義される。SWITCHESは `[短縮形, 長形式, 説明]` の形式。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | command.coffee | `src/command.coffee` | run関数（72行目〜）がCLIのエントリーポイント |
| 2-2 | command.coffee | `src/command.coffee` | compilePath関数（151行目〜）で監視処理の分岐 |

**主要処理フロー**:
1. **72行目**: `exports.run` でCLI開始
2. **169行目**: `watchDir source, base if opts.watch` でディレクトリ監視
3. **180行目**: `watch source, base if opts.watch` でファイル監視

#### Step 3: ファイル監視処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | command.coffee | `src/command.coffee` | watch関数（274行目〜）の実装詳細 |

**主要処理フロー**:
- **274-276行目**: 変数初期化（watcher, prevStats, compileTimeout）
- **279-287行目**: watchErr関数でエラーハンドリング
- **289-301行目**: compile関数でデバウンスと再コンパイル処理
- **303-312行目**: startWatcher/rewatch関数でfs.watch管理

#### Step 4: ディレクトリ監視処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | command.coffee | `src/command.coffee` | watchDir関数（320行目〜）の実装詳細 |

**主要処理フロー**:
- **320-322行目**: 変数初期化
- **324-338行目**: startWatcher関数でディレクトリ変更監視
- **340-342行目**: stopWatcher関数で監視停止処理

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

```
exports.run (72行目)
    │
    ├─ compilePath (151行目)
    │      ├─ watchDir (169行目) [ディレクトリの場合]
    │      │      └─ fs.watch → onChange → compilePath
    │      │
    │      └─ watch (180行目) [ファイルの場合]
    │             └─ fs.watch → onChange → compile
    │                    └─ fs.stat
    │                    └─ fs.readFile
    │                    └─ compileScript (202行目)
    │
    └─ compileScript (102行目) [初回コンパイル]
           └─ CoffeeScript.compile / .run / .tokens / .nodes
```

### データフロー図

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

ファイル変更イベント ───▶ fs.watch (274行目)
                              │
                              ▼
                        compile関数 (289行目)
                              │
                              ▼
                        fs.stat (292行目) ───▶ prevStats比較
                              │
                              ▼
                        fs.readFile (298行目)
                              │
                              ▼
                        compileScript (202行目) ───▶ .jsファイル / 標準出力
                              │
                              ▼
                        timeLog (432行目) ───▶ タイムスタンプログ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| command.coffee | `src/command.coffee` | ソース | CLIメイン処理、watch/watchDir関数の実装 |
| optparse.coffee | `src/optparse.coffee` | ソース | コマンドライン引数パーサー |
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | コンパイル処理の実装 |
| helpers.coffee | `src/helpers.coffee` | ソース | ファイル名判定等のユーティリティ |
