cl 0.1.23 → 0.1.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +99 -4
- data/examples/readme/abstract +25 -0
- data/examples/readme/note +17 -0
- data/examples/readme/secret +21 -0
- data/lib/cl.rb +2 -2
- data/lib/cl/ctx.rb +2 -1
- data/lib/cl/help.rb +1 -1
- data/lib/cl/help/cmd.rb +2 -8
- data/lib/cl/help/cmds.rb +7 -9
- data/lib/cl/help/usage.rb +6 -8
- data/lib/cl/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72952e2db91c199b725e62742a795797062e4ce6
|
4
|
+
data.tar.gz: 44492b50481c1622bc45436f611ae1a4211169a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b4a5998249ae7521747203fc2e7b3f21f66bcbef86568d025113b4e808faa84f4f7f7b2aa7401eb9ca1e190f25977bf0c5a5856a5b128181e551584a021e665
|
7
|
+
data.tar.gz: 11d40ccbca05ab8dc596dca41d7610992a09745809fb19fdb1ba3c17828a1bf49a0bf1f4e935e5776b6d5a541980b4fe482f82b228d9afd08c760f3bc76be16e
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -18,7 +18,9 @@ Further documentation is available on [rubydoc.info](https://www.rubydoc.info/gi
|
|
18
18
|
* [Command Registry](#command-registry)
|
19
19
|
* [Runners](#runners)
|
20
20
|
* [Command DSL](#command-dsl)
|
21
|
-
* [
|
21
|
+
* [Commands](#commands)
|
22
|
+
* [Description, Summary, Examples](#description-summary-examples)
|
23
|
+
* [Abstract](#abstract)
|
22
24
|
* [Arguments](#arguments)
|
23
25
|
* [Types](#types)
|
24
26
|
* [Splat](#splat)
|
@@ -32,6 +34,8 @@ Further documentation is available on [rubydoc.info](https://www.rubydoc.info/gi
|
|
32
34
|
* [Format](#format)
|
33
35
|
* [Internal](#internal)
|
34
36
|
* [Min and Max](#min-and-max)
|
37
|
+
* [Note](#note)
|
38
|
+
* [Secret](#secret)
|
35
39
|
* [See Also](#see-also)
|
36
40
|
* [Types](#types)
|
37
41
|
* [Required Options](#required-options)
|
@@ -135,6 +139,13 @@ module One
|
|
135
139
|
end
|
136
140
|
```
|
137
141
|
|
142
|
+
Be aware that if you derive a common base command class from `Cl::Cmd` it
|
143
|
+
should be declared as `abstract` in order to unregister itself from the command
|
144
|
+
registry.
|
145
|
+
|
146
|
+
This will prevent the runner to consider it as a runnable command, and omit it
|
147
|
+
from help output. See [abstract](#abstract) for details.
|
148
|
+
|
138
149
|
### Runners
|
139
150
|
|
140
151
|
Runners lookup the command to execute from the registry, by checking the
|
@@ -217,7 +228,11 @@ See the example [rakeish](blob/master/examples/rakeish) for more details.
|
|
217
228
|
|
218
229
|
The DSL is defined on the class body.
|
219
230
|
|
220
|
-
|
231
|
+
### Commands
|
232
|
+
|
233
|
+
Commands are classes that are derived from the base class `Cl::Cmd`.
|
234
|
+
|
235
|
+
#### Description, Summary, Examples
|
221
236
|
|
222
237
|
The description, summary, and examples are used in the help output.
|
223
238
|
|
@@ -234,16 +249,48 @@ module Owners
|
|
234
249
|
examples <<~str
|
235
250
|
Adding a single user to the group admins:
|
236
251
|
|
237
|
-
|
252
|
+
owners add user --to admins
|
238
253
|
|
239
254
|
Adding a several users at once:
|
240
255
|
|
241
|
-
|
256
|
+
owners add one two three --to admins
|
242
257
|
str
|
243
258
|
end
|
244
259
|
end
|
245
260
|
```
|
246
261
|
|
262
|
+
#### Abstract
|
263
|
+
|
264
|
+
Command base classes can be declared abstract in order to prevent them from
|
265
|
+
being identified as a runnable command and to omit them from help output.
|
266
|
+
|
267
|
+
This is only relevant if a command base class is registered. See [Command
|
268
|
+
Registry](#command-registry) for details.
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
class Base < Cl::Cmd
|
272
|
+
abstract
|
273
|
+
end
|
274
|
+
|
275
|
+
class Add < Base
|
276
|
+
end
|
277
|
+
|
278
|
+
Cl.new('owners').help
|
279
|
+
|
280
|
+
# Output:
|
281
|
+
#
|
282
|
+
# Type "owners help COMMAND [SUBCOMMAND]" for more details:
|
283
|
+
#
|
284
|
+
# owners add [options]
|
285
|
+
|
286
|
+
Cl.new('owners').run(%w(base))
|
287
|
+
|
288
|
+
# Error output:
|
289
|
+
#
|
290
|
+
# Unknown command: base
|
291
|
+
|
292
|
+
```
|
293
|
+
|
247
294
|
### Arguments
|
248
295
|
|
249
296
|
Arguments can be declared like so:
|
@@ -677,6 +724,54 @@ Cl.new('owners').run(%w(add --retries 10))
|
|
677
724
|
|
678
725
|
```
|
679
726
|
|
727
|
+
#### Note
|
728
|
+
|
729
|
+
Options can have a note that will be printed in the help output.
|
730
|
+
|
731
|
+
```ruby
|
732
|
+
class Add < Cl::Cmd
|
733
|
+
opt '--to GROUP', note: 'needs to be a group'
|
734
|
+
end
|
735
|
+
|
736
|
+
Cl.new('owners').run(%w(add --help))
|
737
|
+
|
738
|
+
# Usage: owners add [options]
|
739
|
+
#
|
740
|
+
# Options:
|
741
|
+
#
|
742
|
+
# --to GROUP type: string, note: needs to be a group
|
743
|
+
# --help Get help on this command
|
744
|
+
|
745
|
+
```
|
746
|
+
|
747
|
+
#### Secret
|
748
|
+
|
749
|
+
Options can be declared as secret.
|
750
|
+
|
751
|
+
This makes it possible for client code to inspect if a given option is secret.
|
752
|
+
Also, option values given by the user will be tainted, so client code can rely
|
753
|
+
on this in order to, for example, obfuscate values from log output.
|
754
|
+
|
755
|
+
```ruby
|
756
|
+
class Add < Cl::Cmd
|
757
|
+
opt '--to GROUP'
|
758
|
+
opt '--password PASS', secret: true
|
759
|
+
|
760
|
+
def run
|
761
|
+
puts [:secret?, self.class.opts[:password].secret?].join(' ')
|
762
|
+
puts [:tainted?, password.tainted?].join(' ')
|
763
|
+
end
|
764
|
+
end
|
765
|
+
|
766
|
+
Cl.new('owners').run(%w(add --password pass))
|
767
|
+
|
768
|
+
# Output:
|
769
|
+
#
|
770
|
+
# secret? true
|
771
|
+
# tainted? true
|
772
|
+
|
773
|
+
```
|
774
|
+
|
680
775
|
#### See Also
|
681
776
|
|
682
777
|
Options can refer to documentation using the `see` option. This will be printed
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.expand_path('lib')
|
3
|
+
|
4
|
+
require 'cl'
|
5
|
+
|
6
|
+
class Base < Cl::Cmd
|
7
|
+
abstract
|
8
|
+
end
|
9
|
+
|
10
|
+
class Add < Base
|
11
|
+
end
|
12
|
+
|
13
|
+
Cl.new('owners').help
|
14
|
+
|
15
|
+
# Output:
|
16
|
+
#
|
17
|
+
# Type "owners help COMMAND [SUBCOMMAND]" for more details:
|
18
|
+
#
|
19
|
+
# owners add [options]
|
20
|
+
|
21
|
+
Cl.new('owners').run(%w(base))
|
22
|
+
|
23
|
+
# Error output:
|
24
|
+
#
|
25
|
+
# Unknown command: base
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.expand_path('lib')
|
3
|
+
|
4
|
+
require 'cl'
|
5
|
+
|
6
|
+
class Add < Cl::Cmd
|
7
|
+
opt '--to GROUP', note: 'needs to be a group'
|
8
|
+
end
|
9
|
+
|
10
|
+
Cl.new('owners').run(%w(add --help))
|
11
|
+
|
12
|
+
# Usage: owners add [options]
|
13
|
+
#
|
14
|
+
# Options:
|
15
|
+
#
|
16
|
+
# --to GROUP type: string, note: needs to be a group
|
17
|
+
# --help Get help on this command
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.expand_path('lib')
|
3
|
+
|
4
|
+
require 'cl'
|
5
|
+
|
6
|
+
class Add < Cl::Cmd
|
7
|
+
opt '--to GROUP'
|
8
|
+
opt '--password PASS', secret: true
|
9
|
+
|
10
|
+
def run
|
11
|
+
puts [:secret?, self.class.opts[:password].secret?].join(' ')
|
12
|
+
puts [:tainted?, password.tainted?].join(' ')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Cl.new('owners').run(%w(add --password pass))
|
17
|
+
|
18
|
+
# Output:
|
19
|
+
#
|
20
|
+
# secret? true
|
21
|
+
# tainted? true
|
data/lib/cl.rb
CHANGED
@@ -8,14 +8,14 @@ class Cl
|
|
8
8
|
|
9
9
|
# @overload initialize(ctx, name, opts)
|
10
10
|
# @param ctx [Cl::Ctx] the current execution context (optional)
|
11
|
-
# @param name [String] the program (executable) name (optional, defaults to $0)
|
11
|
+
# @param name [String] the program (executable) name (optional, defaults to the last segment of $0)
|
12
12
|
# @param opts [Hash] options (optional)
|
13
13
|
# @option opts [Cl::Runner] :runner registry key for a runner (optional, defaults to :default)
|
14
14
|
# @option opts [Cl::Ui] :ui the ui for handling user interaction
|
15
15
|
def initialize(*args)
|
16
16
|
ctx = args.shift if args.first.is_a?(Ctx)
|
17
17
|
@opts = args.last.is_a?(Hash) ? args.pop : {}
|
18
|
-
@name = args.shift || $0
|
18
|
+
@name = args.shift || $0.split('/').last
|
19
19
|
@ctx = ctx || Ctx.new(name, opts)
|
20
20
|
end
|
21
21
|
|
data/lib/cl/ctx.rb
CHANGED
@@ -9,11 +9,12 @@ class Cl
|
|
9
9
|
def_delegators :ui, :puts, :stdout, :announce, :info, :notice, :warn,
|
10
10
|
:error, :success, :cmd
|
11
11
|
|
12
|
-
attr_accessor :config, :ui
|
12
|
+
attr_accessor :config, :name, :ui
|
13
13
|
|
14
14
|
def initialize(name, opts = {})
|
15
15
|
@config = Config.new(name).to_h
|
16
16
|
@ui = opts[:ui] || Ui.new(self, opts)
|
17
|
+
@name = name
|
17
18
|
end
|
18
19
|
|
19
20
|
def abort(error, *strs)
|
data/lib/cl/help.rb
CHANGED
data/lib/cl/help/cmd.rb
CHANGED
@@ -3,21 +3,15 @@ require 'cl/help/usage'
|
|
3
3
|
|
4
4
|
class Cl
|
5
5
|
class Help
|
6
|
-
class Cmd
|
6
|
+
class Cmd < Struct.new(:ctx, :cmd)
|
7
7
|
include Regex
|
8
8
|
|
9
|
-
attr_reader :cmd
|
10
|
-
|
11
|
-
def initialize(cmd)
|
12
|
-
@cmd = cmd
|
13
|
-
end
|
14
|
-
|
15
9
|
def format
|
16
10
|
[usage, summary, description, arguments, options, common, examples].compact.join("\n\n")
|
17
11
|
end
|
18
12
|
|
19
13
|
def usage
|
20
|
-
"Usage: #{Usage.new(cmd).format}"
|
14
|
+
"Usage: #{Usage.new(ctx, cmd).format}"
|
21
15
|
end
|
22
16
|
|
23
17
|
def summary
|
data/lib/cl/help/cmds.rb
CHANGED
@@ -3,17 +3,15 @@ require 'cl/help/usage'
|
|
3
3
|
|
4
4
|
class Cl
|
5
5
|
class Help
|
6
|
-
class Cmds
|
7
|
-
HEAD = %(Type "
|
6
|
+
class Cmds < Struct.new(:ctx, :cmds)
|
7
|
+
HEAD = %(Type "%s help COMMAND [SUBCOMMAND]" for more details:\n)
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(cmds)
|
12
|
-
@cmds = cmds
|
9
|
+
def format
|
10
|
+
[head, Table.new(list).format].join("\n")
|
13
11
|
end
|
14
12
|
|
15
|
-
def
|
16
|
-
|
13
|
+
def head
|
14
|
+
HEAD % ctx.name
|
17
15
|
end
|
18
16
|
|
19
17
|
def list
|
@@ -21,7 +19,7 @@ class Cl
|
|
21
19
|
end
|
22
20
|
|
23
21
|
def format_cmd(cmd)
|
24
|
-
["#{Usage.new(cmd).format}", cmd.summary]
|
22
|
+
["#{Usage.new(ctx, cmd).format}", cmd.summary]
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
data/lib/cl/help/usage.rb
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
class Cl
|
2
2
|
class Help
|
3
|
-
class Usage
|
4
|
-
attr_reader :cmd
|
5
|
-
|
6
|
-
def initialize(cmd)
|
7
|
-
@cmd = cmd
|
8
|
-
end
|
9
|
-
|
3
|
+
class Usage < Struct.new(:ctx, :cmd)
|
10
4
|
def format
|
11
|
-
usage = [
|
5
|
+
usage = [executable, name]
|
12
6
|
usage += cmd.args.map(&:to_s) # { |arg| "[#{arg}]" }
|
13
7
|
usage << '[options]' if opts?
|
14
8
|
usage.join(' ')
|
15
9
|
end
|
16
10
|
|
11
|
+
def executable
|
12
|
+
ctx.name
|
13
|
+
end
|
14
|
+
|
17
15
|
def name
|
18
16
|
cmd.registry_key.to_s.gsub(':', ' ')
|
19
17
|
end
|
data/lib/cl/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Fuchs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: regstry
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- examples/gem
|
44
44
|
- examples/heroku
|
45
45
|
- examples/rakeish
|
46
|
+
- examples/readme/abstract
|
46
47
|
- examples/readme/alias
|
47
48
|
- examples/readme/arg
|
48
49
|
- examples/readme/arg_array
|
@@ -57,12 +58,14 @@ files:
|
|
57
58
|
- examples/readme/example
|
58
59
|
- examples/readme/format
|
59
60
|
- examples/readme/internal
|
61
|
+
- examples/readme/note
|
60
62
|
- examples/readme/opts
|
61
63
|
- examples/readme/opts_block
|
62
64
|
- examples/readme/range
|
63
65
|
- examples/readme/required
|
64
66
|
- examples/readme/requireds
|
65
67
|
- examples/readme/requires
|
68
|
+
- examples/readme/secret
|
66
69
|
- examples/readme/see
|
67
70
|
- examples/readme/type
|
68
71
|
- lib/cl.rb
|