benry-cmdapp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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>