Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Commit

Permalink
Update vendored Thor to 0.13.3
Browse files Browse the repository at this point in the history
  • Loading branch information
indirect committed Feb 18, 2010
1 parent 44b5c80 commit 749214d
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 105 deletions.
16 changes: 10 additions & 6 deletions lib/bundler/vendor/thor.rb
Expand Up @@ -120,8 +120,8 @@ def method_option(name, options={})
# script = MyScript.new(args, options, config)
# script.invoke(:task, first_arg, second_arg, third_arg)
#
def start(given_args=ARGV, config={})
super do
def start(original_args=ARGV, config={})
super do |given_args|
meth = normalize_task_name(given_args.shift)
task = all_tasks[meth]

Expand All @@ -145,8 +145,9 @@ def start(given_args=ARGV, config={})
# task_name<String>
#
def task_help(shell, task_name)
task = all_tasks[task_name]
raise UndefinedTaskError, "task '#{task_name}' could not be found in namespace '#{self.namespace}'" unless task
meth = normalize_task_name(task_name)
task = all_tasks[meth]
handle_no_task_error(meth) unless task

shell.say "Usage:"
shell.say " #{banner(task)}"
Expand Down Expand Up @@ -183,6 +184,10 @@ def printable_tasks(all=true)
end
end

def handle_argument_error(task, error) #:nodoc:
raise InvocationError, "#{task.name.inspect} was called incorrectly. Call as #{task.formatted_usage(self, banner_base == "thor").inspect}."
end

protected

# The banner for this class. You can customize it if you are invoking the
Expand All @@ -191,8 +196,7 @@ def printable_tasks(all=true)
# the namespace should be displayed as arguments.
#
def banner(task)
base = $thor_runner ? "thor" : File.basename($0.split(" ").first)
"#{base} #{task.formatted_usage(self, base == "thor")}"
"#{banner_base} #{task.formatted_usage(self, banner_base == "thor")}"
end

def baseclass #:nodoc:
Expand Down
50 changes: 30 additions & 20 deletions lib/bundler/vendor/thor/base.rb
Expand Up @@ -38,9 +38,8 @@ module Base
# config<Hash>:: Configuration for this Thor class.
#
def initialize(args=[], options={}, config={})
Thor::Arguments.parse(self.class.arguments, args).each do |key, value|
send("#{key}=", value)
end
args = Thor::Arguments.parse(self.class.arguments, args)
args.each { |key, value| send("#{key}=", value) }

parse_options = self.class.class_options

Expand All @@ -52,9 +51,9 @@ def initialize(args=[], options={}, config={})
array_options, hash_options = [], options
end

options = Thor::Options.parse(parse_options, array_options)
self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).merge!(hash_options)
self.options.freeze
opts = Thor::Options.new(parse_options, hash_options)
self.options = opts.parse(array_options)
opts.check_unknown! if self.class.check_unknown_options?
end

class << self
Expand Down Expand Up @@ -109,6 +108,16 @@ def attr_accessor(*) #:nodoc:
no_tasks { super }
end

# If you want to raise an error for unknown options, call check_unknown_options!
# This is disabled by default to allow dynamic invocations.
def check_unknown_options!
@check_unknown_options = true
end

def check_unknown_options? #:nodoc:
@check_unknown_options || false
end

# Adds an argument to the class and creates an attr_accessor for it.
#
# Arguments are different from options in several aspects. The first one
Expand Down Expand Up @@ -355,7 +364,7 @@ def no_tasks
def namespace(name=nil)
case name
when nil
@namespace ||= Thor::Util.namespace_from_thor_class(self, false)
@namespace ||= Thor::Util.namespace_from_thor_class(self)
else
@namespace = name.to_s
end
Expand All @@ -366,14 +375,18 @@ def namespace(name=nil)
def start(given_args=ARGV, config={})
self.debugging = given_args.include?("--debug")
config[:shell] ||= Thor::Base.shell.new
yield
yield(given_args.dup)
rescue Thor::Error => e
if debugging
raise e
debugging ? (raise e) : config[:shell].error(e.message)
exit(1) if exit_on_failure?
end

def handle_no_task_error(task) #:nodoc:
if self.banner_base == "thor"
raise UndefinedTaskError, "Could not find task #{task.inspect} in #{namespace.inspect} namespace."
else
config[:shell].error e.message
raise UndefinedTaskError, "Could not find task #{task.inspect}."
end
exit(1) if exit_on_failure?
end

protected
Expand Down Expand Up @@ -419,7 +432,6 @@ def print_options(shell, options, group_name=nil)
end

# Raises an error if the word given is a Thor reserved word.
#
def is_thor_reserved_word?(word, type) #:nodoc:
return false unless THOR_RESERVED_WORDS.include?(word.to_s)
raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}"
Expand All @@ -430,7 +442,6 @@ 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.
#
def build_option(name, options, scope) #:nodoc:
scope[name] = Thor::Option.new(name, options[:desc], options[:required],
options[:type], options[:default], options[:banner],
Expand All @@ -444,7 +455,6 @@ def build_option(name, options, scope) #:nodoc:
#
# ==== Parameters
# Hash[Symbol => Object]
#
def build_options(options, scope) #:nodoc:
options.each do |key, value|
scope[key] = Thor::Option.parse(key, value)
Expand All @@ -454,7 +464,6 @@ def build_options(options, scope) #:nodoc:
# Finds a task with the given name. If the task belongs to the current
# class, just return it, otherwise dup it and add the fresh copy to the
# current task hash.
#
def find_and_refresh_task(name) #:nodoc:
task = if task = tasks[name.to_s]
task
Expand All @@ -467,14 +476,12 @@ def find_and_refresh_task(name) #:nodoc:

# Everytime someone inherits from a Thor class, register the klass
# and file into baseclass.
#
def inherited(klass)
Thor::Base.register_klass_file(klass)
end

# Fire this callback whenever a method is added. Added methods are
# tracked as tasks by invoking the create_task method.
#
def method_added(meth)
meth = meth.to_s

Expand All @@ -495,7 +502,6 @@ def method_added(meth)

# Retrieves a value from superclass. If it reaches the baseclass,
# returns default.
#
def from_superclass(method, default=nil)
if self == baseclass || !superclass.respond_to?(method, true)
default
Expand All @@ -506,11 +512,15 @@ def from_superclass(method, default=nil)
end

# A flag that makes the process exit with status 1 if any error happens.
#
def exit_on_failure?
false
end

# Returns the base for banner.
def banner_base
@banner_base ||= $thor_runner ? "thor" : File.basename($0.split(" ").first)
end

# SIGNATURE: Sets the baseclass. This is where the superclass lookup
# finishes.
def baseclass #:nodoc:
Expand Down
3 changes: 3 additions & 0 deletions lib/bundler/vendor/thor/error.rb
Expand Up @@ -19,6 +19,9 @@ class UndefinedTaskError < Error
class InvocationError < Error
end

class UnknownArgumentError < Error
end

class RequiredArgumentMissingError < InvocationError
end

Expand Down
31 changes: 14 additions & 17 deletions lib/bundler/vendor/thor/invocation.rb
Expand Up @@ -5,21 +5,20 @@ def self.included(base) #:nodoc:
end

module ClassMethods
# Prepare for class methods invocations. This method must return a klass to
# have the invoked class options showed in help messages in generators.
#
# This method is responsible for receiving a name and find the proper
# class and task for it. The key is an optional parameter which is
# available only in class methods invocations (i.e. in Thor::Group).
def prepare_for_invocation(key, name) #:nodoc:
case name
when Symbol, String
Thor::Util.namespace_to_thor_class_and_task(name.to_s, false)
Thor::Util.find_class_and_task_by_namespace(name.to_s)
else
name
end
end
end

# Make initializer aware of invocations and the initializer proc.
#
# Make initializer aware of invocations and the initialization args.
def initialize(args=[], options={}, config={}, &block) #:nodoc:
@_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] }
@_initializer = [ args, options, config ]
Expand All @@ -34,6 +33,8 @@ def initialize(args=[], options={}, config={}, &block) #:nodoc:
# the task to be invoked, if none is given, the same values used to
# initialize the invoker are used to initialize the invoked.
#
# When no name is given, it will invoke the default task of the current class.
#
# ==== Examples
#
# class A < Thor
Expand Down Expand Up @@ -92,9 +93,9 @@ def initialize(args=[], options={}, config={}, &block) #:nodoc:
#
# invoke Rspec::RR, [], :style => :foo
#
def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil)
task, args, opts, config = nil, task, args, opts if task.nil? || task.is_a?(Array)
args, opts, config = nil, args, opts if args.is_a?(Hash)
def invoke(name=nil, *args)
args.unshift(nil) if Array === args.first || NilClass === args.first
task, args, opts, config = args

object, task = _prepare_for_invocation(name, task)
klass, instance = _initialize_klass_with_initializer(object, args, opts, config)
Expand All @@ -121,15 +122,13 @@ def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil)
protected

# Configuration values that are shared between invocations.
#
def _shared_configuration #:nodoc:
{ :invocations => @_invocations }
end

# Prepare for invocation in the instance level. In this case, we have to
# take into account that a just a task name from the current class was
# given or even a Thor::Task object.
#
# This method can receive several different types of arguments and it's then
# responsible to normalize them by returning the object where the task should
# be invoked and a Thor::Task object.
def _prepare_for_invocation(name, sent_task=nil) #:nodoc:
if name.is_a?(Thor::Task)
task = name
Expand All @@ -147,18 +146,16 @@ def _prepare_for_invocation(name, sent_task=nil) #:nodoc:

# Check if the object given is a Thor class object and get a task object
# for it.
#
def _validate_task(object, task) #:nodoc:
klass = object.is_a?(Class) ? object : object.class
raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base

task ||= klass.default_task if klass <= Thor
task ||= klass.default_task if klass.respond_to?(:default_task)
task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task)
task
end

# Initialize klass using values stored in the @_initializer.
#
def _initialize_klass_with_initializer(object, args, opts, config) #:nodoc:
if object.is_a?(Class)
klass = object
Expand Down
9 changes: 5 additions & 4 deletions lib/bundler/vendor/thor/parser/arguments.rb
Expand Up @@ -16,8 +16,9 @@ def self.split(args)
return arguments, args[Range.new(arguments.size, -1)]
end

def self.parse(base, args)
new(base).parse(args)
def self.parse(*args)
to_parse = args.pop
new(*args).parse(to_parse)
end

# Takes an array of Thor::Argument objects.
Expand Down Expand Up @@ -116,7 +117,7 @@ def parse_numeric(name)
return shift if peek.is_a?(Numeric)

unless peek =~ NUMERIC && $& == peek
raise MalformattedArgumentError, "expected numeric value for '#{name}'; got #{peek.inspect}"
raise MalformattedArgumentError, "Expected numeric value for '#{name}'; got #{peek.inspect}"
end

$&.index('.') ? shift.to_f : shift.to_i
Expand All @@ -137,7 +138,7 @@ def check_requirement!
end.join("', '")

class_name = self.class.name.split('::').last.downcase
raise RequiredArgumentMissingError, "no value provided for required #{class_name} '#{names}'"
raise RequiredArgumentMissingError, "No value provided for required #{class_name} '#{names}'"
end
end

Expand Down
4 changes: 0 additions & 4 deletions lib/bundler/vendor/thor/parser/option.rb
Expand Up @@ -55,10 +55,6 @@ def self.parse(key, value)
value
elsif required = (value == :required)
:string
elsif value == :optional
# TODO Remove this warning in the future.
warn "Optional type is deprecated. Choose :boolean or :string instead. Assumed to be :boolean."
:boolean
end
when TrueClass, FalseClass
:boolean
Expand Down
33 changes: 23 additions & 10 deletions lib/bundler/vendor/thor/parser/options.rb
Expand Up @@ -10,7 +10,6 @@ class Options < Arguments #:nodoc:
SHORT_NUM = /^(-[a-z])#{NUMERIC}$/i

# Receives a hash and makes it switches.
#
def self.to_switches(options)
options.map do |key, value|
case value
Expand All @@ -28,12 +27,18 @@ def self.to_switches(options)
end.join(" ")
end

# Takes a hash of Thor::Option objects.
#
def initialize(options={})
options = options.values
# Takes a hash of Thor::Option and a hash with defaults.
def initialize(hash_options={}, defaults={})
options = hash_options.values
super(options)
@shorts, @switches = {}, {}

# Add defaults
defaults.each do |key, value|
@assigns[key.to_s] = value
@non_assigned_required.delete(hash_options[key])
end

@shorts, @switches, @unknown = {}, {}, []

options.each do |option|
@switches[option.switch_name] = option
Expand Down Expand Up @@ -61,16 +66,24 @@ def parse(args)
end

switch = normalize_switch(switch)
next unless option = switch_option(switch)

option = switch_option(switch)
@assigns[option.human_name] = parse_peek(switch, option)
elsif peek =~ /^\-/
@unknown << shift
else
shift
end
end

check_requirement!
@assigns

assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns)
assigns.freeze
assigns
end

def check_unknown!
raise UnknownArgumentError, "Unknown switches '#{@unknown.join(', ')}'" unless @unknown.empty?
end

protected
Expand Down Expand Up @@ -130,7 +143,7 @@ def parse_peek(switch, option)
elsif option.string? && !option.required?
return option.human_name # Return the option name
else
raise MalformattedArgumentError, "no value provided for option '#{switch}'"
raise MalformattedArgumentError, "No value provided for option '#{switch}'"
end
end

Expand Down

0 comments on commit 749214d

Please sign in to comment.