lib/github_cli/vendor/thor/base.rb in github_cli-0.5.3 vs lib/github_cli/vendor/thor/base.rb in github_cli-0.5.4
- old
+ new
@@ -1,17 +1,18 @@
+require 'thor/command'
require 'thor/core_ext/hash_with_indifferent_access'
require 'thor/core_ext/ordered_hash'
require 'thor/error'
-require 'thor/shell'
require 'thor/invocation'
require 'thor/parser'
-require 'thor/task'
+require 'thor/shell'
require 'thor/util'
class Thor
autoload :Actions, 'thor/actions'
autoload :RakeCompat, 'thor/rake_compat'
+ autoload :Group, 'thor/group'
# Shortcuts for help.
HELP_MAPPINGS = %w(-h -? --help -D)
# Thor methods that should not be overwritten by the user.
@@ -44,24 +45,26 @@
# 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.
if options.is_a?(Array)
- task_options = config.delete(:task_options) # hook for start
- parse_options = parse_options.merge(task_options) if task_options
+ command_options = config.delete(:command_options) # hook for start
+ parse_options = parse_options.merge(command_options) if command_options
array_options, hash_options = options, {}
else
# Handle the case where the class was explicitly instantiated
# with pre-parsed options.
array_options, hash_options = [], options
end
# 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.
- opts = Thor::Options.new(parse_options, hash_options)
+ stop_on_unknown = self.class.stop_on_unknown_option? config[:current_command]
+ opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown)
self.options = opts.parse(array_options)
+ self.options = config[:class_options].merge(self.options) if config[:class_options]
# If unknown options are disallowed, make sure that none of the
# remaining arguments looks like an option.
opts.check_unknown! if self.class.check_unknown_options?(config)
@@ -114,22 +117,10 @@
file_subclasses << klass unless file_subclasses.include?(klass)
end
end
module ClassMethods
- def attr_reader(*) #:nodoc:
- no_tasks { super }
- end
-
- def attr_writer(*) #:nodoc:
- no_tasks { super }
- end
-
- def attr_accessor(*) #:nodoc:
- no_tasks { super }
- end
-
# If you want to raise an error for unknown options, call check_unknown_options!
# This is disabled by default to allow dynamic invocations.
def check_unknown_options!
@check_unknown_options = true
end
@@ -140,10 +131,17 @@
def check_unknown_options?(config) #:nodoc:
!!check_unknown_options
end
+ # If true, option parsing is suspended as soon as an unknown option or a
+ # regular argument is encountered. All remaining arguments are passed to
+ # the command as regular arguments.
+ def stop_on_unknown_option?(command_name) #:nodoc:
+ false
+ end
+
# If you want only strict string args (useful when cascading thor classes),
# call strict_args_position! This is disabled by default to allow dynamic
# invocations.
def strict_args_position!
@strict_args_position = true
@@ -161,15 +159,15 @@
#
# Arguments are different from options in several aspects. The first one
# is how they are parsed from the command line, arguments are retrieved
# from position:
#
- # thor task NAME
+ # thor command NAME
#
# Instead of:
#
- # thor task --name=NAME
+ # thor command --name=NAME
#
# Besides, arguments are used inside your code as an accessor (self.argument),
# while options are all kept in a hash (self.options).
#
# Finally, arguments cannot have type :default or :boolean but can be
@@ -192,11 +190,11 @@
# ==== Errors
# ArgumentError:: Raised if you supply a required argument after a non required one.
#
def argument(name, options={})
is_thor_reserved_word?(name, :argument)
- no_tasks { attr_accessor name }
+ no_commands { attr_accessor name }
required = if options.key?(:optional)
!options[:optional]
elsif options.key?(:required)
options[:required]
@@ -296,92 +294,96 @@
class_options.delete(name)
end
end
# Defines the group. This is used when thor list is invoked so you can specify
- # that only tasks from a pre-defined group will be shown. Defaults to standard.
+ # that only commands from a pre-defined group will be shown. Defaults to standard.
#
# ==== Parameters
# name<String|Symbol>
#
def group(name=nil)
- case name
- when nil
- @group ||= from_superclass(:group, 'standard')
- else
- @group = name.to_s
+ @group = case name
+ when nil
+ @group || from_superclass(:group, 'standard')
+ else
+ name.to_s
end
end
- # Returns the tasks for this Thor class.
+ # Returns the commands for this Thor class.
#
# ==== Returns
- # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task
+ # OrderedHash:: An ordered hash with commands names as keys and Thor::Command
# objects as values.
#
- def tasks
- @tasks ||= Thor::CoreExt::OrderedHash.new
+ def commands
+ @commands ||= Thor::CoreExt::OrderedHash.new
end
+ alias tasks commands
- # Returns the tasks for this Thor class and all subclasses.
+ # Returns the commands for this Thor class and all subclasses.
#
# ==== Returns
- # OrderedHash:: An ordered hash with tasks names as keys and Thor::Task
+ # OrderedHash:: An ordered hash with commands names as keys and Thor::Command
# objects as values.
#
- def all_tasks
- @all_tasks ||= from_superclass(:all_tasks, Thor::CoreExt::OrderedHash.new)
- @all_tasks.merge(tasks)
+ def all_commands
+ @all_commands ||= from_superclass(:all_commands, Thor::CoreExt::OrderedHash.new)
+ @all_commands.merge(commands)
end
+ alias all_tasks all_commands
- # Removes a given task from this Thor class. This is usually done if you
+ # Removes a given command from this Thor class. This is usually done if you
# are inheriting from another class and don't want it to be available
# anymore.
#
- # By default it only remove the mapping to the task. But you can supply
+ # By default it only remove the mapping to the command. But you can supply
# :undefine => true to undefine the method from the class as well.
#
# ==== Parameters
- # name<Symbol|String>:: The name of the task to be removed
- # options<Hash>:: You can give :undefine => true if you want tasks the method
+ # name<Symbol|String>:: The name of the command to be removed
+ # options<Hash>:: You can give :undefine => true if you want commands the method
# to be undefined from the class as well.
#
- def remove_task(*names)
+ def remove_command(*names)
options = names.last.is_a?(Hash) ? names.pop : {}
names.each do |name|
- tasks.delete(name.to_s)
- all_tasks.delete(name.to_s)
+ commands.delete(name.to_s)
+ all_commands.delete(name.to_s)
undef_method name if options[:undefine]
end
end
+ alias remove_task remove_command
- # All methods defined inside the given block are not added as tasks.
+ # All methods defined inside the given block are not added as commands.
#
# So you can do:
#
# class MyScript < Thor
- # no_tasks do
- # def this_is_not_a_task
+ # no_commands do
+ # def this_is_not_a_command
# end
# end
# end
#
- # You can also add the method and remove it from the task list:
+ # You can also add the method and remove it from the command list:
#
# class MyScript < Thor
- # def this_is_not_a_task
+ # def this_is_not_a_command
# end
- # remove_task :this_is_not_a_task
+ # remove_command :this_is_not_a_command
# end
#
- def no_tasks
- @no_tasks = true
+ def no_commands
+ @no_commands = true
yield
ensure
- @no_tasks = false
+ @no_commands = false
end
+ alias no_tasks no_commands
# Sets the namespace for the Thor or Thor::Group class. By default the
# namespace is retrieved from the class name. If your Thor class is named
# Scripts::MyScript, the help method, for example, will be called as:
#
@@ -389,88 +391,90 @@
#
# If you change the namespace:
#
# namespace :my_scripts
#
- # You change how your tasks are invoked:
+ # You change how your commands are invoked:
#
# thor my_scripts -h
#
# Finally, if you change your namespace to default:
#
# namespace :default
#
- # Your tasks can be invoked with a shortcut. Instead of:
+ # Your commands can be invoked with a shortcut. Instead of:
#
- # thor :my_task
+ # thor :my_command
#
def namespace(name=nil)
- case name
+ @namespace = case name
when nil
- @namespace ||= Thor::Util.namespace_from_thor_class(self)
+ @namespace || Thor::Util.namespace_from_thor_class(self)
else
@namespace = name.to_s
end
end
- # Parses the task and options from the given args, instantiate the class
- # and invoke the task. This method is used when the arguments must be parsed
+ # Parses the command and options from the given args, instantiate the class
+ # and invoke the command. This method is used when the arguments must be parsed
# from an array. If you are inside Ruby and want to use a Thor class, you
# can simply initialize it:
#
# script = MyScript.new(args, options, config)
- # script.invoke(:task, first_arg, second_arg, third_arg)
+ # script.invoke(:command, first_arg, second_arg, third_arg)
#
def start(given_args=ARGV, config={})
config[:shell] ||= Thor::Base.shell.new
dispatch(nil, given_args.dup, nil, config)
rescue Thor::Error => e
ENV["THOR_DEBUG"] == "1" ? (raise e) : config[:shell].error(e.message)
exit(1) if exit_on_failure?
rescue Errno::EPIPE
- # This happens if a thor task is piped to something like `head`,
+ # This happens if a thor command is piped to something like `head`,
# which closes the pipe when it's done reading. This will also
# mean that if the pipe is closed, further unnecessary
# computation will not occur.
exit(0)
end
- # Allows to use private methods from parent in child classes as tasks.
+ # Allows to use private methods from parent in child classes as commands.
#
# ==== Parameters
- # names<Array>:: Method names to be used as tasks
+ # names<Array>:: Method names to be used as commands
#
# ==== Examples
#
- # public_task :foo
- # public_task :foo, :bar, :baz
+ # public_command :foo
+ # public_command :foo, :bar, :baz
#
- def public_task(*names)
+ def public_command(*names)
names.each do |name|
class_eval "def #{name}(*); super end"
end
end
+ alias public_task public_command
- def handle_no_task_error(task, has_namespace = $thor_runner) #:nodoc:
+ def handle_no_command_error(command, has_namespace = $thor_runner) #:nodoc:
if has_namespace
- raise UndefinedTaskError, "Could not find task #{task.inspect} in #{namespace.inspect} namespace."
+ raise UndefinedCommandError, "Could not find command #{command.inspect} in #{namespace.inspect} namespace."
else
- raise UndefinedTaskError, "Could not find task #{task.inspect}."
+ raise UndefinedCommandError, "Could not find command #{command.inspect}."
end
end
+ alias handle_no_task_error handle_no_command_error
- def handle_argument_error(task, error, arity=nil) #:nodoc:
- msg = "#{basename} #{task.name}"
- if arity
+ def handle_argument_error(command, error, arity=nil) #:nodoc:
+ msg = "#{basename} #{command.name}"
+ if arity && arity != 0
required = arity < 0 ? (-1 - arity) : arity
msg << " requires at least #{required} argument"
msg << "s" if required > 1
else
msg = "call #{msg} as"
end
- msg << ": #{self.banner(task).inspect}."
+ msg << ": #{self.banner(command).inspect}."
raise InvocationError, msg
end
protected
@@ -544,47 +548,50 @@
options.each do |key, value|
scope[key] = Thor::Option.parse(key, value)
end
end
- # Finds a task with the given name. If the task belongs to the current
+ # Finds a command with the given name. If the command belongs to the current
# class, just return it, otherwise dup it and add the fresh copy to the
- # current task hash.
- def find_and_refresh_task(name) #:nodoc:
- task = if task = tasks[name.to_s]
- task
- elsif task = all_tasks[name.to_s]
- tasks[name.to_s] = task.clone
+ # current command hash.
+ def find_and_refresh_command(name) #:nodoc:
+ command = if command = commands[name.to_s]
+ command
+ elsif command = all_commands[name.to_s]
+ commands[name.to_s] = command.clone
else
- raise ArgumentError, "You supplied :for => #{name.inspect}, but the task #{name.inspect} could not be found."
+ raise ArgumentError, "You supplied :for => #{name.inspect}, but the command #{name.inspect} could not be found."
end
end
+ alias find_and_refresh_task find_and_refresh_command
# Everytime someone inherits from a Thor class, register the klass
# and file into baseclass.
def inherited(klass)
Thor::Base.register_klass_file(klass)
- klass.instance_variable_set(:@no_tasks, false)
+ klass.instance_variable_set(:@no_commands, false)
end
# Fire this callback whenever a method is added. Added methods are
- # tracked as tasks by invoking the create_task method.
+ # tracked as commands by invoking the create_command method.
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_instance_methods.include?(meth) ||
- public_instance_methods.include?(meth.to_sym)
+ return unless public_method_defined?(meth.to_sym)
- return if @no_tasks || !create_task(meth)
+ # Return if attr_* added the method
+ return if caller.first.to_s[/`attr_(reader|writer|accessor)'/]
- is_thor_reserved_word?(meth, :task)
+ return if @no_commands || !create_command(meth)
+
+ is_thor_reserved_word?(meth, :command)
Thor::Base.register_klass_file(self)
end
# Retrieves a value from superclass. If it reaches the baseclass,
# returns default.
@@ -619,21 +626,22 @@
# SIGNATURE: Sets the baseclass. This is where the superclass lookup
# finishes.
def baseclass #:nodoc:
end
- # SIGNATURE: Creates a new task if valid_task? is true. This method is
+ # SIGNATURE: Creates a new command if valid_command? is true. This method is
# called when a new method is added to the class.
- def create_task(meth) #:nodoc:
+ def create_command(meth) #:nodoc:
end
+ alias create_task create_command
# SIGNATURE: Defines behavior when the initialize method is added to the
# class.
def initialize_added #:nodoc:
end
# SIGNATURE: The hook invoked by start.
- def dispatch(task, given_args, given_opts, config) #:nodoc:
+ def dispatch(command, given_args, given_opts, config) #:nodoc:
raise NotImplementedError
end
end
end