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