benry-actionrunner 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.
data/README.md ADDED
@@ -0,0 +1,764 @@
1
+ # Benry-ActionRunner
2
+
3
+ ($Release: 0.1.0 $)
4
+
5
+
6
+ ## What's this?
7
+
8
+ Benry-ActionRunner is a task runner.
9
+ Similar to Rake, but much improved over Rake.
10
+
11
+ The main feature of Benry-ActionRunner compared to Rake is that each actions can take options and arguments.
12
+ For example, `arun hello -l fr Alice` runs `hello` action with an option `-l fr` and an argument `Alice`.
13
+
14
+ * Document: <https://kwatch.github.io/benry-ruby/benry-actionrunner.html>
15
+ * GitHub: <https://github.com/kwatch/benry-ruby/tree/main/benry-actionrunner>
16
+ * Changes: <https://github.com/kwatch/benry-ruby/blob/main/benry-actionrunner/CHANGES.md>
17
+
18
+ (Benry-ActionRunner requires Ruby >= 2.3)
19
+
20
+
21
+
22
+ ### Table of Contents
23
+
24
+ <!-- TOC -->
25
+
26
+ * [What's this?](#whats-this)
27
+ * [Install](#install)
28
+ * [Example](#example)
29
+ * [Basic Features](#basic-features)
30
+ * [Action](#action)
31
+ * [Arguments](#arguments)
32
+ * [Options](#options)
33
+ * [Validation for Option Value](#validation-for-option-value)
34
+ * [Boolean Option](#boolean-option)
35
+ * [Prefix of Actions](#prefix-of-actions)
36
+ * [Nested Prefix](#nested-prefix)
37
+ * [Alias of Action](#alias-of-action)
38
+ * [Prefix Action and Prefix Alias](#prefix-action-and-prefix-alias)
39
+ * [Prerequisite Action](#prerequisite-action)
40
+ * [Global Variable](#global-variable)
41
+ * [Available Commands](#available-commands)
42
+ * [More Features](#more-features)
43
+ * [Search Actionfile in Parent or Higher Directory](#search-actionfile-in-parent-or-higher-directory)
44
+ * [Hidden Action, Alias or Option](#hidden-action-alias-or-option)
45
+ * [Important Action, Alias or Option](#important-action-alias-or-option)
46
+ * [Delete Action/Alias](#delete-actionalias)
47
+ * [Default Action](#default-action)
48
+ * [More Topics](#more-topics)
49
+ * [License and Copyright](#license-and-copyright)
50
+
51
+ <!-- /TOC -->
52
+
53
+
54
+
55
+ ## Install
56
+
57
+ ```console
58
+ $ gem install benry-actionrunner
59
+ $ arun --version
60
+ 1.0.0
61
+ ```
62
+
63
+
64
+ ## Example
65
+
66
+ ```console
67
+ [bash]$ arun -h | less # print help message
68
+ [bash]$ arun -g # generate action file ('Actionfile.rb')
69
+ [bash]$ less Actionfile.rb # read content of action file
70
+ [bash]$ arun # list actions (or: `arun -l`)
71
+ [bash]$ arun -h hello # show help message of 'hello' action
72
+ [bash]$ arun hello Alice # run 'hello' action with arguments
73
+ Hello, Alice!
74
+ [bash]$ arun hello Alice -l fr # run 'hello' action with args and options
75
+ Bonjour, Alice!
76
+ [bash]$ arun xxxx: # list actions starting with 'xxxx:'
77
+ [bash]$ arun : # list prefixes of actions (or '::', ':::')
78
+ ```
79
+
80
+
81
+ ## Basic Features
82
+
83
+
84
+ ### Action
85
+
86
+ File: Actionfile.rb
87
+
88
+ ```ruby
89
+ # coding: utf-8
90
+ require 'benry/actionrunner'
91
+ include Benry::ActionRunner::Export
92
+
93
+ class MyAction < Action
94
+
95
+ @action.("print greeting message")
96
+ def hello()
97
+ puts "Hello, world!"
98
+ end
99
+
100
+ end
101
+ ```
102
+
103
+ Output:
104
+
105
+ ```console
106
+ [bash]$ ls Actionfile.rb
107
+ Actionfile.rb
108
+
109
+ [bash]$ arun hello
110
+ Hello, world!
111
+ ```
112
+
113
+ It is not allowed to override existing method by action method.
114
+ For example, you can't define `print()` or `test()` method as action method
115
+ because these methods are defined in parent or ancestor class.
116
+ In this case, please rename action methods to `print_()` or `test_()`.
117
+ These action methods are treated as action name `print` or `test`.
118
+
119
+
120
+ ### Arguments
121
+
122
+ File: Actionfile.rb
123
+
124
+ ```ruby
125
+ # coding: utf-8
126
+ require 'benry/actionrunner'
127
+ include Benry::ActionRunner::Export
128
+
129
+ class MyAction < Action
130
+
131
+ @action.("print greeting message")
132
+ def hello(name="world")
133
+ puts "Hello, #{name}!"
134
+ end
135
+
136
+ end
137
+ ```
138
+
139
+ Output:
140
+
141
+ ```console
142
+ [bash]$ arun hello Alice
143
+ Hello, Alice!
144
+ ```
145
+
146
+ Arguments are displayed in help message of actions.
147
+
148
+ ```console
149
+ [bash]$ arun -h hello
150
+ arun hello --- print greeting message
151
+
152
+ Usage:
153
+ $ arun hello [<options>] [<name>]
154
+ ```
155
+
156
+
157
+ ### Options
158
+
159
+ File: Actionfile.rb
160
+
161
+ ```ruby
162
+ # coding: utf-8
163
+ require 'benry/actionrunner'
164
+ include Benry::ActionRunner::Export
165
+
166
+ class MyAction < Action
167
+
168
+ @action.("print greeting message")
169
+ @option.(:lang, "-l, --lang=<lang>", "language (en/fr/it)")
170
+ @option.(:repeat, "-n <N>", "repeat N times")
171
+ def hello(name="world", lang: "en", repeat: 1)
172
+ repeat.times do
173
+ case lang
174
+ when "en" ; puts "Hello, #{name}!"
175
+ when "fr" ; puts "Bonjour, #{name}!"
176
+ when "it" ; puts "Chao, #{name}!"
177
+ else ; raise "#{lang}: Unknown language."
178
+ end
179
+ end
180
+ end
181
+
182
+ end
183
+ ```
184
+
185
+ Output:
186
+
187
+ ```console
188
+ [bash]$ arun hello -l fr Alice # or: arun hello Alice -l fr
189
+ Bonjour, Alice!
190
+
191
+ [bash]$ arun hello --lang=it Alice # or: arun hello Alice --lang=it
192
+ Chao, Alice!
193
+ ```
194
+
195
+ Available option formats:
196
+
197
+ * No arguments
198
+ * `-h` --- short
199
+ * `--help` --- long
200
+ * `-h, --help` --- both
201
+ * Argument required
202
+ * `-f <file>` --- short
203
+ * `--file=<file>` --- long
204
+ * `-f, --file=<file>` --- both
205
+ * Optional argument
206
+ * `-i[<width>]` --- short
207
+ * `--indent[=<width>]` --- long
208
+ * `-i, --indent[=<width>]` --- both
209
+
210
+ Notice: `--lang it` style option is not supported for usability reason.
211
+ Use `--lang=it` style instead.
212
+
213
+
214
+ ### Validation for Option Value
215
+
216
+ Keyword arguments of `@option.()`:
217
+
218
+ * `type: Integer` --- Option value should be an integer.
219
+ * `rexp: /^\d+$/ --- Option value should match to pattern.
220
+ * `enum: ["A", "B", "C"]` --- Option value should be one of "A", "B", or "C".
221
+ * `range: 1..10 --- Option value should be between 1 and 10.
222
+
223
+ File: Actionfile.rb
224
+
225
+ ```ruby
226
+ # coding: utf-8
227
+ require 'benry/actionrunner'
228
+ include Benry::ActionRunner::Export
229
+
230
+ class MyAction < Action
231
+
232
+ @action.("print greeting message")
233
+ @option.(:lang, "-l, --lang=<lang>", "language", enum: ["en", "fr", "it"])
234
+ @option.(:repeat, "-n <N>", "repeat N times", type: Integer, range: 1..5)
235
+ def hello(name="world", lang: "en", repeat: 1)
236
+ repeat.times do
237
+ case lang
238
+ when "en" ; puts "Hello, #{name}!"
239
+ when "fr" ; puts "Bonjour, #{name}!"
240
+ when "it" ; puts "Chao, #{name}!"
241
+ else ; raise "#{lang}: Unknown language."
242
+ end
243
+ end
244
+ end
245
+
246
+ end
247
+ ```
248
+
249
+ Output:
250
+
251
+ ```console
252
+ [bash]$ arun hello -l po Alice
253
+ [ERROR] -l po: Expected one of en/fr/it.
254
+
255
+ [bash]$ arun hello -n 99 Alice
256
+ [ERROR] -n 99: Too large (max: 5)
257
+ ```
258
+
259
+
260
+ ### Boolean Option
261
+
262
+ File: Actionfile.rb
263
+
264
+ ```ruby
265
+ # coding: utf-8
266
+ require 'benry/actionrunner'
267
+ include Benry::ActionRunner::Export
268
+
269
+ class MyAction < Action
270
+
271
+ @action.("print greeting message")
272
+ @option.(:lang, "-l, --lang=<lang>", "language", enum: ["en", "fr", "it"])
273
+ @option.(:repeat, "-n <N>", "repeat N times", type: Integer, range: 1..5)
274
+ @option.(:color, "-c, --color[=<on|off>]", "color mode", type: TrueClass)
275
+ def hello(name="world", lang: "en", repeat: 1, color: false)
276
+ if color
277
+ name = "\e[32m#{name}\e[0m"
278
+ end
279
+ repeat.times do
280
+ case lang
281
+ when "en" ; puts "Hello, #{name}!"
282
+ when "fr" ; puts "Bonjour, #{name}!"
283
+ when "it" ; puts "Chao, #{name}!"
284
+ else ; raise "#{lang}: Unknown language."
285
+ end
286
+ end
287
+ end
288
+
289
+ end
290
+ ```
291
+
292
+ Output:
293
+
294
+ ```console
295
+ [bash]$ arun hello --color=on Alice
296
+ Hello, Alice! # displayed with color
297
+
298
+ [bash]$ arun hello --color Alice
299
+ Hello, Alice! # displayed with color
300
+ ```
301
+
302
+
303
+ ### Prefix of Actions
304
+
305
+ File: Actionfile.rb
306
+
307
+ ```ruby
308
+ # coding: utf-8
309
+ require 'benry/actionrunner'
310
+ include Benry::ActionRunner::Export
311
+
312
+ class GitAction < Action
313
+ prefix "git:" # should be "git:", not "git" !!!
314
+
315
+ @action.("show current status in compact format")
316
+ def status(path=".")
317
+ sys "git status -sb #{path}" # `sys` is like `system` or `sh`.
318
+ end
319
+
320
+ end
321
+
322
+ ### or:
323
+ #class GitAction < Action
324
+ # @action.("show current status in compact format")
325
+ # def git__status(path=".")
326
+ # sys "git status -sb #{path}"
327
+ # end
328
+ #end
329
+ ```
330
+
331
+ Output:
332
+
333
+ ```console
334
+ [bash]$ arun -l
335
+ Actions:
336
+ git:status : show current status in compact format
337
+ help : print help message (of action if specified)
338
+
339
+ [bash]$ arun git:status
340
+ $ git status -sb .
341
+ ```
342
+
343
+ Prefix name should be a string which ends with ":".
344
+ Symbol is not avaiable.
345
+
346
+ ```ruby
347
+ class GitAction < Action
348
+ prefix :git #=> error because Symbol is specified
349
+ ```
350
+
351
+
352
+ ### Nested Prefix
353
+
354
+ File: Actionfile.rb
355
+
356
+ ```ruby
357
+ # coding: utf-8
358
+ require 'benry/actionrunner'
359
+ include Benry::ActionRunner::Export
360
+
361
+ class GitAction < Action
362
+
363
+ prefix "git:" do
364
+
365
+ prefix "commit:" do
366
+
367
+ @action.("create a commit of current changes")
368
+ def create(msg); sys "git commit -m '#{msg}'"; end
369
+
370
+ end
371
+
372
+ prefix "branch:" do
373
+
374
+ @action.("create a new branch")
375
+ def create(name); sys "git checkout -b #{name}" ; end
376
+
377
+ @action.("switch current branch")
378
+ def switch(name); sys "git checkout #{name}"; end
379
+
380
+ end
381
+
382
+ end
383
+
384
+ end
385
+ ```
386
+
387
+ Output:
388
+
389
+ ```console
390
+ [bash]$ arun -l
391
+ Actions:
392
+ git:branch:create : create a new branch
393
+ git:branch:switch : switch current branch
394
+ git:commit:create : create a commit of current changes
395
+ help : print help message (of action if specified)
396
+ ```
397
+
398
+
399
+ ### Alias of Action
400
+
401
+ Alias is a shortcut of action.
402
+
403
+ File: Actionfile.rb
404
+
405
+ ```ruby
406
+ # coding: utf-8
407
+ require 'benry/actionrunner'
408
+ include Benry::ActionRunner::Export
409
+
410
+ class GitAction < Action
411
+
412
+ prefix "git:" do
413
+
414
+ prefix "commit:" do
415
+
416
+ @action.("create a commit of current changes")
417
+ def create(msg); sys "git commit -m '#{msg}'"; end
418
+
419
+ end
420
+
421
+ prefix "branch:" do
422
+
423
+ @action.("create a new branch")
424
+ def create(name); sys "git checkout -b #{name}" ; end
425
+
426
+ @action.("switch current branch")
427
+ def switch(name); sys "git checkout #{name}"; end
428
+
429
+ end
430
+
431
+ end
432
+
433
+ end
434
+
435
+ ## define aliases
436
+ define_alias "ci" , "git:commit:create"
437
+ define_alias "fork" , "git:branch:create"
438
+ define_alias "sw" , "git:branch:switch"
439
+ ```
440
+
441
+ Output:
442
+
443
+ ```console
444
+ [bash]$ arun -l
445
+ Actions:
446
+ ci : alias of 'git:commit:create'
447
+ fork : alias of 'git:branch:create'
448
+ git:branch:create : create a new branch
449
+ git:branch:switch : switch current branch
450
+ git:commit:create : create a commit of current changes
451
+ help : print help message (of action if specified)
452
+ sw : alias of 'git:branch:switch'
453
+
454
+ [bash]$ arun fork topic-foo # same as `arun git:branch:create topic-foo`
455
+ [bash]$ arun sw topic-foo # same as `arun git:branch:switch topic-foo`
456
+ ```
457
+
458
+ Alias definition can include options and arguments.
459
+ For example, `define_alias "correct", ["git:commit", "--amend"]` defines an alias `correct` which invokes `git:commit` action with `--amend` option.
460
+
461
+
462
+ ### Prefix Action and Prefix Alias
463
+
464
+ Rename `git:status` action to `git` (= prefix name):
465
+
466
+ File: Actionfile.rb
467
+
468
+ ```ruby
469
+ # coding: utf-8
470
+ require 'benry/actionrunner'
471
+ include Benry::ActionRunner::Export
472
+
473
+ class GitAction < Action
474
+ prefix "git:", action: "status"
475
+
476
+ @action.("show current status in compact format")
477
+ def status(path=".")
478
+ sys "git status -sb #{path}" # `sys` is like `system` or `sh`.
479
+ end
480
+
481
+ end
482
+ ```
483
+
484
+ Output: (`git:status` is renamed to `git`)
485
+
486
+ ```console
487
+ [bash]$ arun -l
488
+ Actions:
489
+ git : show current status in compact format
490
+ help : print help message (of action if specified)
491
+ ```
492
+
493
+ Define an alias of `git:status` task as `git` (= prefix name):
494
+
495
+ File: Actionfile.rb
496
+
497
+ ```ruby
498
+ # coding: utf-8
499
+ require 'benry/actionrunner'
500
+ include Benry::ActionRunner::Export
501
+
502
+ class GitAction < Action
503
+ prefix "git:", alias_of: "status"
504
+
505
+ @action.("show current status in compact format")
506
+ def status(path=".")
507
+ sys "git status -sb #{path}" # `sys` is like `system` or `sh`.
508
+ end
509
+
510
+ end
511
+ ```
512
+
513
+ Output: (`git` is an alias of `git:status`)
514
+
515
+ ```console
516
+ [bash]$ arun -l
517
+ Actions:
518
+ git : alias of 'git:status'
519
+ git:status : show current status in compact format
520
+ help : print help message (of action if specified)
521
+ ```
522
+
523
+
524
+ ### Prerequisite Action
525
+
526
+ Prerequisite Action is not supported.
527
+ Instead, use `run_once()` which invokes other action only once.
528
+
529
+ File: Actionfile.rb
530
+
531
+ ```ruby
532
+ # coding: utf-8
533
+ require 'benry/actionrunner'
534
+ include Benry::ActionRunner::Export
535
+
536
+ class BuildAction < Action
537
+
538
+ @action.("setup something")
539
+ def setup()
540
+ puts ".... setup ...."
541
+ ## register teardown block which will be invoked at end of process.
542
+ at_end {
543
+ puts ".... teardown ...."
544
+ }
545
+ end
546
+
547
+ @action.("build something")
548
+ def build()
549
+ run_once "setup" # invoke other action only once
550
+ run_once "setup" # !!! not invoked !!!
551
+ #run_action "setup" # run anyway
552
+ puts ".... build ...."
553
+ end
554
+
555
+ end
556
+ ```
557
+
558
+ Output:
559
+
560
+ ```console
561
+ [bash]$ arun build
562
+ .... setup ....
563
+ .... build ....
564
+ .... teardown ....
565
+ ```
566
+
567
+
568
+ ### Global Variable
569
+
570
+ Global long option such as `--release=1.2.3` is recognized as global variable name and value.
571
+
572
+ File: Actionfile.rb
573
+
574
+ ```ruby
575
+ # coding: utf-8
576
+ require 'benry/actionrunner'
577
+ include Benry::ActionRunner::Export
578
+
579
+ ## global variables
580
+ $project = "exmaple"
581
+ $release = "1.0.0"
582
+
583
+ class MyAction < Action
584
+
585
+ @action.("show global variables")
586
+ def gvars()
587
+ puts "$project=#{$project.inspect}, $release=#{$release.inspect}"
588
+ end
589
+
590
+ end
591
+ ```
592
+
593
+ Output:
594
+
595
+ ```console
596
+ [bash]$ arun --project=myapp --release=1.2.3 gvars
597
+ $project="myapp", $release="1.2.3"
598
+ ```
599
+
600
+ Debug option `-D` prints global variables specified in commiand-line.
601
+ This is useful to debug values of global variables.
602
+
603
+ ```console
604
+ [bash]$ arun -l -D --project=myapp --release=1.2.3
605
+ [DEBUG] $project = "myapp"
606
+ [DEBUG] $release = "1.2.3"
607
+ Actions:
608
+ gvars : show global variables
609
+ help : print help message (of action if specified)
610
+ ```
611
+
612
+ Values of global variables in command-line are parsed as JSON string.
613
+ If failed to parse as JSON string, it is handled as string value.
614
+
615
+ ```console
616
+ ### parsed as JSON format
617
+ [bash]$ arun -l -D --data='["abc",123,true]' | grep DEBUG
618
+ [DEBUG] $data = ["abc", 123, true]
619
+
620
+ ### 'null' in JSON results in 'nil' in Ruby
621
+ [bash]$ arun -l -D --data="null" | grep DEBUG
622
+ [DEBUG] $data = nil
623
+
624
+ ### parsed as JSON quoted string
625
+ [bash]$ arun -l -D --data='"foo"' | grep DEBUG
626
+ [DEBUG] $data = "foo"
627
+
628
+ ### failed to parse, because single quotation is not available in JSON
629
+ [bash]$ arun -l -D --data="'foo'" | grep DEBUG
630
+ [DEBUG] $data = "'foo'"
631
+
632
+ ### failed to parse as JSON, therefore handled as just a string
633
+ [bash]$ arun -l -D --data="foo" | grep DEBUG
634
+ [DEBUG] $data = "foo"
635
+ ```
636
+
637
+
638
+ ### Available Commands
639
+
640
+ In action methods, UNIX-like commands are available.
641
+ These commands are implemented in [Benry-UnixCommand](https://kwatch.github.io/benry-ruby/benry-unixcommand.html) and different from FileUtils.rb.
642
+ For example:
643
+
644
+ * `mv "*.txt", to: "dir"` instead of `mv Dir["*.txt"], "dir"`.
645
+ * `cp :p, "*.txt", to: "dir"` instead of `cp_p Dir["*.txt"], "dir"`.
646
+ * `rm :rf, "dir/*"` instead of `rm_rf Dir["dir/*"]`.
647
+ * `mkdir :p, "dir"` instead of `mkdir_p "dir"`.
648
+ * `sys "command"` instead of `sh "command"` or `system "command"`.
649
+
650
+ See the document of Benry-UnixCommand for details:
651
+ <https://kwatch.github.io/benry-ruby/benry-unixcommand.html>
652
+
653
+
654
+
655
+ ## More Features
656
+
657
+
658
+ ### Search Actionfile in Parent or Higher Directory
659
+
660
+ In contrast to Rake, Benry-ActionRunner doesn't automatically look for action file in the parent or higher directory (this is for security reason).
661
+ If you want Benry-ActionRunner to behave like Rake, add `-u` and `-w` options.
662
+
663
+ * `-u` --- search for action file in parent or upper directory.
664
+ * `-w` --- change current directory to where action file exists.
665
+
666
+ If you want to add these options always, set environment variable `$ACTIONRUNNER_OPTION`.
667
+
668
+ ```console
669
+ [bash]$ ls Actionfile.rb
670
+ Actionfile.rb
671
+
672
+ [bash]$ mkdir -p foo/bar/
673
+ [bash]$ cd foo/bar/ # Change current directory.
674
+ [bash]$ arun -l # Error because action file not found here.
675
+ [ERROR] Action file ('Actionfile.rb') not found. Create it by `arun -g` command firstly.
676
+
677
+ [bash]$ arun -l -wu # Search 'Actionfile.rb' and change current directory.
678
+ Actions:
679
+ hello : print greeting message
680
+ help : print help message (of action if specified)
681
+
682
+ [bash]$ export ACTIONRUNNER_OPTION="-up"
683
+ [bash]$ arun -l # No need to add `-wu`.
684
+ $ cd ../..
685
+ Actions:
686
+ build : build something
687
+ help : print help message (of action if specified)
688
+ setup : setup something
689
+ ```
690
+
691
+
692
+ ### Hidden Action, Alias or Option
693
+
694
+ It is possible to make visibility of actions/aliases/options as hidden.
695
+
696
+ ```ruby
697
+ @action.("preparation", hidden: true)
698
+ @option.(:debug, "--debug", "enable debug mode", hidden: true)
699
+ def preparation()
700
+ ....
701
+ end
702
+
703
+ define_alias "prep", "preparation", hidden: true
704
+ ```
705
+
706
+ Hidden actions and options are not displayed in help message.
707
+ If you want to display hidden actions or options, add `-a` or `--all` option.
708
+
709
+ ```console
710
+ [bash]$ arun -la # show all actions including hidden ones
711
+ [bash]$ arun -la hello # show all options of action including hidden ones
712
+ ```
713
+
714
+
715
+ ### Important Action, Alias or Option
716
+
717
+ It is possible to mark actions/aliases/options as important or not.
718
+
719
+ * Actions/aliases/options marked as important are displayed in bold font in help message.
720
+ * Actions/aliases/options marked as not important are displayed in gray color in help message.
721
+
722
+ ```ruby
723
+ @action.("print greeting message", important: true)
724
+ @option.(:lang, "-l, --lang=<lang>", "language", important: true)
725
+ @option.(:repeat, "--repeat=<N>", "repeat N times", important: false)
726
+ def hello(name="world", lang: "en", repeat: 1)
727
+ # ....
728
+ end
729
+
730
+ define_alias "hi", "hello", important: false
731
+ ```
732
+
733
+
734
+ ### Delete Action/Alias
735
+
736
+ ```ruby
737
+ undef_alias("fork") ## delete an alias
738
+ undef_action("git:branch:create") ## delete an action
739
+ ```
740
+
741
+
742
+ ### Default Action
743
+
744
+ ```ruby
745
+ CONFIG.default_action = "xxxx"
746
+ ```
747
+
748
+
749
+ ### More Topics
750
+
751
+ Benry-ActionRunner is empowerd by Benry-CmdApp.
752
+ Many features of Benry-ActionRunner is derived from Benry-CmdApp.
753
+
754
+ If you are looking for any features not written in this document,
755
+ see the document of Benry-CmdApp framework:
756
+ <https://kwatch.github.io/benry-ruby/benry-cmdapp.html>
757
+
758
+
759
+
760
+ ## License and Copyright
761
+
762
+ $License: MIT License $
763
+
764
+ $Copyright: copyright(c) 2023 kwatch@gmail.com $