tty-option 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/README.md +1653 -1
  4. data/lib/tty/option.rb +63 -4
  5. data/lib/tty/option/aggregate_errors.rb +95 -0
  6. data/lib/tty/option/conversions.rb +126 -0
  7. data/lib/tty/option/converter.rb +63 -0
  8. data/lib/tty/option/deep_dup.rb +48 -0
  9. data/lib/tty/option/dsl.rb +105 -0
  10. data/lib/tty/option/dsl/arity.rb +49 -0
  11. data/lib/tty/option/dsl/conversion.rb +17 -0
  12. data/lib/tty/option/error_aggregator.rb +35 -0
  13. data/lib/tty/option/errors.rb +144 -0
  14. data/lib/tty/option/formatter.rb +389 -0
  15. data/lib/tty/option/inflection.rb +50 -0
  16. data/lib/tty/option/param_conversion.rb +34 -0
  17. data/lib/tty/option/param_permitted.rb +30 -0
  18. data/lib/tty/option/param_validation.rb +48 -0
  19. data/lib/tty/option/parameter.rb +310 -0
  20. data/lib/tty/option/parameter/argument.rb +18 -0
  21. data/lib/tty/option/parameter/environment.rb +20 -0
  22. data/lib/tty/option/parameter/keyword.rb +15 -0
  23. data/lib/tty/option/parameter/option.rb +99 -0
  24. data/lib/tty/option/parameters.rb +157 -0
  25. data/lib/tty/option/params.rb +122 -0
  26. data/lib/tty/option/parser.rb +57 -3
  27. data/lib/tty/option/parser/arguments.rb +166 -0
  28. data/lib/tty/option/parser/arity_check.rb +34 -0
  29. data/lib/tty/option/parser/environments.rb +169 -0
  30. data/lib/tty/option/parser/keywords.rb +158 -0
  31. data/lib/tty/option/parser/options.rb +273 -0
  32. data/lib/tty/option/parser/param_types.rb +51 -0
  33. data/lib/tty/option/parser/required_check.rb +36 -0
  34. data/lib/tty/option/pipeline.rb +38 -0
  35. data/lib/tty/option/result.rb +46 -0
  36. data/lib/tty/option/section.rb +26 -0
  37. data/lib/tty/option/sections.rb +56 -0
  38. data/lib/tty/option/usage.rb +166 -0
  39. data/lib/tty/option/usage_wrapper.rb +58 -0
  40. data/lib/tty/option/version.rb +3 -3
  41. metadata +37 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5113af6da357aa0bfa67f886aa3c26524eb902439f3800f126541ed4801fe98a
4
- data.tar.gz: 2c32c74dab7046097024772a40f7fda68087b1b179842fb452dd965cee9854f8
3
+ metadata.gz: e48f8a476c72fb96d9f6bf49daea6533b2cc6940a536eb0e5a56fce19ff6c75b
4
+ data.tar.gz: cbadbde794e8469c8d0b1bc5ade00c47e2420d885f5a5fd6e410dce5950d3d8a
5
5
  SHA512:
6
- metadata.gz: 7a42a542f9b2f8916f618d91529ead9e776978397bd431d9a829103305d096f44911eb0625cd4a8d50f8a51b5f9c8a90dffff13cfa1722960cc86843d46f6fde
7
- data.tar.gz: 3d422107e498fa1ea247dac4c07f8812bdc7ab3f21540dde45225ac028006839ec796711d599ee5d14f3931d0dc6b24d9e0b65ce2af597cc21aef88c2cf87bdb
6
+ metadata.gz: b6257d839aefe82f045f8708ebd5b5443a2df85090b1c3a722f8dbe3ba40704c79277a203e44d78e458405200ad465e3471dc4b3575fc101806d7b4b93717ee6
7
+ data.tar.gz: 461f0b5454e44e5bebf59dcd308ffa2fda57f457d0191c709b859dae216880b781ff62d40e96e2cc101f8637ee94b1029174c7d63c2d872c345614b692412e34
data/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change log
2
2
 
3
- ## [v0.1.0] - 2020-01-xx
3
+ ## [v0.1.0] - 2020-05-18
4
4
 
5
5
  * Initial implementation and release
6
6
 
data/README.md CHANGED
@@ -20,6 +20,17 @@
20
20
 
21
21
  > Parser for command line arguments, keywords, options and environment variables
22
22
 
23
+ ## Features
24
+
25
+ * Support for parsing of **positional arguments**, **keyword arguments**, **flags**, **options** and **environment variables**.
26
+ * A convenient way to declare parsed parameters via **DSL** with a fallback to **hash-like syntax**.
27
+ * Flexible parsing that **doesn't force any order for the parameters**.
28
+ * Handling of complex option and keyword argument inputs like **lists** and **maps**.
29
+ * Many **conversions types** provided out of the box, from basic integer to more complex hash structures.
30
+ * Automatic **help generation** that can be customised with **usage** helpers like banner, examples and more.
31
+ * Parsing **doesn't raise errors** by default and collects issues to allow for better user experience.
32
+ * Ability to declare **global options** with inheritance that copies parameters to a child class.
33
+
23
34
  ## Installation
24
35
 
25
36
  Add this line to your application's Gemfile:
@@ -36,14 +47,1655 @@ Or install it yourself as:
36
47
 
37
48
  $ gem install tty-option
38
49
 
39
- ## Usage
50
+ ## Contents
51
+
52
+ * [1. Usage](#1-usage)
53
+ * [2. API](#2-api)
54
+ * [2.1 argument](#21-argument)
55
+ * [2.2 keyword](#22-keyword)
56
+ * [2.3 option](#23-option)
57
+ * [2.4 environment](#24-environment)
58
+ * [2.5 parameter settings](#25-parameter-settings)
59
+ * [2.5.1 arity](#251-arity)
60
+ * [2.5.2 convert](#252-convert)
61
+ * [2.5.3 default](#253-default)
62
+ * [2.5.4 description](#254-description)
63
+ * [2.5.5 hidden](#255-hidden)
64
+ * [2.5.6 name](#256-name)
65
+ * [2.5.7 optional](#257-optional)
66
+ * [2.5.8 permit](#258-permit)
67
+ * [2.5.9 required](#259-required)
68
+ * [2.5.10 validate](#2510-validate)
69
+ * [2.6 parse](#26-parse)
70
+ * [2.6.1 :raise_on_parse_error](#261-raise_on_parse_error)
71
+ * [2.6.2 :check_invalid_params](#262-check_invalid_params)
72
+ * [2.7 params](#27-params)
73
+ * [2.7.1 errors](#271-errors)
74
+ * [2.7.2 remaining](#272-remaining)
75
+ * [2.7.3 valid?](#273-valid?)
76
+ * [2.8 usage](#28-usage)
77
+ * [2.8.1 header](#281-header)
78
+ * [2.8.2 program](#282-program)
79
+ * [2.8.3 command](#283-command)
80
+ * [2.8.4 banner](#284-banner)
81
+ * [2.8.5 description](#285-description)
82
+ * [2.8.6 example](#286-examples)
83
+ * [2.8.7 footer](#287-footer)
84
+ * [2.9 help](#29-help)
85
+ * [2.9.1 sections](#291-sections)
86
+ * [2.9.2 :indent](#292-indent)
87
+ * [2.9.3 :order](#293-order)
88
+ * [2.9.4 :param_display](#294-param_display)
89
+ * [2.9.5 :width](#295-width)
90
+
91
+ ## 1. Usage
92
+
93
+ To start parsing command line parameters include `TTY::Option` module.
94
+
95
+ Now, you're ready to define parsed parameters like arguments, keywords, flags, options or environment variables.
96
+
97
+ For example, a quick demo to create a command that mixes all parameters usage:
40
98
 
41
99
  ```ruby
42
100
  class Command
43
101
  include TTY::Option
102
+
103
+ usage do
104
+ program "dock"
105
+
106
+ command "run"
107
+
108
+ desc "Run a command in a new container"
109
+
110
+ example "Set working directory (-w)",
111
+ " $ dock run -w /path/to/dir/ ubuntu pwd"
112
+
113
+ example <<~EOS
114
+ Mount volume
115
+ $ dock run -v `pwd`:`pwd` -w `pwd` ubuntu pwd
116
+ EOS
117
+ end
118
+
119
+ argument :image do
120
+ required
121
+ desc "The name of the image to use"
122
+ end
123
+
124
+ argument :command do
125
+ optional
126
+ desc "The command to run inside the image"
127
+ end
128
+
129
+ keyword :restart do
130
+ default "no"
131
+ permit %w[no on-failure always unless-stopped]
132
+ desc "Restart policy to apply when a container exits"
133
+ end
134
+
135
+ flag :help do
136
+ short "-h"
137
+ long "--help"
138
+ desc "Print usage"
139
+ end
140
+
141
+ flag :detach do
142
+ short "-d"
143
+ long "--detach"
144
+ desc "Run container in background and print container ID"
145
+ end
146
+
147
+ option :name do
148
+ required
149
+ long "--name string"
150
+ desc "Assign a name to the container"
151
+ end
152
+
153
+ option :port do
154
+ arity one_or_more
155
+ short "-p"
156
+ long "--publish list"
157
+ convert :list
158
+ desc "Publish a container's port(s) to the host"
159
+ end
160
+
161
+ def run
162
+ if params[:help]
163
+ print help
164
+ exit
165
+ else
166
+ pp params.to_h
167
+ end
168
+ end
169
+ end
170
+ ```
171
+
172
+ Then create a command instance:
173
+
174
+ ```ruby
175
+ cmd = Command.new
176
+ ```
177
+
178
+ And provided input from the command line:
179
+
180
+ ```
181
+ restart=always -d -p 5000:3000 5001:8080 --name web ubuntu:16.4 bash
182
+ ```
183
+
184
+ Start parsing from `ARGV` or provide a custom array of inputs:
185
+
186
+ ```ruby
187
+ cmd.parse
188
+ # or
189
+ cmd.parse(%w[restart=always -d -p 5000:3000 5001:8080 --name web ubuntu:16.4 bash])
190
+ ```
191
+
192
+ And run the command to see the values:
193
+
194
+ ```ruby
195
+ cmd.run
196
+ # =>
197
+ # {:help=>false,
198
+ # :detach=>true,
199
+ # :port=>["5000:3000", "5001:8080"],
200
+ # :name=>"web",
201
+ # :restart=>"always",
202
+ # :image=>"ubuntu:16.4",
203
+ # :command=>"bash"}
204
+ ````
205
+
206
+ The `cmd` object also has a direct access to all the parameters via the `params`:
207
+
208
+ ```ruby
209
+ cmd.params[:name] # => "web"
210
+ cmd.params["command"] # => "bash
211
+ ````
212
+
213
+ And when `--help` is found on the command line the run will print help:
214
+
215
+ ```ruby
216
+ cmd.run
217
+ ```
218
+
219
+ To print help information to the terminal use `help` method:
220
+
221
+ ```ruby
222
+ print cmd.help
223
+ ```
224
+
225
+ This will result in the following output:
226
+
227
+ ```
228
+ Usage: dock run [OPTIONS] IMAGE [COMMAND] [RESTART=RESTART]
229
+
230
+ Run a command in a new container
231
+
232
+ Arguments:
233
+ IMAGE The name of the image to use
234
+ COMMAND The command to run inside the image
235
+
236
+ Keywords:
237
+ RESTART=RESTART Restart policy to apply when a container exits (permitted:
238
+ no, on-failure, always, unless-stopped) (default "no")
239
+
240
+ Options:
241
+ -d, --detach Run container in background and print container ID
242
+ -h, --help Print usage
243
+ --name string Assign a name to the container
244
+ -p, --publish list Publish a container's port(s) to the host
245
+
246
+ Examples:
247
+ Set working directory (-w)
248
+ $ dock run -w /path/to/dir/ ubuntu pwd
249
+
250
+ Mount volume
251
+ $ dock run -v `pwd`:`pwd` -w `pwd` ubuntu pwd
252
+ ```
253
+
254
+ ## 2. API
255
+
256
+ ### 2.1 argument
257
+
258
+ You can parse positional arguments with the `argument` method. To declare an argument you need to provide a name for the access key in the `params` like so:
259
+
260
+ ```ruby
261
+ argument :foo
262
+ ```
263
+
264
+ Then parsing command line input:
265
+
266
+ ```
267
+ 11 12 13
268
+ ```
269
+
270
+ Would result only in one argument parsed and the remaining ignored:
271
+
272
+ ```ruby
273
+ params[:foo] # => "11"
274
+ ```
275
+
276
+ A more involved example to parse multiple positional arguments requires use of helper methods:
277
+
278
+ ```ruby
279
+ argument :foo do
280
+ required # a default
281
+ variable "foo(int)" # name for the usage display
282
+ arity one_or_more # how many times to occur
283
+ convert :int # values converted to intenger
284
+ validate -> { |v| v < 14 } # validation rule
285
+ desc "Some foo desc" # description for the usage display
286
+ end
287
+ ```
288
+
289
+ Parsing the previous input:
290
+
291
+ ```bash
292
+ 11 12 13
293
+ ```
294
+
295
+ Would result in all values being collected and converted to integers:
296
+
297
+ ```ruby
298
+ params[:foo] # => [11,12,13]
299
+ ```
300
+
301
+ The previous argument definition can also be written using hash syntax. This is especially useful if you want to specify arguments programmatically:
302
+
303
+ ```ruby
304
+ argument :foo,
305
+ required: true,
306
+ variable: "foo(int)",
307
+ arity: "+",
308
+ convert: :int,
309
+ validate: -> { |v| v < 14 },
310
+ desc: "Some foo desc"
311
+ ```
312
+
313
+ To read more about available settings see [parameter settings](#25-parameter-settings).
314
+
315
+ ### 2.2 keyword
316
+
317
+ To parse keyword arguments use the `keyword` method. To declare a keyword argument you need to provide a name for the key in the `params` like so:
318
+
319
+ ```ruby
320
+ keyword :foo
321
+ ```
322
+
323
+ By default the keyword parameter name will be used as the keyword name on the command line:
324
+
325
+ ```bash
326
+ foo=11
327
+ ```
328
+
329
+ Parsing the above would result in:
330
+
331
+ ```ruby
332
+ params[:foo] # => "11"
333
+ ```
334
+
335
+ A more involved example to parse multiple keyword arguments requires use of helper methods:
336
+
337
+ ```ruby
338
+ keyword :foo do
339
+ required # by default keywrod is not required
340
+ arity one_or_more # how many times to occur
341
+ convert :int # values converted to intenger
342
+ validate -> { |v| v < 14 } # validation rule
343
+ desc "Some foo desc" # description for the usage display
344
+ end
345
+ ```
346
+
347
+ Then provided the following command line input:
348
+
349
+ ```bash
350
+ foo=11 foo=12 foo=13
351
+ ```
352
+
353
+ The result would be:
354
+
355
+ ```ruby
356
+ params[:foo] # => [11,12,13]
357
+ ```
358
+
359
+ You can also specify for the keyword argument to accept a list type:
360
+
361
+ ```ruby
362
+ keyword :foo do
363
+ required # by default keyword is not required
364
+ arity one_or_more # how many times to occur
365
+ convert :int_list # input can be a list of intengers
366
+ validate -> { |v| v < 14 } # validation rule
367
+ desc "Some foo desc" # description for the usage display
368
+ end
369
+ ```
370
+
371
+ Then command line input can contain a list as well:
372
+
373
+ ```bash
374
+ foo=11 12 foo=13
375
+ ```
376
+
377
+ Which will result in the same value:
378
+
379
+ ```ruby
380
+ params[:foo] # => [11,12,13]
381
+ ```
382
+
383
+ A keyword definition can be also a hash. This is especially useful if you intend to specify keyword arguments programmatically:
384
+
385
+ ```ruby
386
+ keyword :foo,
387
+ required: true,
388
+ arity: :+,
389
+ convert: :int_list,
390
+ validate: -> { |v| v < 14 },
391
+ desc: "Some foo desc"
392
+ ```
393
+
394
+ To read more about available settings see [parameter settings](#25-parameter-settings).
395
+
396
+ ### 2.3 option
397
+
398
+ To parse options and flags use the `option` or `flag` methods.
399
+
400
+ To declare an option you need to provide a name for the key used to access value in the `params`:
401
+
402
+ ```ruby
403
+ option :foo
404
+ ```
405
+
406
+ By default the option parameter name will be used to generate a long option name:
407
+
408
+ ```
409
+ --foo=11
410
+ ```
411
+
412
+ Parsing the above will result in:
413
+
414
+ ```ruby
415
+ params[:foo] # => "11"
416
+ ```
417
+
418
+ To specify a different name for the parsed option use the `short` and `long` helpers:
419
+
420
+ ```ruby
421
+ option :foo do
422
+ short "-f" # declares a short flag
423
+ long "--foo" # declares a long flag
424
+ end
425
+ ```
426
+
427
+ If you wish for an option to accept an argument, you need to provide an extra label.
428
+
429
+ For example, for both short and long flag to require argument do:
430
+
431
+ ```ruby
432
+ option :foo do
433
+ short "-f"
434
+ long "--foo string" # use any name after the flag name to specify required argument
435
+ # or
436
+ long "--foo=string" # you can also separate required argument with =
437
+ end
438
+ ```
439
+
440
+ To make a long option with an optional argument do:
441
+
442
+ ```ruby
443
+ option :foo do
444
+ long "--foo [string]" # use any name within square brackets to make argument optional
445
+ end
446
+ ```
447
+
448
+ A more involved example that parses a list of integer may look like this:
449
+
450
+ ```ruby
451
+ option :foo do
452
+ required # by default option is not required
453
+ arity one_or_more # how many times option can occur
454
+ short "-f" # declares a short flag name
455
+ long "--foo list" # declares a long flag with a required argument
456
+ convert :int_list # input can be a list of intengers
457
+ validate -> { |v| v < 14 } # validation rule
458
+ desc "Some foo desc" # description for the usage display
459
+ end
460
+ ```
461
+
462
+ Given command line input:
463
+
464
+ ```bash
465
+ --foo=10,11 -f 12 13
466
+ ```
467
+
468
+ The resulting value will be:
469
+
470
+ ```ruby
471
+ params[:foo] # => [10,11,12,13]
472
+ ```
473
+
474
+ An option definition can be declared as a hash as well. This is especially useful if you intend to specify options programmatically:
475
+
476
+ ```ruby
477
+ option :foo,
478
+ required: true,
479
+ arity: :+,
480
+ short: "-f",
481
+ long: "--foo list",
482
+ convert: :int_list,
483
+ validate: -> { |v| v < 14 },
484
+ desc: "Some foo desc"
485
+ ```
486
+
487
+ To read more about available settings see [parameter settings](#25-parameter-settings).
488
+
489
+ ### 2.4 environment
490
+
491
+ To parse environment variables use `environment` or `env` methods.
492
+
493
+ By default, a parameter name will match a environment variable with the same name. For example, specifying a variable `:foo`:
494
+
495
+ ```ruby
496
+ env :foo
497
+ ```
498
+
499
+ And then given the following command line input:
500
+
501
+ ```
502
+ FOO=bar
503
+ ```
504
+
505
+ The resulting parameter would be:
506
+
507
+ ```ruby
508
+ params[:foo] # => "bar"
509
+ ````
510
+
511
+ To change the variable name to something else use `var` or `variable` helper:
512
+
513
+ ```ruby
514
+ env :foo do
515
+ var "FOO_ENV"
516
+ end
517
+ ```
518
+
519
+ And then given a `FOO_ENV=bar` on the command line would result in:
520
+
521
+ ```ruby
522
+ params[:foo] # => "bar"
523
+ ```
524
+
525
+ A more involved example that parses a list of integer may look like this:
526
+
527
+ ```ruby
528
+ environment :foo do
529
+ required # by default environment is not required
530
+ arity one_or_more # how many times env var can occur
531
+ variable "FOO_ENV" # the command line input name
532
+ convert map_of(:int) # input can be a map of integers
533
+ validate -> { |v| v < 14 } # validation rule
534
+ desc "Some foo desc" # description for the usage display
535
+ end
536
+ ```
537
+
538
+ Given command line input:
539
+
540
+ ```bash
541
+ FOO_ENV=a:1&b:2 FOO_ENV=c=3 d=4
542
+ ```
543
+
544
+ The resulting `params` would be:
545
+
546
+ ```ruby
547
+ params[:foo] # => {a:1,b:2,c:3,d:4}
548
+ ```
549
+
550
+ To read more about available settings see [parameter settings](#25-parameter-settings).
551
+
552
+ ### 2.5 parameter settings
553
+
554
+ These settings are supported by all parameter types with the exception of `short` and `long` which are specific to options only.
555
+
556
+ #### 2.5.1 arity
557
+
558
+ To describe how many times a given parameter may appear in the command line use the `arity` setting.
559
+
560
+ By default every parameter is assumed to appear only once. Any other occurrence will be disregarded and included in the remaining parameters list.
561
+
562
+ For example, to match argument exactly 2 times do:
563
+
564
+ ```ruby
565
+ argument :foo do
566
+ arity 2
567
+ end
568
+ ````
569
+
570
+ Then parsing from the command line:
571
+
572
+ ```ruby
573
+ bar baz
574
+ ```
575
+
576
+ Will give the following:
577
+
578
+ ```ruby
579
+ params[:foo] # => ["bar", "baz"]
580
+ ```
581
+
582
+ For parameters that expect a value, specifying arity will collect all the values matching arity requirement. For example, matching keywords:
583
+
584
+ ```ruby
585
+ keyword :foo do
586
+ arity 3
587
+ end
588
+ ```
589
+
590
+ And then parsing the following:
591
+
592
+ ```
593
+ foo=1 foo=2 foo=3
594
+ ```
595
+
596
+ Will produce:
597
+
598
+ ```ruby
599
+ params[:foo] # => ["1", "2", "3"]
600
+ ```
601
+
602
+ To match any number of times use `:any`, `:*`, `-1`, `any` or `zero_or_more`:
603
+
604
+ ```ruby
605
+ argument :foo do
606
+ arity zero_or_more
607
+ end
608
+ ```
609
+
610
+ To match at at least one time use `:+` or `one_or_more`:
611
+
612
+ ```ruby
613
+ option :foo do
614
+ arity one_or_more
615
+ short "-b"
616
+ long "--bar string"
617
+ end
618
+ ```
619
+
620
+ You can also specify upper boundary with `at_least` helper as well:
621
+
622
+ ```ruby
623
+ keyword :foo do
624
+ arity at_least(3)
44
625
  end
45
626
  ```
46
627
 
628
+ The [help](#29-help) method will handle the arity for the display. Given the following argument definition:
629
+
630
+ ```ruby
631
+ argument :foo do
632
+ arity one_or_more
633
+ end
634
+ ```
635
+
636
+ The usage banner will display:
637
+
638
+ ```
639
+ Usage: foobar FOO [FOO...]
640
+ ```
641
+
642
+ #### 2.5.2 convert
643
+
644
+ You can convert any parameter argument to another type using the `convert` method with a predefined symbol or class name. For example, to convert an argument to integer you can do:
645
+
646
+ ```ruby
647
+ argument :foo do
648
+ convert :int
649
+ # or
650
+ convert Integer
651
+ end
652
+ ```
653
+
654
+ The conversion types that are supported:
655
+
656
+ * `:boolean`|`:bool` - e.g. 'yes/1/y/t/' becomes `true`, 'no/0/n/f' becomes `false`
657
+ * `:date` - parses dates formats "28/03/2020", "March 28th 2020"
658
+ * `:float` - e.g. `-1` becomes `-1.0`
659
+ * `:int`|`:integer` - e.g. `+1` becomes `1`
660
+ * `:path`|`:pathname` - converts to `Pathname` object
661
+ * `:regexp` - e.g. "foo|bar" becomes `/foo|bar/`
662
+ * `:uri` - converts to `URI` object
663
+ * `:sym`|`:symbol` - e.g. "foo" becomes `:foo`
664
+ * `:list`|`:array` - e.g. 'a,b,c' becomes `["a", "b", "c"]`
665
+ * `:map`|`:hash` - e.g. 'a:1 b:2 c:3' becomes `{a: "1", b: "2", c: "3"}`
666
+
667
+ In addition you can specify a plural or append `list` to any base type:
668
+
669
+ * `:ints` or `:int_list` - will convert to a list of integers
670
+ * `:floats` or `:float_list` - will convert to a list of floats
671
+ * `:bools` or `:bool_list` - will convert to a list of booleans, e.g. `t,f,t` becomes `[true, false, true]`
672
+
673
+ If like you can also use `list_of` helper and pass the type as a first argument.
674
+
675
+ Similarly, you can append `map` to any base type:
676
+
677
+ * `:int_map` - will convert to a map of integers, e.g `a:1 b:2 c:3` becomes `{a: 1, b: 2, c: 3}`
678
+ * `:bool_map` - will convert to a map of booleans, e.g `a:t b:f c:t` becomes `{a: true, b: false, c: true}`
679
+
680
+ For convenience and readability you can also use `map_of` helper and pass the type as a first argument.
681
+
682
+ For example, to parse options with required list and map arguments:
683
+
684
+ ```ruby
685
+ option :foo do
686
+ long "--foo map"
687
+ convert :bools # or `convert list_of(:bool)`
688
+ end
689
+
690
+ option :bar do
691
+ long "--bar int map"
692
+ convert :int_map # or `conert map_of(:int)`
693
+ end
694
+ ````
695
+
696
+ And then parsing the following:
697
+
698
+ ```bash
699
+ --foo t,f,t --bar a:1 b:2 c:3
700
+ ```
701
+
702
+ Will give the following:
703
+
704
+ ```ruby
705
+ params[:foo]
706
+ # => [true, false, true]
707
+ params[:bar]
708
+ # => {:a=>1, :b=>2, :c=>3}
709
+ ````
710
+
711
+ You can also provide `proc` to define your own custom conversion:
712
+
713
+ ```ruby
714
+ option :bar do
715
+ long "--bar string"
716
+ convert ->(val) { val.upcase }
717
+ end
718
+ ```
719
+
720
+ #### 2.5.3 default
721
+
722
+ Any optional parameter such as options, flag, keyword or environment variable, can have a default value. This value can be specified with the `default` setting and will be used when the command-line input doesn't match any parameter definitions.
723
+
724
+ For example, given the following option definition:
725
+
726
+ ```ruby
727
+ option :foo do
728
+ long "--foo string"
729
+ default "bar"
730
+ end
731
+ ```
732
+
733
+ When no option `--foo` is parsed, then the `params` will be populated:
734
+
735
+ ```ruby
736
+ params[:foo] # => "bar"
737
+ ```
738
+
739
+ The default can also be specified with a `proc` object:
740
+
741
+ ```ruby
742
+ option :foo do
743
+ long "--foo string"
744
+ default -> { "bar" }
745
+ end
746
+ ```
747
+
748
+ A parameter cannot be both required and have default value. Specifying both will raise `ConfigurationError`. For example, all positional arguments are required by default. If you want to have a default for a required argument make it `optional`:
749
+
750
+ ```ruby
751
+ argument :foo do
752
+ optional
753
+ default "bar"
754
+ desc "Some description"
755
+ end
756
+ ```
757
+
758
+ The default will be automatically displayed in the usage information:
759
+
760
+ ```
761
+ Usage: foobar [OPTIONS] [FOO]
762
+
763
+ Arguments:
764
+ FOO Some description (default "bar")
765
+ ```
766
+
767
+ #### 2.5.4 desc(ription)
768
+
769
+ To provide a synopsis for a parameter use the `description` or shorter `desc` setting. This information is used by the [help](#29-help) method to produce usage information:
770
+
771
+ ```ruby
772
+ option :foo do
773
+ desc "Some description"
774
+ end
775
+ ```
776
+
777
+ The above will result in:
778
+
779
+ ```
780
+ Usage: foobar [OPTIONS]
781
+
782
+ Options:
783
+ --foo Some description
784
+ ```
785
+
786
+ #### 2.5.5 hidden
787
+
788
+ To hide a parameter from display in the usage information use the `hidden` setting:
789
+
790
+ ```ruby
791
+ argument :foo
792
+
793
+ argument :bar do
794
+ hidden
795
+ end
796
+ ```
797
+
798
+ The above will hide the `:bar` parameter from the usage:
799
+
800
+ ```
801
+ Usage: foobar FOO
802
+ ```
803
+
804
+ #### 2.5.6 name
805
+
806
+ By default the parameter key will be used to match command-line input arguments.
807
+
808
+ This means that a key `:foo_bar` will match `"foo-bar"` parameter name. For example, given a keyword:
809
+
810
+ ```ruby
811
+ keyword :foo_bar
812
+ ```
813
+
814
+ And then command-line input:
815
+
816
+ ```
817
+ foo-bar=baz
818
+ ```
819
+
820
+ The parsed result will be:
821
+
822
+ ```ruby
823
+ params[:foo_bar] # => "baz"
824
+ ```
825
+
826
+ To change the parameter name to a custom one, use the `name` setting:
827
+
828
+ ```ruby
829
+ keywor :foo_bar do
830
+ name "fum"
831
+ end
832
+ ```
833
+
834
+ Then parsing:
835
+
836
+ ```
837
+ fum=baz
838
+ ```
839
+
840
+ Will result in:
841
+
842
+ ```
843
+ params[:foo] # => "baz"
844
+ ````
845
+
846
+ For environment variables use the upper case when changing name:
847
+
848
+ ```ruby
849
+ env :foo do
850
+ name "FOO_VAR"
851
+ end
852
+ ```
853
+
854
+ #### 2.5.7 optional
855
+
856
+ Apart from the positional argument, all other parameters are optional. To mark an argument as optional use similar naming `optional` setting:
857
+
858
+ ```ruby
859
+ argument :foo do
860
+ desc "Foo arg description"
861
+ end
862
+
863
+ argument :bar do
864
+ optional
865
+ desc "Bar arg description"
866
+ end
867
+ ```
868
+
869
+ The optional argument will be surrounded by brackets in the usage display:
870
+
871
+ ```
872
+ Usage: foobar [OPTIONS] FOO [BAR]
873
+
874
+ Arguments:
875
+ FOO Foo arg description
876
+ BAR Bar arg description
877
+ ```
878
+
879
+ #### 2.5.8 permit
880
+
881
+ The `permit` setting allows you to restrict an input to a set of possible values.
882
+
883
+ For example, let's restrict option to only `"bar"` and `"baz"` strings:
884
+
885
+ ```ruby
886
+ option :foo do
887
+ long "--foo string"
888
+ permit ["bar", "baz"]
889
+ end
890
+ ```
891
+
892
+ And then parsing
893
+
894
+ ```
895
+ --foo bar
896
+ ```
897
+
898
+ Will populate parameters value:
899
+
900
+ ```ruby
901
+ params[:foo] # => "bar"
902
+ ```
903
+
904
+ Attempting to parse not permitted value:
905
+
906
+ ```
907
+ --foo qux
908
+ ```
909
+
910
+ Will internally produce a `TTY::Option::UnpermittedArgument` error and make the `params` invalid.
911
+
912
+ Permitted values are checked after applying conversion. Because of this, you need to provide the expected type for the `permit` setting:
913
+
914
+ ```ruby
915
+ option :foo do
916
+ long "--foo int"
917
+ confert :int
918
+ permit [11, 12, 13]
919
+ end
920
+ ```
921
+
922
+ Then parsing an unpermitted value:
923
+
924
+ ```
925
+ --foo 14
926
+ ```
927
+
928
+ Will invalidate `params` and collect the `TTY::Option::UnpermittedArgument` error.
929
+
930
+ The permitted values are automatically appended to the parameter synopsis when displayed in the usage information. For example, given an option:
931
+
932
+ ```ruby
933
+ option :foo do
934
+ short "-f"
935
+ long "--foo string"
936
+ permit %w[a b c d]
937
+ desc "Some description"
938
+ end
939
+ ```
940
+
941
+ Then the usage information for the option would be:
942
+
943
+ ```
944
+ Usage: foobar [OPTIONS]
945
+
946
+ Options:
947
+ -f, --foo string Some description (permitted: a,b,c,d)
948
+ ```
949
+
950
+ #### 2.5.9 required
951
+
952
+ Only arguments are required. Any other parameters like options, keywords and environment variables are optional. To force parameter presence in input use `required` setting.
953
+
954
+ ```ruby
955
+ keyword :foo do
956
+ required
957
+ desc "Foo keyword description"
958
+ end
959
+
960
+ keyword :bar do
961
+ desc "Bar keyword description"
962
+ end
963
+ ```
964
+
965
+ Because `foo` keyword is required it won't have brackets around the parameter in the usage display:
966
+
967
+ ```
968
+ Usage: foobar FOO=FOO [BAR=BAR]
969
+
970
+ Keywords:
971
+ FOO=FOO Foo keyword description
972
+ BAR=BAR Bar keyword description
973
+ ```
974
+
975
+ Note: Using required options is rather discouraged as these are typically expected to be optional.
976
+
977
+ #### 2.5.10 validate
978
+
979
+ Use the `validate` setting if you wish to ensure only inputs matching filter criteria are allowed.
980
+
981
+ You can use a string or regular expression to describe your validation rule:
982
+
983
+ ```ruby
984
+ option :foo do
985
+ long "--foo VAL"
986
+ validate "\d+"
987
+ end
988
+ ```
989
+
990
+ Then parsing:
991
+
992
+ ```
993
+ --foo bar
994
+ ```
995
+
996
+ Will internally cause an exception `TTY::Option::InvalidArgument` that will make `params` invalid.
997
+
998
+ You can also express a validation rule with a `proc` object:
999
+
1000
+ ```ruby
1001
+ keyword :foo do
1002
+ arity one_or_more
1003
+ convert :int
1004
+ validate ->(val) { val < 12 }
1005
+ end
1006
+ ```
1007
+
1008
+ Then parsing:
1009
+
1010
+ ```
1011
+ foo=11 foo=13
1012
+ ```
1013
+
1014
+ Will similarly collect the `TTY::Option::InvalidArgument` error and render `params` invalid.
1015
+
1016
+ ### 2.6 parse
1017
+
1018
+ After all parameters are defined, use the `parse` to process command line inputs.
1019
+
1020
+ By default the `parse` method takes the input from the `ARGV` and the `ENV` variables.
1021
+
1022
+ Alternatively, you can call `parse` with custom inputs. This is especially useful for testing your commands.
1023
+
1024
+ Given parameter definitions:
1025
+
1026
+ ```ruby
1027
+ argument :foo
1028
+
1029
+ flag :bar
1030
+
1031
+ keyword :baz
1032
+
1033
+ env :qux
1034
+ ```
1035
+
1036
+ Then parsing the following inputs:
1037
+
1038
+ ```ruby
1039
+ parse(%w[12 --bar baz=a QUX=b])
1040
+ ```
1041
+
1042
+ Would populate parameters:
1043
+
1044
+ ```ruby
1045
+ params[:foo] # => "12"
1046
+ params[:bar] # => true
1047
+ params[:baz] # => "a"
1048
+ params[:qux] # => "b"
1049
+ ```
1050
+
1051
+ The parsing is flexible and doesn't force any order for the parameters. Options can be inserted anywhere between positional or keyword arguments.
1052
+
1053
+ It handles parsing of compacted shorthand options that start with a single dash. These need to be boolean options bar the last one that can accept argument. All these are valid:
1054
+
1055
+ ```
1056
+ -f
1057
+ -fbq
1058
+ -fbqs 12 # mixed with an argument
1059
+ ```
1060
+
1061
+ Parameter parsing stops after the `--` terminator is found. The leftover inputs are collected and accessible via the `remaining` method.
1062
+
1063
+ #### 2.6.1 :raise_on_parse_error
1064
+
1065
+ By default no parse errors are raised. Why? Users do not appreciate Ruby errors in their terminal output. Instead, parsing errors are made accessible on the `params` object with the [errors](#271-errors) method.
1066
+
1067
+ However, if you prefer to handle parsing errors yourself, you can do so with `:raise_on_parse_error` keyword:
1068
+
1069
+ ```ruby
1070
+ parse(raise_on_parse_error: true)
1071
+ ```
1072
+
1073
+ Then in your code you may want to surround your `parse` call with a rescue clause:
1074
+
1075
+ ```ruby
1076
+ begin
1077
+ parse(raise_on_parse_error: true)
1078
+ rescue TTY::Option::ParseError => err
1079
+ # do something here
1080
+ end
1081
+ ```
1082
+
1083
+ #### 2.6.2 :check_invalid_params
1084
+
1085
+ Users can provide any input, including parameters you didn't expect and define.
1086
+
1087
+ By default, when unknown parameter is found in the input, an `TTY::Option::InvalidParameter` error will be raised internally and collected in the `errors` list.
1088
+
1089
+ If, on the other hand, you want to ignore unknown parameters and instead leave them alone during the parsing use the `:check_invalid_params` option like so:
1090
+
1091
+ ```ruby
1092
+ parse(check_invalid_params: false)
1093
+ ```
1094
+
1095
+ This way all the unrecognized parameters will be collected into a [remaining](#272-remaining) list accessible on the `params` instance.
1096
+
1097
+ ### 2.7 params
1098
+
1099
+ Once all parameters are defined, they are accessible via the `params` instance method.
1100
+
1101
+ The `params` behaves like a hash with an indifferent access. It doesn't distinguish between arguments, keywords or options. Each parameter needs to have a unique identifier.
1102
+
1103
+ For example, given a command with all parameter definitions:
1104
+
1105
+ ```ruby
1106
+ class Command
1107
+ include TTY::Option
1108
+
1109
+ argument :foo
1110
+
1111
+ keyword :bar
1112
+
1113
+ option :baz
1114
+
1115
+ env :qux
1116
+
1117
+ def run
1118
+ print params[:foo]
1119
+ print params["bar"]
1120
+ print params["baz"]
1121
+ print params[:qux]
1122
+ end
1123
+ end
1124
+ ```
1125
+
1126
+ Then parsing the command:
1127
+
1128
+ ```ruby
1129
+ cmd = Command.new
1130
+ cmd.parse
1131
+ ```
1132
+
1133
+ With the command-line input:
1134
+
1135
+ ```
1136
+ a bar=b --baz c QUX=d
1137
+ ```
1138
+
1139
+ And running the command:
1140
+
1141
+ ```ruby
1142
+ cmd.run
1143
+ ```
1144
+
1145
+ Will output:
1146
+
1147
+ ```
1148
+ abcd
1149
+ ```
1150
+
1151
+ #### 2.7.1 errors
1152
+
1153
+ Only configuration errors are raised. The parsing errors are not raised by default. Instead any parse error is made available via the `errors` method on the `params` object:
1154
+
1155
+ ```ruby
1156
+ params.errors
1157
+ # => AggregateErors
1158
+ ````
1159
+
1160
+ The returned `AggregateErrors` object is an `Enumerable` that allows you to iterate over all of the errors.
1161
+
1162
+ It has also a convenience methods like:
1163
+
1164
+ * `messages` - access all error messages as an array
1165
+ * `summary` - a string of nicely formatted error messages ready to display in terminal
1166
+
1167
+ For example, let's say we have an argument definition that requires at least 2 occurrences on the command line:
1168
+
1169
+ ```ruby
1170
+ argument :foo do
1171
+ arity at_least(2)
1172
+ end
1173
+ ```
1174
+
1175
+ And only one argument is provided in the input. Then output summary:
1176
+
1177
+ ```ruby
1178
+ puts params.errors.summary
1179
+ ````
1180
+
1181
+ Would result in the following being printed:
1182
+
1183
+ ```
1184
+ Error: argument 'foo' should appear at least 2 times but appeared 1 time
1185
+ ```
1186
+
1187
+ Let's change the previous example and add conversion to the mix:
1188
+
1189
+ ```ruby
1190
+ argument :foo do
1191
+ arity at_least(2)
1192
+ convert :int
1193
+ end
1194
+ ````
1195
+
1196
+ And provided only one argument string "zzz", the summary would be:
1197
+
1198
+ ```
1199
+ Errors:
1200
+ 1) Argument 'foo' should appear at least 2 times but appeared 1 time
1201
+ 2) Cannot convert value of `zzz` into 'int' type for 'foo' argument
1202
+ ```
1203
+
1204
+ If, on the other hand, you prefer to raise errors, you can do so using the `:raise_on_parse_error` keyword:
1205
+
1206
+ ```ruby
1207
+ parse(raise_on_parse_error: true)
1208
+ ```
1209
+
1210
+ This way any attempt at parsing invalid input will raise to the terminal.
1211
+
1212
+ #### 2.7.2 remaining
1213
+
1214
+ Users can provide any input, including parameters you didn't expect and define.
1215
+
1216
+ By default, when unknown parameter is found in the input, an `TTY::Option::InvalidParameter` error will be raised internally and collected in the `errors` list.
1217
+
1218
+ If, on the other hand, you want to ignore unknown parameters and instead leave them alone during the parsing use the `:check_invalid_params` option like so:
1219
+
1220
+ ```ruby
1221
+ parse(check_invalid_params: true)
1222
+ ```
1223
+
1224
+ This way all the unrecognized parameters will be collected into a list. You can access them on the `params` instance with the `remaining` method.
1225
+
1226
+ For example, let's assume that user provided `--unknown` option that we didn't expect. Inspecting the `remaining` parameters, we would get:
1227
+
1228
+ ```ruby
1229
+ params.remaining # => ["--unknown"]
1230
+ ```
1231
+
1232
+ Any parameters after the `--` terminator will be left alone during the parsing process and collected into the `remaining` list. This is useful in situations when you want to pass parameters over to another command-line applications.
1233
+
1234
+ #### 2.7.3 valid?
1235
+
1236
+ Once parsing of the command-line input is done, you can check if all the conditions defined by the parameters are met with the `valid?` method.
1237
+
1238
+ ```ruby
1239
+ params.valid?
1240
+ ```
1241
+
1242
+ You can use this to decide how to deal with parsing errors and what exit status to use.
1243
+
1244
+ For example, you can decide to implement a command method like this:
1245
+
1246
+ ```ruby
1247
+ if params.valid?
1248
+ # ... process params
1249
+ else
1250
+ puts params.errors.summary
1251
+ exit
1252
+ end
1253
+ ```
1254
+
1255
+ You can combine errors reporting with existing with the [tty-exit](https://github.com/piotrmurach/tty-exit) module.
1256
+
1257
+ The `TTY::Exit` module exposes the `exit_with` method and can be used like this:
1258
+
1259
+ ```ruby
1260
+ class Command
1261
+ include TTY::Exit
1262
+ include TTY::Option
1263
+
1264
+ def run
1265
+ if params.valid?
1266
+ # ... process params
1267
+ else
1268
+ exit_with(:usage_error, params.errors.summary)
1269
+ end
1270
+ end
1271
+ end
1272
+ ```
1273
+
1274
+ ### 2.8 usage
1275
+
1276
+ The `usage` and its helper methods allow you to configure the `help` display to your liking. The `header`, `desc(ription)`, `example` and `footer` can be called many times. Each new call will create a new paragraph. If you wish to insert multiple lines inside a given paragraph separate arguments with a comma.
1277
+
1278
+ #### 2.8.1 header
1279
+
1280
+ To provide information above the banner explaining how to execute a program, use the `header` helper.
1281
+
1282
+ ```ruby
1283
+ usage do
1284
+ header "A command-line interface for foo service"
1285
+ end
1286
+ ```
1287
+
1288
+ Further, you can add more paragraphs as comma-separated arguments to `header` with an empty string to represent a new line:
1289
+
1290
+ ```ruby
1291
+ usage do
1292
+ header "A command-line interface for foo service",
1293
+ "",
1294
+ "Access and retrieve data from foo service"
1295
+ end
1296
+ ```
1297
+
1298
+ Alternatively, you can add paragraphs calling `header` multiple times:
1299
+
1300
+ ```ruby
1301
+ usage do
1302
+ header "A command-line interface for foo service"
1303
+
1304
+ header "Access and retrieve data from foo service"
1305
+ end
1306
+ ```
1307
+
1308
+ #### 2.8.2 program
1309
+
1310
+ By default the program name is inferred for you from the executable file name.
1311
+
1312
+ You can override the default name using the `program` helper.
1313
+
1314
+ ```ruby
1315
+ usage do
1316
+ program "custom-name"
1317
+ end
1318
+ ````
1319
+
1320
+ Then the program name will be used in the banner:
1321
+
1322
+ ```bash
1323
+ Usage: custom-name
1324
+ ```
1325
+
1326
+ #### 2.8.3 command
1327
+
1328
+ By default the command name is inferred from the class name.
1329
+
1330
+ For example, based on the following:
1331
+
1332
+ ```ruby
1333
+ class NetworkCreate
1334
+ include TTY::Option
1335
+ end
1336
+ ```
1337
+
1338
+ The command name will become `network-create`. To change this use the `command` and `commands` helpers:
1339
+
1340
+ ```ruby
1341
+ class NetworkCreate
1342
+ include TTY::Option
1343
+
1344
+ usage do
1345
+ commands "network", "create"
1346
+ end
1347
+ end
1348
+ ````
1349
+
1350
+ This will result in the following usage information:
1351
+
1352
+ ```
1353
+ Usage: program network create
1354
+ ```
1355
+
1356
+ If you don't wish to infer the command name use the `no_command` method:
1357
+
1358
+ ```ruby
1359
+ usage do
1360
+ no_command
1361
+ end
1362
+ ````
1363
+
1364
+ #### 2.8.4 banner
1365
+
1366
+ The usage information of how to use a program is displayed right after header. If no header is specified, it will be displayed first.
1367
+
1368
+ This information is handled by the `banner` helper. By default, it will use the parameter definitions to generate usage information.
1369
+
1370
+ For example, given the following declarations:
1371
+
1372
+ ```ruby
1373
+ usage do
1374
+ program :foo
1375
+
1376
+ command :bar
1377
+ end
1378
+
1379
+ argument :baz
1380
+
1381
+ keyword :qux do
1382
+ convert :uri
1383
+ end
1384
+
1385
+ option :fum
1386
+ ```
1387
+
1388
+ The generated usage information will be:
1389
+
1390
+ ```bash
1391
+ Usage: foo bar [OPTIONS] BAZ [QUX=URI]
1392
+ ```
1393
+
1394
+ If you want to configure how arguments are displayed specify [2.8.2 :param_display](#282-param_display) setting.
1395
+
1396
+ You can also change completely how to the banner is displayed:
1397
+
1398
+ ```ruby
1399
+ usage do
1400
+ program "foo"
1401
+
1402
+ banner "Usage: #{program} BAR BAZ"
1403
+ end
1404
+ ```
1405
+
1406
+ #### 2.8.5 desc(ription)
1407
+
1408
+ The description is placed between usage information and the parameters and given with `desc` or `description` helpers.
1409
+
1410
+ The `desc` helper accepts multiple strings that will be displayed on separate lines.
1411
+
1412
+ ```ruby
1413
+ usage do
1414
+ desc "Some description", "on multiline"
1415
+ end
1416
+ ```
1417
+
1418
+ This will result in the following help output:
1419
+
1420
+ ```
1421
+ Some description
1422
+ on multiline
1423
+ ```
1424
+
1425
+ The `desc` helper can be called multiple times to build an examples section:
1426
+
1427
+ ```ruby
1428
+ usage do
1429
+ desc "Some description", "on multiline"
1430
+
1431
+ desc <<~EOS
1432
+ Another description
1433
+ on multiline
1434
+ EOS
1435
+ end
1436
+ ```
1437
+
1438
+ #### 2.8.6 example(s)
1439
+
1440
+ To add usage examples section to the help information use the `example` or `examples` methods.
1441
+
1442
+ The `example` helper accepts multiple strings that will be displayed on separate lines. For instance, the following class will add a single example:
1443
+
1444
+ ```ruby
1445
+ usage do
1446
+ example "Some example how to use foo",
1447
+ " $ foo bar"
1448
+ end
1449
+ ```
1450
+
1451
+ This will result in the following help output:
1452
+
1453
+ ```
1454
+ Examples:
1455
+ Some example how to use foo
1456
+ $ foo bar
1457
+ ```
1458
+
1459
+ The `example` helper can be called multiple times to build an examples section:
1460
+
1461
+ ```ruby
1462
+ usage do
1463
+ example "Some example how to use foo",
1464
+ " $ foo bar"
1465
+
1466
+ example <<~EOS
1467
+ Another example how to use foo"
1468
+ $ foo baz
1469
+ EOS
1470
+ end
1471
+ ```
1472
+
1473
+ The usage help will contain the following:
1474
+
1475
+ ```
1476
+ Examples:
1477
+ Some example how to use foo
1478
+ $ foo bar
1479
+
1480
+ Another example how to use foo
1481
+ $ foo baz
1482
+ ```
1483
+
1484
+ #### 2.8.7 footer
1485
+
1486
+ To provide information after all information in the usage help, use the `footer` helper.
1487
+
1488
+ ```ruby
1489
+ usage do
1490
+ footer "Run a command followed by --help to see more info"
1491
+ end
1492
+ ```
1493
+
1494
+ Further, you can add more paragraphs as comma-separated arguments to `footer` with an empty string to represent a new line:
1495
+
1496
+ ```ruby
1497
+ usage do
1498
+ footer "Run a command followed by --help to see more info",
1499
+ "",
1500
+ "Options marked with (...) can be given more than once"
1501
+ end
1502
+ ```
1503
+
1504
+ Alternatively, you can add paragraphs calling `footer` multiple times:
1505
+
1506
+ ```ruby
1507
+ usage do
1508
+ footer "Run a command followed by --help to see more info"
1509
+
1510
+ footer "Options marked with (...) can be given more than once"
1511
+ end
1512
+ ```
1513
+
1514
+ ### 2.9 help
1515
+
1516
+ With the `help` instance method you can generate usage information from the defined parameters and the usage. The [usage](#28-usage) describes how to add different sections to the help display.
1517
+
1518
+ Let's assume you have the following command with a run method that prints help:
1519
+
1520
+
1521
+ ```ruby
1522
+ class Command
1523
+ include TTY::Option
1524
+
1525
+ usage do
1526
+ program "foobar",
1527
+ header "foobar CLI"
1528
+ desc "Some foobar description"
1529
+ example "Some example"
1530
+ footer "Run --help to see more info"
1531
+ end
1532
+
1533
+ argument :bar, desc: "Some argument description"
1534
+ keyword :baz, desc: "Some keyword description"
1535
+ env :fum, desc: "Some env description"
1536
+
1537
+ flag :help do
1538
+ short "-h"
1539
+ long "--help"
1540
+ desc "Print usage"
1541
+ end
1542
+
1543
+ def run
1544
+ if params[:help]
1545
+ print help
1546
+ exit
1547
+ end
1548
+ end
1549
+ end
1550
+ ```
1551
+
1552
+ Running the command with `--help` flag:
1553
+
1554
+ ```ruby
1555
+ cmd = Command.new
1556
+ cmd.parse(%w[--help])
1557
+ cmd.run
1558
+ ```
1559
+
1560
+ Will produce:
1561
+
1562
+ ```
1563
+ foobar CLI
1564
+
1565
+ Usage: foobar [OPTIONS] [ENVIRONMENT] BAR [BAZ=BAZ]
1566
+
1567
+ Some foobar description
1568
+
1569
+ Arguments:
1570
+ BAR Some argument description
1571
+
1572
+ Keywords:
1573
+ BAZ=BAZ Some keyword description
1574
+
1575
+ Options:
1576
+ -h, --help Print usage
1577
+
1578
+ Envrionment:
1579
+ FUM Some env description
1580
+
1581
+ Examples:
1582
+ Some example
1583
+
1584
+ Run --help to see more info
1585
+ ```
1586
+
1587
+ #### 2.9.1 sections
1588
+
1589
+ It is possible to change the usage content by passing a block to `help`. The `help` method yields an object that contains all the sections and provides a hash-like access to each of its sections.
1590
+
1591
+ The following are the names for all supported sections:
1592
+
1593
+ * `:header`
1594
+ * `:banner`
1595
+ * `:description`
1596
+ * `:arguments`
1597
+ * `:keywords`
1598
+ * `:options`
1599
+ * `:environments`
1600
+ * `:exmaples`
1601
+ * `:footer`
1602
+
1603
+ You can use `add_before`, `add_after`, `delete` and `replace` to modify currently existing sections or add new ones.
1604
+
1605
+ For example, to remove a header section do:
1606
+
1607
+ ```ruby
1608
+ help do |sections|
1609
+ sections.delete :header
1610
+ end
1611
+ ```
1612
+
1613
+ To insert a new section after `:arguments` called `:commands` do:
1614
+
1615
+ ```ruby
1616
+ help do |sections|
1617
+ sections.add_after :arguments, :commands,
1618
+ "\nCommands:\n create A command description"
1619
+ end
1620
+ ```
1621
+
1622
+ To replace a section's content use `replace`:
1623
+
1624
+ ```ruby
1625
+ help do |sections|
1626
+ sections.replace :footer, "\nGoodbye"
1627
+ end
1628
+ ```
1629
+
1630
+ #### 2.9.2 :indent
1631
+
1632
+ By default has not indentation for any of the sections bar parameters.
1633
+
1634
+ To change the indentation for the entire usage information use `:indent` keyword:
1635
+
1636
+ ```ruby
1637
+ help(indent: 2)
1638
+ ```
1639
+
1640
+ #### 2.9.3 :order
1641
+
1642
+ All parameters are alphabetically ordered in their respective sections. To change this default behaviour use the `:order` keyword when invoking `help`.
1643
+
1644
+ The `:order` expects a `Proc` object. For example, to remove any ordering and preserve the parameter declaration order do:
1645
+
1646
+ ```ruby
1647
+ help(order: ->(params) { params })
1648
+ ````
1649
+
1650
+ #### 2.9.4 :param_display
1651
+
1652
+ By default banner positional and keyword arguments are displayed with all letters uppercased.
1653
+
1654
+ For example, given the following parameter declarations:
1655
+
1656
+ ```ruby
1657
+ program "run"
1658
+
1659
+ argument :foo
1660
+
1661
+ keyword :bar do
1662
+ required
1663
+ convert :uri
1664
+ end
1665
+
1666
+ option :baz
1667
+ ```
1668
+
1669
+ The banner output would be as follows:
1670
+
1671
+ ```bash
1672
+ Usage: run [OPTIONS] FOO BAR=URI
1673
+ ```
1674
+
1675
+ To change the banner parameter display use `:param_display` keyword.
1676
+
1677
+ For example, to lowercase and surround your parameters with `< >` brackets do:
1678
+
1679
+ ```ruby
1680
+ help(param_display: ->(str) { "<#{str.downcase}>" })
1681
+ ```
1682
+
1683
+ This will produce the following output:
1684
+
1685
+ ```
1686
+ Usage: run [<options>] <foo> <bar>=<uri>
1687
+ ```
1688
+
1689
+ #### 2.9.5 :width
1690
+
1691
+ By default the help information is wrapped at `80` columns. If this is not what you want you can change it with `:width` keyword.
1692
+
1693
+ For example, to change the help to always take up all the terminal columns consider using [tty-screen](https://github.com/piotrmurach/tty-screen):
1694
+
1695
+ ```ruby
1696
+ help(width: TTY::Screen.width)
1697
+ ```
1698
+
47
1699
  ## Development
48
1700
 
49
1701
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.