cl 0.1.23 → 0.1.24

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e48bfc8c20e185f62bb0b729a9bbbb27a24f470
4
- data.tar.gz: a8c88e60d22e9ee3d4961301b6322d0b2961a3ab
3
+ metadata.gz: 72952e2db91c199b725e62742a795797062e4ce6
4
+ data.tar.gz: 44492b50481c1622bc45436f611ae1a4211169a6
5
5
  SHA512:
6
- metadata.gz: f147afa28916b0b348a840ad74da1373f418756160128bc2e48401abaa003fc431c803df74f9b1a924b4cb8fbf529073713efe13cac2af37b09ae4a92a9355ef
7
- data.tar.gz: 87d62debde99d4d840dad4811c828868bb3feeea6aaa84f4eda65fd5a26f565beb2d18e3b149e5a739eae8299b4b7657d1582f14767dccdeb7f9dabbf93522f3
6
+ metadata.gz: 7b4a5998249ae7521747203fc2e7b3f21f66bcbef86568d025113b4e808faa84f4f7f7b2aa7401eb9ca1e190f25977bf0c5a5856a5b128181e551584a021e665
7
+ data.tar.gz: 11d40ccbca05ab8dc596dca41d7610992a09745809fb19fdb1ba3c17828a1bf49a0bf1f4e935e5776b6d5a541980b4fe482f82b228d9afd08c760f3bc76be16e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cl (0.1.22)
4
+ cl (0.1.23)
5
5
  regstry (~> 1.0.3)
6
6
 
7
7
  GEM
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
- * [Description, Summary, Examples](#description-summary-examples)
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
- ## Description, Summary, Examples
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
- ./bin/owners add user --to admins
252
+ owners add user --to admins
238
253
 
239
254
  Adding a several users at once:
240
255
 
241
- ./bin/owners add one two three --to admins
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
@@ -7,7 +7,7 @@ class Cl
7
7
  end
8
8
 
9
9
  def help
10
- args.any? ? Cmd.new(cmd).format : Cmds.new(cmds).format
10
+ args.any? ? Cmd.new(ctx, cmd).format : Cmds.new(ctx, cmds).format
11
11
  end
12
12
 
13
13
  private
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 "#{$0.split('/').last} help COMMAND [SUBCOMMAND]" for more details:\n)
6
+ class Cmds < Struct.new(:ctx, :cmds)
7
+ HEAD = %(Type "%s help COMMAND [SUBCOMMAND]" for more details:\n)
8
8
 
9
- attr_reader :cmds
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 format
16
- [HEAD, Table.new(list).format].join("\n")
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 = [$0.split('/').last, name]
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
@@ -1,3 +1,3 @@
1
1
  class Cl
2
- VERSION = '0.1.23'
2
+ VERSION = '0.1.24'
3
3
  end
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.23
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-24 00:00:00.000000000 Z
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