module Thor::Base
Shared base behavior included in {Thor} and {Thor::Group}.
Declarations
¶ ↑
Attributes
Public Class Methods
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
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
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
Returns the classes that inherits from Thor
or Thor::Group
.
Returns¶ ↑
# File lib/thor/base.rb, line 84 def self.subclasses @subclasses ||= [] end
Public Instance Methods
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 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
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
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
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
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
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
Receives a set of options and print them.
# File lib/thor/base/class_methods.rb, line 468 def print_options(shell, options, group_name = nil) return if options.empty? list = [] padding = options.map { |o| o.aliases.size }.max.to_i * 4 options.each do |option| next if option.hide item = [option.usage(padding)] item.push(option.description ? "# #{option.description}" : "") list << item list << ["", "# Default: #{option.default}"] if option.show_default? if option.enum list << ["", "# Possible values: #{option.enum.join(', ')}"] end end shell.say(group_name ? "#{group_name} options:" : "Options:") shell.print_table(list, :indent => 2) shell.say "" end
Protected Instance Methods
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
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