lib/thor/base.rb in thor-0.13.1 vs lib/thor/base.rb in thor-0.13.2
- old
+ new
@@ -36,13 +36,12 @@
# access, magic predicates (options.skip?) and then frozen.
#
# 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
if options.is_a?(Array)
task_options = config.delete(:task_options) # hook for start
@@ -50,13 +49,13 @@
array_options, hash_options = options, {}
else
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
def included(base) #:nodoc:
base.send :extend, ClassMethods
@@ -107,10 +106,20 @@
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
# is how they are parsed from the command line, arguments are retrieved
# from position:
@@ -353,29 +362,33 @@
# thor :my_task
#
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
end
# Default way to start generators from the command line.
#
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
# Prints the class options per group. If an option does not belong to
@@ -417,22 +430,20 @@
shell.print_table(list, :ident => 2)
shell.say ""
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}"
end
# Build an option and adds it to the given scope.
#
# ==== 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],
options[:group], options[:aliases])
end
@@ -442,21 +453,19 @@
#
# build_options :foo => true, :bar => :required, :baz => :string
#
# ==== Parameters
# Hash[Symbol => Object]
- #
def build_options(options, scope) #:nodoc:
options.each do |key, value|
scope[key] = Thor::Option.parse(key, value)
end
end
# 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
elsif task = all_tasks[name.to_s]
tasks[name.to_s] = task.clone
@@ -465,18 +474,16 @@
end
end
# 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
if meth == "initialize"
initialize_added
@@ -493,23 +500,26 @@
Thor::Base.register_klass_file(self)
end
# 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
else
value = superclass.send(method)
value.dup if value
end
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: