Skip to content

Commit

Permalink
Avoid insanely long method signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
sferik committed Jun 15, 2012
1 parent 20a96f2 commit cd6c411
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 35 deletions.
10 changes: 5 additions & 5 deletions lib/thor/base.rb
Expand Up @@ -196,8 +196,9 @@ def argument(name, options={})
"the non-required argument #{argument.human_name.inspect}."
end if required

arguments << Thor::Argument.new(name, options[:desc], required, options[:type],
options[:default], options[:banner])
options[:required] = required

arguments << Thor::Argument.new(name, options)
end

# Returns this class arguments, looking up in the ancestors chain.
Expand Down Expand Up @@ -510,10 +511,9 @@ def is_thor_reserved_word?(word, type) #:nodoc:
# ==== Parameters
# name<Symbol>:: The name of the argument.
# options<Hash>:: Described in both class_option and method_option.
# scope<Hash>:: Options hash that is being built up
def build_option(name, options, scope) #:nodoc:
scope[name] = Thor::Option.new(name, options[:desc], options[:required],
options[:type], options[:default], options[:banner],
options[:lazy_default], options[:group], options[:aliases], options[:hide])
scope[name] = Thor::Option.new(name, options)
end

# Receives a hash of options, parse them and add to the scope. This is a
Expand Down
12 changes: 7 additions & 5 deletions lib/thor/parser/argument.rb
Expand Up @@ -5,18 +5,20 @@ class Argument #:nodoc:
attr_reader :name, :description, :required, :type, :default, :banner
alias :human_name :name

def initialize(name, description=nil, required=true, type=:string, default=nil, banner=nil)
def initialize(name, options={})
class_name = self.class.name.split("::").last

type = options[:type]

raise ArgumentError, "#{class_name} name can't be nil." if name.nil?
raise ArgumentError, "Type :#{type} is not valid for #{class_name.downcase}s." if type && !valid_type?(type)

@name = name.to_s
@description = description
@required = required || false
@description = options[:desc]
@required = options.key?(:required) ? options[:required] : true
@type = (type || :string).to_sym
@default = default
@banner = banner || default_banner
@default = options[:default]
@banner = options[:banner] || default_banner

validate! # Trigger specific validations
end
Expand Down
16 changes: 8 additions & 8 deletions lib/thor/parser/option.rb
Expand Up @@ -4,12 +4,13 @@ class Option < Argument #:nodoc:

VALID_TYPES = [:boolean, :numeric, :hash, :array, :string]

def initialize(name, description=nil, required=nil, type=nil, default=nil, banner=nil, lazy_default=nil, group=nil, aliases=nil, hide=nil)
super(name, description, required, type, default, banner)
@lazy_default = lazy_default
@group = group.to_s.capitalize if group
@aliases = [*aliases].compact
@hide = hide
def initialize(name, options={})
options[:required] = false unless options.key?(:required)
super
@lazy_default = options[:lazy_default]
@group = options[:group].to_s.capitalize if options[:group]
@aliases = Array(options[:aliases])
@hide = options[:hide]
end

# This parse quick options given as method_options. It makes several
Expand Down Expand Up @@ -64,8 +65,7 @@ def self.parse(key, value)
when Hash, Array, String
value.class.name.downcase.to_sym
end

self.new(name.to_s, nil, required, type, default, nil, nil, nil, aliases)
self.new(name.to_s, :required => required, :type => type, :default => default, :aliases => aliases)
end

def switch_name
Expand Down
16 changes: 8 additions & 8 deletions spec/parser/argument_spec.rb
Expand Up @@ -3,8 +3,8 @@

describe Thor::Argument do

def argument(name, type=:string, default=nil, required=nil)
@argument ||= Thor::Argument.new(name, nil, required || default.nil?, type, default)
def argument(name, options={})
@argument ||= Thor::Argument.new(name, options)
end

describe "errors" do
Expand All @@ -16,32 +16,32 @@ def argument(name, type=:string, default=nil, required=nil)

it "raises an error if type is unknown" do
lambda {
argument(:task, :unknown)
argument(:task, :type => :unknown)
}.should raise_error(ArgumentError, "Type :unknown is not valid for arguments.")
end

it "raises an error if argument is required and have default values" do
lambda {
argument(:task, :string, "bar", true)
argument(:task, :type => :string, :default => "bar", :required => true)
}.should raise_error(ArgumentError, "An argument cannot be required and have default value.")
end
end

describe "#usage" do
it "returns usage for string types" do
argument(:foo, :string).usage.should == "FOO"
argument(:foo, :type => :string).usage.should == "FOO"
end

it "returns usage for numeric types" do
argument(:foo, :numeric).usage.should == "N"
argument(:foo, :type => :numeric).usage.should == "N"
end

it "returns usage for array types" do
argument(:foo, :array).usage.should == "one two three"
argument(:foo, :type => :array).usage.should == "one two three"
end

it "returns usage for hash types" do
argument(:foo, :hash).usage.should == "key:value"
argument(:foo, :type => :hash).usage.should == "key:value"
end
end
end
3 changes: 2 additions & 1 deletion spec/parser/arguments_spec.rb
Expand Up @@ -4,7 +4,8 @@
describe Thor::Arguments do
def create(opts={})
arguments = opts.map do |type, default|
Thor::Argument.new(type.to_s, nil, default.nil?, type, default)
options = {:required => default.nil?, :type => type, :default => default}
Thor::Argument.new(type.to_s, options)
end

arguments.sort!{ |a,b| b.name <=> a.name }
Expand Down
12 changes: 6 additions & 6 deletions spec/parser/option_spec.rb
Expand Up @@ -6,8 +6,8 @@ def parse(key, value)
Thor::Option.parse(key, value)
end

def option(name, *args)
@option ||= Thor::Option.new(name, *args)
def option(name, options={})
@option ||= Thor::Option.new(name, options)
end

describe "#parse" do
Expand Down Expand Up @@ -130,14 +130,14 @@ def option(name, *args)
end

it "can be required and have default values" do
option = option("foo", nil, true, :string, "bar")
option = option("foo", :required => true, :type => :string, :default => "bar")
option.default.should == "bar"
option.should be_required
end

it "cannot be required and have type boolean" do
lambda {
option("foo", nil, true, :boolean)
option("foo", :required => true, :type => :boolean)
}.should raise_error(ArgumentError, "An option cannot be boolean and required.")
end

Expand Down Expand Up @@ -180,11 +180,11 @@ def option(name, *args)
end

it "uses banner when supplied" do
option(:foo, nil, false, :string, nil, "BAR").usage.should == "[--foo=BAR]"
option(:foo, :required => false, :type => :string, :banner => "BAR").usage.should == "[--foo=BAR]"
end

it "checkes when banner is an empty string" do
option(:foo, nil, false, :string, nil, "").usage.should == "[--foo]"
option(:foo, :required => false, :type => :string, :banner => "").usage.should == "[--foo]"
end

describe "with required values" do
Expand Down
3 changes: 2 additions & 1 deletion spec/parser/options_spec.rb
Expand Up @@ -168,7 +168,8 @@ def check_unknown!
end

it "does not raises an error if the required option has a default value" do
create :foo => Thor::Option.new("foo", nil, true, :string, "baz"), :bar => :boolean
options = {:required => true, :type => :string, :default => "baz"}
create :foo => Thor::Option.new("foo", options), :bar => :boolean
lambda { parse("--bar") }.should_not raise_error
end
end
Expand Down
3 changes: 2 additions & 1 deletion spec/task_spec.rb
Expand Up @@ -26,7 +26,8 @@ def task(options={})
end

it "injects arguments into usage" do
object = Struct.new(:namespace, :arguments).new("foo", [Thor::Argument.new(:bar, nil, true, :string)])
options = {:required => true, :type => :string}
object = Struct.new(:namespace, :arguments).new("foo", [Thor::Argument.new(:bar, options)])
task(:foo => :required).formatted_usage(object).should == "foo:can_has BAR --foo=FOO"
end
end
Expand Down

0 comments on commit cd6c411

Please sign in to comment.