samovar 1.5.0 → 1.6.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
2
  SHA1:
3
- metadata.gz: 245b83811d09cc997ce160fa8c6a5481e3efe0cc
4
- data.tar.gz: b7e021a4cad13a340d6b77dbd2cbe4c066383c5d
3
+ metadata.gz: 06e76d86b275ed684abaabcadd799765248b67d8
4
+ data.tar.gz: 5dbb428a9e5523779b394d3c14cb8661ca14271c
5
5
  SHA512:
6
- metadata.gz: 9a7e9e3e968d94c1d88eb308f1bf1e46c3c29ee2e7c1847d3a42b2b5f55f686e7e45a10ba43b75a98ccff09288a99e733bccd030bf58f05a721e8c43084014f1
7
- data.tar.gz: b8d72d941e4f5f2659c7e4ea9235a66667ed637945d43ee0772eb3774b929afdfff013719ba677a00ff8f4da92cb07d39c822dae2e50e1c1775a2ec1a5a9ec58
6
+ metadata.gz: e412c9871a224a1ad5049fd9d13a94dc1cf6f3f1a6b5c4bb2a92f085ce3a7b629f9a2ab142fe428b1e6a766c2252ef93eaf059b3d92e9bd48582fa9aca6c5abd
7
+ data.tar.gz: ba4f76b3c6b9457647cf8132e02d94df20add0d19e6c7c610ca2277291544db21e767735b4a9850a4756fd765e341c8ecefa3ecc4d0016b063e008a8d1a9f3d9
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .rspec_status
11
+ .tags
data/.rspec CHANGED
@@ -1,3 +1,4 @@
1
1
  --format documentation
2
- --color
2
+ --backtrace
3
3
  --warnings
4
+ --require spec_helper
data/README.md CHANGED
@@ -116,6 +116,18 @@ Or install it yourself as:
116
116
  application.fruit # 'apple'
117
117
  application.cakes # ['chocolate cake', 'fruit cake']
118
118
 
119
+ ### Explicit Commands
120
+
121
+ Given a custom `Samovar::Command` subclass, you can instantiate it with options:
122
+
123
+ application = Application['--root', path]
124
+
125
+ You can also duplicate an existing command instance with additions/changes:
126
+
127
+ concurrent_application = application['--threads', 12]
128
+
129
+ These forms can be useful when invoking one command from another, or in unit tests.
130
+
119
131
  ## Contributing
120
132
 
121
133
  1. Fork it
data/Rakefile CHANGED
@@ -1,12 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
3
 
4
- RSpec::Core::RakeTask.new(:spec) do |task|
5
- begin
6
- require('simplecov/version')
7
- task.rspec_opts = %w{--require simplecov} if ENV['COVERAGE']
8
- rescue LoadError
9
- end
10
- end
4
+ # Load all rake tasks:
5
+ import(*Dir.glob('tasks/**/*.rake'))
11
6
 
12
- task :default => :spec
7
+ RSpec::Core::RakeTask.new(:test)
8
+
9
+ task :default => :test
@@ -52,9 +52,7 @@ module Samovar
52
52
  end
53
53
 
54
54
  def parse(input)
55
- self.class.table.parse(input) do |key, value|
56
- self.send("#{key}=", value)
57
- end
55
+ self.class.table.parse(input, self)
58
56
  end
59
57
 
60
58
  def initialize(input = nil)
@@ -36,12 +36,12 @@ module Samovar
36
36
  [to_s, @description]
37
37
  end
38
38
 
39
- def parse(input)
39
+ def parse(input, default)
40
40
  if @stop and stop_index = input.index{|item| @stop === item}
41
41
  input.shift(stop_index)
42
42
  else
43
43
  input.shift(input.size)
44
- end
44
+ end || default
45
45
  end
46
46
  end
47
47
  end
@@ -20,10 +20,13 @@
20
20
 
21
21
  module Samovar
22
22
  class Nested
23
- def initialize(name, commands, key: :command)
23
+ def initialize(name, commands, key: :command, default: nil)
24
24
  @name = name
25
25
  @commands = commands
26
26
  @key = key
27
+
28
+ # This is the default name [of a command], not the default command:
29
+ @default = default
27
30
  end
28
31
 
29
32
  attr :key
@@ -33,15 +36,31 @@ module Samovar
33
36
  end
34
37
 
35
38
  def to_a
36
- [@name, "One of #{@commands.keys.join(', ')}."]
39
+ usage = [@name]
40
+
41
+ if @commands.size == 0
42
+ usage << "No commands available."
43
+ elsif @commands.size == 1
44
+ usage << "Only #{@commands.first}."
45
+ else
46
+ usage << "One of: #{@commands.keys.join(', ')}."
47
+ end
48
+
49
+ if @default
50
+ usage << "Default: #{@default}"
51
+ end
52
+
53
+ return usage
37
54
  end
38
55
 
39
- def parse(input)
56
+ def parse(input, default)
40
57
  if command = @commands[input.first]
41
58
  input.shift
42
59
 
43
60
  # puts "Instantiating #{command} with #{input}"
44
61
  command.new(input)
62
+ elsif @default
63
+ default || @commands[@default].new(input)
45
64
  end
46
65
  end
47
66
 
@@ -36,10 +36,10 @@ module Samovar
36
36
  [to_s, @description]
37
37
  end
38
38
 
39
- def parse(input)
39
+ def parse(input, default)
40
40
  if input.first =~ @pattern
41
41
  input.shift
42
- end
42
+ end || default
43
43
  end
44
44
  end
45
45
  end
@@ -74,12 +74,10 @@ module Samovar
74
74
  return result
75
75
  end
76
76
 
77
- def parse(input)
77
+ def parse(input, default = @default)
78
78
  if result = @flags.parse(input)
79
79
  @value.nil? ? coerce(result) : @value
80
- else
81
- @default
82
- end
80
+ end || default
83
81
  end
84
82
 
85
83
  def to_s
@@ -138,8 +136,8 @@ module Samovar
138
136
  end
139
137
  end
140
138
 
141
- def parse(input)
142
- values = @defaults.dup
139
+ def parse(input, default)
140
+ values = (default || @defaults).dup
143
141
 
144
142
  while option = @keyed[input.first]
145
143
  if result = option.parse(input)
@@ -36,10 +36,10 @@ module Samovar
36
36
  [to_s, @description]
37
37
  end
38
38
 
39
- def parse(input)
39
+ def parse(input, default = nil)
40
40
  if offset = input.index(@marker)
41
41
  input.pop(input.size - offset).tap(&:shift)
42
- end
42
+ end || default
43
43
  end
44
44
  end
45
45
  end
@@ -36,19 +36,15 @@ module Samovar
36
36
  end
37
37
 
38
38
  def usage
39
- items = Array.new
40
-
41
- @rows.each do |row|
42
- items << row.to_s
43
- end
44
-
45
- items.join(' ')
39
+ @rows.collect(&:to_s).join(' ')
46
40
  end
47
41
 
48
- def parse(input)
42
+ def parse(input, command)
49
43
  @parser.each do |row|
50
- if result = row.parse(input)
51
- yield row.key, result, row
44
+ current = command.send(row.key)
45
+
46
+ if result = row.parse(input, current)
47
+ command.send("#{row.key}=", result)
52
48
  end
53
49
  end
54
50
  end
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Samovar
22
- VERSION = "1.5.0"
22
+ VERSION = "1.6.0"
23
23
  end
@@ -23,5 +23,5 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_development_dependency "bundler", "~> 1.11"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "rspec", "~> 3.6"
27
27
  end
@@ -0,0 +1,27 @@
1
+
2
+ require 'samovar'
3
+ require 'stringio'
4
+
5
+ module Samovar::CoerceSpec
6
+ class Coerce < Samovar::Command
7
+ options do
8
+ option '--things <array>', "A list of things" do |input|
9
+ input.split(/\s*,\s*/)
10
+ end
11
+
12
+ option '--count <integer>', "A number to count", type: Integer
13
+ end
14
+ end
15
+
16
+ RSpec.describe Samovar::Command do
17
+ it "should coerce to array" do
18
+ top = Coerce['--things', 'a,b,c']
19
+ expect(top.options[:things]).to be == ['a', 'b', 'c']
20
+ end
21
+
22
+ it "should coerce to integer" do
23
+ top = Coerce['--count', '10']
24
+ expect(top.options[:count]).to be == 10
25
+ end
26
+ end
27
+ end
@@ -2,7 +2,7 @@
2
2
  require 'samovar'
3
3
  require 'stringio'
4
4
 
5
- module Command
5
+ module Samovar::CommandSpec
6
6
  class Bottom < Samovar::Command
7
7
  self.description = "Create a new teapot package using the specified repository."
8
8
 
@@ -25,37 +25,46 @@ module Command
25
25
  nested '<command>',
26
26
  'bottom' => Bottom
27
27
  end
28
- end
29
28
 
30
- describe Samovar::Command do
31
- it "should use default value" do
32
- top = Command::Top.parse([])
33
- expect(top.options[:configuration]).to be == 'TEAPOT_CONFIGURATION'
34
- end
35
-
36
- it "should parse a simple command" do
37
- top = Command::Top.parse(["-c", "path", "bottom", "foobar", "A", "B", "--", "args", "args"])
29
+ RSpec.describe Samovar::Command do
30
+ it "should use default value" do
31
+ top = Top[]
32
+ expect(top.options[:configuration]).to be == 'TEAPOT_CONFIGURATION'
33
+ end
38
34
 
39
- expect(top.options[:configuration]).to be == 'path'
40
- expect(top.command.class).to be == Command::Bottom
41
- expect(top.command.project_name).to be == 'foobar'
42
- expect(top.command.packages).to be == ['A', 'B']
43
- expect(top.command.argv).to be == ["args", "args"]
44
- end
45
-
46
- it "should generate documentation" do
47
- top = Command::Top.new([])
48
- buffer = StringIO.new
49
- top.print_usage('top', output: buffer)
35
+ it "can update options" do
36
+ top = Top[]
37
+ expect(top.options[:configuration]).to be == 'TEAPOT_CONFIGURATION'
38
+
39
+ top = top['--verbose']
40
+ expect(top.options[:configuration]).to be == 'TEAPOT_CONFIGURATION'
41
+ expect(top.options[:logging]).to be == :verbose
42
+ end
50
43
 
51
- expect(buffer.string).to be_include(Command::Top.description)
52
- end
53
-
54
- it "can run commands" do
55
- expect(subject.system("ls")).to be_truthy
56
- expect(subject.system!("ls")).to be_truthy
44
+ it "should parse a simple command" do
45
+ top = Top["-c", "path", "bottom", "foobar", "A", "B", "--", "args", "args"]
46
+
47
+ expect(top.options[:configuration]).to be == 'path'
48
+ expect(top.command.class).to be == Bottom
49
+ expect(top.command.project_name).to be == 'foobar'
50
+ expect(top.command.packages).to be == ['A', 'B']
51
+ expect(top.command.argv).to be == ["args", "args"]
52
+ end
57
53
 
58
- expect(subject.system("fail")).to be_falsey
59
- expect{subject.system!("fail")}.to raise_error(Samovar::SystemError)
54
+ it "should generate documentation" do
55
+ top = Top[]
56
+ buffer = StringIO.new
57
+ top.print_usage('top', output: buffer)
58
+
59
+ expect(buffer.string).to be_include(Top.description)
60
+ end
61
+
62
+ it "can run commands" do
63
+ expect(subject.system("ls")).to be_truthy
64
+ expect(subject.system!("ls")).to be_truthy
65
+
66
+ expect(subject.system("fail")).to be_falsey
67
+ expect{subject.system!("fail")}.to raise_error(Samovar::SystemError)
68
+ end
60
69
  end
61
70
  end
@@ -0,0 +1,30 @@
1
+
2
+ require 'samovar'
3
+ require 'stringio'
4
+
5
+ module Samovar::NestedSpec
6
+ class InnerA < Samovar::Command
7
+ end
8
+
9
+ class InnerB < Samovar::Command
10
+ end
11
+
12
+ class Outer < Samovar::Command
13
+ nested '<command>',
14
+ 'inner-a' => InnerA,
15
+ 'inner-b' => InnerB,
16
+ default: 'inner-b'
17
+ end
18
+
19
+ RSpec.describe Samovar::Nested do
20
+ it "should select default nested command" do
21
+ outer = Outer[]
22
+ expect(outer.command).to be_kind_of(InnerB)
23
+ end
24
+
25
+ it "should select explicitly named nested command" do
26
+ outer = Outer['inner-a']
27
+ expect(outer.command).to be_kind_of(InnerA)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,24 @@
1
+
2
+ RSpec.describe Samovar::Options do
3
+ subject(:options) do
4
+ described_class.parse do
5
+ option '-x <value>', "The x factor", default: 2
6
+ option '-y <value>', "The y factor"
7
+ end
8
+ end
9
+
10
+ it "should set defaults" do
11
+ values = options.parse([], nil)
12
+ expect(values).to be == {x: 2}
13
+ end
14
+
15
+ it "should preserve current values" do
16
+ values = options.parse([], {x: 1, y: 2, z: 3})
17
+ expect(values).to be == {x: 1, y: 2, z: 3}
18
+ end
19
+
20
+ it "should update specified values" do
21
+ values = options.parse(['-x', 10], {x: 1, y: 2, z: 3})
22
+ expect(values).to be == {x: 10, y: 2, z: 3}
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+
2
+ if ENV['COVERAGE'] || ENV['TRAVIS']
3
+ begin
4
+ require 'simplecov'
5
+
6
+ SimpleCov.start do
7
+ add_filter "/spec/"
8
+ end
9
+
10
+ if ENV['TRAVIS']
11
+ require 'coveralls'
12
+ Coveralls.wear!
13
+ end
14
+ rescue LoadError
15
+ warn "Could not load simplecov: #{$!}"
16
+ end
17
+ end
18
+
19
+ require "bundler/setup"
20
+ require "samovar"
21
+
22
+ RSpec.configure do |config|
23
+ # Enable flags like --only-failures and --next-failure
24
+ config.example_status_persistence_file_path = ".rspec_status"
25
+
26
+ config.expect_with :rspec do |c|
27
+ c.syntax = :expect
28
+ end
29
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: samovar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-05 00:00:00.000000000 Z
11
+ date: 2017-07-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mapping
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3.0'
75
+ version: '3.6'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3.0'
82
+ version: '3.6'
83
83
  description:
84
84
  email:
85
85
  - samuel.williams@oriontransfer.co.nz
@@ -89,7 +89,6 @@ extra_rdoc_files: []
89
89
  files:
90
90
  - ".gitignore"
91
91
  - ".rspec"
92
- - ".simplecov"
93
92
  - ".travis.yml"
94
93
  - Gemfile
95
94
  - README.md
@@ -109,8 +108,11 @@ files:
109
108
  - lib/samovar/table.rb
110
109
  - lib/samovar/version.rb
111
110
  - samovar.gemspec
111
+ - spec/samovar/coerce_spec.rb
112
112
  - spec/samovar/command_spec.rb
113
- - spec/samovar/type_spec.rb
113
+ - spec/samovar/nested_spec.rb
114
+ - spec/samovar/options_spec.rb
115
+ - spec/spec_helper.rb
114
116
  - teapot.png
115
117
  homepage: https://github.com/ioquatix/samovar
116
118
  licenses:
@@ -138,5 +140,8 @@ specification_version: 4
138
140
  summary: Samovar is a flexible option parser excellent support for sub-commands and
139
141
  help documentation.
140
142
  test_files:
143
+ - spec/samovar/coerce_spec.rb
141
144
  - spec/samovar/command_spec.rb
142
- - spec/samovar/type_spec.rb
145
+ - spec/samovar/nested_spec.rb
146
+ - spec/samovar/options_spec.rb
147
+ - spec/spec_helper.rb
data/.simplecov DELETED
@@ -1,9 +0,0 @@
1
-
2
- SimpleCov.start do
3
- add_filter "/spec/"
4
- end
5
-
6
- if ENV['TRAVIS']
7
- require 'coveralls'
8
- Coveralls.wear!
9
- end
@@ -1,27 +0,0 @@
1
-
2
- require 'samovar'
3
- require 'stringio'
4
-
5
- module Command
6
- class Coerce < Samovar::Command
7
- options do
8
- option '--things <array>', "A list of things" do |input|
9
- input.split(/\s*,\s*/)
10
- end
11
-
12
- option '--count <integer>', "A number to count", type: Integer
13
- end
14
- end
15
- end
16
-
17
- describe Samovar::Command do
18
- it "should coerce to array" do
19
- top = Command::Coerce.parse(['--things', 'a,b,c'])
20
- expect(top.options[:things]).to be == ['a', 'b', 'c']
21
- end
22
-
23
- it "should coerce to integer" do
24
- top = Command::Coerce.parse(['--count', '10'])
25
- expect(top.options[:count]).to be == 10
26
- end
27
- end