class Thor
def banner(command, namespace = nil, subcommand = false)
the namespace should be displayed as arguments.
the command that is going to be invoked and a boolean which indicates if
thor class by another ways which is not the Thor::Runner. It receives
The banner for this class. You can customize it if you are invoking the
def banner(command, namespace = nil, subcommand = false) "#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}" end
def baseclass #:nodoc:
def baseclass #:nodoc: Thor end
def check_unknown_options!(options={})
=== Parameters
Extend check unknown options to accept a hash of conditions.
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
def check_unknown_options?(config) #:nodoc:
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 command = config[:current_command] return true unless command name = command.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
def command_help(shell, command_name)
command_name
shell
==== Parameters
Prints help information for the given command.
def command_help(shell, command_name) meth = normalize_command_name(command_name) command = all_commands[meth] handle_no_command_error(meth) unless command shell.say "Usage:" shell.say " #{banner(command)}" shell.say class_options_help(shell, nil => command.options.map { |_, o| o }) if command.long_description shell.say "Description:" shell.print_wrapped(command.long_description, :indent => 2) else shell.say command.description end end
def create_command(meth) #:nodoc:
def create_command(meth) #:nodoc: if @usage && @desc base_class = @hide ? Thor::HiddenCommand : Thor::Command commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options) @usage, @desc, @long_desc, @method_options, @hide = nil true elsif self.all_commands[meth] || meth == "method_missing" true else puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " << "Call desc if you want this method to be available as command or declare it inside a " << "no_commands{} block. Invoked from #{caller[1].inspect}." false end end
def default_command(meth=nil)
meth
==== Parameters
Sets the default command when thor is executed without an explicit command to be called.
def default_command(meth=nil) @default_command = case meth when :none 'help' when nil @default_command || from_superclass(:default_command, 'help') else meth.to_s end end
def desc(usage, description, options={})
options
description
usage
==== Parameters
Defines the usage and the description of the next command.
def desc(usage, description, options={}) if options[:for] command = find_and_refresh_command(options[:for]) command.usage = usage if usage command.description = description if description else @usage, @desc, @hide = usage, description, options[:hide] || false end end
def dispatch(meth, given_args, given_opts, config) #:nodoc:
The method responsible for dispatching given the args.
def dispatch(meth, given_args, given_opts, config) #:nodoc: # There is an edge case when dispatching from a subcommand. # A problem occurs invoking the default command. This case occurs # when arguments are passed and a default command is defined, and # the first given_args does not match the default command. # Thor use "help" by default so we skip that case. # Note the call to retrieve_command_name. It's called with # given_args.dup since that method calls args.shift. Then lookup # the command normally. If the first item in given_args is not # a command then use the default command. The given_args will be # intact later since dup was used. if config[:invoked_via_subcommand] && given_args.size >= 1 && default_command != "help" && given_args.first != default_command meth ||= retrieve_command_name(given_args.dup) command = all_commands[normalize_command_name(meth)] command ||= all_commands[normalize_command_name(default_command)] else meth ||= retrieve_command_name(given_args) command = all_commands[normalize_command_name(meth)] end if command args, opts = Thor::Options.split(given_args) if stop_on_unknown_option?(command) && !args.empty? # given_args starts with a non-option, so we treat everything as # ordinary arguments args.concat opts opts.clear end else args, opts = given_args, nil command = Thor::DynamicCommand.new(meth) end opts = given_opts || opts || [] config.merge!(:current_command => command, :command_options => command.options) instance = new(args, opts, config) yield instance if block_given? args = instance.args trailing = args[Range.new(arguments.size, -1)] instance.invoke_command(command, trailing || []) end
def find_command_possibilities(meth)
and determines whether it is an unambiguous substrings of a command or
this is the logic that takes the command name passed in by the user
def find_command_possibilities(meth) len = meth.to_s.length possibilities = all_commands.merge(map).keys.select { |n| meth == n[0, len] }.sort unique_possibilities = possibilities.map { |k| map[k] || k }.uniq if possibilities.include?(meth) [meth] elsif unique_possibilities.size == 1 unique_possibilities else possibilities end end
def help(shell, subcommand = false)
shell
==== Parameters
Prints help information for this class.
def help(shell, subcommand = false) list = printable_commands(true, subcommand) Thor::Util.thor_classes_in(self).each do |klass| list += klass.printable_commands(false) end list.sort!{ |a,b| a[0] <=> b[0] } if @package_name shell.say "#{@package_name} commands:" else shell.say "Commands:" end shell.print_table(list, :indent => 2, :truncate => true) shell.say class_options_help(shell) end
def help(command = nil, subcommand = false)
def help(command = nil, subcommand = false) command ? self.class.command_help(shell, command) : self.class.help(shell, subcommand) end
def initialize_added #:nodoc:
def initialize_added #:nodoc: class_options.merge!(method_options) @method_options = nil end
def long_desc(long_description, options={})
long description
==== Parameters
Defines the long description of the next command.
def long_desc(long_description, options={}) if options[:for] command = find_and_refresh_command(options[:for]) command.long_description = long_description if long_description else @long_desc = long_description end end
def map(mappings=nil)
Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command.
==== Parameters
Will invoke the list command.
thor -T
Running:
map "-T" => "list"
Maps an input to a command. If you define:
def map(mappings=nil) @map ||= from_superclass(:map, {}) if mappings mappings.each do |key, value| if key.respond_to?(:each) key.each {|subkey| @map[subkey] = value} else @map[key] = value end end end @map end
def method_option(name, options={})
:hide - If you want to hide this option from the help.
:banner - String to show on usage notes.
:type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean.
:aliases - Aliases for this option.
:default - Default value for this argument. It cannot be required and have default values.
:required - If the argument is required or not.
:desc - Description for the argument.
==== Options
options
name
==== Parameters
end
# magic
def next_command
method_option :foo => :bar, :for => :previous_command
end
# magic
def previous_command
it allows you to change the options from a previous defined command.
Adds an option to the set of method options. If :for is given as option,
def method_option(name, options={}) scope = if options[:for] find_and_refresh_command(options[:for]).options else method_options end build_option(name, options, scope) end
def method_options(options=nil)
or :required (string). If you give a value, the type of the value is used.
is the type of the option. Can be :string, :array, :hash, :boolean, :numeric
Hash[Symbol => Object]:: The hash key is the name of the option and the value
==== Parameters
Declares the options for the next command to be declared.
def method_options(options=nil) @method_options ||= {} build_options(options, @method_options) if options @method_options end
def normalize_command_name(meth) #:nodoc:
into +animal_prison+.
+normalize_command_name+ also converts names like +animal-prison+
a command or alias.
will determine if a shortened command is an unambiguous substring of
the commands hash. In addition to normalizing aliases, this logic
receives a (possibly nil) command name and returns a name that is in
def normalize_command_name(meth) #:nodoc: return default_command.to_s.gsub('-', '_') unless meth possibilities = find_command_possibilities(meth) if possibilities.size > 1 raise AmbiguousTaskError, "Ambiguous command #{meth} matches [#{possibilities.join(', ')}]" elsif possibilities.size < 1 meth = meth || default_command elsif map[meth] meth = map[meth] else meth = possibilities.first end meth.to_s.gsub('-','_') # treat foo-bar as foo_bar end
def package_name(name, options={})
options
name
=== Parameters
Allows for custom "Command" package naming.
def package_name(name, options={}) @package_name = name.nil? || name == '' ? nil : name end
def printable_commands(all = true, subcommand = false)
def printable_commands(all = true, subcommand = false) (all ? all_commands : commands).map do |_, command| next if command.hidden? item = [] item << banner(command, false, subcommand) item << (command.description ? "# #{command.description.gsub(/\s+/m,' ')}" : "") item end.compact end
def register(klass, subcommand_name, usage, description, options={})
usage
command
klass
==== Parameters
Registers another Thor subclass as a command.
def register(klass, subcommand_name, usage, description, options={}) if klass <= Thor::Group desc usage, description, options define_method(subcommand_name) { |*args| invoke(klass, args) } else desc usage, description, options subcommand subcommand_name, klass end end
def retrieve_command_name(args) #:nodoc:
Retrieve the command name from given args.
def retrieve_command_name(args) #:nodoc: meth = args.first.to_s unless args.empty? if meth && (map[meth] || meth !~ /^\-/) args.shift else nil end end
def stop_on_unknown_option!(*command_names)
==== Parameters
--verbose foo
$ thor exec echo --verbose foo
But if +--verbose+ is given after +echo+, it is passed to +echo+ instead:
foo
diagnostic output
$ thor exec --verbose echo foo
e.g.:
Here +exec+ can be called with +--verbose+ to get diagnostic output,
end
Kernel.exec(*args)
puts "diagnostic output" if options[:verbose]
def exec(*args)
desc "exec", "Run a shell command"
check_unknown_options! :except => :exec
stop_on_unknown_option! :exec
class_option "verbose", :type => :boolean
which should be handled by Thor.
arguments to that command. The command itself also accepts some options,
an external command. A user may want to pass arbitrary options and
To better understand how this is useful, let's consider a command that calls
==== Example
Thor.
options, and where those additional options should not be handled by
This is useful if you have a command that can receive arbitrary additional
argument is encountered. All remaining arguments are passed to the command.
Stop parsing of options as soon as an unknown option or a regular
def stop_on_unknown_option!(*command_names) @stop_on_unknown_option ||= Set.new @stop_on_unknown_option.merge(command_names) end
def stop_on_unknown_option?(command) #:nodoc:
def stop_on_unknown_option?(command) #:nodoc: command && !@stop_on_unknown_option.nil? && @stop_on_unknown_option.include?(command.name.to_sym) end
def subcommand(subcommand, subcommand_class)
def subcommand(subcommand, subcommand_class) self.subcommands << subcommand.to_s subcommand_class.subcommand_help subcommand define_method(subcommand) do |*args| args, opts = Thor::Arguments.split(args) invoke subcommand_class, args, opts, :invoked_via_subcommand => true, :class_options => options end end
def subcommand_help(cmd)
def subcommand_help(cmd) desc "help [COMMAND]", "Describe subcommands or one specific subcommand" class_eval <<-RUBY def help(command = nil, subcommand = true); super; end RUBY end
def subcommands
def subcommands @subcommands ||= from_superclass(:subcommands, []) end