mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
added some integration tests for class based commands && renamed Pry::CommandContext:Command#block to #callable
This commit is contained in:
parent
1cbe7d4c9c
commit
f52626e169
6 changed files with 160 additions and 74 deletions
|
@ -161,17 +161,19 @@ class Pry
|
|||
# Execute a Pry command.
|
||||
# This method should not need to be invoked directly.
|
||||
# @param [Binding] target The target of the Pry session.
|
||||
# @param [String] command The name of the command to be run.
|
||||
# @param [Pry::CommandSet::Command] command The command object.
|
||||
# @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)
|
||||
ret = nil
|
||||
|
||||
if command.block.is_a?(Proc)
|
||||
if command.callable.is_a?(Proc)
|
||||
context = CommandContext.new
|
||||
else
|
||||
context = command.block
|
||||
|
||||
# in the case of non-procs the callable *is* the context
|
||||
context = command.callable
|
||||
end
|
||||
|
||||
# set some useful methods to be used by the action blocks
|
||||
|
@ -187,19 +189,19 @@ class Pry
|
|||
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.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._pry_ = @pry_instance
|
||||
|
||||
context.command_processor = self
|
||||
context.command_processor = self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,17 +8,19 @@ 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 < Struct.new(:name, :description, :options, :block)
|
||||
class Command < Struct.new(:name, :description, :options, :callable)
|
||||
|
||||
def call(context, *args)
|
||||
|
||||
if stub_block = options[:stub_info]
|
||||
context.instance_eval(&stub_block)
|
||||
else
|
||||
if block.is_a?(Proc)
|
||||
ret = context.instance_exec(*correct_arg_arity(block.arity, args), &block)
|
||||
if callable.is_a?(Proc)
|
||||
ret = context.instance_exec(*correct_arg_arity(callable.arity, args), &callable)
|
||||
else
|
||||
ret = block.call(*correct_arg_arity(block.method(:call).arity, args))
|
||||
|
||||
# in the case of non-procs the callable *is* the context
|
||||
ret = callable.call(*correct_arg_arity(callable.method(:call).arity, args))
|
||||
end
|
||||
|
||||
if options[:keep_retval]
|
||||
|
@ -157,13 +159,18 @@ class Pry
|
|||
# end
|
||||
def before_command(name, &block)
|
||||
cmd = find_command_by_name_or_listing(name)
|
||||
prev_block = cmd.block
|
||||
prev_callable = cmd.callable
|
||||
|
||||
wrapper_block = proc do |*args|
|
||||
instance_exec(*args, &block)
|
||||
instance_exec(*args, &prev_block)
|
||||
|
||||
if prev_callable.is_a?(Proc)
|
||||
instance_exec(*args, &prev_callable)
|
||||
else
|
||||
prev_callable.call(*args)
|
||||
end
|
||||
end
|
||||
cmd.block = wrapper_block
|
||||
cmd.callable = wrapper_block
|
||||
end
|
||||
|
||||
# Execute a block of code after a command is invoked. The block also
|
||||
|
@ -177,13 +184,18 @@ class Pry
|
|||
# end
|
||||
def after_command(name, &block)
|
||||
cmd = find_command_by_name_or_listing(name)
|
||||
prev_block = cmd.block
|
||||
prev_callable = cmd.callable
|
||||
|
||||
wrapper_block = proc do |*args|
|
||||
instance_exec(*args, &prev_block)
|
||||
if prev_callable.is_a?(Proc)
|
||||
instance_exec(*args, &prev_callable)
|
||||
else
|
||||
prev_callable.call(*args)
|
||||
end
|
||||
|
||||
instance_exec(*args, &block)
|
||||
end
|
||||
cmd.block = wrapper_block
|
||||
cmd.callable = wrapper_block
|
||||
end
|
||||
|
||||
def each &block
|
||||
|
@ -279,6 +291,8 @@ class Pry
|
|||
# @raise [NoCommandError] If the command is not defined in this set
|
||||
def run_command(context, command_name, *args)
|
||||
command = commands[command_name]
|
||||
|
||||
|
||||
context.extend helper_module
|
||||
|
||||
if command.nil?
|
||||
|
|
|
@ -69,7 +69,7 @@ class Pry
|
|||
end
|
||||
|
||||
if find_command(command_name)
|
||||
block = Pry::Method.new(find_command(command_name).block)
|
||||
block = Pry::Method.new(find_command(command_name).callable)
|
||||
|
||||
next unless block.source
|
||||
set_file_and_dir_locals(block.source_file)
|
||||
|
|
61
test/test_class_based_commands.rb
Normal file
61
test/test_class_based_commands.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
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 !~ /i_enjoyed_the_song_new_flame_by_simply_red_as_a_child_wandering_around_supermarkets/
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -376,7 +376,7 @@ describe Pry::CommandSet do
|
|||
|
||||
it 'should share the context with the original command' do
|
||||
@ctx.target = "test target string"
|
||||
after_val = nil
|
||||
after_val = nil
|
||||
orig_val = nil
|
||||
@set.command('foo') { orig_val = target }
|
||||
@set.after_command('foo') { after_val = target }
|
||||
|
@ -429,7 +429,7 @@ describe Pry::CommandSet do
|
|||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].block
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo', 1, 2, 3
|
||||
end
|
||||
|
||||
|
@ -444,7 +444,7 @@ describe Pry::CommandSet do
|
|||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].block
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo', 1
|
||||
end
|
||||
|
||||
|
@ -458,7 +458,7 @@ describe Pry::CommandSet do
|
|||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].block
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo', 1, 2, 3, 4
|
||||
end
|
||||
|
||||
|
@ -471,7 +471,7 @@ describe Pry::CommandSet do
|
|||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].block
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command(ctx, 'foo').should == Pry::CommandContext::VOID_VALUE
|
||||
end
|
||||
|
||||
|
@ -484,7 +484,7 @@ describe Pry::CommandSet do
|
|||
|
||||
@set.command 'foo', "desc", :keep_retval => true, :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].block
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command(ctx, 'foo').should == :i_have_a_dog_called_tobina
|
||||
end
|
||||
|
||||
|
@ -503,7 +503,7 @@ describe Pry::CommandSet do
|
|||
end
|
||||
end
|
||||
|
||||
ctx = @set.commands['foo'].block
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo'
|
||||
end
|
||||
|
||||
|
@ -518,7 +518,7 @@ describe Pry::CommandSet do
|
|||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].block
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.run_command ctx, 'foo'
|
||||
@set.run_command ctx, 'foo'
|
||||
ctx.state.should == 2
|
||||
|
@ -535,7 +535,7 @@ describe Pry::CommandSet do
|
|||
|
||||
@set.command 'foo', "desc", :definition => c.new
|
||||
|
||||
ctx = @set.commands['foo'].block
|
||||
ctx = @set.commands['foo'].callable
|
||||
@set.before_command('foo') { foo << 2 }
|
||||
@set.run_command(ctx, 'foo')
|
||||
|
||||
|
@ -543,5 +543,24 @@ describe Pry::CommandSet do
|
|||
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
|
||||
|
|
|
@ -2,16 +2,6 @@ require 'helper'
|
|||
|
||||
describe Pry do
|
||||
|
||||
# if RUBY_PLATFORM !~ /mingw/ && RUBY_PLATFORM !~ /mswin/ && RUBY_PLATFORM != 'java'
|
||||
# describe 'warning emissions' do
|
||||
# it 'should emit no warnings' do
|
||||
# Open4.popen4 'ruby -I lib -rubygems -r"pry" -W -e "exit"' do |pid, stdin, stdout, stderr|
|
||||
# stderr.read.empty?.should == true
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
if RUBY_VERSION =~ /1.9/
|
||||
describe "Exotic object support" do
|
||||
# regression test for exotic object support
|
||||
|
@ -792,7 +782,7 @@ describe Pry do
|
|||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /nil/
|
||||
str_output.string.should =~ /=>/
|
||||
str_output.string.should =~ /=>/
|
||||
end
|
||||
|
||||
it 'should define a command that keeps its return value but does not return when value is void' do
|
||||
|
@ -806,7 +796,7 @@ describe Pry do
|
|||
str_output.string.empty?.should == true
|
||||
end
|
||||
|
||||
it 'a command (with :keep_retval => false) that replaces eval_string with a valid expression should not have the expression value suppressed' do
|
||||
it 'a command (with :keep_retval => false) that replaces eval_string with a valid expression should not have the expression value suppressed' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "" do
|
||||
eval_string.replace("6")
|
||||
|
@ -818,45 +808,45 @@ describe Pry do
|
|||
end
|
||||
|
||||
|
||||
it 'a command (with :keep_retval => true) that replaces eval_string with a valid expression should overwrite the eval_string with the return value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
it 'a command (with :keep_retval => true) that replaces eval_string with a valid expression should overwrite the eval_string with the return value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
eval_string.replace("6")
|
||||
7
|
||||
end
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /7/
|
||||
str_output.string.should.not =~ /6/
|
||||
end
|
||||
|
||||
it 'a command that return a value in a multi-line expression should clear the expression and return the value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
5
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /5/
|
||||
end
|
||||
|
||||
|
||||
it 'should set the commands default, and the default should be overridable' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello" do
|
||||
output.puts "hello world"
|
||||
it 'a command that return a value in a multi-line expression should clear the expression and return the value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
5
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /5/
|
||||
end
|
||||
|
||||
Pry.commands = klass
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("hello"), :output => str_output).rep
|
||||
str_output.string.should =~ /hello world/
|
||||
it 'should set the commands default, and the default should be overridable' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello" do
|
||||
output.puts "hello world"
|
||||
end
|
||||
end
|
||||
|
||||
other_klass = Pry::CommandSet.new do
|
||||
Pry.commands = klass
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("hello"), :output => str_output).rep
|
||||
str_output.string.should =~ /hello world/
|
||||
|
||||
other_klass = Pry::CommandSet.new do
|
||||
command "goodbye", "" do
|
||||
output.puts "goodbye world"
|
||||
end
|
||||
|
@ -896,7 +886,7 @@ describe Pry do
|
|||
klass = Pry::CommandSet.new do
|
||||
alias_command "help2", "help"
|
||||
end
|
||||
klass.commands["help2"].block.should == klass.commands["help"].block
|
||||
klass.commands["help2"].callable.should == klass.commands["help"].callable
|
||||
end
|
||||
|
||||
it 'should change description of a command using desc' do
|
||||
|
@ -1312,7 +1302,7 @@ describe Pry do
|
|||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output,
|
||||
:hooks => Pry::Hooks.new.
|
||||
add_hook(:before_session, :my_name) { |out,_,_| out.puts "OPEN" }
|
||||
add_hook(:before_session, :my_name) { |out,_,_| out.puts "OPEN" }
|
||||
).repl
|
||||
|
||||
str_output.string.should =~ /OPEN/
|
||||
|
@ -1321,7 +1311,7 @@ describe Pry do
|
|||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output,
|
||||
:hooks => Pry::Hooks.new.
|
||||
add_hook(:after_session, :my_name) { |out,_,_| out.puts "CLOSE" }
|
||||
add_hook(:after_session, :my_name) { |out,_,_| out.puts "CLOSE" }
|
||||
).repl
|
||||
|
||||
str_output.string.should =~ /CLOSE/
|
||||
|
|
Loading…
Reference in a new issue