module Bundler::Thor::Invocation

def self.included(base) #:nodoc:

:nodoc:
def self.included(base) #:nodoc:
  super(base)
  base.extend ClassMethods
end

def _parse_initialization_options(args, opts, config) #:nodoc:

:nodoc:
Initialize klass using values stored in the @_initializer.
def _parse_initialization_options(args, opts, config) #:nodoc:
  stored_args, stored_opts, stored_config = @_initializer
  args ||= stored_args.dup
  opts ||= stored_opts.dup
  config ||= {}
  config = stored_config.merge(_shared_configuration).merge!(config)
  [args, opts, config]
end

def _retrieve_class_and_command(name, sent_command = nil) #:nodoc:

:nodoc:
prepare_for_invocation in the current class.
use the given name and return self as class. Otherwise, call
If the name is nil or the given name is a command in the current class,
This method simply retrieves the class and command to be invoked.
def _retrieve_class_and_command(name, sent_command = nil) #:nodoc:
  if name.nil?
    [self.class, nil]
  elsif self.class.all_commands[name.to_s]
    [self.class, name.to_s]
  else
    klass, command = self.class.prepare_for_invocation(nil, name)
    [klass, command || sent_command]
  end
end

def _shared_configuration #:nodoc:

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

def current_command_chain

Make the current command chain accessible with in a Bundler::Thor-(sub)command
def current_command_chain
  @_invocations.values.flatten.map(&:to_sym)
end

def initialize(args = [], options = {}, config = {}, &block) #:nodoc:

:nodoc:
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]
  super
end

def invoke(name = nil, *args)


invoke Rspec::RR, [], :style => :foo

Besides giving an instance, you can also give a class to invoke:

invoke "rspec:rr", [], :style => :foo

have to do that explicitly:
If you want Rspec::RR to be initialized with its own set of options, you

that it's going to use.
is invoked all options are parsed again, so RR can extract only the options
Since it's not rspec concern to parse mock framework options, when RR

end
class_option :style, :type => :string, :default => :mock
class Rspec::RR < Bundler::Thor::Group

own options:
As you noticed, it invokes the given mock framework, which might have its

end
end
invoke "rspec:#{options[:mock_framework]}"
def invoke_mock_framework

class_option :mock_framework, :type => :string, :default => :rr
class Rspec < Bundler::Thor::Group

some rspec commands:
supplied to B. This allows lazy parse of options. Let's suppose you have
When class A invokes class B, all arguments used on A initialization are

if it's invoked later by "bar" method.
In the example above, invoking "foo" will invoke "b:hello" just once, even
By using an invocation system you ensure that a command is invoked only once.

which belongs to the same class and "hello" which belongs to the class B.
You can notice that the method "foo" above invokes two commands: "bar",

end
end
puts "hello #{name}"
def hello(name)
class B < Bundler::Thor

end
end
invoke "b:hello", ["Erik"]
def bar

end
invoke "b:hello", ["Erik"]
invoke :bar
def foo
class A < Bundler::Thor

==== Examples

When no name is given, it will invoke the default command of the current class.

initialize the invoker are used to initialize the invoked.
the command to be invoked, if none is given, the same values used to
You can also supply the arguments, options and configuration values for

command cannot be guessed by name, it can also be supplied as second argument.
"namespace:command"), a Bundler::Thor::Command, a Class or a Bundler::Thor instance. If the
Receives a name and invokes it. The name can be a string (either "command" or
def invoke(name = nil, *args)
  if name.nil?
    warn "[Bundler::Thor] Calling invoke() without argument is deprecated. Please use invoke_all instead.\n#{caller.join("\n")}"
    return invoke_all
  end
  args.unshift(nil) if args.first.is_a?(Array) || args.first.nil?
  command, args, opts, config = args
  klass, command = _retrieve_class_and_command(name, command)
  raise "Missing Bundler::Thor class for invoke #{name}" unless klass
  raise "Expected Bundler::Thor class, got #{klass}" unless klass <= Bundler::Thor::Base
  args, opts, config = _parse_initialization_options(args, opts, config)
  klass.send(:dispatch, command, args, opts, config) do |instance|
    instance.parent_options = options
  end
end

def invoke_all #:nodoc:

:nodoc:
Invoke all commands for the current instance.
def invoke_all #:nodoc:
  self.class.all_commands.map { |_, command| invoke_command(command) }
end

def invoke_command(command, *args) #:nodoc:

:nodoc:
Invoke the given command if the given args.
def invoke_command(command, *args) #:nodoc:
  current = @_invocations[self.class]
  unless current.include?(command.name)
    current << command.name
    command.run(self, *args)
  end
end

def invoke_with_padding(*args)

Invokes using shell padding.
def invoke_with_padding(*args)
  with_padding { invoke(*args) }
end