benry-actionrunner 0.1.0

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