class Thor::Group
commands.
invocations to be done at the class method, which are not available to Thor
is that it invokes all commands at once. It also include some methods that allows
Thor has a special class called Thor::Group. The main difference to Thor class
def _invoke_for_class_method(klass, command = nil, *args, &block) #:nodoc:
invoke and invoke_from_option class methods.
Shortcut to invoke with padding and block handling. Use internally by
def _invoke_for_class_method(klass, command = nil, *args, &block) #:nodoc: with_padding do if block case block.arity when 3 yield(self, klass, command) when 2 yield(self, klass) when 1 instance_exec(klass, &block) end else invoke klass, command, *args end end end
def banner
The banner for this class. You can customize it if you are invoking the
def banner "#{basename} #{self_command.formatted_usage(self, false)}" end
def baseclass #:nodoc:
def baseclass #:nodoc: Thor::Group end
def class_options_help(shell, groups = {}) #:nodoc:
shown recursively when invoking a generator.
Overwrite class options help to allow invoked generators options to be
def class_options_help(shell, groups = {}) #:nodoc: get_options_from_invocations(groups, class_options) do |klass| klass.send(:get_options_from_invocations, groups, class_options) end super(shell, groups) end
def create_command(meth) #:nodoc:
def create_command(meth) #:nodoc: commands[meth.to_s] = Thor::Command.new(meth, nil, nil, nil, nil) true end
def desc(description = nil)
description
==== Parameters
in the superclass.
exists, tries to find the USAGE one folder above it, otherwise searches
The description for this Thor::Group. If none is provided, but a source root
def desc(description = nil) if description @desc = description else @desc ||= from_superclass(:desc, nil) end end
def dispatch(command, given_args, given_opts, config) #:nodoc:
The method responsible for dispatching given the args.
def dispatch(command, given_args, given_opts, config) #:nodoc: if Thor::HELP_MAPPINGS.include?(given_args.first) help(config[:shell]) return end args, opts = Thor::Options.split(given_args) opts = given_opts || opts instance = new(args, opts, config) yield instance if block_given? if command instance.invoke_command(all_commands[command]) else instance.invoke_all end end
def get_options_from_invocations(group_options, base_options) #:nodoc: # rubocop:disable MethodLength
in base_options are not added twice.
options are added to group_options hash. Options that already exists
Get invocations array and merge options from invocations. Those
def get_options_from_invocations(group_options, base_options) #:nodoc: # rubocop:disable MethodLength invocations.each do |name, from_option| value = if from_option option = class_options[name] option.type == :boolean ? name : option.default else name end next unless value klass, _ = prepare_for_invocation(name, value) next unless klass && klass.respond_to?(:class_options) value = value.to_s human_name = value.respond_to?(:classify) ? value.classify : value group_options[human_name] ||= [] group_options[human_name] += klass.class_options.values.select do |class_option| base_options[class_option.name.to_sym].nil? && class_option.group.nil? && !group_options.values.flatten.any? { |i| i.name == class_option.name } end yield klass if block_given? end end
def handle_argument_error(command, error, _args, arity) #:nodoc:
def handle_argument_error(command, error, _args, arity) #:nodoc: msg = "#{basename} #{command.name} takes #{arity} argument".dup msg << "s" if arity > 1 msg << ", but it should not." raise error, msg end
def help(shell)
short:: When true, shows only usage.
==== Options
Prints help information.
def help(shell) shell.say "Usage:" shell.say " #{banner}\n" shell.say class_options_help(shell) shell.say desc if desc end
def invocation_blocks #:nodoc:
Stores invocation blocks used on invoke_from_option.
def invocation_blocks #:nodoc: @invocation_blocks ||= from_superclass(:invocation_blocks, {}) end
def invocations #:nodoc:
Stores invocations for this class merging with superclass values.
def invocations #:nodoc: @invocations ||= from_superclass(:invocations, {}) end
def invoke(*names, &block)
usage. Check invoke_from_option for more information.
The namespace/class given will have its options showed on the help
configure how it will be invoked.
method that will invoke the klass and command. You can give a block to
Invoke the given namespace or class given. It adds an instance
def invoke(*names, &block) options = names.last.is_a?(Hash) ? names.pop : {} verbose = options.fetch(:verbose, true) names.each do |name| invocations[name] = false invocation_blocks[name] = block if block_given? class_eval <<-METHOD, __FILE__, __LINE__ + 1 def _invoke_#{name.to_s.gsub(/\W/, '_')} klass, command = self.class.prepare_for_invocation(nil, #{name.inspect}) if klass say_status :invoke, #{name.inspect}, #{verbose.inspect} block = self.class.invocation_blocks[#{name.inspect}] _invoke_for_class_method klass, command, &block else say_status :error, %(#{name.inspect} [not found]), :red end end METHOD end end
def invoke_from_option(*names, &block)
class and the klass to be invoked.
invoked. The block receives two parameters, an instance of the current
You can also supply a block to customize how the option is going to be
==== Custom invocations
and an optional command.
prepare_for_invocation. The class method must necessarily return a klass
invoked. You can do that by overwriting the class method
In some cases you want to customize how a specified hook is going to be
==== Preparing for invocation
option name is used to invoke the generator.
false. This is automatically handled by invoke_from_option. Then the
In some cases, you want to invoke a thor class if some option is true or
==== Boolean options
end
invoke_from_option :test_framework
class_option :test_framework, :type => :string
class GemGenerator < Thor::Group
==== Examples
method is invoked for each name given.
given option named "name". A class option must be created before this
Invoke a thor class based on the value supplied by the user to the
def invoke_from_option(*names, &block) options = names.last.is_a?(Hash) ? names.pop : {} verbose = options.fetch(:verbose, :white) names.each do |name| unless class_options.key?(name) raise ArgumentError, "You have to define the option #{name.inspect} " \ "before setting invoke_from_option." end invocations[name] = true invocation_blocks[name] = block if block_given? class_eval <<-METHOD, __FILE__, __LINE__ + 1 def _invoke_from_option_#{name.to_s.gsub(/\W/, '_')} return unless options[#{name.inspect}] value = options[#{name.inspect}] value = #{name.inspect} if TrueClass === value klass, command = self.class.prepare_for_invocation(#{name.inspect}, value) if klass say_status :invoke, value, #{verbose.inspect} block = self.class.invocation_blocks[#{name.inspect}] _invoke_for_class_method klass, command, &block else say_status :error, %(\#{value} [not found]), :red end end METHOD end end
def printable_commands(*)
def printable_commands(*) item = [] item << banner item << (desc ? "# #{desc.gsub(/\s+/m, ' ')}" : "") [item] end
def remove_invocation(*names)
remove_invocation :test_framework
==== Examples
Remove a previously added invocation.
def remove_invocation(*names) names.each do |name| remove_command(name) remove_class_option(name) invocations.delete(name) invocation_blocks.delete(name) end end
def self_command #:nodoc:
Represents the whole class as a command.
def self_command #:nodoc: Thor::DynamicCommand.new(namespace, class_options) end