cl 0.1.12 → 0.1.13
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 +5 -3
- data/Gemfile.lock +2 -2
- data/NOTES.md +12 -8
- data/README.md +897 -13
- data/examples/readme/alias +22 -0
- data/examples/readme/arg +16 -0
- data/examples/readme/arg_array +16 -0
- data/examples/readme/arg_type +18 -0
- data/examples/readme/args_splat +43 -0
- data/examples/readme/array +18 -0
- data/examples/readme/default +18 -0
- data/examples/readme/deprecated +21 -0
- data/examples/readme/deprecated_alias +20 -0
- data/examples/readme/downcase +18 -0
- data/examples/readme/enum +26 -0
- data/examples/readme/example +17 -0
- data/examples/readme/format +29 -0
- data/examples/readme/internal +18 -0
- data/examples/readme/opts +29 -0
- data/examples/readme/opts_block +26 -0
- data/examples/readme/range +29 -0
- data/examples/readme/required +29 -0
- data/examples/readme/requireds +36 -0
- data/examples/readme/requires +32 -0
- data/examples/readme/see +21 -0
- data/examples/readme/type +22 -0
- data/lib/cl.rb +26 -66
- data/lib/cl/arg.rb +9 -5
- data/lib/cl/cast.rb +5 -1
- data/lib/cl/cmd.rb +11 -49
- data/lib/cl/ctx.rb +3 -5
- data/lib/cl/dsl.rb +176 -0
- data/lib/cl/errors.rb +73 -0
- data/lib/cl/help/cmd.rb +8 -3
- data/lib/cl/helper.rb +8 -0
- data/lib/cl/opt.rb +13 -0
- data/lib/cl/opts.rb +27 -8
- data/lib/cl/runner.rb +10 -0
- data/lib/cl/runner/default.rb +22 -2
- data/lib/cl/runner/multi.rb +6 -4
- data/lib/cl/ui.rb +11 -2
- data/lib/cl/version.rb +1 -1
- metadata +27 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c566fcf9fc49fe3d3565f2f5bad09aef48ff75a
|
4
|
+
data.tar.gz: 5dcdd36b075b21ece0b05780955029467d29986c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13b77f339a3d479f8a6b7295ee9f0ba22b0b352ad439af63223a31ab062d34936313f34a44cce9042099d38fea7243d31f64c70801b23a76cf765af848220297
|
7
|
+
data.tar.gz: 21bde54f28368e44ca3decb3bb0337e2e5c58606a0474e53beedaeae18540747ea9fbdc60744164079374174b6c24bc9d85cb47438c2fb35a18341efed195199
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## 0.1.
|
3
|
+
## 0.1.x
|
4
4
|
|
5
5
|
### Added
|
6
6
|
|
7
7
|
* Add config, reading from env vars and yml files (inspired by gem-release)
|
8
8
|
* Add `abstract` in order to signal a cmd is a base class that is not meant to be executed
|
9
|
+
* Add `examples` in order to add examples for the command to the help output
|
9
10
|
* Add `required :one, [:two, :three]` (DNF, i.e: either `:one` or both `:two` and `:three` must be given)
|
10
11
|
* Add `opt '--one STR', type: :array` for options that can be given multiple times
|
11
12
|
* Add `opt '--one STR', default: 'one'`
|
@@ -13,6 +14,7 @@
|
|
13
14
|
* Add `opt '--one', alias: :other`
|
14
15
|
* Add `opt '--one', deprecated: 'message'`, and `cmd.deprected_opts`, so clients can look up which deprecated options were used
|
15
16
|
* Add `opt '--one', alias: :other, deprecated: :other`, so that `cmd.deprecated_opts` returns the alias name if it was used
|
17
|
+
* Add `opt '--int INT', min: 10, type: :integer`
|
16
18
|
* Add `opt '--int INT', max: 10, type: :integer`
|
17
19
|
* Add `opt '--one STR', format: /.+/`
|
18
20
|
* Add `opt '--one STR', enum: ['one', /\w+/]`
|
@@ -26,8 +28,8 @@
|
|
26
28
|
* Much improved help output, modeled after rubygems' help output
|
27
29
|
* Cl is now a class
|
28
30
|
* Use the regstry gem, remove the local Registry implementation
|
29
|
-
* If a flag (boolean option) has a default `true` automatically add `[no-]` to
|
30
|
-
|
31
|
+
* If a flag (boolean option) has a default `true` automatically add `[no-]` to it, allowing to opt out
|
32
|
+
* Runners are now registered in order to make them more easily extendable
|
31
33
|
|
32
34
|
### Removed
|
33
35
|
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cl (0.1.
|
4
|
+
cl (0.1.12)
|
5
5
|
regstry (~> 1.0.3)
|
6
6
|
|
7
7
|
GEM
|
@@ -9,7 +9,7 @@ GEM
|
|
9
9
|
specs:
|
10
10
|
diff-lcs (1.3)
|
11
11
|
memfs (1.0.0)
|
12
|
-
regstry (1.0.
|
12
|
+
regstry (1.0.9)
|
13
13
|
rspec (3.8.0)
|
14
14
|
rspec-core (~> 3.8.0)
|
15
15
|
rspec-expectations (~> 3.8.0)
|
data/NOTES.md
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
x add args descriptions
|
2
|
+
x add Cmd#examples
|
3
|
+
x add min to opts
|
4
|
+
x error message for required option (see readme/required)
|
5
|
+
x document arg splats, types
|
6
|
+
x make sure runners raise proper exceptions if a command was not found
|
7
|
+
x register runners, accept any object as a runner, too
|
8
|
+
x readme passing a block to opt
|
9
|
+
x complete readme (e.g. description, summary, examples)
|
10
|
+
x add toc
|
11
|
+
|
12
|
+
- add yard docs
|
5
13
|
- refactor Help::Cmd and Table so that everything goes into one big table
|
6
|
-
|
7
|
-
- add args descriptions
|
8
|
-
|
9
|
-
|
data/README.md
CHANGED
@@ -1,16 +1,47 @@
|
|
1
|
-
#
|
1
|
+
# Cl [](https://travis-ci.org/svenfuchs/cl)
|
2
2
|
|
3
3
|
This library wraps Ruby's `OptionParser` in order to make it easier to use it
|
4
4
|
in an object oriented context.
|
5
5
|
|
6
6
|
It uses `OptionParser` for parsing your options, so you get all the goodness that
|
7
|
-
this
|
8
|
-
|
9
|
-
|
7
|
+
this gem from Ruby's stoneage provides.
|
8
|
+
|
9
|
+
But on top of that it also provides a rich DSL for defining, validating, and
|
10
|
+
normalizing options, as well as automatic and gorgeous help output (modeled
|
11
|
+
after Rubygem's `gem --help` output).
|
12
|
+
|
13
|
+
Further documentation is available on [rubydoc.info](https://www.rubydoc.info/github/svenfuchs/cl)
|
14
|
+
|
15
|
+
## Table of Contents
|
16
|
+
|
17
|
+
* [Basic Usage](#basic-usage)
|
18
|
+
* [Command Registry](#command-registry)
|
19
|
+
* [Runners](#runners)
|
20
|
+
* [Command DSL](#command-dsl)
|
21
|
+
* [Description, Summary, Examples](#description-summary-examples)
|
22
|
+
* [Arguments](#arguments)
|
23
|
+
* [Types](#types)
|
24
|
+
* [Splat](#splat)
|
25
|
+
* [Options](#options)
|
26
|
+
* [Aliases](#aliases)
|
27
|
+
* [Defaults](#defaults)
|
28
|
+
* [Deprecations](#deprecations)
|
29
|
+
* [Downcase](#downcase)
|
30
|
+
* [Enum](#enum)
|
31
|
+
* [Example](#example)
|
32
|
+
* [Format](#format)
|
33
|
+
* [Internal](#internal)
|
34
|
+
* [Min and Max](#min-and-max)
|
35
|
+
* [See Also](#see-also)
|
36
|
+
* [Types](#types)
|
37
|
+
* [Required Options](#required-options)
|
38
|
+
* [Config Files](#config-files)
|
39
|
+
* [Environment Variables](#environment-variables)
|
10
40
|
|
11
41
|
## Basic Usage
|
12
42
|
|
13
43
|
```ruby
|
44
|
+
# lib/cli/owners/add.rb
|
14
45
|
module Owners
|
15
46
|
class Add < Cl::Cmd
|
16
47
|
summary 'Add one or more owners to an existing owner group'
|
@@ -19,23 +50,43 @@ module Owners
|
|
19
50
|
Use this command to add one or more owners to an existing
|
20
51
|
owner group.
|
21
52
|
|
22
|
-
|
53
|
+
[...]
|
23
54
|
str
|
24
55
|
|
25
56
|
args :owners
|
26
57
|
|
27
|
-
opt '-t', '--to TO', 'An existing owner group'
|
28
|
-
|
58
|
+
opt '-t', '--to TO', 'An existing owner group'
|
59
|
+
|
60
|
+
def run
|
61
|
+
# add owners as listed in `owners` to the group given in
|
62
|
+
# `to`, as well as `opts[:to]`.
|
29
63
|
end
|
30
64
|
end
|
31
65
|
end
|
66
|
+
|
67
|
+
# bin/owners
|
68
|
+
Cl.new('owners').run(ARGV)
|
32
69
|
```
|
33
70
|
|
71
|
+
Running this, e.g. using `bin/owners add one,two --to group` will instantiate the
|
72
|
+
class `Owners::Add`, and call the method `run` on it.
|
73
|
+
|
34
74
|
Help output:
|
35
75
|
|
36
76
|
```txt
|
37
77
|
Usage: owners add [owners] [options]
|
38
78
|
|
79
|
+
Summary:
|
80
|
+
|
81
|
+
Add one or more owners to an existing owner group
|
82
|
+
|
83
|
+
Description:
|
84
|
+
|
85
|
+
Use this command to add one or more owners to an existing
|
86
|
+
owner group.
|
87
|
+
|
88
|
+
These will be visible in [...]
|
89
|
+
|
39
90
|
Arguments:
|
40
91
|
|
41
92
|
owners type: string
|
@@ -44,15 +95,848 @@ Options:
|
|
44
95
|
|
45
96
|
-t --to TO An existing owner group (type: string, required: true)
|
46
97
|
--help Get help on this command (type: flag)
|
98
|
+
```
|
47
99
|
|
48
|
-
|
100
|
+
### Command Registry
|
49
101
|
|
50
|
-
|
102
|
+
Commands are Ruby classes that extend the class `Cl::Cmd`.
|
51
103
|
|
52
|
-
|
104
|
+
They register to a [Ruby class registry](https://github.com/svenfuchs/registry) in order
|
105
|
+
to decouple looking up command classes from their Ruby namespace.
|
53
106
|
|
54
|
-
|
55
|
-
owner group.
|
107
|
+
For example:
|
56
108
|
|
57
|
-
|
109
|
+
```ruby
|
110
|
+
module One
|
111
|
+
class Cmd < Cl::Cmd
|
112
|
+
register :one
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
module Two
|
117
|
+
class Cmd < Cl::Cmd
|
118
|
+
register :two
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
Cl::Cmd[:one] # => One::Cmd
|
123
|
+
Cl::Cmd[:two] # => Two::Cmd
|
124
|
+
```
|
125
|
+
|
126
|
+
Commands auto register themselves with the underscored name of the last part of
|
127
|
+
their class name (as seen in the example above). It is possible to ovewrite this
|
128
|
+
key by manually registering the class, like so:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
module One
|
132
|
+
class Cmd < Cl::Cmd
|
133
|
+
register :'cmd:one'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
### Runners
|
139
|
+
|
140
|
+
Runners lookup the command to execute from the registry, by checking the
|
141
|
+
arguments given by the user for registered command keys.
|
142
|
+
|
143
|
+
With the two command classes `One` and `Two` from the example above (and
|
144
|
+
assuming that the executable that calls `Cl` is `bin/run`) the default runner
|
145
|
+
would recognize and run the following commands:
|
146
|
+
|
147
|
+
```
|
148
|
+
$ bin/run one something else
|
149
|
+
# instantiates One, passing the args array `["something", "else"]`, and calls `run`
|
150
|
+
|
151
|
+
$ bin/run two something else
|
152
|
+
# instantiates One, passing an empty args arry `[]`, and calls `run`
|
153
|
+
```
|
154
|
+
|
155
|
+
The default runner also supports nested namespaces, and checks for command classes
|
156
|
+
with keys separated by colons. For instance:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
module Git
|
160
|
+
class Pull < Cl::Cmd
|
161
|
+
register :'git:pull'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
module Git
|
166
|
+
class Push < Cl::Cmd
|
167
|
+
register :'git:push'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
With these classes registered (and assuming the executable that calls `Cl` is
|
173
|
+
`bin/git`) the default runner would recognize and run the following commands:
|
174
|
+
|
175
|
+
```
|
176
|
+
$ bin/git pull:master # instantiates Git::Pull, and passes ["master"] as args
|
177
|
+
$ bin/git pull master # does the same
|
178
|
+
|
179
|
+
$ bin/git push:master # instantiates Git::Push, and passes ["master"] as args
|
180
|
+
$ bin/git push master # does the same
|
181
|
+
```
|
182
|
+
|
183
|
+
Runners are registered on the module `Cl::Runner`. It is possible to register custom
|
184
|
+
runners, and use them by passing the option `runner` to `Cl.new`:
|
185
|
+
|
186
|
+
```
|
187
|
+
# in bin/run
|
188
|
+
Cli.new('run', runner: :custom).run(ARGV)
|
189
|
+
|
190
|
+
# anywhere in your library
|
191
|
+
class Runner
|
192
|
+
Cl::Runner.register :custom, self
|
193
|
+
|
194
|
+
def initialize(ctx, args)
|
195
|
+
# ...
|
196
|
+
end
|
197
|
+
|
198
|
+
def run
|
199
|
+
const = identify_cmd_class_from_args
|
200
|
+
const.new(ctx, args).run
|
201
|
+
end
|
202
|
+
end
|
203
|
+
```
|
204
|
+
|
205
|
+
See `Cl::Runner::Default` for more details.
|
206
|
+
|
207
|
+
There also is an experimental runner `:multi`, which supports rake-style
|
208
|
+
execution of multiple commands at once, like so:
|
209
|
+
|
210
|
+
```
|
211
|
+
bin/rake db:drop production -f db:create db:migrate production -v 1
|
212
|
+
```
|
213
|
+
|
214
|
+
See the example [rakeish](blob/master/examples/rakeish) for more details.
|
215
|
+
|
216
|
+
## Command DSL
|
217
|
+
|
218
|
+
The DSL is defined on the class body.
|
219
|
+
|
220
|
+
## Description, Summary, Examples
|
221
|
+
|
222
|
+
The description, summary, and examples are used in the help output.
|
223
|
+
|
224
|
+
```
|
225
|
+
module Owners
|
226
|
+
class Add < Cl::Cmd
|
227
|
+
summary 'Add one or more owners to an existing owner group'
|
228
|
+
|
229
|
+
description <<~str
|
230
|
+
Use this command to add one or more owners to an existing
|
231
|
+
owner group.
|
232
|
+
str
|
233
|
+
|
234
|
+
examples <<~str
|
235
|
+
Adding a single user to the group admins:
|
236
|
+
|
237
|
+
./bin/owners add user --to admins
|
238
|
+
|
239
|
+
Adding a several users at once:
|
240
|
+
|
241
|
+
./bin/owners add one two three --to admins
|
242
|
+
str
|
243
|
+
end
|
244
|
+
end
|
58
245
|
```
|
246
|
+
|
247
|
+
### Arguments
|
248
|
+
|
249
|
+
Arguments can be declared like so:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
arg :arg_name, description: 'arg description', type: :[array|string|integer|float|boolean]
|
253
|
+
```
|
254
|
+
|
255
|
+
This will define an `attr_accessor` on the `Cmd` class. I.e. in the following
|
256
|
+
example the method `ownsers` will be available on the `Cmd` instance:
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
class Add < Cl::Cmd
|
260
|
+
arg :owner
|
261
|
+
|
262
|
+
def run
|
263
|
+
p owner
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
Cl.new('owners').run(%w(add one))
|
268
|
+
|
269
|
+
# => "one"
|
270
|
+
|
271
|
+
```
|
272
|
+
|
273
|
+
#### Types
|
274
|
+
|
275
|
+
Arguments can have a type. Known types are: `:array`, `:string`, `:integer`,
|
276
|
+
`:float`, `:boolean`.
|
277
|
+
|
278
|
+
The type `:array` makes sure the argument accessible on the `Cmd` instance is a
|
279
|
+
Ruby Array. (This currently only supports arrays of strings).
|
280
|
+
|
281
|
+
If the option `sep` is given on the argument, then the argument value is split
|
282
|
+
using this separator.
|
283
|
+
|
284
|
+
```ruby
|
285
|
+
class Add < Cl::Cmd
|
286
|
+
arg :owners, type: :array, sep: ','
|
287
|
+
|
288
|
+
def run
|
289
|
+
p owners
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
Cl.new('owners').run(%w(add one,two))
|
294
|
+
|
295
|
+
# => ["one", "two"]
|
296
|
+
|
297
|
+
```
|
298
|
+
|
299
|
+
Other types cast the given argument to the expected Ruby type.
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
class Cmd < Cl::Cmd
|
303
|
+
arg :one, type: :integer
|
304
|
+
arg :two, type: :float
|
305
|
+
arg :three, type: :boolean
|
306
|
+
|
307
|
+
def run
|
308
|
+
p [one.class, two.class, three.class]
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
Cl.new('owners').run(%w(cmd 1 2.1 yes))
|
313
|
+
|
314
|
+
# => [Integer, Float, TrueClass]
|
315
|
+
|
316
|
+
```
|
317
|
+
|
318
|
+
#### Splat
|
319
|
+
|
320
|
+
Array arguments support splats, modeled after Ruby argument splats.
|
321
|
+
|
322
|
+
For example:
|
323
|
+
|
324
|
+
```ruby
|
325
|
+
class Cmd < Cl::Cmd
|
326
|
+
arg :one, type: :integer
|
327
|
+
arg :two, type: :float
|
328
|
+
arg :three, type: :boolean
|
329
|
+
|
330
|
+
def run
|
331
|
+
p [one.class, two.class, three.class]
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
Cl.new('owners').run(%w(cmd 1 2.1 yes))
|
336
|
+
|
337
|
+
# => [Integer, Float, TrueClass]
|
338
|
+
|
339
|
+
```
|
340
|
+
|
341
|
+
### Options
|
342
|
+
|
343
|
+
Declaring options can be done by calling the method `opt` on the class body.
|
344
|
+
|
345
|
+
This will add the option, if given by the user, to the hash `opts` on the `Cmd` instance.
|
346
|
+
It also defines a reader method that returns the respective value from the `opts` hash,
|
347
|
+
and a predicate that will be true if the option has been given.
|
348
|
+
|
349
|
+
For example:
|
350
|
+
|
351
|
+
```ruby
|
352
|
+
class Add < Cl::Cmd
|
353
|
+
opt '--to GROUP', 'Target group to add owners to'
|
354
|
+
|
355
|
+
def run
|
356
|
+
p opts, to, to?
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
Cl.new('owners').run(%w(add --to one))
|
361
|
+
|
362
|
+
# Output:
|
363
|
+
#
|
364
|
+
# {"to" => "one"}
|
365
|
+
# "one"
|
366
|
+
# true
|
367
|
+
|
368
|
+
Cl.new('owners').run(%w(add --help))
|
369
|
+
|
370
|
+
# Usage: opts add [options]
|
371
|
+
#
|
372
|
+
# Options:
|
373
|
+
#
|
374
|
+
# --to GROUP Target group to add owners to (type: string)
|
375
|
+
# --help Get help on this command
|
376
|
+
|
377
|
+
```
|
378
|
+
|
379
|
+
Options optionally accept a block in case custom normalization is needed.
|
380
|
+
|
381
|
+
Depending on the block's arity the following arguments are passed to the block:
|
382
|
+
option value, option name, option type, collection of all options defined on
|
383
|
+
the command.
|
384
|
+
|
385
|
+
```ruby
|
386
|
+
class Add < Cl::Cmd
|
387
|
+
# depending on its arity the block can receive:
|
388
|
+
#
|
389
|
+
# * value
|
390
|
+
# * value, name
|
391
|
+
# * value, name, type
|
392
|
+
# * value, name, type, opts
|
393
|
+
opt '--to GROUP' do |value|
|
394
|
+
opts[:to] = "#{value.upcase}!"
|
395
|
+
end
|
396
|
+
|
397
|
+
def run
|
398
|
+
p to
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
Cl.new('owners').run(%w(add --to one))
|
403
|
+
|
404
|
+
# Output:
|
405
|
+
#
|
406
|
+
# "ONE!"
|
407
|
+
|
408
|
+
```
|
409
|
+
|
410
|
+
#### Aliases
|
411
|
+
|
412
|
+
Options can have one or many alias names, given as a Symbol or Array of Symbols:
|
413
|
+
|
414
|
+
```ruby
|
415
|
+
class Add < Cl::Cmd
|
416
|
+
opt '--to GROUP', alias: :group
|
417
|
+
|
418
|
+
def run
|
419
|
+
p opts, to, to?, group, group?
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
Cl.new('owners').run(%w(add --to one))
|
424
|
+
|
425
|
+
# Output:
|
426
|
+
#
|
427
|
+
# {"to" => "one"}
|
428
|
+
# "one"
|
429
|
+
# true
|
430
|
+
# "one"
|
431
|
+
# true
|
432
|
+
|
433
|
+
```
|
434
|
+
|
435
|
+
#### Defaults
|
436
|
+
|
437
|
+
Options can have a default value.
|
438
|
+
|
439
|
+
I.e. this value is going to be used if the user does not provide the option:
|
440
|
+
|
441
|
+
```ruby
|
442
|
+
class Add < Cl::Cmd
|
443
|
+
opt '--to GROUP', default: 'default'
|
444
|
+
|
445
|
+
def run
|
446
|
+
p to
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
Cl.new('owners').run(%w(add))
|
451
|
+
|
452
|
+
# Output:
|
453
|
+
#
|
454
|
+
# "default"
|
455
|
+
|
456
|
+
```
|
457
|
+
|
458
|
+
#### Deprecations
|
459
|
+
|
460
|
+
Options, and option alias name can be deprecated.
|
461
|
+
|
462
|
+
For a deprecated option:
|
463
|
+
|
464
|
+
```ruby
|
465
|
+
class Add < Cl::Cmd
|
466
|
+
opt '--to GROUP'
|
467
|
+
opt '--target GROUP', deprecated: 'Deprecated: --target'
|
468
|
+
|
469
|
+
def run
|
470
|
+
p to, deprecated_opts
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
Cl.new('owners').run(%w(add --target one))
|
475
|
+
|
476
|
+
# Output:
|
477
|
+
#
|
478
|
+
# "one"
|
479
|
+
# {:target=>'Deprecated: --target'}
|
480
|
+
|
481
|
+
|
482
|
+
```
|
483
|
+
|
484
|
+
For a deprecated option alias name:
|
485
|
+
|
486
|
+
```ruby
|
487
|
+
class Add < Cl::Cmd
|
488
|
+
opt '--to GROUP', alias: :target, deprecated: :target
|
489
|
+
|
490
|
+
def run
|
491
|
+
p to, deprecated_opts
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
Cl.new('owners').run(%w(add --target one))
|
496
|
+
|
497
|
+
# Output:
|
498
|
+
#
|
499
|
+
# "one"
|
500
|
+
# {:target=>:to}
|
501
|
+
|
502
|
+
|
503
|
+
```
|
504
|
+
|
505
|
+
#### Downcase
|
506
|
+
|
507
|
+
Options can be declared to be downcased.
|
508
|
+
|
509
|
+
For example:
|
510
|
+
|
511
|
+
```ruby
|
512
|
+
class Add < Cl::Cmd
|
513
|
+
opt '--to GROUP', downcase: true
|
514
|
+
|
515
|
+
def run
|
516
|
+
p to
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
Cl.new('owners').run(%w(add --to ONE))
|
521
|
+
|
522
|
+
# Output:
|
523
|
+
#
|
524
|
+
# "one"
|
525
|
+
|
526
|
+
```
|
527
|
+
|
528
|
+
#### Enum
|
529
|
+
|
530
|
+
Options can be enums (i.e. have known values).
|
531
|
+
|
532
|
+
If an unknown values is given by the user the parser will reject the option,
|
533
|
+
and print the help output for this command.
|
534
|
+
|
535
|
+
For example:
|
536
|
+
|
537
|
+
```ruby
|
538
|
+
class Add < Cl::Cmd
|
539
|
+
opt '--to GROUP', enum: %w(one two)
|
540
|
+
|
541
|
+
def run
|
542
|
+
p to
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
546
|
+
Cl.new('owners').run(%w(add --to one))
|
547
|
+
|
548
|
+
# Output:
|
549
|
+
#
|
550
|
+
# "one"
|
551
|
+
|
552
|
+
Cl.new('owners').run(%w(add --to unknown))
|
553
|
+
|
554
|
+
# Unknown value: to=unknown (known values: one, two)
|
555
|
+
#
|
556
|
+
# Usage: enum add [options]
|
557
|
+
#
|
558
|
+
# Options: ...
|
559
|
+
|
560
|
+
```
|
561
|
+
|
562
|
+
#### Example
|
563
|
+
|
564
|
+
Options can have examples that will be printed in the help output.
|
565
|
+
|
566
|
+
```ruby
|
567
|
+
class Add < Cl::Cmd
|
568
|
+
opt '--to GROUP', example: 'group-one'
|
569
|
+
end
|
570
|
+
|
571
|
+
Cl.new('owners').run(%w(add --help))
|
572
|
+
|
573
|
+
# Usage: example add [options]
|
574
|
+
#
|
575
|
+
# Options:
|
576
|
+
#
|
577
|
+
# --to GROUP type: string, e.g.: group-one
|
578
|
+
# --help Get help on this command
|
579
|
+
|
580
|
+
```
|
581
|
+
|
582
|
+
#### Format
|
583
|
+
|
584
|
+
Options can have a required format.
|
585
|
+
|
586
|
+
If a value is given by the user that does not match the format then the parser
|
587
|
+
will reject the option, and print the help output for this command.
|
588
|
+
|
589
|
+
For example:
|
590
|
+
|
591
|
+
```ruby
|
592
|
+
class Add < Cl::Cmd
|
593
|
+
opt '--to GROUP', format: /^\w+$/
|
594
|
+
|
595
|
+
def run
|
596
|
+
p to
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
Cl.new('owners').run(%w(add --to one))
|
601
|
+
|
602
|
+
# Output:
|
603
|
+
#
|
604
|
+
# "one"
|
605
|
+
|
606
|
+
Cl.new('owners').run(['add', '--to', 'does not match!'])
|
607
|
+
|
608
|
+
Invalid format: to (format: /^\w+$/)
|
609
|
+
|
610
|
+
Usage: format add [options]
|
611
|
+
|
612
|
+
Options:
|
613
|
+
|
614
|
+
--to GROUP type: string, format: /^\w+$/
|
615
|
+
--help Get help on this command
|
616
|
+
|
617
|
+
```
|
618
|
+
|
619
|
+
#### Internal
|
620
|
+
|
621
|
+
Options can be declared to be internal, hiding the option from the help output.
|
622
|
+
|
623
|
+
For example:
|
624
|
+
|
625
|
+
```ruby
|
626
|
+
class Add < Cl::Cmd
|
627
|
+
opt '--to GROUP'
|
628
|
+
opt '--hidden', internal: true
|
629
|
+
end
|
630
|
+
|
631
|
+
Cl.new('owners').run(%w(add --help))
|
632
|
+
|
633
|
+
# Usage: example add [options]
|
634
|
+
#
|
635
|
+
# Options:
|
636
|
+
#
|
637
|
+
# --to GROUP type: string, e.g.: group-one
|
638
|
+
# --help Get help on this command
|
639
|
+
|
640
|
+
```
|
641
|
+
|
642
|
+
#### Min and Max
|
643
|
+
|
644
|
+
Options can have mininum and/or maximum values.
|
645
|
+
|
646
|
+
If a value is given by the user that does not match the required min and/or max
|
647
|
+
values then the parser will reject the option, and print the help output for
|
648
|
+
this command.
|
649
|
+
|
650
|
+
For example:
|
651
|
+
|
652
|
+
```ruby
|
653
|
+
class Add < Cl::Cmd
|
654
|
+
opt '--retries COUNT', type: :integer, min: 1, max: 5
|
655
|
+
|
656
|
+
def run
|
657
|
+
p retries
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
661
|
+
Cl.new('owners').run(%w(add --retries 1))
|
662
|
+
|
663
|
+
# Output:
|
664
|
+
#
|
665
|
+
# 1
|
666
|
+
|
667
|
+
Cl.new('owners').run(%w(add --retries 10))
|
668
|
+
|
669
|
+
# Out of range: retries (max: 5)
|
670
|
+
#
|
671
|
+
# Usage: max add [options]
|
672
|
+
#
|
673
|
+
# Options:
|
674
|
+
#
|
675
|
+
# --retries COUNT type: integer, min: 1, max: 5
|
676
|
+
# --help Get help on this command
|
677
|
+
|
678
|
+
```
|
679
|
+
|
680
|
+
#### See Also
|
681
|
+
|
682
|
+
Options can refer to documentation using the `see` option. This will be printed
|
683
|
+
in the help output.
|
684
|
+
|
685
|
+
For example:
|
686
|
+
|
687
|
+
```ruby
|
688
|
+
class Add < Cl::Cmd
|
689
|
+
opt '--to GROUP', see: 'https://docs.io/cli/owners/add'
|
690
|
+
|
691
|
+
def run
|
692
|
+
p retries
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
Cl.new('owners').run(%w(add --help))
|
697
|
+
|
698
|
+
# Usage: see add [options]
|
699
|
+
#
|
700
|
+
# Options:
|
701
|
+
#
|
702
|
+
# --to GROUP type: string, see: https://docs.io/cli/owners/add
|
703
|
+
# --help Get help on this command
|
704
|
+
|
705
|
+
```
|
706
|
+
|
707
|
+
#### Types
|
708
|
+
|
709
|
+
Options can have a type. Known types are: `:array`, `:string`, `:integer`,
|
710
|
+
`:float`, `:boolean`.
|
711
|
+
|
712
|
+
The type `:array` allows an option to be given multiple times, and makes sure
|
713
|
+
the value accessible on the `Cmd` instance is a Ruby Array. (This currently
|
714
|
+
only supports arrays of strings).
|
715
|
+
|
716
|
+
```ruby
|
717
|
+
class Add < Cl::Cmd
|
718
|
+
opt '--to GROUP', type: :array
|
719
|
+
|
720
|
+
def run
|
721
|
+
p to
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
Cl.new('owners').run(%w(add --to one --to two))
|
726
|
+
|
727
|
+
# Output:
|
728
|
+
#
|
729
|
+
# ["one", "two"]
|
730
|
+
|
731
|
+
```
|
732
|
+
|
733
|
+
Other types cast the given value to the expected Ruby type.
|
734
|
+
|
735
|
+
```ruby
|
736
|
+
class Add < Cl::Cmd
|
737
|
+
opt '--active BOOL', type: :boolean
|
738
|
+
opt '--retries INT', type: :integer
|
739
|
+
opt '--sleep FLOAT', type: :float
|
740
|
+
|
741
|
+
def run
|
742
|
+
p active.class, retries.class, sleep.class
|
743
|
+
end
|
744
|
+
end
|
745
|
+
|
746
|
+
Cl.new('owners').run(%w(add --active yes --retries 1 --sleep 0.1))
|
747
|
+
|
748
|
+
# Output:
|
749
|
+
#
|
750
|
+
# TrueClass
|
751
|
+
# Integer
|
752
|
+
# Float
|
753
|
+
|
754
|
+
```
|
755
|
+
|
756
|
+
#### Required Options
|
757
|
+
|
758
|
+
There are three ways options can be required:
|
759
|
+
|
760
|
+
* using `required: true` on the option: the option itself is required to be given
|
761
|
+
* using `requires: :other`on the option: the option requires another option to be given
|
762
|
+
* using `required :one, [:two, :three]` on the class: either `one` or both `two` and `three` must be given
|
763
|
+
|
764
|
+
For example, this simply requires the option `--to`:
|
765
|
+
|
766
|
+
```ruby
|
767
|
+
class Add < Cl::Cmd
|
768
|
+
opt '--to GROUP', required: true
|
769
|
+
|
770
|
+
def run
|
771
|
+
p to
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
775
|
+
Cl.new('owners').run(%w(add --to one))
|
776
|
+
|
777
|
+
# Output:
|
778
|
+
#
|
779
|
+
# "one"
|
780
|
+
|
781
|
+
Cl.new('owners').run(%w(add))
|
782
|
+
|
783
|
+
# Missing required option: to
|
784
|
+
#
|
785
|
+
# Usage: required add [options]
|
786
|
+
#
|
787
|
+
# Options:
|
788
|
+
#
|
789
|
+
# --to GROUP type: string, required: true
|
790
|
+
# --help Get help on this command
|
791
|
+
|
792
|
+
```
|
793
|
+
|
794
|
+
This will make the option `--retries` depend on the option `--to`:
|
795
|
+
|
796
|
+
```ruby
|
797
|
+
class Add < Cl::Cmd
|
798
|
+
opt '--to GROUP'
|
799
|
+
opt '--retries INT', requires: :to
|
800
|
+
|
801
|
+
def run
|
802
|
+
p to, retries
|
803
|
+
end
|
804
|
+
end
|
805
|
+
|
806
|
+
Cl.new('owners').run(%w(add --to one --retries 1))
|
807
|
+
|
808
|
+
# Output:
|
809
|
+
#
|
810
|
+
# "one"
|
811
|
+
# 1
|
812
|
+
|
813
|
+
Cl.new('owners').run(%w(add --retries 1))
|
814
|
+
|
815
|
+
# Missing option: to (required by retries)
|
816
|
+
#
|
817
|
+
# Usage: requires add [options]
|
818
|
+
#
|
819
|
+
# Options:
|
820
|
+
#
|
821
|
+
# --to GROUP type: string
|
822
|
+
# --retries INT type: string, requires: to
|
823
|
+
# --help Get help on this command
|
824
|
+
|
825
|
+
```
|
826
|
+
|
827
|
+
This requires either the option `--api_key` or both options `--username` and
|
828
|
+
`--password` to be given:
|
829
|
+
|
830
|
+
```ruby
|
831
|
+
class Add < Cl::Cmd
|
832
|
+
# read DNF, i.e. "apikey OR username AND password
|
833
|
+
required :api_key, [:username, :password]
|
834
|
+
|
835
|
+
opt '--api_key KEY'
|
836
|
+
opt '--username NAME'
|
837
|
+
opt '--password PASS'
|
838
|
+
|
839
|
+
def run
|
840
|
+
p to, retries
|
841
|
+
end
|
842
|
+
end
|
843
|
+
|
844
|
+
Cl.new('owners').run(%w(add --to one --retries 1))
|
845
|
+
|
846
|
+
# Output:
|
847
|
+
#
|
848
|
+
# "one"
|
849
|
+
# 1
|
850
|
+
|
851
|
+
Cl.new('owners').run(%w(add --retries 1))
|
852
|
+
|
853
|
+
# Missing option: to (required by retries)
|
854
|
+
#
|
855
|
+
# Usage: requires add [options]
|
856
|
+
#
|
857
|
+
# Options:
|
858
|
+
#
|
859
|
+
# --to GROUP type: string
|
860
|
+
# --retries INT type: string, requires: to
|
861
|
+
# --help Get help on this command
|
862
|
+
|
863
|
+
```
|
864
|
+
|
865
|
+
### Config Files
|
866
|
+
|
867
|
+
Cl automatically reads config files that match the given executable name (inspired by
|
868
|
+
[gem-release](https://github.com/svenfuchs/gem-release)), stored either in the
|
869
|
+
user directory or the current working directory.
|
870
|
+
|
871
|
+
For example:
|
872
|
+
|
873
|
+
```ruby
|
874
|
+
module Api
|
875
|
+
class Login < Cl::Cmd
|
876
|
+
opt '--username USER'
|
877
|
+
opt '--password PASS'
|
878
|
+
end
|
879
|
+
end
|
880
|
+
|
881
|
+
# bin/api
|
882
|
+
CL.new('api').run(ARGV)
|
883
|
+
|
884
|
+
# ~/api.yml
|
885
|
+
login:
|
886
|
+
username: 'someone'
|
887
|
+
password: 'password'
|
888
|
+
|
889
|
+
# ./api.yml
|
890
|
+
login:
|
891
|
+
username: 'someone else'
|
892
|
+
```
|
893
|
+
|
894
|
+
then running
|
895
|
+
|
896
|
+
```
|
897
|
+
$ bin/api login
|
898
|
+
```
|
899
|
+
|
900
|
+
instantiates `Api::Login`, and passes the hash
|
901
|
+
|
902
|
+
```ruby
|
903
|
+
{ username: 'someone else', password: 'password' }
|
904
|
+
```
|
905
|
+
|
906
|
+
as `opts`.
|
907
|
+
|
908
|
+
Options passed by the user take precedence over defaults defined in config
|
909
|
+
files.
|
910
|
+
|
911
|
+
### Environment Variables
|
912
|
+
|
913
|
+
Cl automatically defaults options to environment variables that are prefixed
|
914
|
+
with the given executable name (inspired by [gem-release](https://github.com/svenfuchs/gem-release)).
|
915
|
+
|
916
|
+
```ruby
|
917
|
+
module Api
|
918
|
+
class Login < Cl::Cmd
|
919
|
+
opt '--username USER'
|
920
|
+
opt '--password PASS'
|
921
|
+
end
|
922
|
+
end
|
923
|
+
|
924
|
+
# bin/api
|
925
|
+
CL.new('api').run(ARGV)
|
926
|
+
```
|
927
|
+
|
928
|
+
then running
|
929
|
+
|
930
|
+
```
|
931
|
+
$ API_USERNAME=someone API_PASSWORD=password bin/api login
|
932
|
+
```
|
933
|
+
|
934
|
+
instantiates `Api::Login`, and passes the hash
|
935
|
+
|
936
|
+
```ruby
|
937
|
+
{ username: 'someone', password: 'password' }
|
938
|
+
```
|
939
|
+
|
940
|
+
Options passed by the user take precedence over defaults given as environment
|
941
|
+
variables, and environment variables take precedence over defaults defined in
|
942
|
+
config files.
|