Merge Pry::CommandContext and Pry::CommandSet::Command into Pry::Command
This commit is contained in:
parent
b6c01c92c4
commit
d221a22d02
|
@ -184,9 +184,9 @@ require "pry/wrapped_module"
|
|||
require "pry/history_array"
|
||||
require "pry/helpers"
|
||||
require "pry/history"
|
||||
require "pry/command"
|
||||
require "pry/command_set"
|
||||
require "pry/commands"
|
||||
require "pry/command_context"
|
||||
require "pry/custom_completions"
|
||||
require "pry/completion"
|
||||
require "pry/plugins"
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
class Pry
|
||||
# Command contexts are the objects runing each command.
|
||||
# Helper modules can be mixed into this class.
|
||||
class Command
|
||||
|
||||
# represents a void return value for a command
|
||||
VOID_VALUE = Object.new
|
||||
|
||||
# give it a nice inspect
|
||||
def VOID_VALUE.inspect() "void" end
|
||||
|
||||
class << self
|
||||
attr_accessor :name
|
||||
attr_accessor :description
|
||||
attr_accessor :options
|
||||
attr_accessor :block
|
||||
end
|
||||
|
||||
attr_accessor :command_name
|
||||
attr_accessor :output
|
||||
attr_accessor :target
|
||||
attr_accessor :target_self
|
||||
attr_accessor :captures
|
||||
attr_accessor :eval_string
|
||||
attr_accessor :arg_string
|
||||
attr_accessor :opts
|
||||
attr_accessor :command_set
|
||||
attr_accessor :command_processor
|
||||
attr_accessor :_pry_
|
||||
|
||||
def initialize(&block)
|
||||
instance_exec(&block) if block
|
||||
end
|
||||
|
||||
# Run a command from another command.
|
||||
# @param [String] command_string The string that invokes the command
|
||||
# @param [Array] args Further arguments to pass to the command
|
||||
# @example
|
||||
# run "show-input"
|
||||
# @example
|
||||
# run ".ls"
|
||||
# @example
|
||||
# run "amend-line", "5", 'puts "hello world"'
|
||||
def run(command_string, *args)
|
||||
complete_string = "#{command_string} #{args.join(" ")}"
|
||||
command_processor.process_commands(complete_string, eval_string, target)
|
||||
end
|
||||
|
||||
def commands
|
||||
command_set.commands
|
||||
end
|
||||
|
||||
def text
|
||||
Pry::Helpers::Text
|
||||
end
|
||||
|
||||
def void
|
||||
VOID_VALUE
|
||||
end
|
||||
|
||||
include Pry::Helpers::BaseHelpers
|
||||
include Pry::Helpers::CommandHelpers
|
||||
|
||||
|
||||
attr_accessor :context
|
||||
|
||||
%w(name description options block).each do |attribute|
|
||||
define_method(attribute) { self.class.send(attribute) }
|
||||
end
|
||||
|
||||
class << self
|
||||
def inspect
|
||||
"#<class(Pry command #{name.inspect})>"
|
||||
end
|
||||
|
||||
def subclass(name, description, options, helpers, &block)
|
||||
klass = Class.new(self)
|
||||
klass.send(:include, helpers)
|
||||
klass.name = name
|
||||
klass.description = description
|
||||
klass.options = options
|
||||
klass.block = block
|
||||
klass
|
||||
end
|
||||
|
||||
def hooks
|
||||
@hooks ||= {:before => [], :after => []}
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(context)
|
||||
self.context = context
|
||||
self.target = context[:target]
|
||||
self.target_self = context[:target].eval('self')
|
||||
self.output = context[:output]
|
||||
self.captures = context[:captures]
|
||||
self.eval_string = context[:eval_string]
|
||||
self.arg_string = context[:arg_string]
|
||||
self.command_set = context[:command_set]
|
||||
self.command_name = self.class.options[:listing]
|
||||
self._pry_ = context[:pry_instance]
|
||||
self.command_processor = context[:command_processor]
|
||||
end
|
||||
|
||||
def call_safely(*args)
|
||||
if dependencies_met?
|
||||
call_with_hooks(*args)
|
||||
else
|
||||
gems_needed = Array(command_options[:requires_gem])
|
||||
gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
|
||||
output.puts "\nThe command '#{name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
|
||||
output.puts "-"
|
||||
output.puts "Type `install-command #{name}` to install the required gems and activate this command."
|
||||
end
|
||||
end
|
||||
|
||||
def call_with_hooks(*args)
|
||||
self.class.hooks[:before].each do |block|
|
||||
instance_exec(*args, &block)
|
||||
end
|
||||
|
||||
ret = call *args
|
||||
|
||||
self.class.hooks[:after].each do |block|
|
||||
ret = instance_exec(*args, &block)
|
||||
end
|
||||
|
||||
command_options[:keep_retval] ? ret : void
|
||||
end
|
||||
|
||||
def command_options; self.class.options; end
|
||||
|
||||
def dependencies_met?
|
||||
@dependencies_met ||= command_dependencies_met?(command_options)
|
||||
end
|
||||
end
|
||||
|
||||
class BlockCommand < Command
|
||||
# backwards compatibility
|
||||
alias_method :opts, :context
|
||||
|
||||
def call(*args)
|
||||
if options[:argument_required] && args.empty?
|
||||
raise CommandError, "The command '#{command.name}' requires an argument."
|
||||
end
|
||||
|
||||
instance_exec(*correct_arg_arity(block.arity, args), &block)
|
||||
end
|
||||
|
||||
private
|
||||
def correct_arg_arity(arity, args)
|
||||
case
|
||||
when arity < 0
|
||||
args
|
||||
when arity == 0
|
||||
[]
|
||||
when arity > 0
|
||||
args.values_at *(0..(arity - 1)).to_a
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ClassCommand < Command
|
||||
attr_accessor :opts
|
||||
attr_accessor :args
|
||||
|
||||
def call(*args)
|
||||
setup
|
||||
|
||||
self.opts = slop
|
||||
self.args = self.opts.parse!(args)
|
||||
|
||||
if opts.present?(:help)
|
||||
output.puts slop.help
|
||||
else
|
||||
run
|
||||
end
|
||||
end
|
||||
|
||||
def setup; end
|
||||
def options(opt); end
|
||||
def run; raise CommandError, "command '#{name}' not implemented" end
|
||||
|
||||
def slop
|
||||
Slop.new do |opt|
|
||||
options(opt)
|
||||
opt.on(:h, :help, "Show this message.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,57 +0,0 @@
|
|||
class Pry
|
||||
# Command contexts are the objects runing each command.
|
||||
# Helper modules can be mixed into this class.
|
||||
class CommandContext
|
||||
|
||||
# represents a void return value for a command
|
||||
VOID_VALUE = Object.new
|
||||
|
||||
# give it a nice inspect
|
||||
def VOID_VALUE.inspect() "void" end
|
||||
|
||||
attr_accessor :command_name
|
||||
attr_accessor :output
|
||||
attr_accessor :target
|
||||
attr_accessor :target_self
|
||||
attr_accessor :captures
|
||||
attr_accessor :eval_string
|
||||
attr_accessor :arg_string
|
||||
attr_accessor :opts
|
||||
attr_accessor :command_set
|
||||
attr_accessor :command_processor
|
||||
attr_accessor :_pry_
|
||||
|
||||
def initialize(&block)
|
||||
instance_exec(&block) if block
|
||||
end
|
||||
|
||||
# Run a command from another command.
|
||||
# @param [String] command_string The string that invokes the command
|
||||
# @param [Array] args Further arguments to pass to the command
|
||||
# @example
|
||||
# run "show-input"
|
||||
# @example
|
||||
# run ".ls"
|
||||
# @example
|
||||
# run "amend-line", "5", 'puts "hello world"'
|
||||
def run(command_string, *args)
|
||||
complete_string = "#{command_string} #{args.join(" ")}"
|
||||
command_processor.process_commands(complete_string, eval_string, target)
|
||||
end
|
||||
|
||||
def commands
|
||||
command_set.commands
|
||||
end
|
||||
|
||||
def text
|
||||
Pry::Helpers::Text
|
||||
end
|
||||
|
||||
def void
|
||||
VOID_VALUE
|
||||
end
|
||||
|
||||
include Pry::Helpers::BaseHelpers
|
||||
include Pry::Helpers::CommandHelpers
|
||||
end
|
||||
end
|
|
@ -22,7 +22,7 @@ class Pry
|
|||
# (one that does not return a value)
|
||||
# @return [Boolean]
|
||||
def void_command?
|
||||
(command? && !keep_retval?) || retval == CommandContext::VOID_VALUE
|
||||
(command? && !keep_retval?) || retval == Command::VOID_VALUE
|
||||
end
|
||||
|
||||
# Is the return value kept for this command? (i.e :keep_retval => true)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
require 'pry/command_context'
|
||||
class Pry
|
||||
class NoCommandError < StandardError
|
||||
def initialize(name, owner)
|
||||
|
@ -9,142 +8,6 @@ class Pry
|
|||
# This class is used to create sets of commands. Commands can be imported from
|
||||
# different sets, aliased, removed, etc.
|
||||
class CommandSet
|
||||
class Command < Pry::CommandContext
|
||||
|
||||
class << self
|
||||
attr_accessor :name
|
||||
attr_accessor :description
|
||||
attr_accessor :options
|
||||
attr_accessor :block
|
||||
end
|
||||
|
||||
attr_accessor :context
|
||||
|
||||
%w(name description options block).each do |attribute|
|
||||
define_method(attribute) { self.class.send(attribute) }
|
||||
end
|
||||
|
||||
class << self
|
||||
def inspect
|
||||
"#<class(Pry command #{name.inspect})>"
|
||||
end
|
||||
|
||||
def subclass(name, description, options, helpers, &block)
|
||||
klass = Class.new(self)
|
||||
klass.send(:include, helpers)
|
||||
klass.name = name
|
||||
klass.description = description
|
||||
klass.options = options
|
||||
klass.block = block
|
||||
klass
|
||||
end
|
||||
|
||||
def hooks
|
||||
@hooks ||= {:before => [], :after => []}
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(context)
|
||||
self.context = context
|
||||
self.target = context[:target]
|
||||
self.target_self = context[:target].eval('self')
|
||||
self.output = context[:output]
|
||||
self.captures = context[:captures]
|
||||
self.eval_string = context[:eval_string]
|
||||
self.arg_string = context[:arg_string]
|
||||
self.command_set = context[:command_set]
|
||||
self.command_name = self.class.options[:listing]
|
||||
self._pry_ = context[:pry_instance]
|
||||
self.command_processor = context[:command_processor]
|
||||
end
|
||||
|
||||
def call_safely(*args)
|
||||
if dependencies_met?
|
||||
call_with_hooks(*args)
|
||||
else
|
||||
gems_needed = Array(command_options[:requires_gem])
|
||||
gems_not_installed = gems_needed.select { |g| !gem_installed?(g) }
|
||||
output.puts "\nThe command '#{name}' is #{Helpers::Text.bold("unavailable")} because it requires the following gems to be installed: #{(gems_not_installed.join(", "))}"
|
||||
output.puts "-"
|
||||
output.puts "Type `install-command #{name}` to install the required gems and activate this command."
|
||||
end
|
||||
end
|
||||
|
||||
def call_with_hooks(*args)
|
||||
self.class.hooks[:before].each do |block|
|
||||
instance_exec(*args, &block)
|
||||
end
|
||||
|
||||
ret = call *args
|
||||
|
||||
self.class.hooks[:after].each do |block|
|
||||
ret = instance_exec(*args, &block)
|
||||
end
|
||||
|
||||
command_options[:keep_retval] ? ret : CommandContext::VOID_VALUE
|
||||
end
|
||||
|
||||
def command_options; self.class.options; end
|
||||
|
||||
def dependencies_met?
|
||||
@dependencies_met ||= command_dependencies_met?(command_options)
|
||||
end
|
||||
end
|
||||
|
||||
class BlockCommand < Command
|
||||
# backwards compatibility
|
||||
alias_method :opts, :context
|
||||
|
||||
def call(*args)
|
||||
if options[:argument_required] && args.empty?
|
||||
raise CommandError, "The command '#{command.name}' requires an argument."
|
||||
end
|
||||
|
||||
instance_exec(*correct_arg_arity(block.arity, args), &block)
|
||||
end
|
||||
|
||||
private
|
||||
def correct_arg_arity(arity, args)
|
||||
case
|
||||
when arity < 0
|
||||
args
|
||||
when arity == 0
|
||||
[]
|
||||
when arity > 0
|
||||
args.values_at *(0..(arity - 1)).to_a
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ClassCommand < Command
|
||||
attr_accessor :opts
|
||||
attr_accessor :args
|
||||
|
||||
def call(*args)
|
||||
setup
|
||||
|
||||
self.opts = slop
|
||||
self.args = self.opts.parse!(args)
|
||||
|
||||
if opts.present?(:help)
|
||||
output.puts slop.help
|
||||
else
|
||||
run
|
||||
end
|
||||
end
|
||||
|
||||
def setup; end
|
||||
def options(opt); end
|
||||
def run; raise CommandError, "command '#{name}' not implemented" end
|
||||
|
||||
def slop
|
||||
Slop.new do |opt|
|
||||
options(opt)
|
||||
opt.on(:h, :help, "Show this message.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
include Enumerable
|
||||
include Pry::Helpers::BaseHelpers
|
||||
|
||||
|
@ -229,7 +92,7 @@ class Pry
|
|||
:use_prefix => true
|
||||
}.merge!(options)
|
||||
|
||||
commands[name] = BlockCommand.subclass(name, description, options, helper_module, &block)
|
||||
commands[name] = Pry::BlockCommand.subclass(name, description, options, helper_module, &block)
|
||||
end
|
||||
|
||||
def command_class(name, description="No description.", options={}, &block)
|
||||
|
@ -243,7 +106,7 @@ class Pry
|
|||
:use_prefix => true
|
||||
}.merge!(options)
|
||||
|
||||
commands[name] = ClassCommand.subclass(name, description, options, helper_module)
|
||||
commands[name] = Pry::ClassCommand.subclass(name, description, options, helper_module)
|
||||
commands[name].class_eval(&block)
|
||||
commands[name]
|
||||
end
|
||||
|
|
|
@ -55,8 +55,6 @@ class Pry
|
|||
EOS
|
||||
end
|
||||
|
||||
require 'pry/command_context'
|
||||
|
||||
command_class "gist", "Gist a method or expression history to github. Type `gist --help` for more info.", :requires_gem => "gist", :shellwords => false do
|
||||
attr_accessor :content
|
||||
attr_accessor :code_type
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class Pry
|
||||
module Helpers
|
||||
|
||||
# The methods defined on {Text} are available to custom commands via {Pry::CommandContext#text}.
|
||||
# The methods defined on {Text} are available to custom commands via {Pry::Command#text}.
|
||||
module Text
|
||||
|
||||
COLORS =
|
||||
|
|
|
@ -378,12 +378,12 @@ class Pry
|
|||
# @param [String] val The command (and its params) to execute.
|
||||
# @param [String] eval_string The current input buffer.
|
||||
# @param [Binding] target The binding to use..
|
||||
# @return [Pry::CommandContext::VOID_VALUE]
|
||||
# @return [Pry::Command::VOID_VALUE]
|
||||
# @example
|
||||
# pry_instance.run_command("ls -m")
|
||||
def run_command(val, eval_string = "", target = binding_stack.last)
|
||||
@command_processor.process_commands(val, eval_string, target)
|
||||
Pry::CommandContext::VOID_VALUE
|
||||
Pry::Command::VOID_VALUE
|
||||
end
|
||||
|
||||
# Set the last result of an eval.
|
||||
|
|
|
@ -162,9 +162,9 @@ describe Pry::CommandSet do
|
|||
@set.desc('foo').should == 'bar'
|
||||
end
|
||||
|
||||
it 'should return Pry::CommandContext::VOID_VALUE for commands by default' do
|
||||
it 'should return Pry::Command::VOID_VALUE for commands by default' do
|
||||
@set.command('foo') { 3 }
|
||||
@set.run_command(@ctx, 'foo').should == Pry::CommandContext::VOID_VALUE
|
||||
@set.run_command(@ctx, 'foo').should == Pry::Command::VOID_VALUE
|
||||
end
|
||||
|
||||
it 'should be able to keep return values' do
|
||||
|
@ -187,7 +187,7 @@ describe Pry::CommandSet do
|
|||
end
|
||||
|
||||
@set.run_command(@ctx, 'foo')
|
||||
Pry::CommandContext.new.should.not.respond_to :my_helper
|
||||
Pry::Command.subclass('foo', '', {}, Module.new).new({:target => binding}).should.not.respond_to :my_helper
|
||||
end
|
||||
|
||||
it 'should not recreate a new helper module when helpers is called' do
|
||||
|
|
|
@ -43,7 +43,7 @@ describe Pry do
|
|||
|
||||
# bug fix for https://github.com/banister/pry/issues/93
|
||||
it 'should not leak pry constants into Object namespace' do
|
||||
input_string = "CommandContext"
|
||||
input_string = "Command"
|
||||
str_output = StringIO.new
|
||||
o = Object.new
|
||||
pry_tester = Pry.new(:input => StringIO.new(input_string),
|
||||
|
|
Loading…
Reference in New Issue