diff options
-rw-r--r-- | lib/bundler/vendor/thor.rb | 123 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/base.rb | 36 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/invocation.rb | 102 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/parser/options.rb | 2 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/shell.rb | 2 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/shell/basic.rb | 8 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/shell/html.rb | 2 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/version.rb | 2 |
8 files changed, 155 insertions, 122 deletions
diff --git a/lib/bundler/vendor/thor.rb b/lib/bundler/vendor/thor.rb index acc547ec..16858446 100644 --- a/lib/bundler/vendor/thor.rb +++ b/lib/bundler/vendor/thor.rb @@ -126,42 +126,6 @@ class Thor build_option(name, options, scope) end - # Parses the task and options from the given args, instantiate the class - # and invoke the task. This method is used when the arguments must be parsed - # from an array. If you are inside Ruby and want to use a Thor class, you - # can simply initialize it: - # - # script = MyScript.new(args, options, config) - # script.invoke(:task, first_arg, second_arg, third_arg) - # - def start(original_args=ARGV, config={}) - @@original_args = original_args - - super do |given_args| - meth = given_args.first.to_s - - if !meth.empty? && (map[meth] || meth !~ /^\-/) - given_args.shift - else - meth = nil - end - - meth = normalize_task_name(meth) - task = all_tasks[meth] - - if task - args, opts = Thor::Options.split(given_args) - config.merge!(:task_options => task.options) - else - args, opts = given_args, {} - end - - task ||= Thor::DynamicTask.new(meth) - trailing = args[Range.new(arguments.size, -1)] - new(args, opts, config).invoke(task, trailing || []) - end - end - # Prints help information for the given task. # # ==== Parameters @@ -215,25 +179,81 @@ class Thor end def subcommands - @@subcommands ||= {} + @subcommands ||= from_superclass(:subcommands, []) end def subcommand(subcommand, subcommand_class) - subcommand = subcommand.to_s - subcommands[subcommand] = subcommand_class + self.subcommands << subcommand.to_s subcommand_class.subcommand_help subcommand - define_method(subcommand) { |*_| subcommand_class.start(subcommand_args) } + define_method(subcommand) { |*args| invoke subcommand_class, args } + end + + # Extend check unknown options to accept a hash of conditions. + # + # === Parameters + # options<Hash>: A hash containing :only and/or :except keys + def check_unknown_options!(options={}) + @check_unknown_options ||= Hash.new + options.each do |key, value| + if value + @check_unknown_options[key] = Array(value) + else + @check_unknown_options.delete(key) + end + end + @check_unknown_options + end + + # Overwrite check_unknown_options? to take subcommands and options into account. + def check_unknown_options?(config) #:nodoc: + options = check_unknown_options + return false unless options + + task = config[:current_task] + return true unless task + + name = task.name + + if subcommands.include?(name) + false + elsif options[:except] + !options[:except].include?(name.to_sym) + elsif options[:only] + options[:only].include?(name.to_sym) + else + true + end end protected + # The method responsible for dispatching given the args. + def dispatch(meth, given_args, given_opts, config) #:nodoc: + meth ||= retrieve_task_name(given_args) + task = all_tasks[normalize_task_name(meth)] + + if task + args, opts = Thor::Options.split(given_args) + else + args, opts = given_args, nil + task = Thor::DynamicTask.new(meth) + end + + opts = given_opts || opts || [] + config.merge!(:current_task => task, :task_options => task.options) + + trailing = args[Range.new(arguments.size, -1)] + new(args, opts, config).invoke_task(task, trailing || []) + end + # The banner for this class. You can customize it if you are invoking the # thor class by another ways which is not the Thor::Runner. It receives # the task that is going to be invoked and a boolean which indicates if # the namespace should be displayed as arguments. # def banner(task, namespace = nil, subcommand = false) - "#{$0} #{task.formatted_usage(self, $thor_runner, subcommand)}" + base = File.basename($0).split(" ").first + "#{base} #{task.formatted_usage(self, $thor_runner, subcommand)}" end def baseclass #:nodoc: @@ -243,10 +263,10 @@ class Thor def create_task(meth) #:nodoc: if @usage && @desc base_class = @hide ? Thor::HiddenTask : Thor::Task - tasks[meth.to_s] = base_class.new(meth, @desc, @long_desc, @usage, method_options) + tasks[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options) @usage, @desc, @long_desc, @method_options, @hide = nil true - elsif self.all_tasks[meth.to_s] || meth.to_sym == :method_missing + elsif self.all_tasks[meth] || meth == "method_missing" true else puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " << @@ -261,9 +281,19 @@ class Thor @method_options = nil end + # Retrieve the task name from given args. + def retrieve_task_name(args) #:nodoc: + meth = args.first.to_s unless args.empty? + + if meth && (map[meth] || meth !~ /^\-/) + args.shift + else + nil + end + end + # Receives a task name (can be nil), and try to get a map from it. # If a map can't be found use the sent name or the default task. - # def normalize_task_name(meth) #:nodoc: meth = map[meth.to_s] || meth || default_task meth.to_s.gsub('-','_') # treat foo-bar > foo_bar @@ -275,11 +305,6 @@ class Thor def help(task = nil, subcommand = true); super; end RUBY end - - end - - def subcommand_args - @@original_args[1..-1] end include Thor::Base diff --git a/lib/bundler/vendor/thor/base.rb b/lib/bundler/vendor/thor/base.rb index 9798cb7e..6412ace6 100644 --- a/lib/bundler/vendor/thor/base.rb +++ b/lib/bundler/vendor/thor/base.rb @@ -53,7 +53,7 @@ class Thor opts = Thor::Options.new(parse_options, hash_options) self.options = opts.parse(array_options) - opts.check_unknown! if self.class.check_unknown_options? + opts.check_unknown! if self.class.check_unknown_options?(config) end class << self @@ -114,8 +114,12 @@ class Thor @check_unknown_options = true end - def check_unknown_options? #:nodoc: - @check_unknown_options || false + def check_unknown_options #:nodoc: + @check_unknown_options ||= from_superclass(:check_unknown_options, false) + end + + def check_unknown_options?(config) #:nodoc: + !!check_unknown_options end # Adds an argument to the class and creates an attr_accessor for it. @@ -364,19 +368,25 @@ class Thor # def namespace(name=nil) case name - when nil - @namespace ||= Thor::Util.namespace_from_thor_class(self) - else - @namespace = name.to_s + when nil + @namespace ||= Thor::Util.namespace_from_thor_class(self) + else + @namespace = name.to_s end end - # Default way to start generators from the command line. + # Parses the task and options from the given args, instantiate the class + # and invoke the task. This method is used when the arguments must be parsed + # from an array. If you are inside Ruby and want to use a Thor class, you + # can simply initialize it: + # + # script = MyScript.new(args, options, config) + # script.invoke(:task, first_arg, second_arg, third_arg) # def start(given_args=ARGV, config={}) - self.debugging = given_args.include?("--debug") + self.debugging = given_args.delete("--debug") config[:shell] ||= Thor::Base.shell.new - yield(given_args.dup) + dispatch(nil, given_args.dup, nil, config) rescue Thor::Error => e debugging ? (raise e) : config[:shell].error(e.message) exit(1) if exit_on_failure? @@ -535,6 +545,12 @@ class Thor # class. def initialize_added #:nodoc: end + + # SIGNATURE: The hook invoked by start. + def dispatch(task, given_args, given_opts, config) #:nodoc: + raise NotImplementedError + end + end end end diff --git a/lib/bundler/vendor/thor/invocation.rb b/lib/bundler/vendor/thor/invocation.rb index 73c8bb5d..6315dd42 100644 --- a/lib/bundler/vendor/thor/invocation.rb +++ b/lib/bundler/vendor/thor/invocation.rb @@ -10,10 +10,10 @@ class Thor # 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.find_class_and_task_by_namespace(name.to_s, !key) - else - name + when Symbol, String + Thor::Util.find_class_and_task_by_namespace(name.to_s, !key) + else + name end end end @@ -94,29 +94,34 @@ class Thor # invoke Rspec::RR, [], :style => :foo # def invoke(name=nil, *args) + if name.nil? + warn "[Thor] Calling invoke() without argument is deprecated. Please use invoke_all instead.\n#{caller.join("\n")}" + return invoke_all + end + 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) + klass, task = _retrieve_class_and_task(name, task) + raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base + + args, opts, config = _parse_initialization_options(args, opts, config) + klass.send(:dispatch, task, args, opts, config) + end - method_args = [] - current = @_invocations[klass] + # Invoke the given task if the given args. + def invoke_task(task, *args) #:nodoc: + current = @_invocations[self.class] - iterator = proc do |_, task| - unless current.include?(task.name) - current << task.name - task.run(instance, method_args) - end + unless current.include?(task.name) + current << task.name + task.run(self, *args) end + end - if task - args ||= [] - method_args = args[Range.new(klass.arguments.size, -1)] || [] - iterator.call(nil, task) - else - klass.all_tasks.map(&iterator) - end + # Invoke all tasks for the current instance. + def invoke_all #:nodoc: + self.class.all_tasks.map { |_, task| invoke_task(task) } end # Invokes using shell padding. @@ -131,50 +136,33 @@ class Thor { :invocations => @_invocations } end - # 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 - elsif task = self.class.all_tasks[name.to_s] - object = self + # This method simply retrieves the class and task to be invoked. + # If the name is nil or the given name is a task in the current class, + # use the given name and return self as class. Otherwise, call + # prepare_for_invocation in the current class. + def _retrieve_class_and_task(name, sent_task=nil) #:nodoc: + case + when name.nil? + [self.class, nil] + when self.class.all_tasks[name.to_s] + [self.class, name.to_s] else - object, task = self.class.prepare_for_invocation(nil, name) - task ||= sent_task + klass, task = self.class.prepare_for_invocation(nil, name) + [klass, task || sent_task] end - - # If the object was not set, use self and use the name as task. - object, task = self, name unless object - return object, _validate_task(object, task) - end - - # 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.respond_to?(:default_task) - task = klass.all_tasks[task.to_s] || Thor::DynamicTask.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 + def _parse_initialization_options(args, opts, config) #:nodoc: + stored_args, stored_opts, stored_config = @_initializer - stored_args, stored_opts, stored_config = @_initializer - args ||= stored_args.dup - opts ||= stored_opts.dup + args ||= stored_args.dup + opts ||= stored_opts.dup - config ||= {} - config = stored_config.merge(_shared_configuration).merge!(config) - [ klass, klass.new(args, opts, config) ] - else - [ object.class, object ] - end + config ||= {} + config = stored_config.merge(_shared_configuration).merge!(config) + + [ args, opts, config ] end end end diff --git a/lib/bundler/vendor/thor/parser/options.rb b/lib/bundler/vendor/thor/parser/options.rb index 8da20f6b..bd0b892d 100644 --- a/lib/bundler/vendor/thor/parser/options.rb +++ b/lib/bundler/vendor/thor/parser/options.rb @@ -151,6 +151,8 @@ class Thor elsif option.string? && !option.required? # Return the default if there is one, else the human name return option.lazy_default || option.default || option.human_name + elsif option.lazy_default + return option.lazy_default else raise MalformattedArgumentError, "No value provided for option '#{switch}'" end diff --git a/lib/bundler/vendor/thor/shell.rb b/lib/bundler/vendor/thor/shell.rb index 58bde8b3..2214202b 100644 --- a/lib/bundler/vendor/thor/shell.rb +++ b/lib/bundler/vendor/thor/shell.rb @@ -27,7 +27,7 @@ class Thor autoload :Basic, 'thor/shell/basic' autoload :Color, 'thor/shell/color' - autoload :HTML, 'thor/shell/HTML' + autoload :HTML, 'thor/shell/html' # Add shell to initialize config values. # diff --git a/lib/bundler/vendor/thor/shell/basic.rb b/lib/bundler/vendor/thor/shell/basic.rb index 39249ffc..9235f00a 100644 --- a/lib/bundler/vendor/thor/shell/basic.rb +++ b/lib/bundler/vendor/thor/shell/basic.rb @@ -35,8 +35,8 @@ class Thor # say("I know you knew that.") # def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/)) - message = message.to_s - message = set_color(message, color) if color + message = message.to_s + message = set_color(message, color) if color spaces = " " * padding @@ -60,7 +60,9 @@ class Thor status = status.to_s.rjust(12) status = set_color status, color, true if color - say "#{status}#{spaces}#{message}", nil, true + + $stdout.puts "#{status}#{spaces}#{message}" + $stdout.flush end # Make a question the to user and returns true if the user replies "y" or diff --git a/lib/bundler/vendor/thor/shell/html.rb b/lib/bundler/vendor/thor/shell/html.rb index d1952862..b8b3f9c5 100644 --- a/lib/bundler/vendor/thor/shell/html.rb +++ b/lib/bundler/vendor/thor/shell/html.rb @@ -58,7 +58,7 @@ class Thor bold, end_bold = bold ? [BOLD, END_BOLD] : ['', ''] "#{bold}#{color}#{string}#{CLEAR}#{end_bold}" end - + # Ask something to the user and receives a response. # # ==== Example diff --git a/lib/bundler/vendor/thor/version.rb b/lib/bundler/vendor/thor/version.rb index 503cd65b..b3efbb53 100644 --- a/lib/bundler/vendor/thor/version.rb +++ b/lib/bundler/vendor/thor/version.rb @@ -1,3 +1,3 @@ class Thor - VERSION = "0.13.8".freeze + VERSION = "0.14.0".freeze end |