rubycli 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.ja.md CHANGED
@@ -1,12 +1,49 @@
1
1
  # Rubycli — Python Fire 風の Ruby 向け CLI
2
2
 
3
- ![Rubycli ロゴ](assets/rubycli-logo.png)
3
+ ![Rubycli ロゴ](https://raw.githubusercontent.com/inakaegg/rubycli/main/assets/rubycli-logo.png)
4
4
 
5
- Rubycli は Ruby のクラス/モジュールにある公開メソッドの定義と、そのメソッドに付けたドキュメントコメントから CLI を自動生成する小さなフレームワークです。Python Fire にインスパイアされていますが、互換や公式ポートを目指すものではありません。Ruby のコメント記法と型アノテーションに合わせて設計しており、コメントに書いた型ヒントや繰り返し指定が CLI の引数解釈もコントロールします。
5
+ [![Gem Version](https://img.shields.io/gem/v/rubycli)](https://rubygems.org/gems/rubycli)
6
6
 
7
- > English guide is available in [README.md](README.md).
7
+ Rubycli は、既存の Ruby クラス/モジュールをそのままコマンドラインインターフェースにするツールです。
8
+ 公開メソッドの定義と、メソッドに付けたドキュメントコメントを読み取って CLI を組み立てるため、
9
+ 最小構成ではスクリプト側の変更が一切不要です(`require "rubycli"` すら要りません)。
10
+ コメント内の型アノテーションは単なる説明ではなく、CLI 引数の解釈そのものを制御します
11
+ (例: `TAG... [String[]]` と書くと配列としてパースされます)。
8
12
 
9
- ### 1. Rubycli を意識しない既存スクリプト
13
+ [Python Fire](https://github.com/google/python-fire) にインスパイアされていますが、
14
+ 移植や公式プロジェクトではなく、Ruby のコメント記法と型アノテーションに焦点を当てた独自実装です。
15
+
16
+ > English documentation: [README.md](README.md)
17
+
18
+ ![Rubycli のデモ(コマンド生成と実行の様子)](https://raw.githubusercontent.com/inakaegg/rubycli/main/assets/rubycli-demo.gif)
19
+
20
+ ## プロジェクトの状態
21
+
22
+ Rubycli は**メンテナンスを終了しました。** 0.2.0 が最終リリースで、公開済み gem の挙動を
23
+ 全面監査して見つかった 8 件の不具合を修正し、区切りとしています
24
+ ([CHANGELOG.md](CHANGELOG.md) 参照)。Issue・Pull Request の対応は行わず、
25
+ 今後のリリース予定もありません。
26
+
27
+ コードは参考のため公開したまま残しています。実務で CLI ライブラリを選ぶのであれば、
28
+ [Thor](https://github.com/rails/thor)、[dry-cli](https://dry-rb.org/gems/dry-cli/)、
29
+ または Ruby 標準の `OptionParser` をご利用ください。
30
+
31
+ ## インストール
32
+
33
+ ```bash
34
+ gem install rubycli
35
+ ```
36
+
37
+ ```ruby
38
+ # Gemfile
39
+ gem "rubycli"
40
+ ```
41
+
42
+ Ruby 3.0 以上が必要です。ライセンスは [MIT](LICENSE) です。
43
+
44
+ ## クイックスタート
45
+
46
+ ### 1. 既存スクリプトをそのまま実行する
10
47
 
11
48
  ```ruby
12
49
  # hello_app.rb
@@ -19,7 +56,8 @@ module HelloApp
19
56
  end
20
57
  ```
21
58
 
22
- > リポジトリには `examples/hello_app.rb` を同梱しているので、プロジェクト直下で `rubycli examples/hello_app.rb` を実行すると公開コマンドをすぐに確認できます。
59
+ 同じ内容を `examples/hello_app.rb` として同梱しているので、以下のコマンドは
60
+ プロジェクト直下でそのまま試せます。
23
61
 
24
62
  ```bash
25
63
  rubycli examples/hello_app.rb
@@ -30,11 +68,13 @@ Usage: hello_app.rb COMMAND [arguments]
30
68
 
31
69
  Available commands:
32
70
  Class methods:
33
- greet <NAME>
71
+ greet NAME
34
72
 
35
73
  Detailed command help: hello_app.rb COMMAND help
36
74
  ```
37
75
 
76
+ 引数が足りない場合はスタックトレースではなく使い方が表示されます。
77
+
38
78
  ```bash
39
79
  rubycli examples/hello_app.rb greet
40
80
  ```
@@ -52,16 +92,15 @@ rubycli examples/hello_app.rb greet Hanako
52
92
  #=> Hello, Hanako!
53
93
  ```
54
94
 
55
- `rubycli examples/hello_app.rb --help` を実行しても同じヘルプが表示されます。
95
+ `rubycli examples/hello_app.rb --help` でも、コマンド未指定時と同じ一覧が表示されます。
56
96
 
57
- ### 2. コメントのヒントを足してオプションを有効化
97
+ ### 2. コメントを足して型付きオプションを有効にする
58
98
 
59
- > まだ `require "rubycli"` は不要です。コメントでオプション解析とヘルプを制御します。
60
-
61
- **簡潔なプレースホルダ記法**
99
+ この段階でも `require "rubycli"` は不要です。コメントだけでオプション解析とヘルプが変わります。
100
+ 簡潔なプレースホルダ記法と YARD タグのどちらでも書けます。
62
101
 
63
102
  ```ruby
64
- # hello_app.rb
103
+ # 簡潔なプレースホルダ記法
65
104
  module HelloApp
66
105
  module_function
67
106
 
@@ -75,10 +114,8 @@ module HelloApp
75
114
  end
76
115
  ```
77
116
 
78
- **YARD タグでも同様に動作**
79
-
80
117
  ```ruby
81
- # hello_app.rb
118
+ # YARD タグ
82
119
  module HelloApp
83
120
  module_function
84
121
 
@@ -92,21 +129,13 @@ module HelloApp
92
129
  end
93
130
  ```
94
131
 
95
- > README に合わせたドキュメント付きの版は `examples/hello_app_with_docs.rb` として同梱しています。
96
-
97
- ```bash
98
- rubycli examples/hello_app_with_docs.rb
99
- ```
100
-
101
- ```text
102
- Usage: hello_app_with_docs.rb COMMAND [arguments]
103
-
104
- Available commands:
105
- Class methods:
106
- greet <NAME> [--shout]
107
-
108
- Detailed command help: hello_app_with_docs.rb COMMAND help
109
- ```
132
+ ドキュメント付きの版は `examples/hello_app_with_docs.rb` として同梱しています。
133
+ モジュール名は `HelloApp` のままなので、ファイル末尾に
134
+ `HelloAppWithDocs = HelloApp` を置いてファイル名と一致する定数を用意しています。
135
+ そのため追加のフラグなしで実行できます。一致する定数がないファイルの扱いは
136
+ 後述の[対象定数の解決](#対象定数の解決)を参照してください。
137
+ (この別名の検出は Rubycli 0.1.7 以前では未対応です。それらのバージョンでは
138
+ `--auto-target` / `-a` を付けてください。)
110
139
 
111
140
  ```bash
112
141
  rubycli examples/hello_app_with_docs.rb greet --help
@@ -116,10 +145,10 @@ rubycli examples/hello_app_with_docs.rb greet --help
116
145
  Usage: hello_app_with_docs.rb greet NAME [--shout]
117
146
 
118
147
  Positional arguments:
119
- NAME [String] required 挨拶対象
148
+ NAME [String] required Name to greet
120
149
 
121
150
  Options:
122
- --shout [Boolean] optional 大文字で出力 (default: false)
151
+ --shout [Boolean] optional Print in uppercase (default: false)
123
152
  ```
124
153
 
125
154
  ```bash
@@ -127,7 +156,11 @@ rubycli examples/hello_app_with_docs.rb greet --shout Hanako
127
156
  #=> HELLO, HANAKO!
128
157
  ```
129
158
 
130
- CLI に公開したくないヘルパーは、特異クラス側で `private` として定義してください:
159
+ CLI コマンドになるのは、対象のクラス/モジュール自身に定義された public メソッドだけです。
160
+ 親クラスから継承したメソッド、`include` で取り込んだメソッド、`attr_accessor` が生成する
161
+ メソッドは公開されないため、CLI から呼びたい場合は対象側にラッパーを定義してください。
162
+
163
+ CLI に公開したくないヘルパーは、特異クラス側で `private` として定義します。
131
164
 
132
165
  ```ruby
133
166
  module HelloApp
@@ -135,99 +168,19 @@ module HelloApp
135
168
  private
136
169
 
137
170
  def internal_ping(url)
138
- # CLI コマンドとしては露出しない
171
+ # CLI コマンドとしては公開されない
139
172
  end
140
173
  end
141
174
  end
142
175
  ```
143
176
 
144
- ### 3. (任意)スクリプト内にランナーを組み込む
145
-
146
- `ruby hello_app.rb ...` の形で呼び出したい場合だけ `require "rubycli"` を追加し、`Rubycli.run` に制御を渡します(後述のクイックスタート参照)。
147
-
148
- ## 定数解決モード
149
-
150
- Rubycli は「ファイル名を CamelCase にした定数」を公開対象だと想定しています。ファイル名とクラス/モジュール名が一致しない場合は、次のモードで挙動を切り替えられます。
151
-
152
- | モード | 有効化方法 | 挙動 |
153
- | --- | --- | --- |
154
- | `strict`(デフォルト) | 何もしない / `RUBYCLI_AUTO_TARGET=strict` | CamelCase が一致しないとエラーになります。検出した定数一覧と再実行コマンド例を表示します。 |
155
- | `auto` | `--auto-target`(短縮 `-a`) または `RUBYCLI_AUTO_TARGET=auto` | ファイル内で CLI として実行できる定数が 1 つだけなら自動選択します。複数あれば従来通りエラーで案内します。 |
156
-
157
- 大規模なコードベースでも安全側を保ちながら、どうしても自動選択したいときだけ 1 フラグで切り替えられます。
158
-
159
- > **インスタンスメソッド専用のクラスについて** – 公開メソッドがインスタンス側(`def greet` など)にしか無い場合は、`--new` を付けて事前にインスタンス化しないと CLI から呼び出せません。クラスメソッドを 1 つ用意するか、`--new` を明示して実行してください。`--new` を付ければ `rubycli --help` でもインスタンスメソッドが一覧に現れ、`rubycli --check --new` でコメントの lint も実行できます。初期化時に引数が必要なら `--new=VALUE` のように続けて指定できます(通常の引数と同様に YAML/JSON ライクな安全パースに加え、`--json-args` / `--eval-args` / `--eval-lax` も適用可能)。`initialize` に書いたコメントも通常の CLI メソッドと同様に型変換に反映されます。
160
-
161
- > 補足: `--new 1` のようにスペース区切りで 1 つだけ値を渡すと、後続トークンがパス扱いされやすいため `--new=VALUE` のように `=` 付きで指定するのが確実です。
162
-
163
- ## 開発方針
164
-
165
- - **便利さが最優先** – 既存の Ruby スクリプトを最小の手間で CLI 化できることを目的にしており、Python Fire の完全移植は目指していません。
166
- - **インスパイアであってポートではない** – アイデアの出自は Fire ですが、同等機能を揃える予定は基本的にありません。Fire 由来の未実装機能は仕様です。
167
- - **メソッド定義が土台、コメントが挙動を補強** – 公開メソッドのシグネチャが CLI に露出する範囲と必須/任意を決めますが、コメントに `TAG...` や `[Integer]` を書くと同じ引数でも配列化や型変換が行われます。さらに Rubycli は `--names='["Alice","Bob"]'` のような JSON/YAML らしい入力を自動的に安全なリテラルとして評価します。`rubycli --check パス/対象.rb` でコメントと実装のズレ(未定義の型ラベルや列挙値の誤記を含む)を DidYouMean の候補付きで検査し、通常実行時に `--strict` を付ければドキュメント通りでない入力をその場でエラーにできます。
168
- - **軽量メンテナンス** – 実装の多くは AI 支援で作られており、深い Ruby メタプログラミングを伴う大規模拡張は想定外です。Fire 互換を求める PR は事前相談をお願いします。
169
-
170
- ## 特徴
177
+ ### 3. (任意)スクリプトにランナーを組み込む
171
178
 
172
- - コメントベースで CLI オプションやヘルプを自動生成
173
- - YARD 形式と `NAME [Type] 説明…` の簡潔記法を同時サポート
174
- - 引数はデフォルトで安全なリテラルとして解釈し、必要に応じて厳格 JSON モードや Ruby eval モードを切り替え可能
175
- - `--pre-script`(エイリアス: `--init`)で任意の Ruby コードを評価し、その結果オブジェクトを公開
176
- - `--check` でコメント整合性を lint、`--strict` で入力値をドキュメント通りに強制する二段構えのガード
177
- - `examples/new_mode_runner.rb` ではインスタンス専用クラスを `--new=VALUE` で初期化し、eval/JSON モードや pre-script を組み合わせる例を示しています。
178
-
179
- ### サンプル / 付属例
180
-
181
- - `examples/hello_app.rb` / `examples/hello_app_with_docs.rb`: 最小のモジュール関数とドキュメント付きの版
182
- - `examples/typed_arguments_demo.rb`: 標準ライブラリ型 (Date/Time/BigDecimal/Pathname) の coercion
183
- - `examples/strict_choices_demo.rb`: リテラル列挙と `--strict` の組み合わせ
184
- - `examples/new_mode_runner.rb`: インスタンス専用クラスを `--new=VALUE` で初期化し、eval/JSON/pre-script を組み合わせる例
185
-
186
- #### サンプルコマンド
187
-
188
- - `rubycli examples/new_mode_runner.rb run --new='["a","b","c"]' --mode reverse`
189
- - `rubycli --json-args --new='["x","y"]' examples/new_mode_runner.rb run --mode summary --options '{"source":"json"}'`
190
- - `rubycli --eval-args --new='["x","y"]' examples/new_mode_runner.rb run --mode summary --options '{tags: [:a, :b]}'`
191
- - `rubycli --pre-script 'NewModeRunner.new(%w[a b c], options: {from: :pre})' examples/new_mode_runner.rb run --mode summary`
192
-
193
- > 補足: `--strict` はコメントに書かれた型/許可値をそのまま信頼して検証するため、コメントが誤記だと実行時には検出できません。CI では必ず `rubycli --check` を走らせ、`--strict` は「 lint を通過したドキュメントを本番で厳密に守る」用途に使ってください。
194
-
195
- ## Python Fire との違い
196
-
197
- - **コメント対応のヘルプ生成**: コメントがあればヘルプに反映しつつ、最終的な判断は常にライブなメソッド定義に基づきます。
198
- - **型に基づく解析**: `NAME [String]` や YARD タグから型を推論し、真偽値・配列・数値などを自動変換します。
199
- - **厳密な整合性チェック**: `rubycli --check` でコメントと実装のズレ(未定義の型ラベルや列挙値の誤記など)をコード実行前に検査し、通常実行時に `--strict` を付ければドキュメントで宣言した型・許可値以外の入力を拒否できます。
200
- - **Ruby 向け拡張**: キーワード引数やブロック (`@yield*`) といった Ruby 固有の構文に合わせたパーサや `RUBYCLI_*` 環境変数を用意しています。
201
-
202
- | 機能 | Python Fire | Rubycli |
203
- | ---- | ----------- | -------- |
204
- | 属性の辿り方 | オブジェクトを辿ってプロパティ/属性を自動公開 | 対象オブジェクトの公開メソッドをそのまま公開(暗黙の辿りは無し) |
205
- | クラス初期化 | `__init__` 引数を CLI で自動受け取りインスタンス化 | `--new` 指定時だけ初期化(コンストラクタ引数は `--new=VALUE` で渡せる。YAML/JSON らしいリテラルは安全にパース、`--json-args` / `--eval-args` / `--eval-lax` も適用可能。より複雑なら pre-script や自前ファクトリを利用) |
206
- | インタラクティブシェル | コマンド未指定時に Fire REPL を提供 | インタラクティブモード無し。コマンド実行専用 |
207
- | 情報源 | 反射で引数・プロパティを解析 | ライブなメソッド定義を基点にしつつコメントをヘルプへ反映 |
208
- | 辞書/配列 | dict/list を自動でサブコマンド化 | クラス/モジュールのメソッドに特化(辞書自動展開なし) |
209
-
210
- ## インストール
211
-
212
- Rubycli は RubyGems からインストールできます。
213
-
214
- ```bash
215
- gem install rubycli
216
- ```
217
-
218
- Bundler 例:
219
-
220
- ```ruby
221
- # Gemfile
222
- gem "rubycli"
223
- ```
224
-
225
- ## クイックスタート(Rubycli をスクリプトに組み込む)
226
-
227
- ステップ3では `require "rubycli"` を追加し、スクリプト自身から CLI を起動できるようにします。
179
+ `ruby スクリプト.rb ...` の形で起動したい場合は、gem を require して
180
+ `Rubycli.run` に委譲します(`examples/hello_app_with_require.rb` として同梱)。
228
181
 
229
182
  ```ruby
230
- # hello_app.rb
183
+ # hello_app_with_require.rb
231
184
  require "rubycli"
232
185
 
233
186
  module HelloApp
@@ -247,133 +200,206 @@ end
247
200
  Rubycli.run(HelloApp)
248
201
  ```
249
202
 
250
- 実行例:
251
-
252
203
  ```bash
253
- ruby hello_app.rb greet Taro
254
- #=> Hello, Taro!
255
-
256
- ruby hello_app.rb greet Taro --shout
204
+ ruby examples/hello_app_with_require.rb greet Taro --shout
257
205
  #=> HELLO, TARO!
258
206
  ```
259
207
 
260
- `require "rubycli"` を書かなくても、付属コマンドから同じファイルを実行できます:
208
+ 付属の `rubycli` コマンド経由で実行した場合は、メソッドの戻り値が自動で標準出力に表示されます。
209
+
210
+ 戻り値は標準出力、警告・エラー・失敗時に表示される usage は標準エラー出力へ送られます。
211
+ そのため `rubycli app.rb command > result.json` としても診断メッセージが結果へ混ざらず、
212
+ 失敗時は終了コードが 0 以外になります。
213
+
214
+ ## 対象定数の解決
215
+
216
+ Rubycli は「ファイル名を CamelCase にした定数」を公開対象と想定します。
217
+ 一致しない場合の挙動はモードで切り替えられます。
218
+
219
+ | モード | 有効化方法 | 挙動 |
220
+ | --- | --- | --- |
221
+ | `strict`(既定) | 何もしない / `RUBYCLI_AUTO_TARGET=strict` | CamelCase 名が一致しないとエラー。検出した定数一覧と再実行方法を表示します。 |
222
+ | `auto` | `--auto-target` / `-a` / `RUBYCLI_AUTO_TARGET=auto` | CLI として実行できる定数がファイル内に 1 つだけなら自動選択します。 |
223
+
224
+ ファイルパスの後ろに定数名を明示することもできます。1 ファイルに候補が複数ある場合や、
225
+ ネストした定数を選びたい場合に便利です。同梱サンプルでは
226
+ `examples/multi_constant_runner.rb` が `MultiConstantRunner` と `HelperRunner` を、
227
+ `examples/mismatched_constant_runner.rb` が `FriendlyGreeter` だけを定義しています。
261
228
 
262
229
  ```bash
263
- rubycli path/to/hello_app.rb greet --shout Hanako
230
+ # ファイル名と一致しない定数を明示(既定の strict モードでも動く)
231
+ rubycli examples/multi_constant_runner.rb HelperRunner inspect
232
+ #=> Helper invoked # メソッド自身が出力した行
233
+ #=> :helper # 戻り値を rubycli が出力した行
234
+
235
+ # auto モードなら候補が 1 つだけのファイルを自動選択
236
+ rubycli -a examples/mismatched_constant_runner.rb greet Hanako --message Hi
237
+ #=> Hi, Hanako! # メソッド自身が出力した行
238
+ #=> Hi, Hanako! # 同じ文字列が戻り値として出力される(--quiet を付けると 1 行になる)
264
239
  ```
265
240
 
266
- クラス/モジュール名を省略した場合でも、ファイル名に対応する定義を自動で推測し、ネストした `Module1::Inner::Runner` のようなクラスも見つけ出します。CLI から実行するとメソッドの戻り値は常に標準出力へ表示されます。
241
+ `Outer::Inner::Runner` のようなネストした定数も、完全修飾名を渡せば検出できます。
267
242
 
268
- 別の定数を明示的に指定したい場合は、ファイルパスの後ろに続けてください:
243
+ ## インスタンスメソッド専用クラスと `--new`
244
+
245
+ 公開メソッドがインスタンス側にしかないクラスは、`--new` を付けて事前にインスタンス化しないと
246
+ CLI から呼び出せません(Rubycli から見えるコマンドが 1 つもない状態になります)。
247
+
248
+ - `--new` を付けると `--help` の一覧にインスタンスメソッドが現れ、
249
+ `rubycli --check --new` でコメントの lint も実行できます。
250
+ - コンストラクタに引数が必要な場合は、**ファイルパスより前に** `--new=VALUE` の形で渡します。
251
+ 値は安全な YAML/JSON ライクなリテラルとして解釈され、`initialize` に付けたコメントも
252
+ 通常の CLI メソッドと同様に型変換へ反映されます。
253
+ - `--new=VALUE` が渡せるのは **値 1 つだけ** で、コンストラクタの第 1 引数に束縛されます。
254
+ `--new='["a","b","c"]'` はこの配列を 1 個の引数として渡します。配列が複数の引数へ
255
+ 展開されたり、ハッシュがキーワード引数になったりはしません。引数が 2 つ以上必要な場合や
256
+ キーワード引数を渡したい場合は `--pre-script` を使ってください。
257
+ - スペース区切りの `--new VALUE` は値がファイルパスと誤認されやすいため、
258
+ `--new=VALUE` の形を推奨します。
259
+ - インスタンスを返す `--pre-script` はそれ自体でインスタンスメソッドを公開できるため、
260
+ `--new` と併用しなくても単独で使えます。
261
+
262
+ 実行例(`examples/new_mode_runner.rb`):
269
263
 
270
264
  ```bash
271
- rubycli scripts/multi_runner.rb Admin::Runner list --active
265
+ rubycli --new='["a","b","c"]' examples/new_mode_runner.rb run --mode reverse
266
+ ```
267
+
268
+ ```text
269
+ [
270
+ "c",
271
+ "b",
272
+ "a"
273
+ ]
272
274
  ```
273
275
 
274
- 1つのファイルに複数の候補がある場合や、ファイル名と異なるネストした定義を選びたいときに便利です。
276
+ コマンドが構造を返した場合、戻り値は整形済み JSON として出力されます。
275
277
 
276
278
  ## コメント記法
277
279
 
280
+ YARD タグと短縮形のどちらでも書けます。
281
+
278
282
  | 用途 | YARD 互換 | Rubycli 標準 |
279
283
  | ---- | --------- | ----------- |
280
284
  | 位置引数 | `@param name [Type] 説明` | `NAME [Type] 説明` |
281
285
  | キーワード引数 | 同上 | `--flag -f VALUE [Type] 説明` |
282
286
  | 戻り値 | `@return [Type] 説明` | `=> [Type] 説明` |
283
287
 
284
- 短いオプション(`-f` など)は任意で、登場順も自由です。Rubycli 標準の書き方では次の例が同義になります。
288
+ 短いオプション(`-f` など)は任意で、順序も自由です。次の 3 つは同義です。
285
289
 
286
290
  - `--flag -f VALUE [Type] 説明`
287
291
  - `--flag VALUE [Type] 説明`
288
292
  - `-f --flag VALUE [Type] 説明`
289
293
 
290
- README のサンプルは既定スタイルとして大文字プレースホルダ(`NAME`, `VALUE` など)を使用しています。次項以降の表記揺れは、必要に応じて選べる追加記法です。
294
+ 型は `[String]` でも `(String)` でも指定でき、`(String, nil)` のように複数型も書けます。
291
295
 
292
296
  ### 互換プレースホルダ表記
293
297
 
294
- コメントやヘルプ出力では次の表記も同じ意味として解釈されます。
298
+ コメントの解析とヘルプ出力の両方で、次の表記も同じ意味として扱われます。
295
299
 
296
- - 山括弧で値を明示: `--flag <value>`, `NAME [<value>]`
297
- - ロングオプションの `=` 付き表記: `--flag=<value>`
300
+ - 山括弧: `--flag <value>`, `NAME [<value>]`
301
+ - `=` 付きロングオプション: `--flag=<value>`
298
302
  - 繰り返し指定: `VALUE...`, `<value>...`
299
303
 
300
- 実行時には `--flag VALUE`, `--flag <value>`, `--flag=<value>` のどれで入力しても同じ扱いです。プロジェクトで読みやすいスタイルを選択してください。`[VALUE]` や `[VALUE...]` のような表記を使うと、真偽値・任意値・リストなどの推論が働きます。値プレースホルダを省略したオプション(例: `--quiet`)は自動で Boolean フラグとして扱われます。
301
-
302
- > 補足: コメント内で任意引数を角括弧で表す必要はありません。Ruby 側のメソッドシグネチャから必須/任意は自動判定され、ヘルプ出力では Rubycli が適切に角括弧を追加します。
304
+ 実行時には `--flag VALUE`, `--flag <value>`, `--flag=<value>` のどれも同じ扱いなので、
305
+ プロジェクトで読みやすいスタイルを選んでください。任意引数を自分で角括弧に包む必要は
306
+ ありません。必須/任意は Ruby のメソッドシグネチャから自動判定され、ヘルプ出力では
307
+ Rubycli が角括弧を補います。
303
308
 
304
- 型ヒントは `[String]` や `(String)` のように角括弧/丸括弧で指定できます。複数型は `(String, nil)` のように列挙してください。
309
+ 注釈が部分的な場合の推論規則:
305
310
 
306
- `VALUE...` のような繰り返し指定(`TAG...` など)や、`[String[]]` / `Array<String>` といった配列型の注釈が付いたオプションは配列として扱われます。JSON/YAML 形式のリスト(例: `--tags '["build","test"]'`)を渡すか、カンマ区切り文字列(`--tags "build,test"`)を渡すことで配列に変換されます。スペース区切りの複数値入力(`--tags build test`)にはまだ対応しておらず、繰り返し注記のないオプションは従来どおりスカラーとして扱われます。`--strict` 実行時は各要素の型も検証されるため、`[String[]]` と書かれているのに `--tags [1,2]` のような数値配列を渡すと即エラーになります。
311
+ - `ARG1` のように型を省略したプレースホルダは `String` として扱われます。
312
+ - 値プレースホルダのないオプション(`--verbose`)は Boolean フラグになります。
313
+ - 位置引数を Boolean にするには `[Boolean]` の明示が必要です。`NAME 説明` のように
314
+ 型を省略すると、Ruby 側のデフォルト値に関わらず `String` とみなされます。
307
315
 
308
- JSON やカンマ区切りで表現しづらいシンボル配列・ハッシュなどを渡したい場合は eval モード(`--eval-args`/`-e` または `--eval-lax`/`-E`)を有効にし、ドキュメントで宣言した型に合わせた Ruby リテラルを渡してください。スペース区切りが未対応でも、安全に複数選択を指定できます(後述の eval 例を参照)。
316
+ ### 配列と繰り返し値
309
317
 
310
- 代表的な推論例:
318
+ `TAG...` のような繰り返し指定、または `[String[]]` / `Array<String>` のような配列型注釈が
319
+ 付いたオプションは配列としてパースされます。JSON/YAML 形式のリスト
320
+ (`--tags '["build","test"]'`)とカンマ区切り文字列(`--tags "build,test"`)の両方を
321
+ 受け付けます。スペース区切りの複数値(`--tags build test`)には対応しておらず、
322
+ 繰り返し注記のないオプションはスカラーのままです。`--strict` 実行時は各要素の型も
323
+ 検証されるため、`[String[]]` と書かれた注釈に対して `--tags [1,2]` を渡すとエラーになります。
324
+ `--tags '["true","null"]'` のように引用された要素は、別のリテラルに見える内容でも文字列の
325
+ まま保持されます。
311
326
 
312
- - `ARG1` のように型ラベルを省略したプレースホルダは既定で `String` として扱われます。
313
- - `--name ARG1` のようにオプションへプレースホルダだけを指定しても同じく `String` が推論されます。
314
- - `--verbose` のように値プレースホルダを省略したオプションは Boolean フラグとして扱われます。
315
- - 位置引数を Boolean にしたい場合は必ず `[Boolean]` を明示してください。`NAME 説明` や `@param name 説明` のように型を省略すると、Ruby 側のデフォルト値に関わらず `String` とみなされます。
327
+ ### リテラル列挙(enum)
316
328
 
317
- ### リテラル列挙による制約
329
+ 許容値の集合を型注釈の中に直接書けます: `--format MODE [:json, :yaml, :auto]`、
330
+ `LEVEL [:info, :warn]` など。シンボル・文字列(裸の単語も可)・真偽値・数値・`nil` に対応し、
331
+ `--channel TARGET [:stdout, :stderr, Boolean]` のように通常の型とも混在できます。
332
+ `%i[info warn]` / `%w[debug info]` の短縮記法も展開されます。選択肢は常にヘルプへ表示され、
333
+ 許可外の値は `--strict` なしなら警告のみで続行、`--strict` 付きなら中断します。
318
334
 
319
- `--format MODE [:json, :yaml, :auto]` や `LEVEL [:info, :warn]` のように型注釈内へ許容リテラルを列挙すると、ヘルプに選択肢を表示しつつ Rubycli が入力制約として解釈します。シンボル・文字列(裸の単語も可)・真偽値・数値・`nil` に対応し、型ヒントと混在させて `--channel TARGET [:stdout, :stderr, Boolean]` のような宣言も書けます。`%i[info warn]` / `%w[debug info]` などの短縮記法も展開されるため、`LEVEL %i[info warn]` でも同じ効果になります。通常実行では許可外の入力に警告を表示して続行し、`--strict` を付けた場合は `Rubycli::ArgumentError` を送出して即座に停止します。
320
-
321
- > シンボルと文字列は厳密に区別されます。`[:info, :warn]` と書いた場合は `:info` のようにコロン付きで入力してください。`["info", "warn"]` を選んだ場合はプレーンな文字列のみ受け付けます。
322
-
323
- > 列挙は各スカラー値に適用されます。`[Symbol[]]` のような配列注釈に対して「許可される組み合わせ」をリテラルで書く構文(例: `[%i[foo bar][]]`)は未サポートなので、必要に応じて文章で説明するか、eval モードで Ruby の配列を渡してください。
335
+ シンボルと文字列は厳密に区別されます。`[:info, :warn]` にはコロン付きの `:info` を、
336
+ `["info", "warn"]` にはプレーンな文字列を入力してください。
324
337
 
325
338
  ```bash
326
- # literal choice デモ (examples/strict_choices_demo.rb)
327
- ruby examples/strict_choices_demo.rb report warn --format json
328
- #=> [WARN] format=json
339
+ # examples/strict_choices_demo.rb — LEVEL の注釈は [:info, :warn, :error]
340
+ rubycli examples/strict_choices_demo.rb report :warn --format json
341
+ #=> [WARN] format=json (続けて戻り値のハッシュが表示される)
329
342
 
330
- # --strict を付けると仕様外の値で即エラー
331
- ruby -Ilib exe/rubycli --strict examples/strict_choices_demo.rb report debug
332
- #=> Rubycli::ArgumentError: Value "debug" for LEVEL is not allowed: allowed values are :info, :warn, :error
333
- ```
343
+ # 裸の文字列はシンボルと一致しない: 警告して続行
344
+ rubycli examples/strict_choices_demo.rb report warn
345
+ #=> [WARN] LEVEL must be one of :info, :warn, :error (received "warn") (use --strict to abort on invalid input)
334
346
 
335
- ```bash
336
- # シンボル入力はコロンを付ける
337
- ruby -Ilib exe/rubycli --strict examples/strict_choices_demo.rb report :warn
338
- #=> [WARN] format=text
339
-
340
- ruby -Ilib exe/rubycli --strict examples/strict_choices_demo.rb report warn
341
- #=> Rubycli::ArgumentError: Value "warn" for LEVEL is not allowed: allowed values are :info, :warn, :error
347
+ # --strict を付けると許可外の入力で中断
348
+ rubycli --strict examples/strict_choices_demo.rb report debug
349
+ #=> [ERROR] LEVEL must be one of :info, :warn, :error (received "debug")
342
350
  ```
343
351
 
344
- ### 標準ライブラリ型ヒント
352
+ 列挙は各スカラー引数に適用されます。`[%i[foo bar][]]` のような「配列の許容組み合わせ」を
353
+ リテラルで書く構文は未サポートです。
354
+
355
+ ### 標準ライブラリの型ヒント
345
356
 
346
- コメントに `Date` や `Time`, `BigDecimal`, `Pathname` など標準ライブラリの型名を書けば、Rubycli が必要な `require` を行った上で CLI 引数をその型へ変換します。
357
+ コメントに `Date`、`Time`、`BigDecimal`、`Pathname` などの標準クラスを書くと、
358
+ Rubycli が必要な stdlib を読み込んだ上で CLI 入力をその型へ変換します。
359
+ ハンドラには実際のオブジェクトが渡るため、追加のパース処理は不要です。
347
360
 
348
361
  ```bash
349
- # examples/typed_arguments_demo.rb より
350
- ruby examples/typed_arguments_demo.rb ingest \
362
+ # examples/typed_arguments_demo.rb を参照
363
+ rubycli examples/typed_arguments_demo.rb ingest \
351
364
  --date 2024-12-25 \
352
365
  --moment 2024-12-25T10:00:00Z \
353
366
  --budget 123.45 \
354
367
  --input ./data/input.csv
355
368
  ```
356
369
 
357
- ハンドラ側には `Date` / `Time` / `BigDecimal` / `Pathname` のインスタンスがそのまま渡るため、追加のパース処理は不要です。
370
+ 各オプションには既定値があるため、`... ingest --budget 999.99` のように
371
+ 1 つずつ試すこともできます。
358
372
 
359
- 各オプションには既定値があるため、`ruby examples/typed_arguments_demo.rb ingest --budget 999.99` のように個別の型だけ試すこともできます。
373
+ `@example`、`@raise`、`@see`、`@deprecated` などその他の YARD タグは、
374
+ 現状ヘルプ出力には反映されません。
360
375
 
361
- `@example` や `@raise`, `@see`, `@deprecated` などその他の YARD タグは、現状ヘルプ出力には反映されません。
376
+ > すべての記法をまとめて試すには
377
+ > `rubycli examples/documentation_style_showcase.rb canonical --help` などの
378
+ > showcase コマンドを実行してください。
362
379
 
363
- > すべての記法をまとめて試したい場合は `rubycli examples/documentation_style_showcase.rb canonical --help` や `... angled --help` などを実行してみてください。
380
+ ### YARD 互換コメントを併用する際の注意
364
381
 
365
- 従来の `@param` 記法も既定で利用できます。簡潔なプレースホルダ記法だけに限定したい場合は `RUBYCLI_ALLOW_PARAM_COMMENT=OFF` を設定してください(厳格モードでの検証は継続されます)。
382
+ - `**kwargs` を受け取るメソッドでも、キーは自動では公開されません。CLI で使わせたいキーは
383
+ すべて `--long-name PLACEHOLDER [Type] 説明` の行として明示してください。
384
+ - `@param` 行に続く箇条書きや補足行は CLI 生成には使われません。補足情報は
385
+ オプションの説明文に含めてください。
386
+ - 簡潔なプレースホルダ記法へ移行したい場合は `RUBYCLI_ALLOW_PARAM_COMMENT=OFF` を設定して
387
+ `rubycli --check` を実行します。`@param` 行がドキュメント不整合として報告され(その lint
388
+ 実行中は無視され)、書き換えが必要な箇所を洗い出せます。これは lint 用のスイッチであり
389
+ 実行時の制限ではありません。通常実行では `@param` は従来どおり有効で、`@return` は
390
+ この設定の対象外です。
366
391
 
367
- ### コメントが不足している場合のフォールバック
392
+ ### コメントが不足している場合
368
393
 
369
- Rubycli は常に実装中のメソッドシグネチャを信頼します。コメントに書いていない引数やオプションがあっても、定義そのものから名前や初期値を推論して CLI に表示します。
394
+ Rubycli は常に実装のメソッドシグネチャを信頼します。コメントに書かれていない引数も、
395
+ 定義から名前・既定値・型を推論して CLI に公開されます。
370
396
 
371
397
  ```ruby
372
- # fallback_example.rb
398
+ # examples/fallback_example.rb
373
399
  module FallbackExample
374
400
  module_function
375
401
 
376
- # AMOUNT [Integer] 処理対象の数値
402
+ # AMOUNT [Integer] Base amount to process
377
403
  def scale(amount, factor = 2, clamp: nil, notify: false)
378
404
  result = amount * factor
379
405
  result = [result, clamp].min if clamp
@@ -383,20 +409,6 @@ module FallbackExample
383
409
  end
384
410
  ```
385
411
 
386
- ```bash
387
- rubycli examples/fallback_example.rb
388
- ```
389
-
390
- ```text
391
- Usage: fallback_example.rb COMMAND [arguments]
392
-
393
- Available commands:
394
- Class methods:
395
- scale AMOUNT [<FACTOR>] [--clamp=<value>] [--notify]
396
-
397
- Detailed command help: fallback_example.rb COMMAND help
398
- ```
399
-
400
412
  ```bash
401
413
  rubycli examples/fallback_example.rb scale --help
402
414
  ```
@@ -405,109 +417,202 @@ rubycli examples/fallback_example.rb scale --help
405
417
  Usage: fallback_example.rb scale AMOUNT [FACTOR] [--clamp=<CLAMP>] [--notify]
406
418
 
407
419
  Positional arguments:
408
- AMOUNT [Integer] required 処理対象の数値
409
- FACTOR optional (default: 2)
420
+ AMOUNT [Integer] required Base amount to process
421
+ FACTOR [String] optional (default: 2)
410
422
 
411
423
  Options:
412
424
  --clamp=<CLAMP> [String] optional (default: nil)
413
425
  --notify [Boolean] optional (default: false)
414
426
  ```
415
427
 
416
- `AMOUNT` だけがドキュメント化されていますが、`factor` や `clamp`, `notify` も自動的に補完され、既定値や型が推論されていることがわかります。開発時は `rubycli --check 対象.rb` でコメントとシグネチャの矛盾を検出し、本番実行で `--strict` を付ければ仕様外の入力をその場で弾けます。
428
+ ドキュメント化されているのは `AMOUNT` だけですが、`factor`・`clamp`・`notify`
429
+ 推論された既定値・型付きで表示されます。
417
430
 
418
- #### 存在しない引数やオプションをコメントに書いた場合
431
+ コメントだけで実引数が増えることはありません。実装に存在しないオプション(例: `--ghost`)や
432
+ 位置引数をコメントに書いた場合、その行はヘルプ末尾の詳細セクションに素のテキストとして
433
+ 表示されるだけで、strict モードでは位置引数のズレに対する警告も出ます。動作するデモ:
434
+ `rubycli examples/fallback_example_with_extra_docs.rb scale --help`
419
435
 
420
- - **整合しないコメントは詳細テキストへフォールバック** – 実装に存在しないオプション(例: `--ghost`)や位置引数(例: `EXTRA`)を記述すると、その行はヘルプ末尾の詳細セクションに素のテキストとして表示され、実際の引数としては機能しません。厳格モードなら `Extra positional argument comments were found: EXTRA` のような警告が出て、位置引数のズレにも気付きやすくなります。
436
+ 開発中は `rubycli --check 対象.rb` でコメントと実装のズレ(未定義の型ラベルや列挙値の
437
+ 誤記を含む。DidYouMean の候補付き)を検出し、実行時に `--strict` を付ければ仕様外の
438
+ 入力を警告ではなくエラーにできます。なお `--check` も実際のシグネチャを読むために対象
439
+ ファイルを load するため、トップレベルのコードは実行されます(例えば
440
+ `examples/hello_app_with_require.rb` は load 時に `Rubycli.run` を呼びます)。
441
+ `--check` が行わないのは、選択したコマンドの実行です。
421
442
 
422
- > 実際に確認したい場合は `rubycli examples/fallback_example_with_extra_docs.rb scale --help` を試してみてください。
443
+ > `--strict` はコメントに書かれた型・許容値をそのまま信頼します。コメント自体の誤記は
444
+ > 実行時には検出できないため、CI で `rubycli --check` を回した上で `--strict` を
445
+ > 使ってください。
423
446
 
424
- コメントだけでは実装を拡張できません。メソッドシグネチャとコメントを一致させておくことで、ヘルプと挙動の整合性を保てます。
447
+ ## 引数解析モード
425
448
 
426
- ### YARD 互換コメントを併用する際の注意点
449
+ ### 既定のリテラル解析
427
450
 
428
- - `**kwargs` を受け取るメソッドでも、Rubycli は個別のキーワードコメント(`--config-path ...` など)が無い限りヘルプへ露出させません。CLI で使わせたいキーはすべて `--LONG-NAME PLACEHOLDER [Type] 説明` の行として明示してください。
429
- - `@param` で位置引数を記述した場合も解析できますが、位置引数・キーワード引数を同じ行形式で列挙する必要があります。`@param source Path` のように書いても、キーワード向けのロングオプションが自動生成されるわけではありません。
430
- - `@param` の行に続く箇条書きや補足行は CLI の自動生成には使われません。補足情報を表示したい場合は、`--flag ...` 行の説明に含めるか、README など別のドキュメントで扱ってください。
431
- - `RUBYCLI_ALLOW_PARAM_COMMENT=OFF` にすると `@param`/`@return` などのタグは警告扱いになります。プロジェクト内で簡潔記法へ統一するときはこの環境変数で段階的に移行できます。
451
+ `{`、`[`、クォート、YAML 記号で始まる「構造化リテラルらしい」引数は `Psych.safe_load`
452
+ 解釈され、`--names='["Alice","Bob"]'` `--config='{foo: 1}'` は追加フラグなしで
453
+ ネイティブな配列・ハッシュとして届きます。`1,2,3` のようなプレーンな文字列はこの段階では
454
+ そのまま維持され(コメントで `String[]` `TAG...` と宣言されていれば後段で配列化)、
455
+ 解釈できない形式は元の文字列にフォールバックします。`"2024-01-01"` は文字列のまま届き、
456
+ 構文が崩れた入力でも実行全体は落ちません。
432
457
 
433
- ## 引数解析モード
458
+ 引数が素の `[String]` としてドキュメント化されている場合は、リテラル解析よりコメント由来の
459
+ 変換が優先され、入力トークンがそのまま渡ります(引用符も含む)。そのため
460
+ `--prefix '"quoted"'` は引用符付きの `"quoted"` として届き、注釈のない引数なら
461
+ `quoted` として届きます。
434
462
 
435
- ### 既定のリテラル解析
463
+ ### JSON モード(`--json-args` / `-j`)
436
464
 
437
- Rubycli `{` や `[`、クォート、YAML の先頭記号といった「構造化リテラルらしい」形の引数に対して `Psych.safe_load` を試み、成功すれば Ruby の配列/ハッシュ/真偽値に変換してからメソッドへ渡します。たとえば `--names='["Alice","Bob"]'` や `--config='{foo: 1}'` のような値は追加フラグ無しでネイティブな配列・ハッシュとして届きます。一方、プレーンな `1,2,3` のような文字列はこの段階ではそのまま維持されます(コメントで `String[]` や `TAG...` と宣言されている場合は後段で配列に整形されます)。扱えない形式は自動的に文字列へフォールバックするため、`"2024-01-01"` のような値もそのまま文字列で受け取れますし、構文が崩れていても CLI 全体が落ちることはありません。
465
+ 後続の引数を厳格に JSON として解釈します。YAML 固有の記法は拒否され、無効な JSON
466
+ `JSON::ParserError` になるため、silent fallback ではなく明示的な失敗が欲しい場合に
467
+ 便利です。プログラムからは `Rubycli.with_json_mode(true) { ... }` で切り替えられます。
438
468
 
439
- ### JSON モード
469
+ ### Eval モード(`--eval-args` / `-e`、`--eval-lax` / `-E`)
440
470
 
441
- CLI 実行時に `--json-args`(短縮形 `-j`)を付けると、後続の引数が厳格に JSON として解釈されます。
471
+ 各引数を Ruby 式として評価してから渡します。シンボル配列・Range・インライン計算など、
472
+ JSON では書きにくい値に便利です。
442
473
 
443
474
  ```bash
444
- rubycli -j my_cli.rb MyCLI run '["--config", "{\"foo\":1}"]'
445
- ```
475
+ # シンボルや %w リテラルがそのままオブジェクトとして届く
476
+ rubycli -e --new='%w[x y]' examples/new_mode_runner.rb run --mode ':reverse'
477
+ #=> ["y", "x"]
446
478
 
447
- YAML 固有の書き方は拒否され、無効な JSON であれば `JSON::ParserError` が発生するため、入力の妥当性を強く保証したいときに便利です。プログラム側では `Rubycli.with_json_mode(true) { … }` で有効化できます。
479
+ # インライン計算は、コメント由来の型変換より先に評価される
480
+ rubycli -e examples/documentation_style_showcase.rb canonical '"Foo"' '2*3'
481
+ #=> {"style": "canonical", "subject": "Foo", "count": 6, ...}
482
+ ```
448
483
 
449
- ### Eval モード
484
+ `--eval-args` では **すべての引数** が有効な Ruby でなければならないため、
485
+ `--mode summary` のような裸の単語はエラーになります。`':summary'`(または
486
+ `'"summary"'`)と書くか、後述の `--eval-lax` を使ってください。
450
487
 
451
- `--eval-args`(短縮形 `-e`)を使うと、後続の引数を Ruby コードとして評価した結果を CLI に渡せます。JSON や YAML では表現しづらいオブジェクトを扱いたいときに便利ですが、評価は `Object.new.instance_eval { binding }` 上で行われるため、信頼できる入力に限定してください。コード内では `Rubycli.with_eval_mode(true) { … }` で切り替えられます。
488
+ 評価は隔離された binding(`Object.new.instance_eval { binding }`)内で行われます。
489
+ 1回の Runner 実行では、`--new=VALUE` のコンストラクタ引数と選択したコマンドの引数を含む
490
+ すべての eval 引数が同じ binding を共有し、実行終了時に破棄されます。入力そのものは
491
+ 信頼できる呼び出し元に限定してください。プログラムからは
492
+ `Rubycli.with_eval_mode(true) { ... }` で切り替えられます。
452
493
 
453
- Ruby 評価はシンボルや配列/ハッシュもそのまま扱えるため、列挙値の組み合わせをオプションへ渡すときにも役立ちます。
494
+ `--eval-lax` / `-E` は `--eval-args` と同様に eval モードを有効にしつつ、Ruby として
495
+ 解釈できなかったトークン(例: 素の `https://example.com`)は警告を出して元の文字列の
496
+ まま渡します。`60*60*24*14` のような式と通常の文字列を混在させたいときに便利です。
454
497
 
455
498
  ```bash
456
- rubycli -E scripts/report_runner.rb publish \
457
- --targets '[:marketing, :sales]' \
458
- --channels '[:email, :slack]'
499
+ rubycli -E examples/hello_app.rb greet https://example.com
500
+ #=> [WARN] Failed to evaluate argument as Ruby (...). Passing it through because --eval-lax is enabled.
501
+ #=> Hello, https://example.com!
459
502
  ```
460
503
 
461
- Ruby 評価を使いつつ、構文エラーが出たときは元の文字列にフォールバックさせたい場合は `--eval-lax`(短縮形 `-E`)を指定します。`--eval-args` と同じく eval モードを有効にしますが、Ruby として解釈できなかったトークン(例: 素の `https://example.com`)は警告を出した上でそのまま渡すため、`60*60*24*14` のような式と文字列を気軽に混在させられます。
462
-
463
- `--json-args`/`-j` は `--eval-args`/`-e` および `--eval-lax`/`-E` と同時指定できません。どのモードも既定のリテラル解析を拡張する位置づけなので、用途に応じて厳格な JSON か Ruby eval(通常/lax)のいずれかを選択してください。
504
+ `--json-args` eval 系フラグは同時指定できません(両方あるとエラーになります)。
464
505
 
465
506
  ## Pre-script ブートストラップ
466
507
 
467
- 付属 CLI を起動するときに `--pre-script SRC`(別名: `--init`)を指定すると、公開メソッドを呼び出す前に任意の Ruby コードを評価できます。評価は隔離された binding 内で行われ、以下のローカル変数があらかじめ用意されています。
508
+ `--pre-script SRC`(別名: `--init`)を付けると、コマンド解決の前に任意の Ruby コードを
509
+ 評価できます。評価は隔離された binding 内で行われ、次のローカル変数が用意されています。
468
510
 
469
- - `target` `--new` を適用する前のクラス/モジュール
470
- - `current` / `instance` 現在公開予定のオブジェクト(`--new` を指定した場合は生成済みインスタンス)
511
+ - `target` 元のクラス/モジュール(`--new` 適用前)
512
+ - `current` / `instance` そのまま公開される予定のオブジェクト
471
513
 
472
- スクリプトの最後に評価された値が新しい公開対象になります。`nil` を返した場合は直前のオブジェクトを維持します。
514
+ 最後に評価された値が新しい公開対象になります(`nil` を返すと直前のオブジェクトを維持)。
515
+ `SRC` にはインラインの Ruby コードとファイルパスのどちらも指定できます。
473
516
 
474
- インラインで書く例:
517
+ 実行例 — `--new` で作られるインスタンスを、自分で組み立てたものに差し替える:
475
518
 
476
519
  ```bash
477
- rubycli --pre-script 'InitArgRunner.new(source: "cli", retries: 2)' \
478
- lib/init_arg_runner.rb summarize --verbose
520
+ rubycli --pre-script 'NewModeRunner.new(%w[a b c], options: {from: :pre})' \
521
+ examples/new_mode_runner.rb run --mode summary
479
522
  ```
480
523
 
481
- ファイルに切り出す例:
524
+ ## フラグと環境変数
482
525
 
483
- ```ruby
484
- # scripts/bootstrap_runner.rb
485
- instance = InitArgRunner.new(source: "preset")
486
- instance.logger = Logger.new($stdout)
487
- instance
488
- ```
526
+ | フラグ / 環境変数 | 説明 | 既定値 |
527
+ | ---------------- | ---- | ------ |
528
+ | `--auto-target` / `-a`, `RUBYCLI_AUTO_TARGET=auto` | ファイル名と定数名が一致しないときに自動選択 | `strict` |
529
+ | `--new[=VALUE]` / `-n[=VALUE]` | コマンド解決前にインスタンス化。`VALUE` はコンストラクタの第 1 引数 | off |
530
+ | `--pre-script SRC` / `--init SRC` | 公開対象オブジェクトを Ruby コードで構築・差し替え | off |
531
+ | `--check` / `-c` | コメントと実装のズレを検査(コマンドは実行しない) | off |
532
+ | `--strict` | ドキュメントの型・許容値を強制。仕様外入力はエラー | off |
533
+ | `--json-args` / `-j` | 引数を厳格に JSON として解釈 | off |
534
+ | `--eval-args` / `-e`, `--eval-lax` / `-E` | 引数を Ruby として評価(lax は失敗時に素の文字列へフォールバック) | off |
535
+ | `--help` / `-h` / `help` | `rubycli` の使い方を表示 | — |
536
+ | `--print-result`, `RUBYCLI_PRINT_RESULT=true` | 戻り値を標準出力へ表示。同梱の `rubycli` コマンドでは既定で有効なので、`Rubycli.run` を自分のスクリプトへ組み込む場合に効く | `rubycli` は on、`Rubycli.run` は off |
537
+ | `RUBYCLI_DEBUG=true` | デバッグログを表示 | `false` |
538
+ | `RUBYCLI_ALLOW_PARAM_COMMENT=OFF` | `rubycli --check` 実行時に YARD `@param` 行を不整合として報告(通常実行には影響しない) | `ON` |
539
+
540
+ ## ライブラリ API
541
+
542
+ - `Rubycli.parse_arguments(argv, method)` — コメント情報を考慮した引数解析
543
+ - `Rubycli.available_commands(target)` — 公開 CLI コマンド一覧
544
+ - `Rubycli.usage_for_method(name, method)` — 指定メソッドのヘルプ生成
545
+ - `Rubycli.method_description(method)` — 構造化されたドキュメント取得
546
+
547
+ ## Python Fire との違い
548
+
549
+ - **コメント対応のヘルプ生成** — コメントはヘルプを豊かにしますが、最終的な判断は常に
550
+ ライブなメソッド定義に基づきます。
551
+ - **型に基づく解析** — プレースホルダ記法と YARD タグから、真偽値・配列・数値などへ
552
+ 追加コードなしで変換します。
553
+ - **二段構えの検証** — `--check` はコマンドを実行せずにドキュメントのズレを lint し、
554
+ `--strict` はドキュメントの型・許容値を実行時の契約として強制します。
555
+ - **Ruby 中心の設計** — キーワード引数、ブロックドキュメント(`@yield*` タグ)、
556
+ `RUBYCLI_*` 環境変数に対応します。
557
+
558
+ | 機能 | Python Fire | Rubycli |
559
+ | ---- | ----------- | ------- |
560
+ | 属性の辿り方 | プロパティ/属性を再帰的に自動公開 | 対象の公開メソッドのみ公開(暗黙の辿りなし) |
561
+ | クラス初期化 | `__init__` 引数を自動で受け取る | `--new` 指定時のみ初期化。引数は `--new=VALUE`、複雑な構築は pre-script |
562
+ | インタラクティブシェル | コマンド未指定時に Fire REPL | なし。コマンド実行専用 |
563
+ | 情報源 | 純粋なリフレクション | ライブなメソッド定義 + コメントをヘルプへ反映 |
564
+ | 辞書/配列 | dict/list を自動でサブコマンド化 | クラス/モジュールのメソッドに特化(自動展開なし) |
565
+
566
+ ## 開発方針
567
+
568
+ - **便利さを最優先** — 既存の Ruby スクリプトを最小の手間で CLI 化することが目的です。
569
+ Python Fire との機能一致は目標ではなく、Fire 由来の未実装機能は基本的に仕様です。
570
+ - **メソッド定義が土台、コメントが補強** — 公開範囲と必須/任意はシグネチャが決め、
571
+ コメントは型・ヘルプ・検証を補強します。
572
+ - **メンテナンス** — 実装の多くは AI 支援で作られています。現在はメンテナンスを終了して
573
+ います([プロジェクトの状態](#プロジェクトの状態)を参照)。
574
+
575
+ ## 同梱サンプル
576
+
577
+ - `examples/hello_app.rb` / `examples/hello_app_with_docs.rb` — 最小のモジュール関数、
578
+ ドキュメントなし/あり
579
+ - `examples/hello_app_with_require.rb` — `Rubycli.run` の組み込み
580
+ - `examples/typed_arguments_demo.rb` — 標準ライブラリ型の変換
581
+ (Date/Time/BigDecimal/Pathname)
582
+ - `examples/strict_choices_demo.rb` — リテラル列挙と `--strict`
583
+ - `examples/new_mode_runner.rb` — `--new=VALUE` で初期化するインスタンス専用クラス
584
+ - `examples/documentation_style_showcase.rb` — 全コメント記法のショーケース
585
+ - `examples/fallback_example.rb` / `examples/fallback_example_with_extra_docs.rb`
586
+ — シグネチャからの補完とコメント不一致のデモ(この 2 つは意図的に
587
+ `rubycli --check` に落ちます)
588
+ - `examples/multi_constant_runner.rb` / `examples/mismatched_constant_runner.rb`
589
+ — 定数選択のデモ(1 ファイルに複数候補がある場合と、ファイル名と定数名が
590
+ 一致しない場合)
591
+
592
+ 本 README のコマンドはリポジトリ直下での実行を前提にしています。同じファイルは gem にも
593
+ 同梱されているため、`gem install rubycli` 後は `gem contents rubycli` で場所を確認できます。
594
+
595
+ ## 開発
489
596
 
490
597
  ```bash
491
- rubycli --pre-script scripts/bootstrap_runner.rb \
492
- lib/init_arg_runner.rb summarize --verbose
598
+ bundle install # minitest / rake / rubocop(Rubycli 本体に実行時依存はありません)
599
+ bundle exec rake # テスト + RuboCop
493
600
  ```
494
601
 
495
- この仕組みを使えば、`--new` のシンプルさを保ったまま、DI 風の初期化やラッパーオブジェクトの準備といった高度な前処理を CLI で行えます。
602
+ 個別のタスク:
496
603
 
497
- ## 環境変数とフラグ
604
+ - `bundle exec rake test` — Minitest 一式(実際の `exe/rubycli` を子プロセスで起動する
605
+ E2E テストを含む)
606
+ - `bundle exec rake lint` — RuboCop。未修正の指摘は `.rubocop_todo.yml` で管理しています
607
+ (大半はパーサ側のメソッド長メトリクス)
608
+ - `bundle exec rake coverage` — テストに加えてリポジトリのカバレッジ基準
609
+ (全体 line 90%、branch 70%、`origin/main` から変更した実行可能行 90%)を検査
498
610
 
499
- | 変数 / フラグ | 説明 | 既定値 |
500
- | ------------- | ---- | ------ |
501
- | `RUBYCLI_DEBUG=true` | デバッグログ表示 | `false` |
502
- | `--check` | コメント/実装のズレを検査し、コマンドは実行しない | `off` |
503
- | `--strict` | ドキュメントで許可した型・値以外をエラーとして拒否 | `off` |
504
- | `RUBYCLI_ALLOW_PARAM_COMMENT=OFF` | レガシーな `@param` 記法を無効化(互換性のため既定では ON) | `ON` |
611
+ カバレッジゲートは外部依存なしで動くため、Bundler なしの
612
+ `ruby -Ilib:test test/coverage_runner.rb` でも実行できます。
505
613
 
506
- ## Rubycli API
614
+ ## ライセンス
507
615
 
508
- - `Rubycli.parse_arguments(argv, method)` – コメント情報を考慮した引数解析
509
- - `Rubycli.available_commands(target)` – 公開 CLI コマンド一覧
510
- - `Rubycli.usage_for_method(name, method)` – 指定メソッドのヘルプ生成
511
- - `Rubycli.method_description(method)` – 構造化されたドキュメント取得
616
+ MIT。[LICENSE](LICENSE) を参照してください。
512
617
 
513
- ご意見・フィードバックは Issue や Pull Request でお寄せください。
618
+ ご意見・不具合報告は Issue や Pull Request でお寄せください。