cl 0.0.4 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9857c406109f06a92986bef6a3290f5b6647c17f
4
- data.tar.gz: a861829fbef67c227006437d42a3848380c2b084
2
+ SHA256:
3
+ metadata.gz: bb6a93f33e5cae5c1ec0b0bba6b1d3981b853ee6e5a4fde75d3b5c4df7176162
4
+ data.tar.gz: 0a247824d773fd1251b19e353e629780cb36b6b4f1ef3553e8ab2752ffdf9ad4
5
5
  SHA512:
6
- metadata.gz: e5e446a970a5e7f180df5ee0875e25443c17f0a6599c6103440782a02cc0bb8a8380582deb2fbdaed87eee2edbf9a98a339a455f09101f6bd963a7f02a39b78e
7
- data.tar.gz: d98b7935d11f18eefb33ae70c93cb12be5fb7c1a821877460a1b4cd4adaee6531b4c12991834aafe1c745ef0a0b8c4a11fa1be317b35393b5b81dc7b345ad236
6
+ metadata.gz: f69f9e9840312da35a16d7d27a5705e0cf3d4a8364aaff4e7f90757bad2754e8a47ce6a20779e88a16269fb2b6d3ada9215397e84dd9988eba74afc2b44373c7
7
+ data.tar.gz: ea7533eb5588ddedee0343dbef28a7d0bfb9b2a7bab4e9ca2e427e2ce198bc857e3ca5c55526471f657bea485dee454235939b82dd30b7c718c3c2ea0d757210
data/CHANGELOG.md ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (unreleased)
4
+
5
+ ### Added
6
+
7
+ * Add config, reading from env vars and yml files (inspired by gem-release)
8
+ * Add `abstract` in order to signal a cmd is a base class that is not meant to be executed
9
+ * Add `opt '--path', type: :array` for options that can be given multiple times
10
+ * Add `opt '--one STR', default: 'one'`
11
+ * Add `opt '--one STR', requires :two` or `[:two, :three]` for options that depend on other options
12
+ * Add `opt '--one', alias: :other`
13
+ * Add `opt '--one', deprecated: true`, and `cmd.deprected_opts`, so clients can look up which deprecated options were used
14
+ * Add `opt '--one', alias: :other, deprecated: :other`, so that `cmd.deprecated_opts` returns the alias name if it was used
15
+ * Add `opt '--int', max: 10, type: :integer`
16
+ * Add `opt '--one', format: /.+/`
17
+ * Add `opt '--one', enum: ['one', 'two']`
18
+ * Add `required :one, [:two, :three]` (DNF, i.e: either :one or both :two and :three must be given)
19
+
20
+ ### Changed
21
+
22
+ * Much improved help output, modeled after rubygems' help output
23
+ * Cl is now a class
24
+ * Use the regstry gem, remove the local Registry implementation
25
+ * If a flag (boolean option) has a default `true` automatically add `[no-]` to
26
+ it, allowing to opt out
27
+
28
+ ### Removed
29
+
30
+ * Removed cmd.defaults, options have default: [value] now
31
+
32
+ ## 0.0.4 (2017-08-02)
33
+
34
+ * Ancient history
35
+
36
+ ## 0.0.3 (2017-08-02)
37
+
38
+ * Ancient history
39
+
40
+ ## 0.0.2 (2017-04-09)
41
+
42
+ * Ancient history
43
+
44
+ ## 0.0.1 (2017-04-08)
45
+
46
+ * Ancient history
47
+
data/Gemfile CHANGED
@@ -1,5 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gemspec
4
+
3
5
  group :test do
6
+ gem 'memfs'
4
7
  gem 'rspec'
5
8
  end
data/Gemfile.lock CHANGED
@@ -1,26 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cl (0.0.4)
5
+ regstry (~> 1.0.3)
6
+
1
7
  GEM
2
8
  remote: https://rubygems.org/
3
9
  specs:
4
10
  diff-lcs (1.3)
5
- rspec (3.5.0)
6
- rspec-core (~> 3.5.0)
7
- rspec-expectations (~> 3.5.0)
8
- rspec-mocks (~> 3.5.0)
9
- rspec-core (3.5.4)
10
- rspec-support (~> 3.5.0)
11
- rspec-expectations (3.5.0)
11
+ memfs (1.0.0)
12
+ regstry (1.0.6)
13
+ rspec (3.8.0)
14
+ rspec-core (~> 3.8.0)
15
+ rspec-expectations (~> 3.8.0)
16
+ rspec-mocks (~> 3.8.0)
17
+ rspec-core (3.8.0)
18
+ rspec-support (~> 3.8.0)
19
+ rspec-expectations (3.8.3)
12
20
  diff-lcs (>= 1.2.0, < 2.0)
13
- rspec-support (~> 3.5.0)
14
- rspec-mocks (3.5.0)
21
+ rspec-support (~> 3.8.0)
22
+ rspec-mocks (3.8.0)
15
23
  diff-lcs (>= 1.2.0, < 2.0)
16
- rspec-support (~> 3.5.0)
17
- rspec-support (3.5.0)
24
+ rspec-support (~> 3.8.0)
25
+ rspec-support (3.8.0)
18
26
 
19
27
  PLATFORMS
20
28
  ruby
21
29
 
22
30
  DEPENDENCIES
31
+ cl!
32
+ memfs
23
33
  rspec
24
34
 
25
35
  BUNDLED WITH
26
- 1.14.6
36
+ 1.17.2
data/NOTES.md CHANGED
@@ -1,25 +1,3 @@
1
- Usage: gem release [gemspec] [options]
1
+ - properly catch errors, see examples/cast etc
2
+ - add conditional required: ->(opts) { opts[:key].nil? }
2
3
 
3
- Options:
4
- -t, --[no-]tag Create a git tag and push it to the destination (defaults to false)
5
- -d, --destination DESTINATION Destination git repository (defaults to origin)
6
- -k, --key KEY Use the given API key from ~/.gem/credentials (not set by default)
7
- --host HOST Push to a gemcutter-compatible host other than rubygems.org (not set by default)
8
-
9
-
10
- Common Options:
11
- -h, --help Get help on this command
12
- -V, --[no-]verbose Set the verbose level of output
13
- -q, --quiet Silence command progress meter
14
- --silent Silence rubygems output
15
- --config-file FILE Use this config file instead of default
16
- --backtrace Show stack backtrace on errors
17
- --debug Turn on Ruby debugging
18
- --norc Avoid loading any .gemrc file
19
-
20
-
21
- Arguments:
22
- gemspec - optional gemspec file name, will use the first *.gemspec if not specified
23
-
24
- Summary:
25
- Build gem from a gemspec and push to rubygems.org
data/README.md CHANGED
@@ -14,7 +14,7 @@ module Owners
14
14
 
15
15
  args :owners
16
16
 
17
- on '-t', '--to TO', 'An owner in an existing group' do |value|
17
+ opt '-t', '--to TO', 'An owner in an existing group' do |value|
18
18
  opts[:to] = value
19
19
  end
20
20
  end
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('lib')
3
+
4
+ require 'cl'
5
+
6
+ class Bool < Cl::Cmd
7
+ arg :bool, type: :bool
8
+
9
+ def run
10
+ [registry_key, bool: bool]
11
+ end
12
+ end
13
+
14
+ class Types < Cl::Cmd
15
+ arg :a, type: :bool
16
+ arg :b, type: :int
17
+ arg :c, type: :float
18
+ arg :d
19
+
20
+ def run
21
+ [registry_key, a: a, b: b, c: c, d: d]
22
+ end
23
+ end
24
+
25
+ def output(cmd, args)
26
+ args = args.map { |key, value| "#{key}=#{value.inspect}" }.join(' ')
27
+ puts "Called #{cmd} with #{args}\n\n"
28
+ end
29
+
30
+ output *Cl.new($0).run(%w(bool on))
31
+
32
+ # Output:
33
+ #
34
+ # Called bool with bool=true
35
+
36
+ output *Cl.new($0).run(%w(bool on))
37
+
38
+ # Output:
39
+ #
40
+ # Called bool with bool=true
41
+
42
+ output *Cl.new($0).run(%w(bool on))
43
+
44
+ # Output:
45
+ #
46
+ # Called bool with bool=true
47
+
48
+ output *Cl.new($0).run(%w(bool on))
49
+
50
+ # Output:
51
+ #
52
+ # Called bool with bool=true
53
+
54
+ output *Cl.new($0).run(%w(types true 1 1.2 foo))
55
+
56
+ # Output:
57
+ #
58
+ # Called types with a=true b=1 c=1.2 d="foo"
59
+
60
+ Cl.new($0).run(%w(types true 1 1.2))
61
+
62
+ # Output:
63
+ #
64
+ # Too many arguments (given: 5, allowed: 4)
65
+ #
66
+ # Usage: cast.rb types [a (bool)] [b (int)] [c (float)] [d]
67
+
68
+ Cl.new($0).run(%w(types true one 1.2))
69
+
70
+ # Output:
71
+ #
72
+ # Wrong argument type (given: "one", expected: int)
73
+ #
74
+ # Usage: cast.rb types [a (bool)] [b (int)] [c (float)] [d]
75
+
76
+ Cl.new($0).run(%w(types true 1 one))
77
+
78
+ # Output:
79
+ #
80
+ # Wrong argument type (given: "one", expected: float)
81
+ #
82
+ # Usage: cast.rb types [a (bool)] [b (int)] [c (float)] [d]
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('lib')
3
+
4
+ require 'cl'
5
+
6
+ class Opts < Cl::Cmd
7
+ opt '-p', '--path PATH'
8
+ opt '-v', '--verbose'
9
+
10
+ def run
11
+ [registry_key, args, opts]
12
+ end
13
+ end
14
+
15
+ def output(cmd, args, opts)
16
+ puts "Called #{cmd} with args=#{args} opts=#{opts}\n\n"
17
+ end
18
+
19
+ output *Cl.new($0).run(%w(opts -p path -v))
20
+
21
+ # Output:
22
+ #
23
+ # Called cast with args=[] opts={:path=>"path", :verbose=>true}
24
+
25
+ output *Cl.new($0).run(%w(opts --path path --verbose))
26
+
27
+ # Output:
28
+ #
29
+ # Called cast with args=[] opts={:path=>"path", :verbose=>true}
30
+
31
+ output *Cl.new($0).run(%w(opts one -p path two -v three))
32
+
33
+ # Output:
34
+ #
35
+ # Called cast with args=["one", "two", "three"] opts={:path=>"path", :verbose=>true}
36
+
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('lib')
3
+
4
+ require 'cl'
5
+
6
+ class Required < Cl::Cmd
7
+ arg :one, required: true
8
+ arg :two
9
+
10
+ def run
11
+ [registry_key, one: one, two: two]
12
+ end
13
+ end
14
+
15
+ def output(cmd, args)
16
+ args = args.map { |key, value| "#{key}=#{value.inspect}" }.join(' ')
17
+ puts "Called #{cmd} with #{args}\n\n"
18
+ end
19
+
20
+ output *Cl.new($0).run(%w(required one two))
21
+
22
+ # Output:
23
+ #
24
+ # Called required with one="one" two="two"
25
+
26
+ output *Cl.new($0).run(%w(required one))
27
+
28
+ # Output:
29
+ #
30
+ # Called required with one="one" two=nil
31
+
32
+ output *Cl.new($0).run(%w(required))
33
+
34
+ # Output:
35
+ #
36
+ # Missing arguments (given: 0, required: 1)
37
+ #
38
+ # Usage: args.rb required one [two]
39
+
40
+ output *Cl.new($0).run(%w(required one two three))
41
+
42
+ # Output:
43
+ #
44
+ # Too many arguments (given: 3, allowed: 2)
45
+ #
46
+ # Usage: args.rb required one [two]
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('lib')
3
+
4
+ require 'cl'
5
+
6
+ class SplatLeft < Cl::Cmd
7
+ register 'splat:left'
8
+
9
+ arg :one, type: :array
10
+ args :two, :three
11
+
12
+ def run
13
+ [registry_key, one: one, two: two, three: three]
14
+ end
15
+ end
16
+
17
+ class SplatMiddle < Cl::Cmd
18
+ register 'splat:middle'
19
+
20
+ arg :one
21
+ arg :two, type: :array
22
+ arg :three
23
+
24
+ def run
25
+ [registry_key, one: one, two: two, three: three]
26
+ end
27
+ end
28
+
29
+ class SplatRight < Cl::Cmd
30
+ register 'splat:right'
31
+
32
+ args :one, :two
33
+ arg :three, type: :array
34
+
35
+ def run
36
+ [registry_key, one: one, two: two, three: three]
37
+ end
38
+ end
39
+
40
+ def output(cmd, args)
41
+ args = args.map { |key, value| "#{key}=#{value.inspect}" }.join(' ')
42
+ puts "Called #{cmd} with #{args}\n\n"
43
+ end
44
+
45
+ output *Cl.new($0).run(%w(splat left foo bar baz buz))
46
+
47
+ # Output:
48
+ #
49
+ # Called splat:left with one=["foo", "bar"] two="baz" three="buz"
50
+
51
+ output *Cl.new($0).run(%w(splat middle foo bar baz buz))
52
+
53
+ # Output:
54
+ #
55
+ # Called splat:middle with one="foo" two=["bar", "baz"] three="buz"
56
+
57
+ output *Cl.new($0).run(%w(splat right foo bar baz buz))
58
+
59
+ # Output:
60
+ #
61
+ # Called splat:middle with one="foo" two="bar" three=["baz", "buz"]
data/examples/gem ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('lib')
3
+
4
+ require 'cl'
5
+
6
+ module Gem
7
+ module Release
8
+ module Cmds
9
+ class Release < Cl::Cmd
10
+ arg :gemspec
11
+
12
+ opt '-h', '--host HOST', 'Push to a compatible host other than rubygems.org'
13
+ opt '-k', '--key KEY', 'Rubygems API key to use'
14
+ opt '-q', '--quiet', 'Silence output'
15
+
16
+ def run
17
+ [registry_key, args, opts]
18
+ end
19
+ end
20
+
21
+ class Bump < Cl::Cmd
22
+ defaults commit: true
23
+
24
+ opt '-v', '--version VERSION', 'The version to bump to [1.1.1|major|minor|patch|pre|rc|release]'
25
+ opt '--[no-]commit', 'Bump the version, but do not commit'
26
+
27
+ def run
28
+ [registry_key, args, opts]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ Cl.new($0).run(%w(help))
36
+ puts
37
+
38
+ # Output:
39
+ #
40
+ # Type "gem help COMMAND [SUBCOMMAND]" for more details:
41
+ #
42
+ # gem release [gemspec] [options]
43
+ # gem bump [options]
44
+
45
+ Cl.new($0).run(%w(help release))
46
+ puts
47
+
48
+ # or:
49
+ #
50
+ # Cl.new($0).run(%w(release --help)))
51
+ # Cl.new($0).run(%w(release -h)))
52
+ #
53
+ # Output:
54
+ #
55
+ # Usage: gem release [gemspec] [options]
56
+ #
57
+ # Arguments:
58
+ #
59
+ # gemspec
60
+ #
61
+ # Options:
62
+ #
63
+ # -h --host HOST Push to a compatible host other than rubygems.org
64
+ # -k --key KEY Rubygems API key to use
65
+ # -q --quiet Silence output
66
+ # --help Get help on this command
67
+
68
+ Cl.new($0).run(%w(help release))
69
+ puts
70
+
71
+ # or:
72
+ #
73
+ # Cl.run($0, %w(release --help))
74
+ # Cl.run($0, %w(release -h))
75
+ #
76
+ # Output:
77
+ #
78
+ # Usage: gem bump [options]
79
+ #
80
+ # Options:
81
+ #
82
+ # -v --version VERSION The version to bump to [1.1.1|major|minor|patch|pre|rc|release]
83
+ # --no-commit Bump the version, but do not commit
84
+ # -h --help Get help on this command
85
+
86
+ cmds = [
87
+ Cl.new($0).run(%w(bump -v 1.1.1)),
88
+ Cl.new($0).run(%w(release foo.gemspec -h host -k key -q))
89
+ ]
90
+
91
+ puts "Commands run:\n\n"
92
+ puts cmds.map { |cmd, args, opts| " cmd #{cmd} has run with:\n\n args=#{args}\n opts=#{opts}\n\n" }
93
+
94
+ # Commands run:
95
+ #
96
+ # cmd bump has run with:
97
+ #
98
+ # args=[]
99
+ # opts={:version=>"1.1.1"}
100
+ #
101
+ # cmd release has run with:
102
+ #
103
+ # args=["foo.gemspec"]
104
+ # opts={:host=>"host", :key=>"key", :quiet=>true}
data/examples/heroku ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('lib')
3
+
4
+ require 'cl'
5
+
6
+ module Heroku
7
+ module Apps
8
+ class Create < Cl::Cmd
9
+ register 'apps:create'
10
+
11
+ arg :name, required: true
12
+
13
+ opt '-o', '--org ORG'
14
+
15
+ def run; [registry_key, args, opts] end
16
+ end
17
+
18
+ class List < Cl::Cmd
19
+ register 'apps:info'
20
+
21
+ opt '-a', '--app APP'
22
+
23
+ def run; [registry_key, args, opts] end
24
+ end
25
+ end
26
+ end
27
+
28
+ def output(cmd, args, opts)
29
+ puts "Called #{cmd} with args=#{args} opts=#{opts}\n\n"
30
+ end
31
+
32
+ output *Cl.new($0).run(%w(apps:create name -o org))
33
+
34
+ # Output:
35
+ #
36
+ # Called apps:create with args=["name"] opts={:org=>"org"}
37
+
38
+ output *Cl.new($0).run(%w(apps create name -o org))
39
+
40
+ # Output:
41
+ #
42
+ # Called apps:create with args=["name"] opts={:org=>"org"}
43
+
44
+ output *Cl.new($0).run(%w(apps:info -a app))
45
+
46
+ # Output:
47
+ #
48
+ # Called apps:create with args=["app"] opts={}
49
+
@@ -1,3 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('lib')
3
+
1
4
  require 'cl'
2
5
 
3
6
  module Rakeish
@@ -15,9 +18,7 @@ module Rakeish
15
18
 
16
19
  arg :name
17
20
 
18
- opt '-f', '--force' do
19
- opts[:force] = true
20
- end
21
+ opt '-f', '--force'
21
22
 
22
23
  def run; [registry_key, args, opts] end
23
24
  end
@@ -27,9 +28,7 @@ module Rakeish
27
28
 
28
29
  arg :name
29
30
 
30
- opt '-v', '--version VERSION' do |value|
31
- opts[:version] = value
32
- end
31
+ opt '-v', '--version VERSION'
33
32
 
34
33
  def run; [registry_key, args, opts] end
35
34
  end
@@ -40,11 +39,14 @@ def output(result)
40
39
  result.each do |cmd, args, opts|
41
40
  puts "Called #{cmd} with args=#{args} opts=#{opts}"
42
41
  end
42
+ puts
43
43
  end
44
44
 
45
- Cl.runner = :multi
46
- output Cl.run(*%w(db:drop production -f db:create db:migrate production -v 1))
45
+ argv = %w(db:drop production -f db:create db:migrate production -v 1)
46
+ output Cl.new($0, runner: :multi).run(argv)
47
+
47
48
  # Output:
48
- # Called db:drop with args=["production"] opts={:force=>true}
49
- # Called db:create with args=[] opts={}
50
- # Called db:migrate with args=["production"] opts={:version=>"1"}
49
+ #
50
+ # Called db:drop with args=["production"] opts={:force=>true}
51
+ # Called db:create with args=[] opts={}
52
+ # Called db:migrate with args=["production"] opts={:version=>"1"}
data/lib/cl/arg.rb CHANGED
@@ -1,7 +1,8 @@
1
- module Cl
1
+ require 'cl/cast'
2
+
3
+ class Cl
2
4
  class Arg < Struct.new(:name, :opts)
3
- TRUE = /^(true|yes|on)$/
4
- FALSE = /^(false|no|off)$/
5
+ include Cast
5
6
 
6
7
  def define(const)
7
8
  const.send(:attr_accessor, name)
@@ -12,7 +13,11 @@ module Cl
12
13
  end
13
14
 
14
15
  def type
15
- opts[:type] || :str
16
+ opts[:type] || :string
17
+ end
18
+
19
+ def description
20
+ opts[:description]
16
21
  end
17
22
 
18
23
  def splat?
@@ -23,36 +28,13 @@ module Cl
23
28
  !!opts[:required]
24
29
  end
25
30
 
26
- def cast(value)
27
- case type
28
- when nil
29
- value
30
- when :array
31
- Array(value).flatten.map { |value| value.split(',') }.flatten
32
- when :string, :str
33
- value.to_s
34
- when :boolean, :bool
35
- return true if value.to_s =~ TRUE
36
- return false if value.to_s =~ FALSE
37
- !!value
38
- when :integer, :int
39
- Integer(value)
40
- when :float
41
- Float(value)
42
- else
43
- raise ArgumentError, "Unknown type: #{type}" if value
44
- end
45
- rescue ::ArgumentError => e
46
- raise ArgumentError.new(:wrong_type, value.inspect, type)
47
- end
48
-
49
31
  def to_s
50
32
  str = name
51
33
  case type
52
34
  when :array then str = "#{str}.."
53
- when :integer, :int then str = "#{str} (int)"
54
- when :boolean, :bool then str = "#{str} (bool)"
55
- when :float then str = "#{str} (float)"
35
+ when :integer, :int then str = "#{str}:int"
36
+ when :boolean, :bool then str = "#{str}:bool"
37
+ when :float then str = "#{str}:float"
56
38
  end
57
39
  required? ? str : "[#{str}]"
58
40
  end
data/lib/cl/args.rb CHANGED
@@ -1,13 +1,16 @@
1
1
  require 'cl/arg'
2
2
 
3
- module Cl
3
+ class Cl
4
4
  class Args
5
5
  include Enumerable
6
6
 
7
- def define(const, name, opts = {})
7
+ def define(const, name, *args)
8
+ opts = args.last.is_a?(Hash) ? args.pop.dup : {}
9
+ opts[:description] = args.shift if args.any?
10
+
8
11
  arg = Arg.new(name, opts)
9
12
  arg.define(const)
10
- args << arg
13
+ self.args << arg
11
14
  end
12
15
 
13
16
  def apply(cmd, args)
@@ -41,11 +44,11 @@ module Cl
41
44
  end
42
45
 
43
46
  def splat?
44
- args.any?(&:splat?)
47
+ any?(&:splat?)
45
48
  end
46
49
 
47
50
  def required
48
- args.select { |arg| arg.required? }.size
51
+ select(&:required?).size
49
52
  end
50
53
 
51
54
  def grouped(values)