mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Make all the tests pass again
This commit is contained in:
parent
689e47899b
commit
2b6d0d2149
5 changed files with 85 additions and 280 deletions
|
@ -145,15 +145,20 @@ class Pry
|
|||
args = []
|
||||
end
|
||||
|
||||
options = {
|
||||
context = {
|
||||
:val => val,
|
||||
:arg_string => arg_string,
|
||||
:eval_string => eval_string,
|
||||
:commands => commands.commands,
|
||||
:captures => captures
|
||||
:captures => captures,
|
||||
:pry_instance => @pry_instance,
|
||||
:output => output,
|
||||
:command_processor => self,
|
||||
:command_set => commands,
|
||||
:target => target
|
||||
}
|
||||
|
||||
ret = execute_command(target, command, options, *(captures + args))
|
||||
ret = execute_command(command, context, *(captures + args))
|
||||
|
||||
Result.new(true, command.options[:keep_retval], ret)
|
||||
end
|
||||
|
@ -165,40 +170,19 @@ class Pry
|
|||
# @param [Hash] options The options to set on the Commands object.
|
||||
# @param [Array] args The command arguments.
|
||||
# @return [Object] The value returned by the command
|
||||
def execute_command(target, command, options, *args)
|
||||
def execute_command(command, context, *args)
|
||||
ret = nil
|
||||
|
||||
# allocate, setup and then call initialize so that authors
|
||||
# can do their own setup in initialize.
|
||||
context = command.allocate
|
||||
setup_context(target, command, context, options)
|
||||
context.extend commands.helper_module
|
||||
context.send(:initialize)
|
||||
instance = command.new(context)
|
||||
|
||||
catch(:command_done) do
|
||||
ret = context.call(*args)
|
||||
ret = instance.call_with_hooks(*args)
|
||||
end
|
||||
|
||||
# FIXME: wtf?
|
||||
options[:val].replace("")
|
||||
context[:val].replace("")
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
def setup_context(target, command, context, options)
|
||||
context.opts = options
|
||||
context.target = target
|
||||
context.target_self = target.eval('self')
|
||||
context.output = output
|
||||
context.captures = options[:captures]
|
||||
context.eval_string = options[:eval_string]
|
||||
context.arg_string = options[:arg_string]
|
||||
context.command_set = commands
|
||||
context.command_name = command.options[:listing]
|
||||
|
||||
context._pry_ = @pry_instance
|
||||
|
||||
context.command_processor = self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,23 +18,58 @@ class Pry
|
|||
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}>"
|
||||
"#<class(Pry command #{name.inspect})>"
|
||||
end
|
||||
|
||||
def subclass(name, description, options, &block)
|
||||
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_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
|
||||
|
||||
self.class.options[:keep_retval] ? ret : CommandContext::VOID_VALUE
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -49,6 +84,9 @@ class Pry
|
|||
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."
|
||||
|
@ -75,6 +113,8 @@ class Pry
|
|||
attr_accessor :args
|
||||
|
||||
def call(*args)
|
||||
setup
|
||||
|
||||
self.opts = slop
|
||||
self.args = self.opts.parse!(args)
|
||||
|
||||
|
@ -85,7 +125,9 @@ class Pry
|
|||
end
|
||||
end
|
||||
|
||||
def setup; end
|
||||
def options(opt); end
|
||||
def run; raise CommandError, "command '#{name}' not implemented" end
|
||||
|
||||
def slop
|
||||
Slop.new do |opt|
|
||||
|
@ -94,7 +136,6 @@ class Pry
|
|||
end
|
||||
end
|
||||
|
||||
def run; raise CommandError, "command '#{name}' not implemented" end
|
||||
end
|
||||
|
||||
include Enumerable
|
||||
|
@ -182,9 +223,9 @@ class Pry
|
|||
}.merge!(options)
|
||||
|
||||
if command_dependencies_met? options
|
||||
commands[name] = BlockCommand.subclass(name, description, options, &block)
|
||||
commands[name] = BlockCommand.subclass(name, description, options, helper_module, &block)
|
||||
else
|
||||
commands[name] = StubCommand.subclass(name, description, options)
|
||||
commands[name] = StubCommand.subclass(name, description, options, helper_module)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -200,10 +241,10 @@ class Pry
|
|||
}.merge!(options)
|
||||
|
||||
if command_dependencies_met? options
|
||||
commands[name] = ClassCommand.subclass(name, description, options)
|
||||
commands[name] = ClassCommand.subclass(name, description, options, helper_module)
|
||||
commands[name].class_eval(&block)
|
||||
else
|
||||
commands[name] = StubCommand.subclass(name, description, options)
|
||||
commands[name] = StubCommand.subclass(name, description, options, helper_module)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -218,18 +259,7 @@ class Pry
|
|||
# end
|
||||
def before_command(name, &block)
|
||||
cmd = find_command_by_name_or_listing(name)
|
||||
prev_callable = cmd.callable
|
||||
|
||||
wrapper_block = proc do |*args|
|
||||
instance_exec(*args, &block)
|
||||
|
||||
if prev_callable.is_a?(Proc)
|
||||
instance_exec(*args, &prev_callable)
|
||||
else
|
||||
prev_callable.call(*args)
|
||||
end
|
||||
end
|
||||
cmd.callable = wrapper_block
|
||||
cmd.hooks[:before].unshift block
|
||||
end
|
||||
|
||||
# Execute a block of code after a command is invoked. The block also
|
||||
|
@ -243,18 +273,7 @@ class Pry
|
|||
# end
|
||||
def after_command(name, &block)
|
||||
cmd = find_command_by_name_or_listing(name)
|
||||
prev_callable = cmd.callable
|
||||
|
||||
wrapper_block = proc do |*args|
|
||||
if prev_callable.is_a?(Proc)
|
||||
instance_exec(*args, &prev_callable)
|
||||
else
|
||||
prev_callable.call(*args)
|
||||
end
|
||||
|
||||
instance_exec(*args, &block)
|
||||
end
|
||||
cmd.callable = wrapper_block
|
||||
cmd.hooks[:after] << block
|
||||
end
|
||||
|
||||
def each &block
|
||||
|
@ -382,6 +401,11 @@ class Pry
|
|||
commands.keys
|
||||
end
|
||||
|
||||
def run_command(context, name, *args)
|
||||
command = commands[name] or raise NoCommandError.new(name, self)
|
||||
command.new(context).call_with_hooks(*args)
|
||||
end
|
||||
|
||||
private
|
||||
def define_default_commands
|
||||
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
require 'helper'
|
||||
|
||||
# integration tests
|
||||
describe "integration tests for class-based commands" do
|
||||
before do
|
||||
@set = Pry::CommandSet.new
|
||||
end
|
||||
|
||||
it 'should invoke a class-based command from the REPL' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call
|
||||
output.puts "yippee!"
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
@set.import_from Pry::Commands, "exit-all"
|
||||
|
||||
redirect_pry_io(InputTester.new("foo", "exit-all"), out =StringIO.new) do
|
||||
Pry.start binding, :commands => @set
|
||||
end
|
||||
|
||||
out.string.should =~ /yippee!/
|
||||
end
|
||||
|
||||
it 'should return specified value with :keep_retval => true' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call
|
||||
:i_enjoyed_the_song_new_flame_by_simply_red_as_a_child_wandering_around_supermarkets
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :keep_retval => true, :definition => c.new
|
||||
@set.import_from Pry::Commands, "exit-all"
|
||||
|
||||
redirect_pry_io(InputTester.new("foo", "exit-all"), out =StringIO.new) do
|
||||
Pry.start binding, :commands => @set
|
||||
end
|
||||
|
||||
out.string.should =~ /i_enjoyed_the_song_new_flame_by_simply_red_as_a_child_wandering_around_supermarkets/
|
||||
end
|
||||
|
||||
it 'should NOT return specified value with :keep_retval => false' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call
|
||||
:i_enjoyed_the_song_new_flame_by_simply_red_as_a_child_wandering_around_supermarkets
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :keep_retval => false, :definition => c.new
|
||||
@set.import_from Pry::Commands, "exit-all"
|
||||
|
||||
redirect_pry_io(InputTester.new("foo", "exit-all"), out =StringIO.new) do
|
||||
Pry.start binding, :commands => @set
|
||||
end
|
||||
|
||||
out.string.should.not =~ /i_enjoyed_the_song_new_flame_by_simply_red_as_a_child_wandering_around_supermarkets/
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -3,7 +3,10 @@ require 'helper'
|
|||
describe Pry::CommandSet do
|
||||
before do
|
||||
@set = Pry::CommandSet.new
|
||||
@ctx = Pry::CommandContext.new
|
||||
@ctx = {
|
||||
:target => binding,
|
||||
:command_set => @set
|
||||
}
|
||||
end
|
||||
|
||||
it 'should call the block used for the command when it is called' do
|
||||
|
@ -24,11 +27,11 @@ describe Pry::CommandSet do
|
|||
@set.run_command @ctx, 'foo', 1, 2, 3
|
||||
end
|
||||
|
||||
it 'should use the first argument as self' do
|
||||
it 'should use the first argument as context' do
|
||||
ctx = @ctx
|
||||
|
||||
@set.command 'foo' do
|
||||
self.should == ctx
|
||||
self.context.should == ctx
|
||||
end
|
||||
|
||||
@set.run_command @ctx, 'foo'
|
||||
|
@ -241,8 +244,8 @@ describe Pry::CommandSet do
|
|||
end
|
||||
|
||||
it "should provide a 'help' command" do
|
||||
@ctx.command_set = @set
|
||||
@ctx.output = StringIO.new
|
||||
@ctx[:command_set] = @set
|
||||
@ctx[:output] = StringIO.new
|
||||
|
||||
lambda {
|
||||
@set.run_command(@ctx, 'help')
|
||||
|
@ -255,12 +258,12 @@ describe Pry::CommandSet do
|
|||
@set.command 'moo', "Mooerizes" do; end
|
||||
@set.command 'boo', "Booerizes" do; end
|
||||
|
||||
@ctx.command_set = @set
|
||||
@ctx.output = StringIO.new
|
||||
@ctx[:command_set] = @set
|
||||
@ctx[:output] = StringIO.new
|
||||
|
||||
@set.run_command(@ctx, 'help')
|
||||
|
||||
doc = @ctx.output.string
|
||||
doc = @ctx[:output].string
|
||||
|
||||
order = [doc.index("boo"),
|
||||
doc.index("foo"),
|
||||
|
@ -331,15 +334,15 @@ describe Pry::CommandSet do
|
|||
end
|
||||
|
||||
it 'should share the context with the original command' do
|
||||
@ctx.target = "test target string"
|
||||
@ctx[:target] = "test target string".__binding__
|
||||
before_val = nil
|
||||
orig_val = nil
|
||||
@set.command('foo') { orig_val = target }
|
||||
@set.before_command('foo') { before_val = target }
|
||||
@set.run_command(@ctx, 'foo')
|
||||
|
||||
before_val.should == @ctx.target
|
||||
orig_val.should == @ctx.target
|
||||
before_val.should == @ctx[:target]
|
||||
orig_val.should == @ctx[:target]
|
||||
end
|
||||
|
||||
it 'should work when applied multiple times' do
|
||||
|
@ -375,15 +378,15 @@ describe Pry::CommandSet do
|
|||
end
|
||||
|
||||
it 'should share the context with the original command' do
|
||||
@ctx.target = "test target string"
|
||||
@ctx[:target] = "test target string".__binding__
|
||||
after_val = nil
|
||||
orig_val = nil
|
||||
@set.command('foo') { orig_val = target }
|
||||
@set.after_command('foo') { after_val = target }
|
||||
@set.run_command(@ctx, 'foo')
|
||||
|
||||
after_val.should == @ctx.target
|
||||
orig_val.should == @ctx.target
|
||||
after_val.should == @ctx[:target]
|
||||
orig_val.should == @ctx[:target]
|
||||
end
|
||||
|
||||
it 'should determine the return value for the command' do
|
||||
|
@ -418,149 +421,4 @@ describe Pry::CommandSet do
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
describe "class-based commands" do
|
||||
it 'should pass arguments to the command' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call(*args)
|
||||
args.should == [1, 2, 3]
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo', 1, 2, 3
|
||||
end
|
||||
|
||||
it 'should set unprovided arguments to nil' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call(x, y, z)
|
||||
x.should == 1
|
||||
y.should == nil
|
||||
z.should == nil
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo', 1
|
||||
end
|
||||
|
||||
it 'should clip provided arguments to expected number' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call(x, y, z)
|
||||
x.should == 1
|
||||
y.should == 2
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo', 1, 2, 3, 4
|
||||
end
|
||||
|
||||
it 'should return Pry::CommandContext::VOID by default' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call
|
||||
:i_have_done_thing_i_regret
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command(ctx, 'foo').should == Pry::CommandContext::VOID_VALUE
|
||||
end
|
||||
|
||||
it 'should return specific value when :keep_retval => true' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call
|
||||
:i_have_a_dog_called_tobina
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :keep_retval => true, :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command(ctx, 'foo').should == :i_have_a_dog_called_tobina
|
||||
end
|
||||
|
||||
it 'should have access to helper methods' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
def call
|
||||
im_helping.should == "butterbum"
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
@set.helpers do
|
||||
def im_helping
|
||||
"butterbum"
|
||||
end
|
||||
end
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo'
|
||||
end
|
||||
|
||||
it 'should persist state' do
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
attr_accessor :state
|
||||
def call
|
||||
@state ||= 0
|
||||
@state += 1
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo'
|
||||
@set.run_command ctx, 'foo'
|
||||
ctx.state.should == 2
|
||||
end
|
||||
|
||||
describe "before_command" do
|
||||
it 'should be called before the original command' do
|
||||
foo = []
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
define_method(:call) do
|
||||
foo << 1
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.before_command('foo') { foo << 2 }
|
||||
@set.run_command(ctx, 'foo')
|
||||
|
||||
foo.should == [2, 1]
|
||||
end
|
||||
end
|
||||
|
||||
describe "after_command" do
|
||||
it 'should be called before the original command' do
|
||||
foo = []
|
||||
c = Class.new(Pry::CommandContext) do
|
||||
define_method(:call) do
|
||||
foo << 1
|
||||
end
|
||||
end
|
||||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.after_command('foo') { foo << 2 }
|
||||
@set.run_command(ctx, 'foo')
|
||||
|
||||
foo.should == [1, 2]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -886,7 +886,7 @@ describe Pry do
|
|||
klass = Pry::CommandSet.new do
|
||||
alias_command "help2", "help"
|
||||
end
|
||||
klass.commands["help2"].callable.should == klass.commands["help"].callable
|
||||
klass.commands["help2"].block.should == klass.commands["help"].block
|
||||
end
|
||||
|
||||
it 'should change description of a command using desc' do
|
||||
|
|
Loading…
Reference in a new issue