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: