benry-cmdapp 0.1.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.
@@ -0,0 +1,2314 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1"/>
6
+ <meta name="description" content="">
7
+ <meta name="theme-color" content="#fafafa">
8
+ <meta property="og:title" content="">
9
+ <meta property="og:type" content="">
10
+ <meta property="og:url" content="">
11
+ <meta property="og:image" content="">
12
+ <title></title>
13
+ <link rel="stylesheet" href="lib/sanitize.css/2.0.0/sanitize.min.css">
14
+ <link rel="stylesheet" href="css/style.css">
15
+ </head>
16
+ <body>
17
+ <main>
18
+ <section class="chapter" id="benry-cmdapp">
19
+ <h1>Benry-CmdApp</h1>
20
+ <nav class="nav">
21
+ <ul class="nav">
22
+ </ul>
23
+ </nav>
24
+ <p>($Release: 0.1.0 $)</p>
25
+ <section class="section" id="whats-this">
26
+ <h2>What's This?</h2>
27
+ <p>Benry-CmdApp is a framework to create command-line application.
28
+ If you want create command-line application which takes sub-commands
29
+ like <code>git</code>, <code>docker</code>, or <code>npm</code>, Benry-CmdApp is the solution.</p>
30
+ <p>Base idea:</p>
31
+ <ul>
32
+ <li>Sub-command (= action) is defined as a method in Ruby.</li>
33
+ <li>Commnad-line arguments are passed to action method as positional arguments.</li>
34
+ <li>Command-line options are passed to action method as keyword arguments.</li>
35
+ </ul>
36
+ <p>For example:</p>
37
+ <ul>
38
+ <li><code>&ltcommand&gt; foo</code> in command-line invokes action method <code>foo()</code> in Ruby.</li>
39
+ <li><code>&ltcommand&gt; foo arg1 arg2</code> invokes <code>foo("arg1", "arg2")</code>.</li>
40
+ <li><code>&ltcommand&gt; foo arg --opt=val</code> invokes <code>foo("arg", opt: "val")</code>.</li>
41
+ </ul>
42
+ <p>Links:</p>
43
+ <ul>
44
+ <li>Document: <a href="https://kwatch.github.io/benry-ruby/benry-cmdapp.html">https://kwatch.github.io/benry-ruby/benry-cmdapp.html</a></li>
45
+ <li>GitHub: <a href="https://github.com/kwatch/benry-ruby/tree/main/benry-cmdapp">https://github.com/kwatch/benry-ruby/tree/main/benry-cmdapp</a></li>
46
+ <li>Changes: <a href="https://github.com/kwatch/benry-ruby/tree/main/benry-cmdapp/CHANGES.md">https://github.com/kwatch/benry-ruby/tree/main/benry-cmdapp/CHANGES.md</a></li>
47
+ </ul>
48
+ <p>Benry-CmdApp requires Ruby &gt;= 2.3.</p>
49
+ <section class="subsection" id="table-of-contents">
50
+ <h3>Table of Contents</h3>
51
+ <div class="toc">
52
+ <ul>
53
+ <li><a href="#whats-this">What's This?</a></li>
54
+ <li><a href="#install">Install</a></li>
55
+ <li><a href="#usage">Usage</a>
56
+ <ul>
57
+ <li><a href="#action">Action</a></li>
58
+ <li><a href="#method-name-and-action-name">Method Name and Action Name</a></li>
59
+ <li><a href="#parameter-name-in-help-message-of-action">Parameter Name in Help Message of Action</a></li>
60
+ <li><a href="#options">Options</a></li>
61
+ <li><a href="#option-definition-format">Option Definition Format</a></li>
62
+ <li><a href="#option-value-validation">Option Value Validation</a></li>
63
+ <li><a href="#callback-for-option-value">Callback for Option Value</a></li>
64
+ <li><a href="#boolean-onoff-option">Boolean (On/Off) Option</a></li>
65
+ <li><a href="#prefix-of-action-name">Prefix of Action Name</a></li>
66
+ <li><a href="#invoke-other-action">Invoke Other Action</a></li>
67
+ <li><a href="#action-alias">Action Alias</a></li>
68
+ <li><a href="#default-action">Default Action</a></li>
69
+ <li><a href="#default-help">Default Help</a></li>
70
+ <li><a href="#private-hidden-action">Private (Hidden) Action</a></li>
71
+ <li><a href="#private-hidden-option">Private (Hidden) Option</a></li>
72
+ </ul></li>
73
+ <li><a href="#configuratoin-and-customization">Configuratoin and Customization</a>
74
+ <ul>
75
+ <li><a href="#application-configuration">Application Configuration</a></li>
76
+ <li><a href="#customization-of-global-options">Customization of Global Options</a></li>
77
+ <li><a href="#customization-of-global-option-behaviour">Customization of Global Option Behaviour</a></li>
78
+ <li><a href="#custom-hook-of-application">Custom Hook of Application</a></li>
79
+ <li><a href="#customization-of-command-help-message">Customization of Command Help Message</a></li>
80
+ <li><a href="#customization-of-action-help-message">Customization of Action Help Message</a></li>
81
+ </ul></li>
82
+ <li><a href="#q--a">Q &amp; A</a>
83
+ <ul>
84
+ <li><a href="#q-how-to-append-some-tasks-to-existing-action">Q: How to Append Some Tasks to Existing Action?</a></li>
85
+ <li><a href="#q-how-to-re-define-existing-action">Q: How to Re-define Existing Action?</a></li>
86
+ <li><a href="#q-how-to-delete-existing-actionalias">Q: How to Delete Existing Action/Alias?</a></li>
87
+ <li><a href="#q-how-to-show-entering-into-or-exitting-from-action">Q: How to Show Entering Into or Exitting From Action?</a></li>
88
+ <li><a href="#q-how-to-enabledisable-color-mode">Q: How to Enable/Disable Color Mode?</a></li>
89
+ <li><a href="#q-how-to-define-multiple-option-like--i-option-of-ruby">Q: How to Define Multiple Option, like <code>-I</code> Option of Ruby?</a></li>
90
+ <li><a href="#q-how-to-specify-detailed-description-of-option">Q: How to Specify Detailed Description of Option?</a></li>
91
+ <li><a href="#q-how-to-copy-all-options-from-other-action">Q: How to Copy All Options from Other Action?</a></li>
92
+ <li><a href="#q-what-is-the-difference-between-prefixalias_of-and-prefixaction">Q: What is the Difference Between <code>prefix(alias_of:)</code> and <code>prefix(action:)</code>?</a></li>
93
+ <li><a href="#q-how-to-change-order-of-options-in-help-message">Q: How to Change Order of Options in Help Message?</a></li>
94
+ <li><a href="#q-is-it-possible-to-make-action-names-emphasised-or-weaken">Q: Is It Possible to Make Action Names Emphasised or Weaken?</a></li>
95
+ <li><a href="#q-is-it-possible-to-add-metadata-to-action-or-option">Q: Is It Possible to Add Metadata to Action or Option?</a></li>
96
+ <li><a href="#q-how-to-make-error-messages-i18ned">Q: How to Make Error Messages I18Ned?</a></li>
97
+ </ul></li>
98
+ <li><a href="#license-and-copyright">License and Copyright</a></li>
99
+ </ul>
100
+ </div>
101
+ </section>
102
+ </section>
103
+ <section class="section" id="install">
104
+ <h2>Install</h2>
105
+ <pre class="language-console">
106
+ $ gem install benry-cmdapp
107
+ </pre>
108
+ </section>
109
+ <section class="section" id="usage">
110
+ <h2>Usage</h2>
111
+ <section class="subsection" id="action">
112
+ <h3>Action</h3>
113
+ <ul>
114
+ <li>Inherit action class and define action methods in it.</li>
115
+ <li>An action class can have several action methods.</li>
116
+ <li>It is ok to define multiple action classes.</li>
117
+ <li>Command-line arguments are passed to action method as positional arguments.</li>
118
+ </ul>
119
+ <p>File: ex01.rb</p>
120
+ <pre class="language-ruby">
121
+ #!/usr/bin/env ruby
122
+ <strong>require 'benry/cmdapp'</strong>
123
+
124
+ ## action
125
+ class MyAction &lt <strong>Benry::CmdApp::Action</strong> # !!!!
126
+
127
+ <strong>@action.("print greeting message")</strong> # !!!!
128
+ <strong>def hello(user="world")</strong> # !!!!
129
+ puts "Hello, #{user}!"
130
+ end
131
+
132
+ end
133
+
134
+ ## configuration
135
+ config = <strong>Benry::CmdApp::Config.new("sample app", "1.0.0")</strong>
136
+ config.default_help = true
137
+
138
+ ## run application
139
+ app = <strong>Benry::CmdApp::Application.new(config)</strong>
140
+ status_code = app.main()
141
+ exit status_code
142
+ </pre>
143
+ <p>Output:</p>
144
+ <pre class="language-console">
145
+ [bash]$ ruby ex01.rb <strong>hello</strong> # action
146
+ Hello, world!
147
+
148
+ [bash]$ ruby ex01.rb <strong>hello Alice</strong> # action + argument
149
+ Hello, <strong>Alice</strong>!
150
+ </pre>
151
+ <p>Help message of command:</p>
152
+ <pre class="language-console">
153
+ [bash]$ ruby ex01.rb <strong>-h</strong> # or `<strong>--help</strong>`
154
+ ex01.rb (1.0.0) -- sample app
155
+
156
+ Usage:
157
+ $ ex01.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
158
+
159
+ Options:
160
+ -h, --help : print help message (of action if action specified)
161
+ -V, --version : print version
162
+
163
+ Actions:
164
+ hello : print greeting message
165
+ </pre>
166
+ <p>Help message of action:</p>
167
+ <pre class="language-console">
168
+ [bash]$ ruby ex01.rb <strong>-h hello</strong>
169
+ ex01.rb hello -- print greeting message
170
+
171
+ Usage:
172
+ $ ex01.rb hello [&ltuser&gt;]
173
+ </pre>
174
+ </section>
175
+ <section class="subsection" id="method-name-and-action-name">
176
+ <h3>Method Name and Action Name</h3>
177
+ <ul>
178
+ <li>Method name <code>print_</code> results in action name <code>print</code>.
179
+ This is useful to define actions which name is same as Ruby keyword or popular functions.</li>
180
+ <li>Method name <code>foo_bar_baz</code> results in action name <code>foo-bar-baz</code>.</li>
181
+ <li>Method name <code>foo__bar__baz</code> results in action name <code>foo:bar:baz</code>.</li>
182
+ </ul>
183
+ <p>File: ex02.rb</p>
184
+ <pre class="language-ruby">
185
+ #!/usr/bin/env ruby
186
+ require 'benry/cmdapp'
187
+
188
+ class SampleAction &lt Benry::CmdApp::Action
189
+
190
+ ## 'print_' =&gt; 'print'
191
+ @action.("sample #1")
192
+ def print<strong>_</strong>() # !!!!
193
+ puts __method__
194
+ end
195
+
196
+ ## 'foo_bar_baz' =&gt; 'foo-bar-baz'
197
+ @action.("sample #2")
198
+ def foo<strong>_</strong>bar<strong>_</strong>baz() # !!!!
199
+ puts __method__
200
+ end
201
+
202
+ ## 'foo__bar__baz' =&gt; 'foo:bar:baz'
203
+ @action.("sample #3")
204
+ def foo<strong>__</strong>ba<strong>r__</strong>baz() # !!!!
205
+ puts __method__
206
+ end
207
+
208
+ end
209
+
210
+ config = Benry::CmdApp::Config.new("test app")
211
+ app = Benry::CmdApp::Application.new(config)
212
+ exit app.main()
213
+ </pre>
214
+ <p>Help message:</p>
215
+ <pre class="language-console">
216
+ [bash]$ ruby ex02.rb --help
217
+ ex02.rb -- test app
218
+
219
+ Usage:
220
+ $ ex02.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
221
+
222
+ Options:
223
+ -h, --help : print help message (of action if action specified)
224
+
225
+ Actions:
226
+ <strong>foo-bar-baz</strong> : sample #2
227
+ <strong>foo:bar:baz</strong> : sample #3
228
+ <strong>print</strong> : sample #1
229
+ </pre>
230
+ <p>Output:</p>
231
+ <pre class="language-console">
232
+ [bash]$ ruby ex02.rb <strong>print</strong> # `print_` method
233
+ print_
234
+
235
+ [bash]$ ruby ex02.rb <strong>foo-bar-baz</strong> # `foo_bar_baz` method
236
+ foo_bar_baz
237
+
238
+ [bash]$ ruby ex02.rb <strong>foo:bar:baz</strong> # `foo__bar__baz` method
239
+ foo__bar__baz
240
+ </pre>
241
+ </section>
242
+ <section class="subsection" id="parameter-name-in-help-message-of-action">
243
+ <h3>Parameter Name in Help Message of Action</h3>
244
+ <p>In help message of action, positional parameters of action methods are printed under the name conversion rule.</p>
245
+ <ul>
246
+ <li>Parameter <code>foo</code> is printed as <code>&ltfoo&gt;</code>.</li>
247
+ <li>Parameter <code>foo_bar_baz</code> is printed as <code>&ltfoo-bar-baz&gt;</code>.</li>
248
+ <li>Parameter <code>foo_or_bar_or_baz</code> is printed as <code>&ltfoo|bar|baz&gt;</code>.</li>
249
+ </ul>
250
+ <p>In addition, positional parameters are printed in different way according to its kind.</p>
251
+ <ul>
252
+ <li>If parameter <code>foo</code> is required (= doesn't have default value), it will be printed as <code>&ltfoo&gt;</code>.</li>
253
+ <li>If parameter <code>foo</code> is optional (= has default value), it will be printed as <code>[&ltfoo&gt;]</code>.</li>
254
+ <li>If parameter <code>foo</code> is variable length (= <code>*foo</code> style), it will be printed as <code>[&ltfoo&gt;...]</code>.</li>
255
+ </ul>
256
+ <p>File: ex03.rb</p>
257
+ <pre class="language-ruby">
258
+ #!/usr/bin/env ruby
259
+ require 'benry/cmdapp'
260
+
261
+ class SampleAction &lt Benry::CmdApp::Action
262
+
263
+ @action.("parameter names test")
264
+ def test1(<strong>aaa, bbb_or_ccc, ddd=nil, eee=nil, *fff</strong>) # !!!!
265
+ # ...
266
+ end
267
+
268
+ end
269
+
270
+ config = Benry::CmdApp::Config.new("sample app")
271
+ app = Benry::CmdApp::Application.new(config)
272
+ exit app.main()
273
+ </pre>
274
+ <p>Help message:</p>
275
+ <pre class="language-console">
276
+ [bash]$ ruby ex03.rb -h test1
277
+ hoge.rb test1 -- parameter names test
278
+
279
+ Usage:
280
+ $ ex03.rb test1 <strong>&ltaaa&gt; &ltbbb|ccc&gt; [&ltddd&gt; [&lteee&gt; [&ltfff&gt;...]]]</strong> # !!!!
281
+ </pre>
282
+ </section>
283
+ <section class="subsection" id="options">
284
+ <h3>Options</h3>
285
+ <ul>
286
+ <li>Action can take command-line options.</li>
287
+ <li>Option values specified in command-line are passed to actio method as keyword arguments.</li>
288
+ </ul>
289
+ <p>File: ex04.rb</p>
290
+ <pre class="language-ruby">
291
+ #!/usr/bin/env ruby
292
+ require 'benry/cmdapp'
293
+
294
+ ## action
295
+ class MyAction &lt Benry::CmdApp::Action
296
+
297
+ @action.("print greeting message")
298
+ <strong>@option.(:lang, "-l, --lang=&lten|fr|it&gt;", "language")</strong> # !!!!
299
+ def hello(user="world", <strong>lang: "en"</strong>) # !!!!
300
+ case lang
301
+ when "en" ; puts "Hello, #{user}!"
302
+ when "fr" ; puts "Bonjour, #{user}!"
303
+ when "it" ; puts "Ciao, #{user}!"
304
+ else
305
+ raise "#{lang}: unknown language."
306
+ end
307
+ end
308
+
309
+ end
310
+
311
+ ## configuration
312
+ config = Benry::CmdApp::Config.new("sample app", "1.0.0")
313
+ config.default_help = true
314
+
315
+ ## run application
316
+ app = Benry::CmdApp::Application.new(config)
317
+ status_code = app.main()
318
+ exit status_code
319
+ </pre>
320
+ <p>Output:</p>
321
+ <pre class="language-console">
322
+ [bash]$ ruby ex04.rb hello
323
+ <strong>Hello</strong>, world!
324
+
325
+ [bash]$ ruby ex04.rb hello <strong>-l fr</strong> # !!!!
326
+ <strong>Bonjour</strong>, world!
327
+
328
+ [bash]$ ruby ex04.rb hello <strong>--lang=it</strong> # !!!!
329
+ <strong>Ciao</strong>, world!
330
+ </pre>
331
+ <ul>
332
+ <li>An action can have multiple options.</li>
333
+ <li>Option format can have indentation spaces, for example <code>' --help'</code>.</li>
334
+ </ul>
335
+ <p>File: ex05.rb</p>
336
+ <pre class="language-ruby">
337
+ #!/usr/bin/env ruby
338
+ require 'benry/cmdapp'
339
+
340
+ ## action
341
+ class MyAction &lt Benry::CmdApp::Action
342
+
343
+ @action.("print greeting message")
344
+ @option.(:lang , "-l, --lang=&lten|fr|it&gt;", "language")
345
+ <strong>@option.(:repeat, " --repeat=&ltN&gt;", "repeat &ltN&gt; times")</strong> # !!!!
346
+ def hello(user="world", lang: "en", <strong>repeat: "1"</strong>)
347
+ #p repeat.class #=&gt; String # !!!!
348
+ repeat.to_i.times do # !!!!
349
+ case lang
350
+ when "en" ; puts "Hello, #{user}!"
351
+ when "fr" ; puts "Bonjour, #{user}!"
352
+ when "it" ; puts "Ciao, #{user}!"
353
+ else
354
+ raise "#{lang}: unknown language."
355
+ end
356
+ end
357
+ end
358
+
359
+ end
360
+
361
+ ## configuration
362
+ config = Benry::CmdApp::Config.new("sample app", "1.0.0")
363
+ config.default_help = true
364
+
365
+ ## run application
366
+ app = Benry::CmdApp::Application.new(config)
367
+ status_code = app.main()
368
+ exit status_code
369
+ </pre>
370
+ <p>Output:</p>
371
+ <pre class="language-console">
372
+ [bash]$ ruby ex05.rb hello Alice -l fr <strong>--repeat=3</strong>
373
+ Bonjour, Alice!
374
+ Bonjour, Alice!
375
+ Bonjour, Alice!
376
+ `````
377
+
378
+ Help message:
379
+
380
+ ```console
381
+ [bash]$ ruby ex05.rb -h hello
382
+ ex05.rb hello -- print greeting message
383
+
384
+ Usage:
385
+ $ ex05.rb hello [&ltoptions&gt;] [&ltuser&gt;]
386
+
387
+ Options:
388
+ -l, --lang=&lten|fr|it&gt; : language # !!!!
389
+ <strong> --repeat=&ltN&gt; : repeat &ltN&gt; times</strong> # !!!!
390
+ </pre>
391
+ <p>For usability reason, Benry::CmdApp supports <code>--lang=&ltval&gt;</code> style long option
392
+ and doesn't support <code>--lang &ltval&gt;</code> style option.
393
+ Benry::CmdApp regards <code>--lang &ltval&gt;</code> as 'long option without argument'
394
+ and 'argument for command'.</p>
395
+ <pre class="language-console">
396
+ [bash]$ ruby ex05.rb hello <strong>--lang fr</strong> # ``--lang fr`` != ``--lang=fr``
397
+ <strong>[ERROR] --lang: argument required.</strong>
398
+ </pre>
399
+ </section>
400
+ <section class="subsection" id="option-definition-format">
401
+ <h3>Option Definition Format</h3>
402
+ <p>Option definition format should be one of:</p>
403
+ <ul>
404
+ <li>(short option) <code>-q</code> : no values.</li>
405
+ <li>(short option) <code>-f &ltfile&gt;</code> : value required.</li>
406
+ <li>(short option) <code>-i[&ltwidth&gt;]</code> : value is optional.</li>
407
+ <li>(long option) <code>--quiet</code> : no values.</li>
408
+ <li>(long option) <code>--file=&ltfile&gt;</code> : value required.</li>
409
+ <li>(long option) <code>--indent[=&ltwidth&gt;]</code> : value is optional.</li>
410
+ <li>(short &amp; long) <code>-q, --quiet</code> : no values.</li>
411
+ <li>(short &amp; long) <code>-f, --file=&ltfile&gt;</code> : value required.</li>
412
+ <li>(short &amp; long) <code>-i, --indent[=&ltwidth&gt;]</code> : value is optional.</li>
413
+ </ul>
414
+ <p>File: ex06.rb</p>
415
+ <pre class="language-ruby">
416
+ #!/usr/bin/env ruby
417
+ require 'benry/cmdapp'
418
+
419
+ class SampleAction &lt Benry::CmdApp::Action
420
+
421
+ ## short options
422
+ @action.("short options")
423
+ @option.(:quiet , <strong>"-q"</strong> , "quiet mode") # none
424
+ @option.(:file , <strong>"-f &ltfile&gt;"</strong> , "filename") # required
425
+ @option.(:indent , <strong>"-i[&ltN&gt;]"</strong> , "indent width") # optional
426
+ def test1(quiet: false, file: nil, indent: nil)
427
+ puts "quiet=#{quiet.inspect}, file=#{file.inspect}, indent=#{indent.inspect}"
428
+ end
429
+
430
+ ## long options
431
+ @action.("long options")
432
+ @option.(:quiet , <strong>"--quiet"</strong> , "quiet mode") # none
433
+ @option.(:file , <strong>"--file=&ltfile&gt;"</strong> , "filename") # required
434
+ @option.(:indent , <strong>"--indent[=&ltN&gt;]"</strong> , "indent width") # optional
435
+ def test2(quiet: false, file: nil, indent: nil)
436
+ puts "quiet=#{quiet.inspect}, file=#{file.inspect}, indent=#{indent.inspect}"
437
+ end
438
+
439
+ ## short and long options
440
+ @action.("short and long options")
441
+ @option.(:quiet , <strong>"-q, --quiet"</strong> , "quiet mode") # none
442
+ @option.(:file , <strong>"-f, --file=&ltfile&gt;"</strong> , "filename") # required
443
+ @option.(:indent , <strong>"-i, --indent[=&ltN&gt;]"</strong> , "indent width") # optional
444
+ def test3(quiet: false, file: nil, indent: nil)
445
+ puts "quiet=#{quiet.inspect}, file=#{file.inspect}, indent=#{indent.inspect}"
446
+ end
447
+
448
+ end
449
+
450
+ config = Benry::CmdApp::Config.new("test app")
451
+ app = Benry::CmdApp::Application.new(config)
452
+ exit app.main()
453
+ </pre>
454
+ <p>Output:</p>
455
+ <pre class="language-console">
456
+ [bash]$ ruby ex06.rb test1 <strong>-q -f readme.txt -i4</strong>
457
+ quiet=true, file="readme.txt", indent="4"
458
+
459
+ [bash]$ ruby ex06.rb test2 <strong>--quiet --file=readme.txt --indent=4</strong>
460
+ quiet=true, file="readme.txt", indent="4"
461
+
462
+ [bash]$ ruby ex06.rb test3 <strong>-q -f readme.txt -i4</strong>
463
+ quiet=true, file="readme.txt", indent="4"
464
+ [bash]$ ruby ex06.rb test3 <strong>--quiet --file=readme.txt --indent=4</strong>
465
+ quiet=true, file="readme.txt", indent="4"
466
+ </pre>
467
+ <p>Optional argument example:</p>
468
+ <pre class="language-console">
469
+ [bash]$ ruby ex06.rb test1 <strong>-i</strong> # ``-i`` results in ``true``
470
+ quiet=false, file=nil, <strong>indent=true</strong>
471
+ [bash]$ ruby ex06.rb test1 <strong>-i4</strong> # ``-i4`` results in ``4``
472
+ quiet=false, file=nil, <strong>indent="4"</strong>
473
+
474
+ [bash]$ ruby ex06.rb test2 <strong>--indent</strong> # ``--indent`` results in ``true``
475
+ quiet=false, file=nil, <strong>indent=true</strong>
476
+ [bash]$ ruby ex06.rb test2 <strong>--indent=4</strong> # ``--indent=4`` results in ``4``
477
+ quiet=false, file=nil, <strong>indent="4"</strong>
478
+ </pre>
479
+ <p>Help message:</p>
480
+ <pre class="language-ruby">
481
+ [bash]$ ruby ex06.rb -h test1
482
+ ex06.rb test1 -- short options
483
+
484
+ Usage:
485
+ $ ex06.rb test1 [&ltoptions&gt;]
486
+
487
+ Options:
488
+ <strong>-q</strong> : quiet mode
489
+ <strong>-f &ltfile&gt;</strong> : filename
490
+ <strong>-i[&ltN&gt;]</strong> : indent width
491
+
492
+ [bash]$ ruby ex06.rb -h test2
493
+ ex06.rb test2 -- long options
494
+
495
+ Usage:
496
+ $ ex06.rb test2 [&ltoptions&gt;]
497
+
498
+ Options:
499
+ <strong>--quiet</strong> : quiet mode
500
+ <strong>--file=&ltfile&gt;</strong> : filename
501
+ <strong>--indent[=&ltN&gt;]</strong> : indent width
502
+
503
+ [bash]$ ruby ex06.rb -h test3
504
+ ex06.rb test3 -- short and long options
505
+
506
+ Usage:
507
+ $ ex06.rb test3 [&ltoptions&gt;]
508
+
509
+ Options:
510
+ <strong>-q, --quiet</strong> : quiet mode
511
+ <strong>-f, --file=&ltfile&gt;</strong> : filename
512
+ <strong>-i, --indent[=&ltN&gt;]</strong> : indent width
513
+ </pre>
514
+ </section>
515
+ <section class="subsection" id="option-value-validation">
516
+ <h3>Option Value Validation</h3>
517
+ <p><code>@option.()</code> can validate option value via keyword argument.</p>
518
+ <ul>
519
+ <li><code>type: &ltclass&gt;</code> specifies option value class.
520
+ Currently supports <code>Integer</code>, <code>Float</code>, <code>TrueClass</code>, and <code>Date</code>.</li>
521
+ <li><code>rexp: &ltrexp&gt;</code> specifies regular expression of option value.</li>
522
+ <li><code>enum: &ltarray&gt;</code> specifies available values as option value.</li>
523
+ <li><code>range: &ltrange&gt;</code> specifies range of option value.</li>
524
+ </ul>
525
+ <p>File: ex07.rb</p>
526
+ <pre class="language-ruby">
527
+ #!/usr/bin/env ruby
528
+ require 'benry/cmdapp'
529
+
530
+ ## action
531
+ class MyAction &lt Benry::CmdApp::Action
532
+
533
+ @action.("print greeting message")
534
+ @option.(:lang , "-l, --lang=&lten|fr|it&gt;", "language",
535
+ <strong>enum: ["en", "fr", "it"]</strong>, # !!!!
536
+ <strong>rexp: /\A\w\w\z/</strong>) # !!!!
537
+ @option.(:repeat, " --repeat=&ltN&gt;", "repeat &ltN&gt; times",
538
+ <strong>type: Integer, range: 1..10</strong>) # !!!!
539
+ def hello(user="world", lang: "en", repeat: 1)
540
+ #p repeat.class #=&gt; Integer
541
+ repeat.times do
542
+ case lang
543
+ when "en" ; puts "Hello, #{user}!"
544
+ when "fr" ; puts "Bonjour, #{user}!"
545
+ when "it" ; puts "Ciao, #{user}!"
546
+ else
547
+ raise "#{lang}: unknown language."
548
+ end
549
+ end
550
+ end
551
+
552
+ end
553
+
554
+ ## configuration
555
+ config = Benry::CmdApp::Config.new("sample app", "1.0.0")
556
+ config.default_help = true
557
+
558
+ ## run application
559
+ app = Benry::CmdApp::Application.new(config)
560
+ status_code = app.main()
561
+ exit status_code
562
+ </pre>
563
+ <p>Output:</p>
564
+ <pre class="language-console">
565
+ [bash]$ ruby ex07.rb hello <strong>-l japan</strong>
566
+ <strong>[ERROR] -l japan: pattern unmatched.</strong>
567
+
568
+ [bash]$ ruby ex07.rb hello <strong>-l ja</strong>
569
+ <strong>[ERROR] -l ja: expected one of en/fr/it.</strong>
570
+
571
+ [bash]$ ruby ex07.rb hello <strong>--repeat=abc</strong>
572
+ <strong>[ERROR] --repeat=abc: integer expected.</strong>
573
+
574
+ [bash]$ ruby ex07.rb hello <strong>--repeat=100</strong>
575
+ <strong>[ERROR] --repeat=100: Too large (max: 10).</strong>
576
+ </pre>
577
+ </section>
578
+ <section class="subsection" id="callback-for-option-value">
579
+ <h3>Callback for Option Value</h3>
580
+ <p><code>@option.()</code> can take a block argument which is a callback for option value.
581
+ Callback can:</p>
582
+ <ul>
583
+ <li>Do custom validation of option value.</li>
584
+ <li>Convert option value into other value.</li>
585
+ </ul>
586
+ <p>File: ex08.rb</p>
587
+ <pre class="language-ruby">
588
+ #!/usr/bin/env ruby
589
+ require 'benry/cmdapp'
590
+
591
+ ## action
592
+ class MyAction &lt Benry::CmdApp::Action
593
+
594
+ @action.("print greeting message")
595
+ @option.(:lang , "-l, --lang=&lten|fr|it&gt;", "language",
596
+ enum: ["en", "fr", "it", "EN", "FR", "IT"],
597
+ rexp: /\A\w\w\z/) <strong>{|v| v.downcase }</strong> # !!!!
598
+ @option.(:repeat, " --repeat=&ltN&gt;", "repeat &ltN&gt; times",
599
+ type: Integer) <strong>{|v|</strong> # !!!!
600
+ <strong>v &gt; 0 or raise "not positive value."</strong> # !!!!
601
+ <strong>v</strong> # !!!!
602
+ <strong>}</strong> # !!!!
603
+ def hello(user="world", lang: "en", repeat: 1)
604
+ repeat.times do
605
+ case lang
606
+ when "en" ; puts "Hello, #{user}!"
607
+ when "fr" ; puts "Bonjour, #{user}!"
608
+ when "it" ; puts "Ciao, #{user}!"
609
+ else
610
+ raise "#{lang}: unknown language."
611
+ end
612
+ end
613
+ end
614
+
615
+ end
616
+
617
+ ## configuration
618
+ config = Benry::CmdApp::Config.new("sample app", "1.0.0")
619
+ config.default_help = true
620
+
621
+ ## run application
622
+ app = Benry::CmdApp::Application.new(config)
623
+ status_code = app.main()
624
+ exit status_code
625
+ </pre>
626
+ <p>Output:</p>
627
+ <pre class="language-console">
628
+ [bash]$ ruby ex08.rb hello <strong>-l FR</strong> # converted into lowercase
629
+ Bonjour, world!
630
+
631
+ [bash]$ ruby ex08.rb hello <strong>--repeat=0</strong>
632
+ <strong>[ERROR] --repeat=0: not positive value.</strong>
633
+ </pre>
634
+ </section>
635
+ <section class="subsection" id="boolean-onoff-option">
636
+ <h3>Boolean (On/Off) Option</h3>
637
+ <p>Benry::CmdApp doesn't support <code>--[no-]foobar</code> style option.
638
+ Instead, define boolean (on/off) option.</p>
639
+ <ul>
640
+ <li>Specify <code>type: TrueClass</code> to <code>@option.()</code>.</li>
641
+ <li>Option value <code>true</code>, <code>yes</code>, and <code>on</code> are converted into true.</li>
642
+ <li>Option value <code>false</code>, <code>no</code>, and <code>off</code> are converted into false.</li>
643
+ </ul>
644
+ <p>File: ex09.rb</p>
645
+ <pre class="language-ruby">
646
+ #!/usr/bin/env ruby
647
+ require 'benry/cmdapp'
648
+
649
+ class SampleAction &lt Benry::CmdApp::Action
650
+
651
+ @action.("flag test")
652
+ @option.(:verbose, <strong>"--verbose[=&lton|off&gt;]"</strong>, # !!!!
653
+ "verbose mode",
654
+ <strong>type: TrueClass</strong>) # !!!!
655
+ def flagtest(<strong>verbose: false</strong>) # !!!!
656
+ puts "verbose=#{verbose}"
657
+ end
658
+
659
+ end
660
+
661
+ config = Benry::CmdApp::Config.new("sample app", "1.0.0")
662
+ app = Benry::CmdApp::Application.new(config)
663
+ exit app.main()
664
+ </pre>
665
+ <p>Output:</p>
666
+ <pre class="language-console">
667
+ [bash]$ ruby ex09.rb flagtest --verbose=<strong>on</strong> # on
668
+ verbose=<strong>true</strong>
669
+
670
+ [bash]$ ruby ex09.rb flagtest --verbose=<strong>off</strong> # off
671
+ verbose=<strong>false</strong>
672
+
673
+ [bash]$ ruby ex09.rb flagtest --verbose=<strong>true</strong> # on
674
+ verbose=<strong>true</strong>
675
+
676
+ [bash]$ ruby ex09.rb flagtest --verbose=<strong>false</strong> # off
677
+ verbose=<strong>false</strong>
678
+
679
+ [bash]$ ruby ex09.rb flagtest --verbose=<strong>yes</strong> # on
680
+ verbose=<strong>true</strong>
681
+
682
+ [bash]$ ruby ex09.rb flagtest --verbose=<strong>no</strong> # off
683
+ verbose=<strong>false</strong>
684
+
685
+ [bash]$ ruby ex09.rb flagtest --verbose=<strong>abc</strong> # error
686
+ <strong>[ERROR] --verbose=abc: boolean expected.</strong>
687
+ </pre>
688
+ <p>If you want default value of flag to <code>true</code>, use <code>value:</code> keyword argument.</p>
689
+ <ul>
690
+ <li><code>value:</code> keyword argument in <code>@option.()</code> specifies the substitute value
691
+ instead of <code>true</code> when no option value specified in command-line.</li>
692
+ </ul>
693
+ <p>File: ex10.rb</p>
694
+ <pre class="language-ruby">
695
+ #!/usr/bin/env ruby
696
+ require 'benry/cmdapp'
697
+
698
+ class SampleAction &lt Benry::CmdApp::Action
699
+
700
+ @action.("flag test")
701
+ @option.(:verbose, "-q, --quiet", "quiet mode",
702
+ <strong>value: false</strong>) # !!!!
703
+ def flagtest2(<strong>verbose: true</strong>) # !!!!
704
+ puts "verbose=#{verbose.inspect}"
705
+ end
706
+
707
+ end
708
+
709
+ config = Benry::CmdApp::Config.new("git helper")
710
+ app = Benry::CmdApp::Application.new(config)
711
+ exit app.main()
712
+ </pre>
713
+ <p>Output:</p>
714
+ <pre class="language-console">
715
+ [bash]$ ruby ex10.rb flagtest2 # true if '--quiet' NOT specified
716
+ verbose=<strong>true</strong>
717
+
718
+ [bash]$ ruby ex10.rb flagtest2 <strong>--quiet</strong> # false if '--quiet' specified
719
+ verbose=<strong>false</strong>
720
+
721
+ [bash]$ ruby ex10.rb flagtest2 <strong>--quiet=on</strong> # error
722
+ <strong>[ERROR] --quiet=on: unexpected argument.</strong>
723
+ </pre>
724
+ <p>In above example, <code>--quiet=on</code> will be error because option is defined as
725
+ <code>@option.(:verbose, "-q, --quiet", ...)</code> which means that this option takes no arguments.
726
+ If you want to allow <code>--quiet=on</code>, specify option argument and <code>type: TrueClass</code>.</p>
727
+ <pre class="language-ruby">
728
+ ...(snip)...
729
+
730
+ @action.("flag test")
731
+ @option.(:verbose, "-q, --quiet<strong>[=&lton|off]</strong>", "quiet mode", # !!!!
732
+ <strong>type: TrueClass</strong>, value: false) # !!!!
733
+ def flagtest2(verbose: true)
734
+ puts "verbose=#{verbose.inspect}"
735
+ end
736
+
737
+ ...(snip)...
738
+ </pre>
739
+ </section>
740
+ <section class="subsection" id="prefix-of-action-name">
741
+ <h3>Prefix of Action Name</h3>
742
+ <ul>
743
+ <li><code>prefix: "foo:bar"</code> in action class adds prefix <code>foo:bar:</code> to each action name.</li>
744
+ <li>Method name <code>def baz__test()</code> with <code>prefix: "foo:bar"</code> results in action name <code>foo:bar:baz:test</code>.</li>
745
+ </ul>
746
+ <p>File: ex11.rb</p>
747
+ <pre class="language-ruby">
748
+ #!/usr/bin/env ruby
749
+ require 'benry/cmdapp'
750
+
751
+ class SampleAction &lt Benry::CmdApp::Action
752
+ <strong>prefix "foo:bar"</strong> # !!!!
753
+
754
+ @action.("test action #1")
755
+ def <strong>test1</strong>() # action name: 'foo:bar:test1'
756
+ puts __method__
757
+ end
758
+
759
+ @action.("test action #2")
760
+ def <strong>baz__test2</strong>() # action name: 'foo:bar:baz:test2'
761
+ puts __method__
762
+ end
763
+
764
+ end
765
+
766
+ config = Benry::CmdApp::Config.new("sample app")
767
+ app = Benry::CmdApp::Application.new(config)
768
+ exit app.main()
769
+ </pre>
770
+ <p>Output:</p>
771
+ <pre class="language-console">
772
+ [bash]$ ruby ex11.rb <strong>foo:bar:test1</strong>
773
+ test1
774
+
775
+ [bash]$ ruby ex11.rb <strong>foo:bar:baz:test2</strong>
776
+ baz__test2
777
+ </pre>
778
+ <p>Help message:</p>
779
+ <pre class="language-console">
780
+ [bash]$ ruby ex11.rb -h
781
+ ex11.rb -- sample app
782
+
783
+ Usage:
784
+ $ ex11.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
785
+
786
+ Options:
787
+ -h, --help : print help message (of action if action specified)
788
+
789
+ Actions:
790
+ <strong>foo:bar:baz:test2</strong> : test action #2
791
+ <strong>foo:bar:test1</strong> : test action #1
792
+ </pre>
793
+ <ul>
794
+ <li><code>prefix: "foo:bar", action: :test</code> defines <code>foo:bar</code> action (intead of <code>foo:bar:test</code>) with <code>test()</code> method.</li>
795
+ </ul>
796
+ <p>File: ex12.rb</p>
797
+ <pre class="language-ruby">
798
+ #!/usr/bin/env ruby
799
+ require 'benry/cmdapp'
800
+
801
+ class SampleAction &lt Benry::CmdApp::Action
802
+ prefix "foo:bar", <strong>action: :test3_</strong> # !!!!
803
+ ## or:
804
+ #prefix "foo:bar", <strong>action: "test3"</strong> # !!!!
805
+
806
+ @action.("test action #1")
807
+ def test1() # action name: 'foo:bar:test1'
808
+ puts __method__
809
+ end
810
+
811
+ @action.("test action #3")
812
+ def <strong>test3_</strong>() # action name: 'foo:bar'
813
+ puts __method__
814
+ end
815
+
816
+ end
817
+
818
+ config = Benry::CmdApp::Config.new("sample app")
819
+ app = Benry::CmdApp::Application.new(config)
820
+ exit app.main()
821
+ </pre>
822
+ <p>Output:</p>
823
+ <pre class="language-console">
824
+ [bash]$ ruby ex12.rb foo:bar:test1
825
+ test1
826
+
827
+ [bash]$ ruby ex12.rb <strong>foo:bar:test3</strong>
828
+ [ERROR] foo:bar:test2: unknown action.
829
+
830
+ [bash]$ ruby ex12.rb <strong>foo:bar</strong>
831
+ test3_
832
+ </pre>
833
+ <p>Help message:</p>
834
+ <pre class="language-console">
835
+ [bash]$ ruby ex12.rb -h
836
+ ex12.rb -- sample app
837
+
838
+ Usage:
839
+ $ ex12.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
840
+
841
+ Options:
842
+ -h, --help : print help message (of action if action specified)
843
+
844
+ Actions:
845
+ <strong>foo:bar</strong> : test action #3
846
+ foo:bar:test1 : test action #1
847
+ </pre>
848
+ </section>
849
+ <section class="subsection" id="invoke-other-action">
850
+ <h3>Invoke Other Action</h3>
851
+ <ul>
852
+ <li><code>run_action!()</code> invokes other action.</li>
853
+ <li><code>run_action_once()</code> invokes other action only once.
854
+ This is equivarent to 'prerequisite task' feature in task runner application.</li>
855
+ </ul>
856
+ <p>File: ex13.rb</p>
857
+ <pre class="language-ruby">
858
+ #!/usr/bin/env ruby
859
+ require 'benry/cmdapp'
860
+
861
+ class SampleAction &lt Benry::CmdApp::Action
862
+
863
+ @action.("create build dir")
864
+ def <strong>prepare</strong>()
865
+ puts <strong>"rm -rf build"</strong>
866
+ puts <strong>"mkdir build"</strong>
867
+ end
868
+
869
+ @action.("build something")
870
+ def build()
871
+ <strong>run_action_once("prepare")</strong> # !!!!
872
+ <strong>run_action_once("prepare")</strong> # skipped because already invoked
873
+ puts "echo 'README' &gt; build/README.txt"
874
+ puts "zip -r build.zip build"
875
+ end
876
+
877
+ end
878
+
879
+ config = Benry::CmdApp::Config.new("sample app")
880
+ app = Benry::CmdApp::Application.new(config)
881
+ exit app.main()
882
+ </pre>
883
+ <p>Output:</p>
884
+ <pre class="language-console">
885
+ [bash]$ ruby ex13.rb build
886
+ <strong>rm -rf build</strong> # invoked only once!!!!
887
+ <strong>mkdir build</strong> # invoked only once!!!!
888
+ echo 'README' &gt; build/README.txt
889
+ zip -r build.zip build
890
+ </pre>
891
+ <ul>
892
+ <li>When looped action is detected, Benry::CmdApp aborts action.</li>
893
+ </ul>
894
+ <p>File: ex14.rb</p>
895
+ <pre class="language-ruby">
896
+ #!/usr/bin/env ruby
897
+ require 'benry/cmdapp'
898
+
899
+ class LoopedAction &lt Benry::CmdApp::Action
900
+
901
+ @action.("test #1")
902
+ def test1()
903
+ run_action_once("test2")
904
+ end
905
+
906
+ @action.("test #2")
907
+ def test2()
908
+ run_action_once("test3")
909
+ end
910
+
911
+ @action.("test #3")
912
+ def test3()
913
+ <strong>run_action_once("test1")</strong> # !!!!
914
+ end
915
+
916
+ end
917
+
918
+ config = Benry::CmdApp::Config.new("sample app")
919
+ app = Benry::CmdApp::Application.new(config)
920
+ exit app.main()
921
+ </pre>
922
+ <p>Output:</p>
923
+ <pre class="language-console">
924
+ [bash]$ ruby ex14.rb test1
925
+ <strong>[ERROR] test1: looped action detected.</strong>
926
+
927
+ [bash]$ ruby ex14.rb test3
928
+ <strong>[ERROR] test3: looped action detected.</strong>
929
+ </pre>
930
+ </section>
931
+ <section class="subsection" id="action-alias">
932
+ <h3>Action Alias</h3>
933
+ <ul>
934
+ <li>Alias of action provides alternative short name of action.</li>
935
+ </ul>
936
+ <p>File: ex15.rb</p>
937
+ <pre class="language-ruby">
938
+ #!/usr/bin/env ruby
939
+ require 'benry/cmdapp'
940
+
941
+ class SampleAction &lt Benry::CmdApp::Action
942
+ <strong>prefix "foo:bar"</strong>
943
+
944
+ @action.("test action #1")
945
+ def <strong>test1</strong>() # action name: 'foo:bar:test1'
946
+ puts __method__
947
+ end
948
+
949
+ end
950
+
951
+ <strong>Benry::CmdApp.action_alias "test", "foo:bar:test1"</strong> # !!!!
952
+
953
+ config = Benry::CmdApp::Config.new("sample app")
954
+ app = Benry::CmdApp::Application.new(config)
955
+ exit app.main()
956
+ </pre>
957
+ <p>Output:</p>
958
+ <pre class="language-console">
959
+ [bash]$ ruby ex15.rb <strong>test</strong> # alias name
960
+ test1
961
+
962
+ [bash]$ ruby ex15.rb <strong>foo:bar:test1</strong> # original action name
963
+ test1
964
+ </pre>
965
+ <p>Help message:</p>
966
+ <pre class="language-console">
967
+ [bash]$ ruby ex15.rb -h
968
+ ex15.rb -- sample app
969
+
970
+ Usage:
971
+ $ ex15.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
972
+
973
+ Options:
974
+ -h, --help : print help message (of action if action specified)
975
+
976
+ Actions:
977
+ foo:bar:test1 : test action #1
978
+ <strong>test : alias to 'foo:bar:test1' action</strong>
979
+ </pre>
980
+ <ul>
981
+ <li>Alias can include positional and keyword arguments in definition.</li>
982
+ </ul>
983
+ <p>File: ex16.rb</p>
984
+ <pre class="language-ruby">
985
+ #!/usr/bin/env ruby
986
+ require 'benry/cmdapp'
987
+
988
+ class MyAction &lt Benry::CmdApp::Action
989
+
990
+ @action.("print greeting message")
991
+ @option.(:lang, "-l, --lang=&ltlang&gt;", "language", enum: ["en", "fr", "it"])
992
+ def hello(user="world", lang: "en")
993
+ case lang
994
+ when "en" ; puts "Hello, #{user}!"
995
+ when "fr" ; puts "Bonjour, #{user}!"
996
+ when "it" ; puts "Ciao, #{user}!"
997
+ else
998
+ raise "#{lang}: unknown language."
999
+ end
1000
+ end
1001
+
1002
+ end
1003
+
1004
+ Benry::CmdApp.action_alias("bonjour", "hello", <strong>"--lang=fr"</strong>) # !!!!
1005
+ Benry::CmdApp.action_alias("ciao" , "hello", <strong>"Bob", "-l", "it"</strong>) # !!!!
1006
+
1007
+ config = Benry::CmdApp::Config.new("sample app")
1008
+ app = Benry::CmdApp::Application.new(config)
1009
+ exit app.main()
1010
+ </pre>
1011
+ <p>Output:</p>
1012
+ <pre class="language-console">
1013
+ [bash]$ ruby ex16.rb hello
1014
+ Hello, world!
1015
+
1016
+ [bash]$ ruby ex16.rb <strong>bonjour</strong> # !!!!
1017
+ Bonjour, world!
1018
+
1019
+ [bash]$ ruby ex16.rb <strong>bonjour Alice</strong> # !!!!
1020
+ Bonjour, Alice!
1021
+
1022
+ [bash]$ ruby ex16.rb <strong>ciao</strong> # !!!!
1023
+ Ciao, Bob!
1024
+ </pre>
1025
+ </section>
1026
+ <section class="subsection" id="default-action">
1027
+ <h3>Default Action</h3>
1028
+ <ul>
1029
+ <li><code>config.default = "test1"</code> defines default action.
1030
+ In this case, action <code>test1</code> will be invoked if action name not specified in command-line.</li>
1031
+ <li>Default action name is shown in help message.</li>
1032
+ </ul>
1033
+ <p>File: ex17.rb</p>
1034
+ <pre class="language-ruby">
1035
+ #!/usr/bin/env ruby
1036
+ require 'benry/cmdapp'
1037
+
1038
+ class SampleAction &lt Benry::CmdApp::Action
1039
+
1040
+ @action.("test action #1")
1041
+ def test1()
1042
+ puts __method__
1043
+ end
1044
+
1045
+ end
1046
+
1047
+ config = Benry::CmdApp::Config.new("sample app")
1048
+ <strong>config.default_action = "test1"</strong> # !!!!
1049
+ app = Benry::CmdApp::Application.new(config)
1050
+ exit app.main()
1051
+ </pre>
1052
+ <p>Output:</p>
1053
+ <pre class="language-console">
1054
+ [bash]$ ruby ex17.rb test1
1055
+ test1
1056
+
1057
+ [bash]$ <strong>ruby ex17.rb</strong> # no action name!!!!
1058
+ test1
1059
+ </pre>
1060
+ <p>Help message:</p>
1061
+ <pre class="language-console">
1062
+ [bash]$ ruby ex17.rb -h
1063
+ ex17.rb -- sample app
1064
+
1065
+ Usage:
1066
+ $ ex17.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
1067
+
1068
+ Options:
1069
+ -h, --help : print help message (of action if action specified)
1070
+
1071
+ Actions: <strong>(default: test1)</strong> # !!!!
1072
+ test1 : test action #1
1073
+ </pre>
1074
+ </section>
1075
+ <section class="subsection" id="default-help">
1076
+ <h3>Default Help</h3>
1077
+ <ul>
1078
+ <li><code>config.default_help = true</code> prints help message if action not specified in command-line.</li>
1079
+ <li>This is very useful when you don't have proper default action. It's recommended.</li>
1080
+ <li><code>config.default_action</code> is prior than <code>config.default_help</code>.</li>
1081
+ </ul>
1082
+ <p>File: ex18.rb</p>
1083
+ <pre class="language-ruby">
1084
+ #!/usr/bin/env ruby
1085
+ require 'benry/cmdapp'
1086
+
1087
+ class SampleAction &lt Benry::CmdApp::Action
1088
+
1089
+ @action.("test action #1")
1090
+ def test1()
1091
+ puts __method__
1092
+ end
1093
+
1094
+ end
1095
+
1096
+ config = Benry::CmdApp::Config.new("sample app")
1097
+ <strong>config.default_help = true</strong> # !!!!
1098
+ app = Benry::CmdApp::Application.new(config)
1099
+ exit app.main()
1100
+ </pre>
1101
+ <p>Output:</p>
1102
+ <pre class="language-console">
1103
+ [bash]$ <strong>ruby ex18.rb</strong> # no action name!!!!
1104
+ ex18.rb -- sample app
1105
+
1106
+ Usage:
1107
+ $ ex18.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
1108
+
1109
+ Options:
1110
+ -h, --help : print help message (of action if action specified)
1111
+
1112
+ Actions:
1113
+ test1 : test action #1
1114
+ </pre>
1115
+ </section>
1116
+ <section class="subsection" id="private-hidden-action">
1117
+ <h3>Private (Hidden) Action</h3>
1118
+ <ul>
1119
+ <li>If action method is private, Benry::CmdApp regards that action as private.</li>
1120
+ <li>Private actions are hidden in help message.</li>
1121
+ <li>Private actions are shown when <code>-a</code> or <code>--all</code> option enabled and specified.</li>
1122
+ </ul>
1123
+ <p>File: ex20.rb</p>
1124
+ <pre class="language-ruby">
1125
+ #!/usr/bin/env ruby
1126
+ require 'benry/cmdapp'
1127
+
1128
+ class SampleAction &lt Benry::CmdApp::Action
1129
+
1130
+ @action.("test action #1")
1131
+ def test1()
1132
+ puts __method__
1133
+ end
1134
+
1135
+ @action.("test action #2")
1136
+ def test2()
1137
+ puts __method__
1138
+ end
1139
+ <strong>private :test2</strong> # !!!! private method !!!!
1140
+
1141
+ <strong>private</strong> # !!!! private method !!!!
1142
+
1143
+ @action.("test action #3")
1144
+ def test3()
1145
+ puts __method__
1146
+ end
1147
+
1148
+ end
1149
+
1150
+ config = Benry::CmdApp::Config.new("sample app")
1151
+ <strong>config.option_all = true</strong> # !!!! enable '-a, --all' option !!!!
1152
+ app = Benry::CmdApp::Application.new(config)
1153
+ exit app.main()
1154
+ </pre>
1155
+ <p>Help message (without <code>-a</code> nor <code>--all</code>):</p>
1156
+ <pre class="language-console">
1157
+ [bash]$ ruby ex20.rb <strong>-h</strong>
1158
+ ex20.rb -- sample app
1159
+
1160
+ Usage:
1161
+ $ ex20.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
1162
+
1163
+ Options:
1164
+ -h, --help : print help message (of action if action specified)
1165
+ -a, --all : list all actions/options including private (hidden) ones
1166
+
1167
+ Actions:
1168
+ test1 : test action #1
1169
+ </pre>
1170
+ <p>Help message (with <code>-a</code> or <code>--all</code>):</p>
1171
+ <pre class="language-console">
1172
+ [bash]$ ruby ex20.rb <strong>-h --all</strong> # !!!!
1173
+ ex20.rb -- sample app
1174
+
1175
+ Usage:
1176
+ $ ex20.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
1177
+
1178
+ Options:
1179
+ -h, --help : print help message (of action if action specified)
1180
+ -a, --all : list all actions/options including private (hidden) ones
1181
+
1182
+ Actions:
1183
+ test1 : test action #1
1184
+ <strong>test2 : test action #2</strong> # !!!!
1185
+ <strong>test3 : test action #3</strong> # !!!!
1186
+ </pre>
1187
+ </section>
1188
+ <section class="subsection" id="private-hidden-option">
1189
+ <h3>Private (Hidden) Option</h3>
1190
+ <ul>
1191
+ <li>Options which name stars with <code>_</code> are treated as private option.</li>
1192
+ <li>Private options are hidden in help message of action.</li>
1193
+ <li>Private options are shown when <code>-a</code> or <code>--all</code> option enabled and specified.</li>
1194
+ </ul>
1195
+ <p>File: ex21.rb</p>
1196
+ <pre class="language-ruby">
1197
+ #!/usr/bin/env ruby
1198
+ require 'benry/cmdapp'
1199
+
1200
+ class SampleAction &lt Benry::CmdApp::Action
1201
+
1202
+ @action.("test action")
1203
+ @option.(:verbose, "-v", "verbose mode")
1204
+ @option.(<strong>:_debug</strong> , "-D", "debug mode") # !!!!
1205
+ def test1(verbose: false, _debug: false)
1206
+ puts "verbose=#{verbose}, _debug=#{_debug}"
1207
+ end
1208
+
1209
+ end
1210
+
1211
+ config = Benry::CmdApp::Config.new("sample app")
1212
+ <strong>config.option_all = true</strong> # !!!! enable '-a, --all' option !!!!
1213
+ app = Benry::CmdApp::Application.new(config)
1214
+ exit app.main()
1215
+ </pre>
1216
+ <p>Help message (without <code>-a</code> nor <code>--all</code>):</p>
1217
+ <pre class="language-console">
1218
+ [bash]$ ruby ex21.rb -h test1
1219
+ ex21.rb test1 -- test action
1220
+
1221
+ Usage:
1222
+ $ ex21.rb test1 [&ltoptions&gt;]
1223
+
1224
+ Options:
1225
+ -v : verbose mode
1226
+ </pre>
1227
+ <p>Help message (with <code>-a</code> or <code>--all</code>)</p>
1228
+ <pre class="language-console">
1229
+ [bash]$ ruby ex21.rb -h <strong>--all</strong> test1 # !!!!
1230
+ ex21.rb test1 -- test action
1231
+
1232
+ Usage:
1233
+ $ ex21.rb test1 [&ltoptions&gt;]
1234
+
1235
+ Options:
1236
+ -v : verbose mode
1237
+ -D : debug mode # !!!!
1238
+ </pre>
1239
+ </section>
1240
+ </section>
1241
+ <section class="section" id="configuratoin-and-customization">
1242
+ <h2>Configuratoin and Customization</h2>
1243
+ <section class="subsection" id="application-configuration">
1244
+ <h3>Application Configuration</h3>
1245
+ <p><code>Benry::CmdApp::Config</code> class configures application behaviour.</p>
1246
+ <ul>
1247
+ <li><code>config.app_desc = "..."</code> sets command description which is shown in help message. (required)</li>
1248
+ <li><code>config.app_version = "1.0.0"</code> enables <code>-V</code> and <code>--version</code> option, and prints version number if <code>-V</code> or <code>--version</code> option specified. (default: <code>nil</code>)</li>
1249
+ <li><code>config.app_command = "&ltcommand&gt;"</code> sets command name which is shown in help message. (default: <code>File.basname($0)</code>)</li>
1250
+ <li><code>config.app_detail = "&lttext&gt;"</code> sets detailed description of command which is showin in help message. (default: <code>nil</code>)</li>
1251
+ <li><code>config.default_action = "&ltaction&gt;"</code> sets default action name. (default: <code>nil</code>)</li>
1252
+ <li><code>config.default_help = true</code> prints help message if no action names specified in command-line. (default: <code>false</code>)</li>
1253
+ <li><code>config.option_help = true</code> enables <code>-h</code> and <code>--help</code> options. (default: <code>true</code>)</li>
1254
+ <li><code>config.option_all = true</code> enables <code>-a</code> and <code>--all</code> options which shows private (hidden) actions and options into help message. (default: <code>false</code>)</li>
1255
+ <li><code>config.option_verbose = true</code> enables <code>-v</code> and <code>--verbose</code> options which sets <code>$QUIET_MODE = false</code>. (default: <code>false</code>)</li>
1256
+ <li><code>config.option_quiet = true</code> enables <code>-q</code> and <code>--quiet</code> options which sets <code>$QUIET_MODE = true</code>. (default: <code>false</code>)</li>
1257
+ <li><code>config.option_color = true</code> enables <code>--color[=&lton|off&gt;]</code> option which sets <code>$COLOR_MODE = true/false</code>. This affects to help message colorized or not. (default: <code>false</code>)</li>
1258
+ <li><code>config.option_debug = true</code> enables <code>-D</code> and <code>--debug</code> options which sets <code>$DEBUG_MODE = true</code>. (default: <code>false</code>)</li>
1259
+ <li><code>config.option_trace = true</code> enables <code>-T</code> and <code>--trace</code> options which sets <code>$TRACE_MODE = true</code>. Entering into and exitting from action are reported when trace mode is on. (default: <code>false</code>)</li>
1260
+ <li><code>config.help_aliases = true</code> adds <code>Aliases:</code> section in help message. (default: <code>false</code>)</li>
1261
+ <li><code>config.help_sections = [["&lttitle&gt;", "&lttext&gt;"], ...]</code> adds section title and text into help message. (default: <code>[]</code>)</li>
1262
+ <li><code>config.help_postamble = "&lttext&gt;"</code> sets postamble text in help message, such as 'Examples:' or 'Tips:'. (default: <code>nil</code>)</li>
1263
+ <li><code>config.feat_candidate = true</code> enables feature to list action names starting with 'foo:' when action name specified in command-line is <code>foo:</code>. (default: <code>true</code>)</li>
1264
+ <li><code>config.format_help = " %-18s : %s"</code> sets format of options and actions in help message. (default: <code>" \e[1m%-18s\e[0m : %s"</code>)</li>
1265
+ <li><code>config.format_usage = " $ %s %s"</code> sets format of usage in help message. (default: <code>" $ \e[1m%s\e[0m %s"</code>)</li>
1266
+ <li><code>config.format_heading = "[%s]"</code> sets format of heading in help message. (default: <code>"\e[34m%s\e[0m"</code>)</li>
1267
+ </ul>
1268
+ <p>File: ex22.rb</p>
1269
+ <pre class="language-ruby">
1270
+ #!/usr/bin/env ruby
1271
+ require 'benry/cmdapp'
1272
+
1273
+ config = Benry::CmdApp::Config.new("sample app", "1.0.0")
1274
+ #config.default_help = true
1275
+
1276
+ config.class.instance_methods(false).each do |name|
1277
+ next if name =~ /=$/
1278
+ next if ! config.class.method_defined?("#{name}=")
1279
+ val = config.__send__(name)
1280
+ puts "%-25s = %s" % ["config.#{name}", val.inspect]
1281
+ end
1282
+ </pre>
1283
+ <p>Output:</p>
1284
+ <pre class="language-console">
1285
+ [bash]$ ruby ex22.rb
1286
+ config<strong>.app_desc</strong> = "sample app"
1287
+ config<strong>.app_version</strong> = "1.0.0"
1288
+ config<strong>.app_name</strong> = "ex22.rb"
1289
+ config<strong>.app_command</strong> = "ex22.rb"
1290
+ config<strong>.app_detail</strong> = nil
1291
+ config<strong>.default_action</strong> = nil
1292
+ config<strong>.default_help</strong> = false
1293
+ config<strong>.option_help</strong> = true
1294
+ config<strong>.option_all</strong> = false
1295
+ config<strong>.option_verbose</strong> = false
1296
+ config<strong>.option_quiet</strong> = false
1297
+ config<strong>.option_color</strong> = false
1298
+ config<strong>.option_debug</strong> = false
1299
+ config<strong>.option_trace</strong> = false
1300
+ config<strong>.help_aliases</strong> = false
1301
+ config<strong>.help_sections</strong> = []
1302
+ config<strong>.help_postamble</strong> = nil
1303
+ config<strong>.feat_candidate</strong> = true
1304
+ config<strong>.format_help</strong> = " \e[1m%-18s\e[0m : %s"
1305
+ config<strong>.format_usage</strong> = " $ \e[1m%s\e[0m %s"
1306
+ config<strong>.format_heading</strong> = "\e[34m%s\e[0m"
1307
+ config<strong>.format_appname</strong> = "\e[1m%s\e[0m"
1308
+ </pre>
1309
+ </section>
1310
+ <section class="subsection" id="customization-of-global-options">
1311
+ <h3>Customization of Global Options</h3>
1312
+ <p>To add custom global options:</p>
1313
+ <ul>
1314
+ <li>(1) Create global option schema object.</li>
1315
+ <li>(2) Add custom options to it.</li>
1316
+ <li>(3) Pass it to <code>Application.new()</code>.</li>
1317
+ </ul>
1318
+ <p>File: ex23.rb</p>
1319
+ <pre class="language-ruby">
1320
+ #!/usr/bin/env ruby
1321
+ require 'benry/cmdapp'
1322
+
1323
+ class SampleAction &lt Benry::CmdApp::Action
1324
+
1325
+ @action.("test action")
1326
+ def test1()
1327
+ puts __method__
1328
+ end
1329
+
1330
+ end
1331
+
1332
+ ## (1) create global option shema
1333
+ config = Benry::CmdApp::Config.new("sample app")
1334
+ <strong>schema = Benry::CmdApp::AppOptionSchema.new(config)</strong> # !!!!
1335
+
1336
+ ## (2) add custom options to it
1337
+ <strong>schema.add(:logging, "--logging", "enable logging")</strong> # !!!!
1338
+
1339
+ ## (3) pass it to ``Application.new()``
1340
+ app = Benry::CmdApp::Application.new(config, <strong>schema</strong>) # !!!!
1341
+
1342
+ exit app.main()
1343
+ </pre>
1344
+ <p>Help message:</p>
1345
+ <pre class="language-console">
1346
+ [bash]$ ruby ex23.rb -h
1347
+ ex23.rb -- sample app
1348
+
1349
+ Usage:
1350
+ $ ex23.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
1351
+
1352
+ Options:
1353
+ -h, --help : print help message (of action if action specified)
1354
+ <strong>--logging : enable logging</strong> # !!!!
1355
+
1356
+ Actions:
1357
+ test1 : test action
1358
+ </pre>
1359
+ <p>To customize global options entirely:</p>
1360
+ <ul>
1361
+ <li>(1) Create empty <code>AppOptionSchema</code> object.</li>
1362
+ <li>(2) Add global options as you want.</li>
1363
+ <li>(3) Create and execute Application object with it.</li>
1364
+ </ul>
1365
+ <p>File: ex24.rb</p>
1366
+ <pre class="language-ruby">
1367
+ #!/usr/bin/env ruby
1368
+ require 'benry/cmdapp'
1369
+
1370
+ ## (1) Create empty ``AppOptionSchema`` object.
1371
+ <strong>schema = Benry::CmdApp::AppOptionSchema.new(nil)</strong> # !!!!
1372
+
1373
+ ## (2) Add global options as you want.
1374
+ <strong>schema.add</strong>(:help , "-h, --help" , "print help message")
1375
+ <strong>schema.add</strong>(:version, "-V, --version", "print version")
1376
+ <strong>schema.add</strong>(:all , "-a, --all" , "list all actions/options")
1377
+ <strong>schema.add</strong>(:verbose, "-v, --verbose", "verbose mode")
1378
+ <strong>schema.add</strong>(:quiet , "-q, --quiet" , "quiet mode")
1379
+ <strong>schema.add</strong>(:color , "--color[=&lton|off&gt;]", "enable/disable color", type: TrueClass)
1380
+ <strong>schema.add</strong>(:debug , "-D, --debug" , "set $DEBUG_MODE to true")
1381
+ <strong>schema.add</strong>(:trace , "-T, --trace" , "report enter into and exit from action")
1382
+
1383
+ ## (3) Create and execute Application object with it.
1384
+ config = Benry::CmdApp::Config.new("sample app")
1385
+ app = Benry::CmdApp::Application.new(config, <strong>schema</strong>) # !!!!
1386
+ exit app.main()
1387
+ </pre>
1388
+ </section>
1389
+ <section class="subsection" id="customization-of-global-option-behaviour">
1390
+ <h3>Customization of Global Option Behaviour</h3>
1391
+ <ul>
1392
+ <li>(1) Define subclass of <code>Application</code> class.</li>
1393
+ <li>(2) Override <code>#do_toggle_global_switches()</code> method.</li>
1394
+ <li>(3) Create and execute subclass object of <code>Application</code>.</li>
1395
+ </ul>
1396
+ <p>File: ex25.rb</p>
1397
+ <pre class="language-ruby">
1398
+ #!/usr/bin/env ruby
1399
+ require 'benry/cmdapp'
1400
+
1401
+ ## (1) Define subclass of ``Application`` class.
1402
+ <strong>class MyApplication &lt Benry::CmdApp::Application</strong>
1403
+
1404
+ ## (2) Override ``#do_toggle_global_switches()`` method.
1405
+ <strong>def do_toggle_global_switches(_args, global_opts)</strong>
1406
+ <strong>super</strong>
1407
+ ## here is original behaviour
1408
+ #global_opts.each do |key, val|
1409
+ # case key
1410
+ # when :verbose ; $QUIET_MODE = ! val
1411
+ # when :quiet ; $QUIET_MODE = val
1412
+ # when :color ; $COLOR_MODE = val
1413
+ # when :debug ; $DEBUG_MODE = val
1414
+ # when :trace ; $TRACE_MODE = val
1415
+ # else ; # do nothing
1416
+ # end
1417
+ #end
1418
+ end
1419
+
1420
+ end
1421
+
1422
+ ## (3) Create and execute subclass object of ``Application``.
1423
+ config = Benry::CmdApp::Config.new("sample app")
1424
+ app = <strong>MyApplication.new(config)</strong> # !!!!
1425
+ exit app.main()
1426
+ </pre>
1427
+ <p>Of course, prepending custom module to Application class is also effective way.</p>
1428
+ <p>File: ex26.rb</p>
1429
+ <pre class="language-ruby">
1430
+ #!/usr/bin/env ruby
1431
+ require 'benry/cmdapp'
1432
+
1433
+ <strong>module MyApplicationMod</strong>
1434
+
1435
+ <strong>def do_toggle_global_switches(_args, global_opts)</strong>
1436
+ # ....
1437
+ end
1438
+
1439
+ end
1440
+
1441
+ Benry::CmdApp::Application<strong>.prepend(MyApplicationMod)</strong> # !!!!
1442
+
1443
+ config = Benry::CmdApp::Config.new("sample app")
1444
+ app = Benry::CmdApp::Application.new(config)
1445
+ exit app.main()
1446
+ </pre>
1447
+ </section>
1448
+ <section class="subsection" id="custom-hook-of-application">
1449
+ <h3>Custom Hook of Application</h3>
1450
+ <ul>
1451
+ <li>(1) Define subclass of Application class.</li>
1452
+ <li>(2) Override callback method.</li>
1453
+ <li>(3) Create and execute custom application object.</li>
1454
+ </ul>
1455
+ <p>File: ex27.rb</p>
1456
+ <pre class="language-ruby">
1457
+ #!/usr/bin/env ruby
1458
+ require 'benry/cmdapp'
1459
+
1460
+ class SampleAction &lt Benry::CmdApp::Action
1461
+
1462
+ @action.("test action")
1463
+ def test1()
1464
+ $logger.info("logging message") if $logger
1465
+ end
1466
+
1467
+ end
1468
+
1469
+ ## (1) Define subclass of Application class
1470
+ <strong>class MyApplication &lt Benry::CmdApp::Application</strong> # !!!!
1471
+
1472
+ ## (2) Override callback method
1473
+ <strong>def do_callback(args, global_opts)</strong> # !!!!
1474
+ #p @config
1475
+ #p @schema
1476
+ if global_opts[:logging]
1477
+ require 'logger'
1478
+ $logger = Logger.new(STDOUT)
1479
+ end
1480
+ ## if return :SKIP, action skipped (not invoked).
1481
+ #return :SKIP
1482
+ end
1483
+
1484
+ ## or:
1485
+ #def do_handle_global_options(args, global_opts)
1486
+ # if global_opts[:logging]
1487
+ # require 'logger'
1488
+ # $logger = Logger.new(STDOUT)
1489
+ # end
1490
+ # super
1491
+ #end
1492
+
1493
+ end
1494
+
1495
+ ## (3) create and execute custom application object
1496
+ config = Benry::CmdApp::Config.new("sample app")
1497
+ schema = Benry::CmdApp::AppOptionSchema.new(config)
1498
+ schema.add(:logging, "--logging", "enable logging")
1499
+ app = <strong>MyApplication</strong>.new(config, schema) # !!!!
1500
+ exit app.main()
1501
+ </pre>
1502
+ <ul>
1503
+ <li>[EXPERIMENTAL] Instead of defining subclass of Application, you can pass callback block to Application object.</li>
1504
+ </ul>
1505
+ <p>File: ex28.rb</p>
1506
+ <pre class="language-ruby">
1507
+ #!/usr/bin/env ruby
1508
+ require 'benry/cmdapp'
1509
+
1510
+ class SampleAction &lt Benry::CmdApp::Action
1511
+
1512
+ @action.("test action")
1513
+ def test1()
1514
+ $logger.info("logging message") if $logger
1515
+ end
1516
+
1517
+ end
1518
+
1519
+ config = Benry::CmdApp::Config.new("sample app")
1520
+ schema = Benry::CmdApp::AppOptionSchema.new(config)
1521
+ schema.add(:logging, "--logging", "enable logging")
1522
+ app = Benry::CmdApp::Application.new(config, schema) <strong>do</strong> # !!!!
1523
+ <strong>|args, global_opts, config|</strong> # !!!!
1524
+ if global_opts[:logging] # !!!!
1525
+ require 'logger' # !!!!
1526
+ $logger = Logger.new(STDOUT) # !!!!
1527
+ end # !!!!
1528
+ #:SKIP # !!!!
1529
+ end # !!!!
1530
+ exit app.main()
1531
+ </pre>
1532
+ </section>
1533
+ <section class="subsection" id="customization-of-command-help-message">
1534
+ <h3>Customization of Command Help Message</h3>
1535
+ <p>If you want to just add more text into command help message,
1536
+ set <code>config.app_detail</code>, <code>config.help_sections</code>, and/or <code>config.help_postamble</code>.</p>
1537
+ <p>File: ex29.rb</p>
1538
+ <pre class="language-ruby">
1539
+ #!/usr/bin/env ruby
1540
+ require 'benry/cmdapp'
1541
+
1542
+ class SampleAction &lt Benry::CmdApp::Action
1543
+
1544
+ @action.("test action #1")
1545
+ def hello(user="world")
1546
+ puts "Hello, #{user}!"
1547
+ end
1548
+
1549
+ end
1550
+
1551
+ config = Benry::CmdApp::Config.new("sample app")
1552
+ <strong>config.app_detail</strong> = "Document: https://...." # !!!!
1553
+ config.help_sections</strong> = [ # !!!!
1554
+ ["Example:", " $ &ltcommand&gt; hello Alice"], # !!!!
1555
+ ] # !!!!
1556
+ <strong>config.help_postamble</strong> = "(Tips: ....)" # !!!!
1557
+ app = Benry::CmdApp::Application.new(config)
1558
+ exit app.main()
1559
+ </pre>
1560
+ <p>Help message:</p>
1561
+ <pre class="language-console">
1562
+ [bash]$ ruby ex29.rb -h
1563
+ ex29.rb -- sample app
1564
+
1565
+ <strong>Document: https://....</strong> # !!!! app.detail !!!!
1566
+
1567
+ Usage:
1568
+ $ ex29.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
1569
+
1570
+ Options:
1571
+ -h, --help : print help message (of action if action specified)
1572
+
1573
+ Actions:
1574
+ hello : test action #1
1575
+
1576
+ <strong>Example:</strong> # !!!! help_sections !!!!
1577
+ <strong>$ &ltcommand&gt; hello Alice</strong> # !!!! help_sections !!!!
1578
+
1579
+ <strong>(Tips: ....)</strong> # !!!! help_postamble !!!!
1580
+ </pre>
1581
+ <p>If you want to change behaviour of building command help message:</p>
1582
+ <ul>
1583
+ <li>(1) Define subclass of <code>Benry::CmdApp::AppHelpBuilder</code> class.</li>
1584
+ <li>(2) Override methods.</li>
1585
+ <li>(3) Create an instance object of the class.</li>
1586
+ <li>(4) Pass it to Application object.</li>
1587
+ </ul>
1588
+ <p>File: ex30.rb</p>
1589
+ <pre class="language-ruby">
1590
+ #!/usr/bin/env ruby
1591
+ require 'benry/cmdapp'
1592
+
1593
+ class SampleAction &lt Benry::CmdApp::Action
1594
+
1595
+ @action.("greeting message")
1596
+ def hello(user="world")
1597
+ puts "Hello, #{user}!"
1598
+ end
1599
+
1600
+ end
1601
+
1602
+ ## (1) Define subclass of ``Benry::CmdApp::AppHelpBuilder`` class.
1603
+ <strong>class MyAppHelpBuilder &lt Benry::CmdApp::AppHelpBuilder</strong>
1604
+
1605
+ ## (2) Override methods.
1606
+ def <strong>build_help_message</strong>(all=false, format=nil)
1607
+ super
1608
+ end
1609
+ def <strong>build_preamble</strong>(all=false)
1610
+ super
1611
+ end
1612
+ def <strong>build_usage</strong>(all=false)
1613
+ super
1614
+ end
1615
+ def <strong>build_options</strong>(all=false, format=nil)
1616
+ super
1617
+ end
1618
+ def <strong>build_actions</strong>(all=false, format=nil)
1619
+ super
1620
+ end
1621
+ def <strong>build_postamble</strong>(all=false)
1622
+ super
1623
+ end
1624
+ def <strong>heading</strong>(str)
1625
+ super
1626
+ end
1627
+ end
1628
+
1629
+ ## (3) Create an instance object of the class.
1630
+ config = Benry::CmdApp::Config.new("sample app")
1631
+ schema = Benry::CmdApp::AppOptionSchema.new(config)
1632
+ schema.add(:logging, "--logging", "enable logging")
1633
+ help_builder = <strong>MyAppHelpBuilder</strong>.new(config, schema) # !!!!
1634
+
1635
+ ## (4) Pass it to Application object.
1636
+ app = Benry::CmdApp::Application.new(config, schema, <strong>help_builder</strong>) # !!!!
1637
+ exit app.main()
1638
+ </pre>
1639
+ <p>More simple way:</p>
1640
+ <ul>
1641
+ <li>(1) Create a module and override methods of <code>Benry::CmdApp::AppHelpBuilder</code> class.</li>
1642
+ <li>(2) Prepend it to <code>Benry::CmdApp::AppHelpBuilder</code> class.</li>
1643
+ <li>(3) Create and execute Application object.</li>
1644
+ </ul>
1645
+ <p>File: ex31.rb</p>
1646
+ <pre class="language-ruby">
1647
+ #!/usr/bin/env ruby
1648
+ require 'benry/cmdapp'
1649
+
1650
+ class SampleAction &lt Benry::CmdApp::Action
1651
+
1652
+ @action.("greeting message")
1653
+ def hello(user="world")
1654
+ puts "Hello, #{user}!"
1655
+ end
1656
+
1657
+ end
1658
+
1659
+ ## (1) Create a module and override methods of ``AppHelpBuilder`` class.
1660
+ <strong>module MyHelpBuilderMod</strong>
1661
+ def build_help_message(all=false, format=nil)
1662
+ super
1663
+ end
1664
+ def build_preamble(all=false)
1665
+ super
1666
+ end
1667
+ def build_usage(all=false)
1668
+ super
1669
+ end
1670
+ def build_options(all=false, format=nil)
1671
+ super
1672
+ end
1673
+ def build_actions(all=false, format=nil)
1674
+ super
1675
+ end
1676
+ def build_postamble(all=false)
1677
+ super
1678
+ end
1679
+ def heading(str)
1680
+ super
1681
+ end
1682
+ end
1683
+
1684
+ ## (2) Prepend it to ``Benry::CmdApp::AppHelpBuilder`` class.
1685
+ <strong>Benry::CmdApp::AppHelpBuilder.prepend(MyHelpBuilderMod)</strong>
1686
+
1687
+ ## (3) Create and execute Application object.
1688
+ config = Benry::CmdApp::Config.new("sample app")
1689
+ app = Benry::CmdApp::Application.new(config)
1690
+ exit app.main()
1691
+ </pre>
1692
+ </section>
1693
+ <section class="subsection" id="customization-of-action-help-message">
1694
+ <h3>Customization of Action Help Message</h3>
1695
+ <p>If you want to just add more text into action help message,
1696
+ pass <code>detail:</code> and/or <code>postamble:</code> keyword arguments to <code>@action.()</code>.</p>
1697
+ <p>File: ex32.rb</p>
1698
+ <pre class="language-ruby">
1699
+ #!/usr/bin/env ruby
1700
+ require 'benry/cmdapp'
1701
+
1702
+ class SampleAction &lt Benry::CmdApp::Action
1703
+
1704
+ @action.("test action #1",
1705
+ <strong>detail:</strong> "Document: https://....", # !!!!
1706
+ <strong>postamble:</strong> "(Tips: ....)") # !!!!
1707
+ def hello(user="world")
1708
+ puts "Hello, #{user}!"
1709
+ end
1710
+
1711
+ end
1712
+
1713
+ config = Benry::CmdApp::Config.new("sample app")
1714
+ app = Benry::CmdApp::Application.new(config)
1715
+ exit app.main()
1716
+ </pre>
1717
+ <p>Help message:</p>
1718
+ <pre class="language-console">
1719
+ [bash]$ ruby ex32.rb -h
1720
+ ex32.rb hello -- test action #1
1721
+
1722
+ <strong>Document: https://....</strong> # !!!!
1723
+
1724
+ Usage:
1725
+ $ ex32.rb hello [&ltuser&gt;]
1726
+
1727
+ <strong>(Tips: ....)</strong> # !!!!
1728
+ </pre>
1729
+ <p>If you want to change behaviour of building action help message:</p>
1730
+ <ul>
1731
+ <li>(1) Create a module and override methods of <code>Benry::CmdApp::ActionHelpBuilder</code> class.</li>
1732
+ <li>(2) Prepend it to <code>Benry::CmdApp::ActionHelpBuilder</code> class.</li>
1733
+ <li>(3) Create and execute Application object.</li>
1734
+ </ul>
1735
+ <p>File: ex33.rb</p>
1736
+ <pre class="language-ruby">
1737
+ #!/usr/bin/env ruby
1738
+ require 'benry/cmdapp'
1739
+
1740
+ class SampleAction &lt Benry::CmdApp::Action
1741
+
1742
+ @action.("greeting message")
1743
+ def hello(user="world")
1744
+ puts "Hello, #{user}!"
1745
+ end
1746
+
1747
+ end
1748
+
1749
+ ## (1) Create a module and override methods of ``ActionHelpBuilder`` class.
1750
+ <strong>module MyActionHelpBuilderMod</strong>
1751
+ def <strong>build_help_message</strong>(command, all=false)
1752
+ super
1753
+ end
1754
+ def <strong>build_preamble</strong>(command, all=false)
1755
+ super
1756
+ end
1757
+ def <strong>build_usage</strong>(command, all=false)
1758
+ super
1759
+ end
1760
+ def <strong>build_options</strong>(command, all=false)
1761
+ super
1762
+ end
1763
+ def <strong>build_postamble</strong>(command, all=false)
1764
+ super
1765
+ end
1766
+ def <strong>heading</strong>(str)
1767
+ super
1768
+ end
1769
+ end
1770
+
1771
+ ## (2) Prepend it to ``Benry::CmdApp::ActionHelpBuilder`` class.
1772
+ Benry::CmdApp::ActionHelpBuilder<strong>.prepend(MyActionHelpBuilderMod)</strong> # !!!!
1773
+
1774
+ ## (3) Create and execute Application object.
1775
+ config = Benry::CmdApp::Config.new("sample app")
1776
+ app = Benry::CmdApp::Application.new(config)
1777
+ exit app.main()
1778
+ </pre>
1779
+ <p>Another way:</p>
1780
+ <ul>
1781
+ <li>(1) Define subclass of <code>ActionHelpBuilder</code> class.</li>
1782
+ <li>(2) Set it to <code>ACTION_HELP_BUILDER_CLASS</code> constant value.</li>
1783
+ <li>(3) Create and execute Application object.</li>
1784
+ </ul>
1785
+ <p>File: ex34.rb</p>
1786
+ <pre class="language-ruby">
1787
+ #!/usr/bin/env ruby
1788
+ require 'benry/cmdapp'
1789
+
1790
+ class SampleAction &lt Benry::CmdApp::Action
1791
+
1792
+ @action.("greeting message")
1793
+ def hello(user="world")
1794
+ puts "Hello, #{user}!"
1795
+ end
1796
+
1797
+ end
1798
+
1799
+ ## (1) Define subclass of ``ActionHelpBuilder`` class.
1800
+ <strong>class MyActionHelpBuilder &lt Benry::CmdApp::ActionHelpBuilder</strong>
1801
+ def build_help_message(command, all=false)
1802
+ super
1803
+ end
1804
+ def build_preamble(command, all=false)
1805
+ super
1806
+ end
1807
+ def build_usage(command, all=false)
1808
+ super
1809
+ end
1810
+ def build_options(command, all=false)
1811
+ super
1812
+ end
1813
+ def build_postamble(command, all=false)
1814
+ super
1815
+ end
1816
+ def heading(str)
1817
+ super
1818
+ end
1819
+ end
1820
+
1821
+ ## (2) Set it to ``ACTION_HELP_BUILDER_CLASS`` constant value.
1822
+ Benry::CmdApp.module_eval do
1823
+ <strong>remove_const :ACTION_HELP_BUILDER_CLASS</strong>
1824
+ <strong>const_set :ACTION_HELP_BUILDER_CLASS, MyActionHelpBuilder</strong>
1825
+ end
1826
+
1827
+ ## (3) Create and execute Application object.
1828
+ config = Benry::CmdApp::Config.new("sample app")
1829
+ app = Benry::CmdApp::Application.new(config)
1830
+ exit app.main()
1831
+ </pre>
1832
+ </section>
1833
+ </section>
1834
+ <section class="section" id="q--a">
1835
+ <h2>Q &amp; A</h2>
1836
+ <section class="subsection" id="q-how-to-append-some-tasks-to-existing-action">
1837
+ <h3>Q: How to Append Some Tasks to Existing Action?</h3>
1838
+ <p>A: (a) Use method alias, or (b) use prepend.</p>
1839
+ <p>File: ex41.rb</p>
1840
+ <pre class="language-ruby">
1841
+ require 'benry/cmdapp'
1842
+
1843
+ class SampleAction &lt Benry::CmdApp::Action
1844
+
1845
+ @action.("test action #1")
1846
+ def hello(user="world")
1847
+ puts "Hello, #{user}!"
1848
+ end
1849
+
1850
+ @action.("test action #2")
1851
+ def hi(user="world")
1852
+ puts "Hi, #{user}!"
1853
+ end
1854
+
1855
+ end
1856
+
1857
+ ## (a) use method alias
1858
+ class SampleAction # open existing class
1859
+ <strong>alias __old_hello hello</strong> # alias of existing method
1860
+ def <strong>hello</strong>(user="world") # override existing method
1861
+ puts "---- &gt;8 ---- &gt;8 ----"
1862
+ <strong>__old_hello(user)</strong> # call original method
1863
+ puts "---- 8&lt ---- 8&lt ----"
1864
+ end
1865
+ end
1866
+
1867
+ ## (b) use prepend
1868
+ <strong>module SampleMod</strong> # define new module
1869
+ def <strong>hi</strong>(user="world") # override existing method
1870
+ puts "~~~~ &gt;8 ~~~~ &gt;8 ~~~~"
1871
+ <strong>super</strong> # call original method
1872
+ puts "~~~~ 8&lt ~~~~ 8&lt ~~~~"
1873
+ end
1874
+ end
1875
+ SampleAction<strong>.prepend(SampleMod)</strong> # prepend it to existing class
1876
+
1877
+ config = Benry::CmdApp::Config.new("sample app")
1878
+ app = Benry::CmdApp::Application.new(config)
1879
+ exit app.main()
1880
+ </pre>
1881
+ <p>Output:</p>
1882
+ <pre class="language-console">
1883
+ [bash]$ ruby ex41.rb hello
1884
+ ---- &gt;8 ---- &gt;8 ----
1885
+ Hello, world!
1886
+ ---- 8&lt ---- 8&lt ----
1887
+
1888
+ [bash]$ ruby ex41.rb hi Alice
1889
+ ~~~~ &gt;8 ~~~~ &gt;8 ~~~~
1890
+ Hi, Alice!
1891
+ ~~~~ 8&lt ~~~~ 8&lt ~~~~
1892
+ </pre>
1893
+ </section>
1894
+ <section class="subsection" id="q-how-to-re-define-existing-action">
1895
+ <h3>Q: How to Re-define Existing Action?</h3>
1896
+ <p>A: Remove existing action at first, and re-define action.</p>
1897
+ <p>File: ex42.rb</p>
1898
+ <pre class="language-ruby">
1899
+ require 'benry/cmdapp'
1900
+
1901
+ class <strong>SampleAction</strong> &lt Benry::CmdApp::Action
1902
+
1903
+ @action.("sample action")
1904
+ def <strong>hello</strong>() # !!!!
1905
+ puts "Hello, world!"
1906
+ end
1907
+
1908
+ end
1909
+
1910
+ Benry::CmdApp<strong>.delete_action("hello")</strong> # !!!!
1911
+
1912
+ class <strong>OtherAction</strong> &lt Benry::CmdApp::Action
1913
+
1914
+ @action.("other action") # !!!!
1915
+ def <strong>hello</strong>() # !!!!
1916
+ puts "Ciao, world!"
1917
+ end
1918
+
1919
+ end
1920
+
1921
+ config = Benry::CmdApp::Config.new("sample app")
1922
+ app = Benry::CmdApp::Application.new(config)
1923
+ exit app.main()
1924
+ </pre>
1925
+ <p>Help message:</p>
1926
+ <pre class="language-console">
1927
+ [bash]$ ruby ex42.rb -h
1928
+ ex42.rb -- sample app
1929
+
1930
+ Usage:
1931
+ $ ex42.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
1932
+
1933
+ Options:
1934
+ -h, --help : print help message (of action if action specified)
1935
+
1936
+ Actions:
1937
+ <strong>hello : other action</strong> # !!!!
1938
+ </pre>
1939
+ </section>
1940
+ <section class="subsection" id="q-how-to-delete-existing-actionalias">
1941
+ <h3>Q: How to Delete Existing Action/Alias?</h3>
1942
+ <p>A: Call <code>Benry::CmdApp.delete_action("&ltaction&gt;")</code> or <code>Benry::CmdApp.delete_alias("&ltalias&gt;")</code>.</p>
1943
+ </section>
1944
+ <section class="subsection" id="q-how-to-show-entering-into-or-exitting-from-action">
1945
+ <h3>Q: How to Show Entering Into or Exitting From Action?</h3>
1946
+ <p>A: Set <code>config.option_trace = true</code> and pass <code>-T</code> (or <code>--trace</code>) option.</p>
1947
+ <p>File: ex43.rb</p>
1948
+ <pre class="language-ruby">
1949
+ require 'benry/cmdapp'
1950
+
1951
+ class SampleAction &lt Benry::CmdApp::Action
1952
+
1953
+ @action.("preparation")
1954
+ def prepare()
1955
+ puts "... prepare something ..."
1956
+ end
1957
+
1958
+ @action.("build")
1959
+ def build()
1960
+ run_action_once("prepare")
1961
+ puts "... build something ..."
1962
+ end
1963
+
1964
+ end
1965
+
1966
+ config = Benry::CmdApp::Config.new("sample app")
1967
+ <strong>config.option_trace = true</strong> # !!!!
1968
+ app = Benry::CmdApp::Application.new(config)
1969
+ exit app.main()
1970
+ </pre>
1971
+ <p>Output:</p>
1972
+ <pre class="language-console">
1973
+ [bash]$ ruby ex43.rb -T build # !!!!
1974
+ <strong>## enter: build</strong>
1975
+ <strong>## enter: prepare</strong>
1976
+ ... prepare something ...
1977
+ <strong>## exit: prepare</strong>
1978
+ ... build something ...
1979
+ <strong>## exit: build</strong>
1980
+ </pre>
1981
+ </section>
1982
+ <section class="subsection" id="q-how-to-enabledisable-color-mode">
1983
+ <h3>Q: How to Enable/Disable Color Mode?</h3>
1984
+ <p>A: Set <code>config.option_color = true</code> and pass <code>--color=on</code> or <code>--color=off</code> option.</p>
1985
+ <p>File: ex44.rb</p>
1986
+ <pre class="language-ruby">
1987
+ require 'benry/cmdapp'
1988
+
1989
+ class SampleAction &lt Benry::CmdApp::Action
1990
+
1991
+ @action.("greeting message")
1992
+ def hello(user="world")
1993
+ puts "Hello, #{user}!"
1994
+ end
1995
+
1996
+ end
1997
+
1998
+ config = Benry::CmdApp::Config.new("sample app")
1999
+ <strong>config.option_color = true</strong> # !!!!
2000
+ app = Benry::CmdApp::Application.new(config)
2001
+ exit app.main()
2002
+ </pre>
2003
+ <p>Help message:</p>
2004
+ <pre class="language-console">
2005
+ [bash]$ ruby ex44.rb -h
2006
+ ex44.rb -- sample app
2007
+
2008
+ Usage:
2009
+ $ ex44.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
2010
+
2011
+ Options:
2012
+ -h, --help : print help message (of action if action specified)
2013
+ <strong>--color[=&lton|off&gt;] : enable/disable color</strong> # !!!!
2014
+
2015
+ Actions:
2016
+ hello : greeting message
2017
+
2018
+ [bash]$ ruby ex44.rb -h <strong>--color=off</strong> # !!!!
2019
+
2020
+ [bash]$ ruby ex44.rb -h <strong>--color=on</strong> # !!!!
2021
+ </pre>
2022
+ </section>
2023
+ <section class="subsection" id="q-how-to-define-multiple-option-like--i-option-of-ruby">
2024
+ <h3>Q: How to Define Multiple Option, like <code>-I</code> Option of Ruby?</h3>
2025
+ <p>A: Provide block parameter on <code>@option.()</code>.</p>
2026
+ <p>File: ex45.rb</p>
2027
+ <pre class="language-ruby">
2028
+ require 'benry/cmdapp'
2029
+
2030
+ class TestAction &lt Benry::CmdApp::Action
2031
+
2032
+ @action.("multiple option test")
2033
+ @option.(:path, "-I &ltpath&gt;", "path") <strong>{|options, key, val|</strong> # !!!!
2034
+ <strong>arr = options[key] || []</strong> # !!!!
2035
+ <strong>arr &lt&lt val</strong> # !!!!
2036
+ <strong>arr</strong> # !!!!
2037
+ ## or: # !!!!
2038
+ #<strong>(options[key] || []) &lt&lt val</strong> # !!!!
2039
+ <strong>}</strong> # !!!!
2040
+ def test(path: [])
2041
+ puts "path=#{path.inspect}" #=&gt; path=["/tmp", "/var/tmp"]
2042
+ end
2043
+
2044
+ end
2045
+
2046
+ config = Benry::CmdApp::Config.new("test app")
2047
+ app = Benry::CmdApp::Application.new(config)
2048
+ exit app.main()
2049
+ </pre>
2050
+ <p>Output:</p>
2051
+ <pre class="language-console">
2052
+ [bash]$ ruby ex45.rb test <strong>-I /tmp -I /var/tmp</strong> # !!!!
2053
+ path=["/tmp", "/var/tmp"] # !!!!
2054
+ </pre>
2055
+ </section>
2056
+ <section class="subsection" id="q-how-to-specify-detailed-description-of-option">
2057
+ <h3>Q: How to Specify Detailed Description of Option?</h3>
2058
+ <p>A: Add <code>detail:</code> keyword argument to <code>@option.()</code>.</p>
2059
+ <p>File: ex46.rb</p>
2060
+ <pre class="language-ruby">
2061
+ require 'benry/cmdapp'
2062
+
2063
+ class TestAction &lt Benry::CmdApp::Action
2064
+
2065
+ @action.("detailed description test")
2066
+ @option.(:mode, "-m &ltmode&gt;", "output mode", <strong>detail:</strong> &lt&lt"END")
2067
+ v, verbose: print many output
2068
+ q, quiet: print litte output
2069
+ c, compact: print summary output
2070
+ END
2071
+ def test(mode: nil)
2072
+ puts "mode=#{mode.inspect}"
2073
+ end
2074
+
2075
+ end
2076
+
2077
+ config = Benry::CmdApp::Config.new("test app")
2078
+ app = Benry::CmdApp::Application.new(config)
2079
+ exit app.main()
2080
+ </pre>
2081
+ <p>Help message:</p>
2082
+ <pre class="language-console">
2083
+ [bash]$ ruby ex46.rb -h test
2084
+ ex46.rb test -- detailed description test
2085
+
2086
+ Usage:
2087
+ $ ex46.rb test [&ltoptions&gt;]
2088
+
2089
+ Options:
2090
+ -m &ltmode&gt; : output mode
2091
+ <strong>v, verbose: print many output</strong>
2092
+ <strong>q, quiet: print litte output</strong>
2093
+ <strong>c, compact: print summary output</strong>
2094
+ </pre>
2095
+ </section>
2096
+ <section class="subsection" id="q-how-to-copy-all-options-from-other-action">
2097
+ <h3>Q: How to Copy All Options from Other Action?</h3>
2098
+ <p>A: Use <code>@copy_options.()</code>.</p>
2099
+ <p>File: ex47.rb</p>
2100
+ <pre class="language-ruby">
2101
+ require 'benry/cmdapp'
2102
+
2103
+ class SampleAction &lt Benry::CmdApp::Action
2104
+
2105
+ @action.("test action #1")
2106
+ @option.(:verbose, "-v, --verbose", "verbose mode")
2107
+ @option.(:file, "-f, --file=&ltfile&gt;", "filename")
2108
+ @option.(:indent, "-i, --indent[=&ltN&gt;]", "indent")
2109
+ def test1(verbose: false, file: nil, indent: nil)
2110
+ puts "verbose=#{verbose}, file=#{file}, indent=#{indent}"
2111
+ end
2112
+
2113
+ @action.("test action #2")
2114
+ <strong>@copy_options.("test1")</strong> # !!!! copy options from test1 !!!!
2115
+ @option.(:debug, "-D, --debug", "debug mode")
2116
+ def test2(verbose: false, file: nil, indent: nil, debug: false)
2117
+ puts "verbose=#{verbose}, file=#{file}, indent=#{indent}, debug=#{debug}"
2118
+ end
2119
+
2120
+ end
2121
+
2122
+ config = Benry::CmdApp::Config.new("sample app")
2123
+ app = Benry::CmdApp::Application.new(config)
2124
+ exit app.main()
2125
+ </pre>
2126
+ <p>Help message of <code>test2</code> action:</p>
2127
+ <pre class="language-console">
2128
+ [bash]$ ruby ex47.rb -h test2
2129
+ ex47.rb test2 -- test action #2
2130
+
2131
+ Usage:
2132
+ $ ex47.rb test2 [&ltoptions&gt;]
2133
+
2134
+ Options:
2135
+ -v, --verbose : verbose mode # copied!!
2136
+ -f, --file=&ltfile&gt; : filename # copied!!
2137
+ -i, --indent[=&ltN&gt;] : indent # copied!!
2138
+ -D, --debug : debug mode
2139
+ </pre>
2140
+ </section>
2141
+ <section class="subsection" id="q-what-is-the-difference-between-prefixalias_of-and-prefixaction">
2142
+ <h3>Q: What is the Difference Between <code>prefix(alias_of:)</code> and <code>prefix(action:)</code>?</h3>
2143
+ <p>A: The former defines an alias, and the latter doesn't.</p>
2144
+ <p>File: ex48.rb</p>
2145
+ <pre class="language-ruby">
2146
+ require 'benry/cmdapp'
2147
+
2148
+ class AaaAction &lt Benry::CmdApp::Action
2149
+ prefix "aaa", <strong>alias_of:</strong> :print_ # (or) alias_of: "print"
2150
+
2151
+ @action.("test #1")
2152
+ def print_()
2153
+ puts "test"
2154
+ end
2155
+
2156
+ end
2157
+
2158
+ class BbbAction &lt Benry::CmdApp::Action
2159
+ prefix "bbb", <strong>action:</strong> :print_ # (or) action: "print"
2160
+
2161
+ @action.("test #2")
2162
+ def print_()
2163
+ puts "test"
2164
+ end
2165
+
2166
+ end
2167
+
2168
+ config = Benry::CmdApp::Config.new("sample app")
2169
+ app = Benry::CmdApp::Application.new(config)
2170
+ exit app.main()
2171
+ </pre>
2172
+ <p>Help message:</p>
2173
+ <pre class="language-console">
2174
+ [bash]$ ruby ex48.rb
2175
+ ex48.rb -- sample app
2176
+
2177
+ Usage:
2178
+ $ ex48.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
2179
+
2180
+ Options:
2181
+ -h, --help : print help message (of action if action specified)
2182
+
2183
+ Actions:
2184
+ <strong>aaa : alias of 'aaa:print' action</strong> # !!!!
2185
+ aaa:print : test #1
2186
+ <strong>bbb : test #2</strong> # !!!!
2187
+ </pre>
2188
+ <p>In the above example, alias <code>aaa</code> is defined due to <code>prefix(alias_of:)</code>,
2189
+ and action <code>bbb</code> is not an alias due to <code>prefix(action:)</code>.</p>
2190
+ </section>
2191
+ <section class="subsection" id="q-how-to-change-order-of-options-in-help-message">
2192
+ <h3>Q: How to Change Order of Options in Help Message?</h3>
2193
+ <p>A: Call <code>AppOptionSchema#sort_options_in_this_order()</code>.</p>
2194
+ <p>File: ex49.rb</p>
2195
+ <pre class="language-ruby">
2196
+ require 'benry/cmdapp'
2197
+
2198
+ config = Benry::CmdApp::Config.new("sample app", "1.0.0",
2199
+ option_all: true,
2200
+ option_quiet: true,
2201
+ option_color: true,
2202
+ )
2203
+ schema = Benry::CmdApp::AppOptionSchema.new(config)
2204
+ <strong>keys = [:all, :quiet, :color, :help, :version]</strong> # !!!!
2205
+ <strong>schema.sort_options_in_this_order(*keys)</strong> # !!!!
2206
+ app = Benry::CmdApp::Application.new(config, schema)
2207
+ ## or:
2208
+ #app = Benry::CmdApp::Application.new(config)
2209
+ #<strong>app.schema.sort_options_in_this_order(*keys)</strong> # !!!!
2210
+ exit app.main()
2211
+ </pre>
2212
+ <p>Help message:</p>
2213
+ <pre class="language-console">
2214
+ [bash]$ ruby ex49.rb -h
2215
+ ex49.rb (1.0.0) -- sample app
2216
+
2217
+ Usage:
2218
+ $ ex49.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
2219
+
2220
+ Options:
2221
+ -a, --all : list all actions/options including private (hidden) ones
2222
+ -q, --quiet : quiet mode
2223
+ --color[=&lton|off&gt;] : enable/disable color
2224
+ -h, --help : print help message (of action if action specified)
2225
+ -V, --version : print version
2226
+
2227
+ Actions:
2228
+
2229
+ </pre>
2230
+ </section>
2231
+ <section class="subsection" id="q-is-it-possible-to-make-action-names-emphasised-or-weaken">
2232
+ <h3>Q: Is It Possible to Make Action Names Emphasised or Weaken?</h3>
2233
+ <p>A: Yes. When you pass <code>important: true</code> to <code>@action.()</code>, that action will be printed with unerline in help message. When you pass <code>important: false</code>, that action will be printed in gray color.</p>
2234
+ <p>File: ex50.rb</p>
2235
+ <pre class="language-ruby">
2236
+ require 'benry/cmdapp'
2237
+
2238
+ class SampleAction &lt Benry::CmdApp::Action
2239
+
2240
+ @action.("empasized", <strong>important: true</strong>) # !!!!
2241
+ def test1()
2242
+ end
2243
+
2244
+ @action.("weaken", <strong>important: false</strong>) # !!!!
2245
+ def test2()
2246
+ end
2247
+
2248
+ end
2249
+
2250
+ config = Benry::CmdApp::Config.new("sample app")
2251
+ app = Benry::CmdApp::Application.new(config)
2252
+ exit app.main()
2253
+ </pre>
2254
+ <p>Help message:</p>
2255
+ <pre class="language-console">
2256
+ [bash]$ ruby ex50.rb -h
2257
+ ex50.rb -- sample app
2258
+
2259
+ Usage:
2260
+ $ ex50.rb [&ltoptions&gt;] [&ltaction&gt; [&ltarguments&gt;...]]
2261
+
2262
+ Options:
2263
+ -h, --help : print help message (of action if action specified)
2264
+
2265
+ Actions:
2266
+ <strong>test1 : empasized</strong> # !!!! printed with underline !!!!
2267
+ <strong>test2 : weaken</strong> # !!!! printed in gray color !!!!
2268
+ </pre>
2269
+ </section>
2270
+ <section class="subsection" id="q-is-it-possible-to-add-metadata-to-action-or-option">
2271
+ <h3>Q: Is It Possible to Add Metadata to Action or Option?</h3>
2272
+ <p>A: Yes. Pass <code>tag:</code> keyword argument to <code>@action.()</code> or <code>@option.()</code>.</p>
2273
+ <ul>
2274
+ <li><code>tag:</code> keyword argument accept any type of value such as symbol, string, array, and so on.</li>
2275
+ <li>Currenty, Benry::CmdApp doesn't provide the good way to use it effectively.
2276
+ This feature may be used by command-line application or framework based on Benry::CmdApp.</li>
2277
+ </ul>
2278
+ <p>File: ex51.rb</p>
2279
+ <pre class="language-ruby">
2280
+ require 'benry/cmdapp'
2281
+
2282
+ class SampleAction &lt Benry::CmdApp::Action
2283
+
2284
+ @action.("print greeting message", <strong>tag: :important</strong>) # !!!!
2285
+ @option.(:repeat, "-r &ltN&gt;", "repeat N times", <strong>tag: :important</strong>) # !!!!
2286
+ def hello(user="world", repeat: nil)
2287
+ (repeat || 1).times do
2288
+ puts "Hello, #{user}!"
2289
+ end
2290
+ end
2291
+
2292
+ end
2293
+
2294
+ config = Benry::CmdApp::Config.new("sample app")
2295
+ app = Benry::CmdApp::Application.new(config)
2296
+ exit app.main()
2297
+ </pre>
2298
+ </section>
2299
+ <section class="subsection" id="q-how-to-make-error-messages-i18ned">
2300
+ <h3>Q: How to Make Error Messages I18Ned?</h3>
2301
+ <p>A: Currently not supported. May be supported in the future release.</p>
2302
+ </section>
2303
+ </section>
2304
+ <section class="section" id="license-and-copyright">
2305
+ <h2>License and Copyright</h2>
2306
+ <ul>
2307
+ <li>$License: MIT License $</li>
2308
+ <li>$Copyright: copyright(c) 2023 kwatch@gmail.com $</li>
2309
+ </ul>
2310
+ </section>
2311
+ </section>
2312
+ </main>
2313
+ </body>
2314
+ </html>