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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/README.md +1653 -1
- data/lib/tty/option.rb +63 -4
- data/lib/tty/option/aggregate_errors.rb +95 -0
- data/lib/tty/option/conversions.rb +126 -0
- data/lib/tty/option/converter.rb +63 -0
- data/lib/tty/option/deep_dup.rb +48 -0
- data/lib/tty/option/dsl.rb +105 -0
- data/lib/tty/option/dsl/arity.rb +49 -0
- data/lib/tty/option/dsl/conversion.rb +17 -0
- data/lib/tty/option/error_aggregator.rb +35 -0
- data/lib/tty/option/errors.rb +144 -0
- data/lib/tty/option/formatter.rb +389 -0
- data/lib/tty/option/inflection.rb +50 -0
- data/lib/tty/option/param_conversion.rb +34 -0
- data/lib/tty/option/param_permitted.rb +30 -0
- data/lib/tty/option/param_validation.rb +48 -0
- data/lib/tty/option/parameter.rb +310 -0
- data/lib/tty/option/parameter/argument.rb +18 -0
- data/lib/tty/option/parameter/environment.rb +20 -0
- data/lib/tty/option/parameter/keyword.rb +15 -0
- data/lib/tty/option/parameter/option.rb +99 -0
- data/lib/tty/option/parameters.rb +157 -0
- data/lib/tty/option/params.rb +122 -0
- data/lib/tty/option/parser.rb +57 -3
- data/lib/tty/option/parser/arguments.rb +166 -0
- data/lib/tty/option/parser/arity_check.rb +34 -0
- data/lib/tty/option/parser/environments.rb +169 -0
- data/lib/tty/option/parser/keywords.rb +158 -0
- data/lib/tty/option/parser/options.rb +273 -0
- data/lib/tty/option/parser/param_types.rb +51 -0
- data/lib/tty/option/parser/required_check.rb +36 -0
- data/lib/tty/option/pipeline.rb +38 -0
- data/lib/tty/option/result.rb +46 -0
- data/lib/tty/option/section.rb +26 -0
- data/lib/tty/option/sections.rb +56 -0
- data/lib/tty/option/usage.rb +166 -0
- data/lib/tty/option/usage_wrapper.rb +58 -0
- data/lib/tty/option/version.rb +3 -3
- metadata +37 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e48f8a476c72fb96d9f6bf49daea6533b2cc6940a536eb0e5a56fce19ff6c75b
|
4
|
+
data.tar.gz: cbadbde794e8469c8d0b1bc5ade00c47e2420d885f5a5fd6e410dce5950d3d8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6257d839aefe82f045f8708ebd5b5443a2df85090b1c3a722f8dbe3ba40704c79277a203e44d78e458405200ad465e3471dc4b3575fc101806d7b4b93717ee6
|
7
|
+
data.tar.gz: 461f0b5454e44e5bebf59dcd308ffa2fda57f457d0191c709b859dae216880b781ff62d40e96e2cc101f8637ee94b1029174c7d63c2d872c345614b692412e34
|
data/CHANGELOG.md
CHANGED
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
|
-
##
|
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.
|