class Object

Public Class Methods

banner(command, namespace = nil, subcommand = false) click to toggle source

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 command that is going to be invoked and a boolean which indicates if the namespace should be displayed as arguments.

@param [Thor::Command] command

The command to render the banner for.

@param [nil | ?] namespace

*Atli*: this argument is _not_ _used_ _at_ _all_. I don't know what it
could or should be, but it doesn't seem like it matters at all :/

@param [Boolean] subcommand

Should be +true+ if the command was invoked as a sub-command; passed
on to {Command#formatted_usage} so it can render correctly.

@return [String]

The banner for the command.
dispatch(meth, given_args, given_opts, config) { |instance| ... } click to toggle source

The method responsible for dispatching given the args.

@param [nil | String | Symbol] meth

The method name of the command to run, which I *think* will be `nil`
when running the "default command"? haven't messed with that yet...

@param [Array<String>] given_args

# File lib/thor.rb, line 573
def self.dispatch meth, given_args, given_opts, config # rubocop:disable MethodLength
  logger.trace "START #{ self.safe_name }.#{ __method__ }",
    meth: meth,
    given_args: given_args,
    given_opts: given_opts,
    config: config

  meth ||= retrieve_command_name( given_args ).tap { |new_meth|
    logger.trace "meth set via .retrieve_command_name",
      meth: new_meth,
      map: map
  }

  normalized_name = normalize_command_name meth
  command = all_commands[normalized_name]

  logger.trace "Fetched command",
    command: command,
    all_commands: all_commands.keys,
    normalized_name: normalized_name

  if !command && config[:invoked_via_subcommand]
    # We're a subcommand and our first argument didn't match any of our
    # commands. So we put it back and call our default command.
    given_args.unshift(meth)
    command = all_commands[normalize_command_name(default_command)]
  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 = given_args
    opts = nil
    command = dynamic_command_class.new(meth)
  end

  opts = given_opts || opts || []
  config[:current_command] = command
  config[:command_options] = command.options

  instance = new(args, opts, config)
  yield instance if block_given?
  args = instance.args
  trailing = args[ arguments( command: command ).size..-1 ]
  instance.invoke_command(command, trailing || [])
end
find_command_possibilities(input) click to toggle source

This is the logic that takes the command name passed in by the user and determines whether it is an unambiguous prefix of a command or alias name.

@param [#to_s] input

Input to match to command names.
# File lib/thor.rb, line 770
def self.find_command_possibilities input
  input = input.to_s

  possibilities = all_commands.merge(map).keys.select { |name|
    name.start_with? input
  }.sort

  unique_possibilities = possibilities.map { |k| map[k] || k }.uniq

  results = if possibilities.include? input
    [ input ]
  elsif unique_possibilities.size == 1
    unique_possibilities
  else
    possibilities
  end

  logger.trace "Found #{ results.length } command possibilities",
    results: results,
    possibilities: possibilities,
    unique_possibilities: unique_possibilities
  
  results
end
retrieve_command_name(args) click to toggle source

Retrieve the command name from given args.

@note

Ugh... this *mutates* `args`

@param [Array<String>] args

@return [nil]`

# File lib/thor.rb, line 718
def self.retrieve_command_name args
  meth = args.first.to_s unless args.empty?
  args.shift if meth && (map[meth] || meth !~ /^\-/)
end
subcommand_help(cmd) click to toggle source
Calls superclass method
# File lib/thor.rb, line 799
def self.subcommand_help(cmd)
  # logger.trace __method__.to_s,
  #   cmd: cmd,
  #   caller: caller
  
  desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
  
  # Atli -  This used to be {#class_eval} (maybe to support really old
  #         Rubies? Who knows...) but that made it really hard to find in
  #         stack traces, so I switched it to {#define_method}.
  #
  define_method :help do |*args|
    
    # Add the `is_subcommand = true` trailing arg
    case args[-1]
    when true
      # pass
    when false
      # Weird, `false` was explicitly passed... whatever, set it to `true`
      args[-1] = true
    else
      # "Normal" case, append it
      args << true
    end
    
    super( *args )
  end
  
end

Public Instance Methods

help(*args) click to toggle source
# File lib/thor.rb, line 882
def help(*args)
  is_subcommand = case args[-1]
  when true, false
    args.pop
  else
    false
  end
  
  # Will be the {String} command (get help on that command)
  # or `nil` (get help on this class)
  command = args.shift
  
  # Possibly empty array of string subcommands from something like
  #
  #     myexe help sub cmd
  #
  # in which case it would end up being `['cmd']` and we actually are just
  # passing through and want to get help on the `cmd` subcommand.
  #
  subcommands = args
  
  logger.trace "#help",
    args: args,
    command: command,
    is_subcommand: is_subcommand,
    subcommands: subcommands
  
  if command
    if self.class.subcommands.include? command
      if subcommands.empty?
        # Get help on a subcommand *class*
        self.class.subcommand_classes[command].help(shell, true)
      else
        # Atli addition - handle things like `myexe help sub cmd`
        # Want help on something (class or command) further down the line
        invoke  self.class.subcommand_classes[command],
                ['help', *subcommands],
                {},
                {:invoked_via_subcommand => true, :class_options => options}
      end
    else
      # Want help on a *command* of this class
      #
      # Atli -  Now that we've modified {.command_help} to accept
      #         `subcommand`, pass it (it seems to have already been getting
      #         the correct value to here).
      self.class.command_help(shell, command, is_subcommand)
    end
  else
    # We want help on *this class itself* (list available commands)
    self.class.help(shell, is_subcommand)
  end
end
namespace(name) click to toggle source
Calls superclass method
# File lib/thor/rake_compat.rb, line 60
def namespace(name)
  if klass = Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition
    const_name = Thor::Util.camel_case(name.to_s).to_sym
    klass.const_set(const_name, Class.new(Thor))
    new_klass = klass.const_get(const_name)
    Thor::RakeCompat.rake_classes << new_klass
  end

  super
  Thor::RakeCompat.rake_classes.pop
end
Also aliased as: rake_namespace
option_kwds(*names, groups: nil) click to toggle source

Get a Hash mapping option name symbols to their values ready for +**+ usage in a method call for the option names and shared option groups.

@param (see .find_shared_method_options)

@return [Hash<Symbol, V>]

Map of option name to value.
# File lib/thor.rb, line 847
def option_kwds *names, groups: nil
  # Transform names into a set of strings
  name_set = Set.new names.map( &:to_s )
  
  # Add groups (if any)
  if groups
    groups = Array( groups )
    
    self.class.
      shared_defs.
      select { |shared_def|
        groups.any? { |group| shared_def[ :groups].include? group }
      }.
      each do |shared|
        name_set << shared[:name].to_s
      end
  end
  
  options.slice( *name_set ).sym_keys
end
rake_namespace(name)
Alias for: namespace
task(*) click to toggle source
Calls superclass method
# File lib/thor/rake_compat.rb, line 40
def task(*)
  task = super

  if klass = Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition
    non_namespaced_name = task.name.split(":").last

    description = non_namespaced_name
    description << task.arg_names.map { |n| n.to_s.upcase }.join(" ")
    description.strip!

    klass.desc description, Rake.application.last_description || non_namespaced_name
    Rake.application.last_description = nil
    klass.send :define_method, non_namespaced_name do |*args|
      Rake::Task[task.name.to_sym].invoke(*args)
    end
  end

  task
end