tty-option 0.0.0 → 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.
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.