# 機能設計書 19-coffeeコマンド

## 概要

本ドキュメントは、CoffeeScriptのcoffeeコマンド（CLI）の設計を記述する。coffeeコマンドは、CoffeeScriptのコンパイル、実行、REPL起動等を行うコマンドラインインターフェースである。

### 本機能の処理概要

coffeeコマンドは、CoffeeScriptの主要なエントリーポイントとして、ファイルのコンパイル、直接実行、REPL起動、ファイル監視など多様な機能を提供するCLIツールである。

**業務上の目的・背景**：CoffeeScriptを日常的に使用する開発者にとって、コマンドラインからの操作は不可欠である。coffeeコマンドは、開発ワークフローをサポートするための多彩なオプションを提供し、ビルドプロセスの自動化、デバッグ、開発時の即座のフィードバックなどを可能にする。ファイル監視による自動再コンパイル、REPL（対話型実行環境）、標準入出力を介したパイプライン処理など、開発効率を大幅に向上させる機能を備えている。

**機能の利用シーン**：
- ファイルコンパイル：`coffee -c script.coffee` でJavaScriptに変換
- 直接実行：`coffee script.coffee` でCoffeeScriptを直接実行
- REPL起動：`coffee -i` で対話型環境を起動
- ファイル監視：`coffee -w -c script.coffee` で変更時に自動再コンパイル
- 標準入出力：`echo "x = 1" | coffee -s` でパイプライン処理
- コード評価：`coffee -e "console.log 'hello'"` で文字列を評価

**主要な処理内容**：
1. オプション解析（parseOptions）：コマンドライン引数を解析
2. 実行モード判定（run）：オプションに応じた処理を分岐
3. ファイルコンパイル（compilePath, compileScript）：CoffeeScriptをJavaScriptに変換
4. 直接実行（CoffeeScript.run）：コンパイル結果を即座に実行
5. REPL起動（require('./repl').start）：対話型環境を起動
6. ファイル監視（watch, watchDir）：ファイル変更の検知と再コンパイル
7. 標準入出力（compileStdio）：stdin/stdoutを介した処理
8. Node.jsオプション転送（forkNode）：nodeバイナリへのオプション転送

**関連システム・外部連携**：
- optparse.coffee：オプション解析
- coffeescript.coffee/index.coffee：コンパイルエンジン
- repl.coffee：REPL環境
- fs, path：ファイルシステム操作

**権限による制御**：特になし。OSレベルのファイルアクセス権限に依存。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 18 | Annotated Source - Command | 主画面 | CLIコマンドcommand.coffeeのソースコード解説表示 |
| 33 | Annotated Source - Command | 主画面 | CLIコマンドcommand.coffeeのソースコード解説表示（v2） |

## 機能種別

CLI / コマンドラインインターフェース

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -c, --compile | Flag | No | JavaScriptにコンパイルして.jsファイルとして保存 | - |
| -e, --eval | Flag | No | 文字列を入力として評価 | - |
| -i, --interactive | Flag | No | REPLを起動 | - |
| -w, --watch | Flag | No | ファイル変更を監視して自動再コンパイル | - |
| -o, --output | Path | No | 出力先パスを指定 | 有効なパス |
| -m, --map | Flag | No | ソースマップを生成 | - |
| -M, --inline-map | Flag | No | インラインソースマップを生成 | - |
| -p, --print | Flag | No | コンパイル結果を標準出力に表示 | - |
| -b, --bare | Flag | No | トップレベル関数ラッパーなしでコンパイル | - |
| -s, --stdio | Flag | No | 標準入出力を使用 | - |
| -t, --transpile | Flag | No | Babelでトランスパイル | - |
| その他多数 | - | No | SWITCHES配列で定義 | - |

### 入力データソース

コマンドライン引数（process.argv）、ファイルシステム、標準入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| .jsファイル | File | コンパイルされたJavaScriptファイル |
| .js.mapファイル | File | ソースマップファイル（オプション） |
| stdout | Stream | コンパイル結果の標準出力（--print時） |

### 出力先

ファイルシステム、標準出力

## 処理フロー

### 処理シーケンス

```
1. exports.run()の呼び出し
   └─ Node.jsから bin/coffee 経由で呼び出される

2. オプション解析
   ├─ buildCSOptionParser()でパーサーを構築
   └─ parseOptions()で引数を解析

3. 実行モード判定
   ├─ --nodejs → forkNode()
   ├─ --help → usage()
   ├─ --version → version()
   ├─ --interactive → REPL起動
   ├─ --stdio → compileStdio()
   ├─ --eval → compileScript()
   ├─ 引数なし → REPL起動
   └─ その他 → compilePath()

4. ファイルコンパイル（compilePath）
   ├─ ディレクトリ → 再帰的に処理
   └─ ファイル → compileScript()

5. スクリプトコンパイル（compileScript）
   ├─ --tokens → トークン出力
   ├─ --nodes → 構文木出力
   ├─ --ast → AST JSON出力
   ├─ --run → 直接実行
   └─ --compile → ファイル出力

6. ファイル監視（オプション）
   └─ --watch → watch()/watchDir()
```

### フローチャート

```mermaid
flowchart TD
    A[coffee コマンド実行] --> B[オプション解析]
    B --> C{モード判定}
    C -->|--help| D[usage表示]
    C -->|--version| E[バージョン表示]
    C -->|--interactive| F[REPL起動]
    C -->|--stdio| G[compileStdio]
    C -->|--eval| H[compileScript]
    C -->|ファイル指定| I[compilePath]
    C -->|引数なし| F
    I --> J{ディレクトリ?}
    J -->|Yes| K[再帰処理]
    J -->|No| L[compileScript]
    K --> L
    L --> M{--watch?}
    M -->|Yes| N[監視開始]
    M -->|No| O[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-19-01 | デフォルトモード | オプションなしでファイルを指定すると直接実行 | 引数がファイルパスのみ |
| BR-19-02 | 暗黙のコンパイル | --outputを指定すると--compileも暗黙的に有効 | --output指定時 |
| BR-19-03 | REPL起動条件 | 引数なしまたは--interactiveでREPL起動 | 該当条件時 |
| BR-19-04 | ディレクトリ再帰 | ディレクトリを指定すると.coffee/.litcoffeeファイルを再帰的に処理 | ディレクトリ指定時 |
| BR-19-05 | node_modules除外 | node_modulesディレクトリは処理対象外 | ディレクトリ走査時 |
| BR-19-06 | 隠しファイル除外 | .で始まるファイルや~で終わるファイルは除外 | ディレクトリ走査時 |

### 計算ロジック

出力パス計算（outputPath関数）:
```coffeescript
outputPath = (source, base, extension=".js") ->
  basename  = helpers.baseFileName source, yes, useWinPathSep
  srcDir    = path.dirname source
  dir = unless opts.outputPath
    srcDir
  else if source is base
    opts.outputPath
  else
    path.join opts.outputPath, path.relative base, srcDir
  path.join dir, basename + extension
```

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

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

データベースは使用しない。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ENOENT | ファイル未発見 | 指定ファイルが存在しない | エラーメッセージを表示してexit 1 |
| SyntaxError | 構文エラー | CoffeeScriptの構文が不正 | エラーメッセージを表示、--watchなら続行 |
| - | Babelエラー | @babel/coreがインストールされていない | インストール手順を表示してexit 1 |

### リトライ仕様

--watchモードでは構文エラー発生後も監視を継続し、ファイル修正後に再コンパイルを試みる。

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

トランザクションは使用しない。

## パフォーマンス要件

特に定められていない。

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

- --evalオプションは任意のコードを実行するため、信頼できない入力には使用しない
- ファイル書き込み先のパス検証はOSレベルの権限に依存

## 備考

- SWITCHES配列に全オプションが定義されている
- CoffeeScript.emitでイベントを発行し、フック可能
- --nodejsオプションでNode.jsに直接オプションを渡せる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | command.coffee | `src/command.coffee` | 27-56行目のBANNERとSWITCHES定義を理解する |

**読解のコツ**: SWITCHESは [短縮形, 長形式, 説明] の配列。短縮形がない場合は最初の要素が空文字列。

**主要処理フロー**:
- **27-31行目**: BANNERでヘルプメッセージのヘッダーを定義
- **34-56行目**: SWITCHESで全オプションを定義

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | command.coffee | `src/command.coffee` | 72-139行目のrun関数を理解する |

**主要処理フロー**:
- **73行目**: オプションパーサーを構築
- **74-77行目**: parseOptionsを呼び出し、エラー処理
- **97-103行目**: オプションに応じた分岐（forkNode, usage, version, repl, stdio, eval）
- **137-139行目**: ファイルパスに対してcompilePathを呼び出し

#### Step 3: ファイルコンパイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | command.coffee | `src/command.coffee` | 151-187行目のcompilePath関数を理解する |
| 3-2 | command.coffee | `src/command.coffee` | 202-246行目のcompileScript関数を理解する |

**主要処理フロー**:
- **162-168行目**: ディレクトリの場合の処理
- **176-185行目**: ファイルの場合、読み込んでcompileScriptを呼び出し
- **207-231行目**: オプションに応じたコンパイル分岐（tokens, nodes, ast, run, compile）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | command.coffee | `src/command.coffee` | 274-317行目のwatch関数を理解する |
| 4-2 | command.coffee | `src/command.coffee` | 320-348行目のwatchDir関数を理解する |

**主要処理フロー**:
- **303-312行目**: fs.watchでファイル変更を検知
- **289-301行目**: 変更検知時にcompileScriptを呼び出し

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

```
bin/coffee (シェルスクリプト)
    │
    └─ require('./lib/coffeescript/command').run()
           │
           ├─ parseOptions() (command.coffee:445)
           │
           ├─ forkNode() (command.coffee:531) - --nodejs時
           │
           ├─ usage() (command.coffee:546) - --help時
           │
           ├─ version() (command.coffee:550) - --version時
           │
           ├─ require('./repl').start() - --interactive時
           │
           ├─ compileStdio() (command.coffee:250) - --stdio時
           │
           ├─ compileScript() (command.coffee:202) - --eval時
           │
           └─ compilePath() (command.coffee:151) - ファイル指定時
                  │
                  ├─ compileScript() (command.coffee:202)
                  │      │
                  │      └─ CoffeeScript.compile/run/tokens/nodes
                  │
                  └─ watch/watchDir (--watch時)
```

### データフロー図

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

コマンドライン          coffeeコマンド                  結果
    │                        │                              │
process.argv ─────▶  ├─ parseOptions
                     ├─ compilePath              ├─ .jsファイル
ファイル ────────────▶  │      └─ compileScript    ├─ .js.mapファイル
                     │            │               ├─ stdout
                     │            └─ CoffeeScript └─ REPL出力
stdin ───────────────▶  └─ compileStdio
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| command.coffee | `src/command.coffee` | ソース | CLIのメイン実装 |
| optparse.coffee | `src/optparse.coffee` | ソース | オプション解析 |
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | コンパイルエンジン |
| repl.coffee | `src/repl.coffee` | ソース | REPL環境 |
| index.coffee | `src/index.coffee` | ソース | CoffeeScriptモジュールエントリーポイント |
| bin/coffee | `bin/coffee` | スクリプト | シェルエントリーポイント |
