Skip to content

Commit

Permalink
Better handling of defaults in parser.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Jul 6, 2017
1 parent c2c7010 commit 70a2537
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 81 deletions.
12 changes: 6 additions & 6 deletions lib/samovar/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,6 @@ def [](*input)
self.dup.tap{|command| command.parse(input)}
end

def parse(input)
self.class.table.parse(input) do |key, value|
self.send("#{key}=", value)
end
end

def initialize(input = nil)
parse(input) if input
end
Expand Down Expand Up @@ -124,5 +118,11 @@ def print_usage(*args, output: $stderr, formatter: Output::DetailedFormatter)

formatter.print(rows, output)
end

private

def parse(input)
self.class.table.parse(input, self)
end
end
end
4 changes: 2 additions & 2 deletions lib/samovar/many.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ def to_a
[to_s, @description]
end

def parse(input)
def parse(input, default)
if @stop and stop_index = input.index{|item| @stop === item}
input.shift(stop_index)
else
input.shift(input.size)
end
end || default
end
end
end
11 changes: 8 additions & 3 deletions lib/samovar/nested.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@

module Samovar
class Nested
def initialize(name, commands, key: :command)
def initialize(name, commands, key: :command, default: nil)
@name = name
@commands = commands
@key = key

# This is the default name [of a command], not the default command:
@default = default
end

attr :key
Expand All @@ -33,15 +36,17 @@ def to_s
end

def to_a
[@name, "One of #{@commands.keys.join(', ')}."]
[@name, "One of: #{@commands.keys.join(', ')}."]
end

def parse(input)
def parse(input, default)
if command = @commands[input.first]
input.shift

# puts "Instantiating #{command} with #{input}"
command.new(input)
elsif @default
default || @commands[@default].new(input)
end
end

Expand Down
4 changes: 2 additions & 2 deletions lib/samovar/one.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ def to_a
[to_s, @description]
end

def parse(input)
def parse(input, default)
if input.first =~ @pattern
input.shift
end
end || default
end
end
end
10 changes: 4 additions & 6 deletions lib/samovar/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,10 @@ def coerce(result)
return result
end

def parse(input)
def parse(input, default = @default)
if result = @flags.parse(input)
@value.nil? ? coerce(result) : @value
else
@default
end
end || default
end

def to_s
Expand Down Expand Up @@ -138,8 +136,8 @@ def << option
end
end

def parse(input)
values = @defaults.dup
def parse(input, default)
values = (default || @defaults).dup

while option = @keyed[input.first]
if result = option.parse(input)
Expand Down
4 changes: 2 additions & 2 deletions lib/samovar/split.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ def to_a
[to_s, @description]
end

def parse(input)
def parse(input, default = nil)
if offset = input.index(@marker)
input.pop(input.size - offset).tap(&:shift)
end
end || default
end
end
end
8 changes: 5 additions & 3 deletions lib/samovar/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ def usage
items.join(' ')
end

def parse(input)
def parse(input, command)
@parser.each do |row|
if result = row.parse(input)
yield row.key, result, row
current = command.send(row.key)

if result = row.parse(input, current)
command.send("#{row.key}=", result)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/samovar/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
# THE SOFTWARE.

module Samovar
VERSION = "1.5.0"
VERSION = "1.6.0"
end
27 changes: 27 additions & 0 deletions spec/samovar/coerce_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

require 'samovar'
require 'stringio'

module Samovar::CoerceSpec
class Coerce < Samovar::Command
options do
option '--things <array>', "A list of things" do |input|
input.split(/\s*,\s*/)
end

option '--count <integer>', "A number to count", type: Integer
end
end

RSpec.describe Samovar::Command do
it "should coerce to array" do
top = Coerce['--things', 'a,b,c']
expect(top.options[:things]).to be == ['a', 'b', 'c']
end

it "should coerce to integer" do
top = Coerce['--count', '10']
expect(top.options[:count]).to be == 10
end
end
end
58 changes: 29 additions & 29 deletions spec/samovar/command_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require 'samovar'
require 'stringio'

module Command
module Samovar::CommandSpec
class Bottom < Samovar::Command
self.description = "Create a new teapot package using the specified repository."

Expand All @@ -25,37 +25,37 @@ class Top < Samovar::Command
nested '<command>',
'bottom' => Bottom
end
end

describe Samovar::Command do
it "should use default value" do
top = Command::Top.parse([])
expect(top.options[:configuration]).to be == 'TEAPOT_CONFIGURATION'
end

it "should parse a simple command" do
top = Command::Top.parse(["-c", "path", "bottom", "foobar", "A", "B", "--", "args", "args"])
RSpec.describe Samovar::Command do
it "should use default value" do
top = Top.parse([])
expect(top.options[:configuration]).to be == 'TEAPOT_CONFIGURATION'
end

expect(top.options[:configuration]).to be == 'path'
expect(top.command.class).to be == Command::Bottom
expect(top.command.project_name).to be == 'foobar'
expect(top.command.packages).to be == ['A', 'B']
expect(top.command.argv).to be == ["args", "args"]
end

it "should generate documentation" do
top = Command::Top.new([])
buffer = StringIO.new
top.print_usage('top', output: buffer)
it "should parse a simple command" do
top = Top.parse(["-c", "path", "bottom", "foobar", "A", "B", "--", "args", "args"])

expect(top.options[:configuration]).to be == 'path'
expect(top.command.class).to be == Bottom
expect(top.command.project_name).to be == 'foobar'
expect(top.command.packages).to be == ['A', 'B']
expect(top.command.argv).to be == ["args", "args"]
end

expect(buffer.string).to be_include(Command::Top.description)
end

it "can run commands" do
expect(subject.system("ls")).to be_truthy
expect(subject.system!("ls")).to be_truthy
it "should generate documentation" do
top = Top.new([])
buffer = StringIO.new
top.print_usage('top', output: buffer)

expect(buffer.string).to be_include(Top.description)
end

expect(subject.system("fail")).to be_falsey
expect{subject.system!("fail")}.to raise_error(Samovar::SystemError)
it "can run commands" do
expect(subject.system("ls")).to be_truthy
expect(subject.system!("ls")).to be_truthy

expect(subject.system("fail")).to be_falsey
expect{subject.system!("fail")}.to raise_error(Samovar::SystemError)
end
end
end
30 changes: 30 additions & 0 deletions spec/samovar/nested_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

require 'samovar'
require 'stringio'

module Samovar::NestedSpec
class InnerA < Samovar::Command
end

class InnerB < Samovar::Command
end

class Outer < Samovar::Command
nested '<command>',
'inner-a' => InnerA,
'inner-b' => InnerB,
default: 'inner-b'
end

RSpec.describe Samovar::Nested do
it "should select default nested command" do
outer = Outer[]
expect(outer.command).to be_kind_of(InnerB)
end

it "should select explicitly named nested command" do
outer = Outer['inner-a']
expect(outer.command).to be_kind_of(InnerA)
end
end
end
24 changes: 24 additions & 0 deletions spec/samovar/options_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

RSpec.describe Samovar::Options do
subject(:options) do
described_class.parse do
option '-x <value>', "The x factor", default: 2
option '-y <value>', "The y factor"
end
end

it "should set defaults" do
values = options.parse([], nil)
expect(values).to be == {x: 2}
end

it "should preserve current values" do
values = options.parse([], {x: 1, y: 2, z: 3})
expect(values).to be == {x: 1, y: 2, z: 3}
end

it "should update specified values" do
values = options.parse(['-x', 10], {x: 1, y: 2, z: 3})
expect(values).to be == {x: 10, y: 2, z: 3}
end
end
27 changes: 0 additions & 27 deletions spec/samovar/type_spec.rb

This file was deleted.

0 comments on commit 70a2537

Please sign in to comment.