module Thor::Base

Shared base behavior included in {Thor} and {Thor::Group}.

Declarations

Attributes

shell[W]
args[RW]

Attributes

options[RW]

Attributes

parent_options[RW]

Attributes

Public Class Methods

included(base) click to toggle source

Hook called when {Thor::Base} is mixed in ({Thor} and {Thor::Group}).

Extends `base` with {Thor::Base::ClassMethods}, and includes {Thor::Invocation} and {Thor::Shell} in `base` as well.

@param [Module] base

Module (or Class) that included {Thor::Base}.

@return [void]

# File lib/thor/base.rb, line 66
def self.included base
  base.extend ClassMethods
  base.send :include, Invocation
  base.send :include, Shell
  base.send :include, ArgumentsConcern
  base.send :include, SharedConcern
  
  base.no_commands {
    base.send :include, NRSER::Log::Mixin
  }
  
end
new(args = [], options_args_or_defaults = {}) click to toggle source

It receives arguments in an Array and two hashes, one for options and other for configuration.

Notice that it does not check if all required arguments were supplied. It should be done by the parser.

Parameters

args>

An array of objects. The objects are applied to their respective accessors declared with argument.

options<Hash>

An options hash that will be available as self.options. The hash given is converted to a hash with indifferent access, magic predicates (options.skip?) and then frozen.

config<Hash>

Configuration for this Thor class.

# File lib/thor/base.rb, line 137
def initialize args = [], options_args_or_defaults = {}, config = {}
  # Before {#initialize} is called arguments have been split out into
  # either:
  #
  # 1.  Positional `args` and args that need to be parsed for options.
  #
  # 2.  Positional `args` and already parsed option values that we call
  #     "defaults".

  if options_args_or_defaults.is_a? Array
    # Case (1)
    #
    # The start method splits inbound arguments at the first argument
    # that looks like an option (starts with - or --). It then calls
    # new, passing in the two halves of the arguments Array as the
    # first two parameters.
    #
    # In this case the first Array stays as `args` and the second Array
    # gets assigned to `args_to_parse_for_options` to be parsed for
    # options:
    #
    args_to_parse_for_options = options_args_or_defaults
    option_defaults = {}
  else
    # Case (2)
    #
    # Handle the case where the class was explicitly instantiated
    # with pre-parsed options.
    #
    args_to_parse_for_options = []
    option_defaults = options_args_or_defaults
  end

  logger.debug "#{ self.class.name }#initialize",
    args:                       args,
    options_args_or_defaults:   options_args_or_defaults,
    args_to_parse_for_options:  args_to_parse_for_options,
    option_defaults:            option_defaults

  # Let {Thor::Options} parse the options first, so it can remove
  # declared options from the array. This will leave us with
  # a list of arguments that weren't declared.

  # Hash of {Thor::Option} that we can parse from the CLI args
  # keyed by their {Thor::Option#name}.
  #
  # @type [HashWithIndifferentAccess<String, Thor::Option>]
  #
  options_to_parse_by_name = [
    # Add class-level options
    self.class.class_options,

    # Options passed in by {Thor.dispatch} for the command to be
    # invoked. May be `nil`, though I'm not totally sure when... in that
    # case those options won't be parsed.
    #
    # This was
    #
    #     config.delete( :command_options ),
    #
    # though I can't figure out why. Specs still pass without it..
    #
    config[:command_options],
  ].compact.reduce( HashWithIndifferentAccess.new, :merge! )

  stop_on_unknown = \
    self.class.stop_on_unknown_option? config[:current_command]
  
  disable_required_check = \
    self.class.disable_required_check? config[:current_command]

  logger.trace "Ready to create options",
    options_to_parse_by_name:     options_to_parse_by_name,
    option_defaults:              option_defaults,
    stop_on_unknown:              stop_on_unknown,
    disable_required_check:       disable_required_check,
    args:                         args,
    args_to_parse_for_options:    args_to_parse_for_options
  
  options_parser = Thor::Options.new \
    options_to_parse_by_name,
    option_defaults,
    stop_on_unknown,
    disable_required_check
  
  self.options = options_parser.parse args_to_parse_for_options
  
  if config[:class_options]
    self.options = config[:class_options].merge(options)
  end

  # If unknown options are disallowed, make sure that none of the
  # remaining arguments looks like an option.
  if self.class.check_unknown_options? config
    options_parser.check_unknown!
  end

  # Add the remaining arguments from the options parser to the
  # arguments passed in to initialize. Then remove any positional
  # arguments declared using #argument (this is primarily used
  # by Thor::Group). Tis will leave us with the remaining
  # positional arguments.
  to_parse  = args
  unless self.class.strict_args_position? config
    to_parse += options_parser.remaining
  end

  thor_args = Thor::Arguments.new [
    *self.class.class_arguments,
    *config[:current_command]&.arguments,
  ]

  # Set the arguments as instance variables.
  thor_args.parse( to_parse ).each { |k, v| __send__ "#{k}=", v }

  # Set whatever is left as args
  @args = thor_args.remaining
end
shell() click to toggle source

Returns the shell used in all Thor classes. If you are in a Unix platform it will use a colored log, otherwise it will use a basic one without color.

# File lib/thor/shell.rb, line 11
def shell
  @shell ||= if ENV["THOR_SHELL"] && !ENV["THOR_SHELL"].empty?
    Thor::Shell.const_get(ENV["THOR_SHELL"])
  elsif RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ && !ENV["ANSICON"]
    Thor::Shell::Basic
  else
    Thor::Shell::Color
  end
end
subclass_files() click to toggle source

Returns the files where the subclasses are kept.

Returns

Hash[path<String> => Class]

# File lib/thor/base.rb, line 93
def self.subclass_files
  @subclass_files ||= Hash.new { |h, k| h[k] = [] }
end
subclasses() click to toggle source

Returns the classes that inherits from Thor or Thor::Group.

Returns

Array

# File lib/thor/base.rb, line 84
def self.subclasses
  @subclasses ||= []
end

Public Instance Methods

basename() click to toggle source

The basename of the program invoking the thor class.

# File lib/thor/base/class_methods.rb, line 611
def basename
  File.basename($PROGRAM_NAME).split(" ").first
end
build_option(name, options, scope) click to toggle source

Build an option and adds it to the given scope.

Parameters

name<Symbol>

The name of the argument.

options<Hash>

Described in both class_option and method_option.

scope<Hash>

Options hash that is being built up

# File lib/thor/base/class_methods.rb, line 506
def build_option(name, options, scope)
  option = Thor::Option.new(
    name,
    options.merge(:check_default_type => check_default_type?)
  )
  scope[option.name] = option
end
build_options(options, scope) click to toggle source

Receives a hash of options, parse them and add to the scope. This is a fast way to set a bunch of options:

build_options :foo => true, :bar => :required, :baz => :string

@param [Hash<(String | Symbol), Object>] options

@param [HashWithIndifferentAccess<String, Thor::Option>] scope

@return [nil]

New {Thor::Option} are added to `scope`.
# File lib/thor/base/class_methods.rb, line 527
def build_options options, scope
  options.each do |key, value|
    option = Thor::Option.parse key, value
    scope[option.name] = option
  end
end
exit_on_failure?() click to toggle source

A flag that makes the process exit with status 1 if any error happens.

# File lib/thor/base/class_methods.rb, line 604
def exit_on_failure?
  false
end
from_superclass(method, default = nil) click to toggle source

Retrieves a value from superclass. If it reaches the baseclass, returns default.

# File lib/thor/base/class_methods.rb, line 583
def from_superclass(method, default = nil)
  if self == baseclass || !superclass.respond_to?(method, true)
    default
  else
    value = superclass.send(method)

    # Ruby implements `dup` on Object, but raises a `TypeError`
    # if the method is called on immediates. As a result, we
    # don't have a good way to check whether dup will succeed
    # without calling it and rescuing the TypeError.
    begin
      value.dup
    rescue TypeError
      value
    end

  end
end
inherited(klass) click to toggle source

Everytime someone inherits from a Thor class, register the klass and file into baseclass.

# File lib/thor/base/class_methods.rb, line 554
def inherited(klass)
  Thor::Base.register_klass_file(klass)
  klass.instance_variable_set(:@no_commands, false)
end
method_added(meth) click to toggle source

Fire this callback whenever a method is added. Added methods are tracked as commands by invoking the create_command method.

# File lib/thor/base/class_methods.rb, line 562
def method_added(meth)
  meth = meth.to_s

  if meth == "initialize"
    initialize_added
    return
  end

  # Return if it's not a public instance method
  return unless public_method_defined?(meth.to_sym)

  @no_commands ||= false
  return if @no_commands || !create_command(meth)

  is_thor_reserved_word?(meth, :command)
  Thor::Base.register_klass_file(self)
end
print_options(shell, options, group_name = nil) click to toggle source

Receives a set of options and print them.

Protected Instance Methods

on_run_error(error, command, args) click to toggle source

Atli addition: An error handling hook that is called from {Thor::Command#run} when running a command raises an unhandled exception.

I don't believe errors are recoverable at this point, but this hook allows the {Thor} subclass to respond to expected errors and gracefully inform the user.

It's basically `goto fail` or whatever.

User overrides should always exit or re-raise the error.

The base implementation here simply re-raises.

Note that {ArgumentError} and {NoMethodError} are both rescued in {Thor::Command#run} and passed off to Thor's relevant `.handle_*_error` methods, so you probably won't be able to intercept any of those.

Generally, it's best to use this to respond to custom, specific errors so you can easily bail out with a `raise` from anywhere in the application and still provide a properly formatted response and exit status to the user.

Errors that are only expected in a single command

@param [Exception] error

The error the bubbled up to {Thor::Command#run}.

@param [Thor::Command] command

The command instance that was running when the error occurred.

@param [Array<String>] args

The arguments to the command that was running.
# File lib/thor/base.rb, line 298
def on_run_error error, command, args
  raise error
end
on_run_success(result, command, args) click to toggle source

Hook for processing values return by command methods. So you can format it or print it or whatever.

This implementation just returns the result per the specs.

@param [Object] result

Whatever the command returned.

@param [Thor::Command] command

The command instance that was running when the error occurred.

@param [Array<String>] args

The arguments to the command that was running.

@return [Object]

The `result`.
# File lib/thor/base.rb, line 320
def on_run_success result, command, args
  result
end