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 +4 -4
- data/.gitignore +2 -0
- data/.rspec +2 -1
- data/README.md +12 -0
- data/Rakefile +5 -8
- data/lib/samovar/command.rb +1 -3
- data/lib/samovar/many.rb +2 -2
- data/lib/samovar/nested.rb +22 -3
- data/lib/samovar/one.rb +2 -2
- data/lib/samovar/options.rb +4 -6
- data/lib/samovar/split.rb +2 -2
- data/lib/samovar/table.rb +6 -10
- data/lib/samovar/version.rb +1 -1
- data/samovar.gemspec +1 -1
- data/spec/samovar/coerce_spec.rb +27 -0
- data/spec/samovar/command_spec.rb +38 -29
- data/spec/samovar/nested_spec.rb +30 -0
- data/spec/samovar/options_spec.rb +24 -0
- data/spec/spec_helper.rb +29 -0
- metadata +12 -7
- data/.simplecov +0 -9
- data/spec/samovar/type_spec.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06e76d86b275ed684abaabcadd799765248b67d8
|
4
|
+
data.tar.gz: 5dbb428a9e5523779b394d3c14cb8661ca14271c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e412c9871a224a1ad5049fd9d13a94dc1cf6f3f1a6b5c4bb2a92f085ce3a7b629f9a2ab142fe428b1e6a766c2252ef93eaf059b3d92e9bd48582fa9aca6c5abd
|
7
|
+
data.tar.gz: ba4f76b3c6b9457647cf8132e02d94df20add0d19e6c7c610ca2277291544db21e767735b4a9850a4756fd765e341c8ecefa3ecc4d0016b063e008a8d1a9f3d9
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
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
|
-
|
5
|
-
|
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
|
-
|
7
|
+
RSpec::Core::RakeTask.new(:test)
|
8
|
+
|
9
|
+
task :default => :test
|
data/lib/samovar/command.rb
CHANGED
data/lib/samovar/many.rb
CHANGED
@@ -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
|
data/lib/samovar/nested.rb
CHANGED
@@ -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
|
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
|
|
data/lib/samovar/one.rb
CHANGED
data/lib/samovar/options.rb
CHANGED
@@ -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
|
-
|
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)
|
data/lib/samovar/split.rb
CHANGED
data/lib/samovar/table.rb
CHANGED
@@ -36,19 +36,15 @@ module Samovar
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def usage
|
39
|
-
|
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
|
-
|
51
|
-
|
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
|
data/lib/samovar/version.rb
CHANGED
data/samovar.gemspec
CHANGED
@@ -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
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
59
|
-
|
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
|
data/spec/spec_helper.rb
ADDED
@@ -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.
|
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-
|
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.
|
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.
|
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/
|
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/
|
145
|
+
- spec/samovar/nested_spec.rb
|
146
|
+
- spec/samovar/options_spec.rb
|
147
|
+
- spec/spec_helper.rb
|
data/.simplecov
DELETED
data/spec/samovar/type_spec.rb
DELETED
@@ -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
|