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.
|
# Execute a Pry command.
|
||||||
# This method should not need to be invoked directly.
|
# This method should not need to be invoked directly.
|
||||||
# @param [Binding] target The target of the Pry session.
|
# @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 [Hash] options The options to set on the Commands object.
|
||||||
# @param [Array] args The command arguments.
|
# @param [Array] args The command arguments.
|
||||||
# @return [Object] The value returned by the command
|
# @return [Object] The value returned by the command
|
||||||
def execute_command(target, command, options, *args)
|
def execute_command(target, command, options, *args)
|
||||||
ret = nil
|
ret = nil
|
||||||
|
|
||||||
if command.block.is_a?(Proc)
|
if command.callable.is_a?(Proc)
|
||||||
context = CommandContext.new
|
context = CommandContext.new
|
||||||
else
|
else
|
||||||
context = command.block
|
|
||||||
|
# in the case of non-procs the callable *is* the context
|
||||||
|
context = command.callable
|
||||||
end
|
end
|
||||||
|
|
||||||
# set some useful methods to be used by the action blocks
|
# set some useful methods to be used by the action blocks
|
||||||
|
@ -187,19 +189,19 @@ class Pry
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_context(target, command, context, options)
|
def setup_context(target, command, context, options)
|
||||||
context.opts = options
|
context.opts = options
|
||||||
context.target = target
|
context.target = target
|
||||||
context.target_self = target.eval('self')
|
context.target_self = target.eval('self')
|
||||||
context.output = output
|
context.output = output
|
||||||
context.captures = options[:captures]
|
context.captures = options[:captures]
|
||||||
context.eval_string = options[:eval_string]
|
context.eval_string = options[:eval_string]
|
||||||
context.arg_string = options[:arg_string]
|
context.arg_string = options[:arg_string]
|
||||||
context.command_set = commands
|
context.command_set = commands
|
||||||
context.command_name = command.options[:listing]
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,17 +8,19 @@ class Pry
|
||||||
# This class is used to create sets of commands. Commands can be imported from
|
# This class is used to create sets of commands. Commands can be imported from
|
||||||
# different sets, aliased, removed, etc.
|
# different sets, aliased, removed, etc.
|
||||||
class CommandSet
|
class CommandSet
|
||||||
class Command < Struct.new(:name, :description, :options, :block)
|
class Command < Struct.new(:name, :description, :options, :callable)
|
||||||
|
|
||||||
def call(context, *args)
|
def call(context, *args)
|
||||||
|
|
||||||
if stub_block = options[:stub_info]
|
if stub_block = options[:stub_info]
|
||||||
context.instance_eval(&stub_block)
|
context.instance_eval(&stub_block)
|
||||||
else
|
else
|
||||||
if block.is_a?(Proc)
|
if callable.is_a?(Proc)
|
||||||
ret = context.instance_exec(*correct_arg_arity(block.arity, args), &block)
|
ret = context.instance_exec(*correct_arg_arity(callable.arity, args), &callable)
|
||||||
else
|
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
|
end
|
||||||
|
|
||||||
if options[:keep_retval]
|
if options[:keep_retval]
|
||||||
|
@ -157,13 +159,18 @@ class Pry
|
||||||
# end
|
# end
|
||||||
def before_command(name, &block)
|
def before_command(name, &block)
|
||||||
cmd = find_command_by_name_or_listing(name)
|
cmd = find_command_by_name_or_listing(name)
|
||||||
prev_block = cmd.block
|
prev_callable = cmd.callable
|
||||||
|
|
||||||
wrapper_block = proc do |*args|
|
wrapper_block = proc do |*args|
|
||||||
instance_exec(*args, &block)
|
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
|
end
|
||||||
cmd.block = wrapper_block
|
cmd.callable = wrapper_block
|
||||||
end
|
end
|
||||||
|
|
||||||
# Execute a block of code after a command is invoked. The block also
|
# Execute a block of code after a command is invoked. The block also
|
||||||
|
@ -177,13 +184,18 @@ class Pry
|
||||||
# end
|
# end
|
||||||
def after_command(name, &block)
|
def after_command(name, &block)
|
||||||
cmd = find_command_by_name_or_listing(name)
|
cmd = find_command_by_name_or_listing(name)
|
||||||
prev_block = cmd.block
|
prev_callable = cmd.callable
|
||||||
|
|
||||||
wrapper_block = proc do |*args|
|
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)
|
instance_exec(*args, &block)
|
||||||
end
|
end
|
||||||
cmd.block = wrapper_block
|
cmd.callable = wrapper_block
|
||||||
end
|
end
|
||||||
|
|
||||||
def each &block
|
def each &block
|
||||||
|
@ -279,6 +291,8 @@ class Pry
|
||||||
# @raise [NoCommandError] If the command is not defined in this set
|
# @raise [NoCommandError] If the command is not defined in this set
|
||||||
def run_command(context, command_name, *args)
|
def run_command(context, command_name, *args)
|
||||||
command = commands[command_name]
|
command = commands[command_name]
|
||||||
|
|
||||||
|
|
||||||
context.extend helper_module
|
context.extend helper_module
|
||||||
|
|
||||||
if command.nil?
|
if command.nil?
|
||||||
|
|
|
@ -69,7 +69,7 @@ class Pry
|
||||||
end
|
end
|
||||||
|
|
||||||
if find_command(command_name)
|
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
|
next unless block.source
|
||||||
set_file_and_dir_locals(block.source_file)
|
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
|
it 'should share the context with the original command' do
|
||||||
@ctx.target = "test target string"
|
@ctx.target = "test target string"
|
||||||
after_val = nil
|
after_val = nil
|
||||||
orig_val = nil
|
orig_val = nil
|
||||||
@set.command('foo') { orig_val = target }
|
@set.command('foo') { orig_val = target }
|
||||||
@set.after_command('foo') { after_val = target }
|
@set.after_command('foo') { after_val = target }
|
||||||
|
@ -429,7 +429,7 @@ describe Pry::CommandSet do
|
||||||
|
|
||||||
@set.command 'foo', "desc", :definition => c.new
|
@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
|
@set.run_command ctx, 'foo', 1, 2, 3
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -444,7 +444,7 @@ describe Pry::CommandSet do
|
||||||
|
|
||||||
@set.command 'foo', "desc", :definition => c.new
|
@set.command 'foo', "desc", :definition => c.new
|
||||||
|
|
||||||
ctx = @set.commands['foo'].block
|
ctx = @set.commands['foo'].callable
|
||||||
@set.run_command ctx, 'foo', 1
|
@set.run_command ctx, 'foo', 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -458,7 +458,7 @@ describe Pry::CommandSet do
|
||||||
|
|
||||||
@set.command 'foo', "desc", :definition => c.new
|
@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
|
@set.run_command ctx, 'foo', 1, 2, 3, 4
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -471,7 +471,7 @@ describe Pry::CommandSet do
|
||||||
|
|
||||||
@set.command 'foo', "desc", :definition => c.new
|
@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
|
@set.run_command(ctx, 'foo').should == Pry::CommandContext::VOID_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -484,7 +484,7 @@ describe Pry::CommandSet do
|
||||||
|
|
||||||
@set.command 'foo', "desc", :keep_retval => true, :definition => c.new
|
@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
|
@set.run_command(ctx, 'foo').should == :i_have_a_dog_called_tobina
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -503,7 +503,7 @@ describe Pry::CommandSet do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ctx = @set.commands['foo'].block
|
ctx = @set.commands['foo'].callable
|
||||||
@set.run_command ctx, 'foo'
|
@set.run_command ctx, 'foo'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ describe Pry::CommandSet do
|
||||||
|
|
||||||
@set.command 'foo', "desc", :definition => c.new
|
@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'
|
||||||
@set.run_command ctx, 'foo'
|
@set.run_command ctx, 'foo'
|
||||||
ctx.state.should == 2
|
ctx.state.should == 2
|
||||||
|
@ -535,7 +535,7 @@ describe Pry::CommandSet do
|
||||||
|
|
||||||
@set.command 'foo', "desc", :definition => c.new
|
@set.command 'foo', "desc", :definition => c.new
|
||||||
|
|
||||||
ctx = @set.commands['foo'].block
|
ctx = @set.commands['foo'].callable
|
||||||
@set.before_command('foo') { foo << 2 }
|
@set.before_command('foo') { foo << 2 }
|
||||||
@set.run_command(ctx, 'foo')
|
@set.run_command(ctx, 'foo')
|
||||||
|
|
||||||
|
@ -543,5 +543,24 @@ describe Pry::CommandSet do
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,16 +2,6 @@ require 'helper'
|
||||||
|
|
||||||
describe Pry do
|
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/
|
if RUBY_VERSION =~ /1.9/
|
||||||
describe "Exotic object support" do
|
describe "Exotic object support" do
|
||||||
# regression test for exotic object support
|
# regression test for exotic object support
|
||||||
|
@ -792,7 +782,7 @@ describe Pry do
|
||||||
str_output = StringIO.new
|
str_output = StringIO.new
|
||||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||||
str_output.string.should =~ /nil/
|
str_output.string.should =~ /nil/
|
||||||
str_output.string.should =~ /=>/
|
str_output.string.should =~ /=>/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should define a command that keeps its return value but does not return when value is void' do
|
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
|
str_output.string.empty?.should == true
|
||||||
end
|
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
|
klass = Pry::CommandSet.new do
|
||||||
command "hello", "" do
|
command "hello", "" do
|
||||||
eval_string.replace("6")
|
eval_string.replace("6")
|
||||||
|
@ -818,45 +808,45 @@ describe Pry do
|
||||||
end
|
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
|
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
|
klass = Pry::CommandSet.new do
|
||||||
command "hello", "", :keep_retval => true do
|
command "hello", "", :keep_retval => true do
|
||||||
eval_string.replace("6")
|
eval_string.replace("6")
|
||||||
7
|
7
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
str_output = StringIO.new
|
||||||
str_output = StringIO.new
|
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
|
||||||
str_output.string.should =~ /7/
|
str_output.string.should =~ /7/
|
||||||
str_output.string.should.not =~ /6/
|
str_output.string.should.not =~ /6/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'a command that return a value in a multi-line expression should clear the expression and return the value' do
|
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
|
klass = Pry::CommandSet.new do
|
||||||
command "hello", "", :keep_retval => true do
|
command "hello", "", :keep_retval => true do
|
||||||
5
|
5
|
||||||
end
|
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"
|
|
||||||
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
|
end
|
||||||
|
|
||||||
Pry.commands = klass
|
|
||||||
|
|
||||||
str_output = StringIO.new
|
it 'should set the commands default, and the default should be overridable' do
|
||||||
Pry.new(:input => InputTester.new("hello"), :output => str_output).rep
|
klass = Pry::CommandSet.new do
|
||||||
str_output.string.should =~ /hello world/
|
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
|
command "goodbye", "" do
|
||||||
output.puts "goodbye world"
|
output.puts "goodbye world"
|
||||||
end
|
end
|
||||||
|
@ -896,7 +886,7 @@ describe Pry do
|
||||||
klass = Pry::CommandSet.new do
|
klass = Pry::CommandSet.new do
|
||||||
alias_command "help2", "help"
|
alias_command "help2", "help"
|
||||||
end
|
end
|
||||||
klass.commands["help2"].block.should == klass.commands["help"].block
|
klass.commands["help2"].callable.should == klass.commands["help"].callable
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should change description of a command using desc' do
|
it 'should change description of a command using desc' do
|
||||||
|
@ -1312,7 +1302,7 @@ describe Pry do
|
||||||
str_output = StringIO.new
|
str_output = StringIO.new
|
||||||
Pry.new(:output => str_output,
|
Pry.new(:output => str_output,
|
||||||
:hooks => Pry::Hooks.new.
|
: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
|
).repl
|
||||||
|
|
||||||
str_output.string.should =~ /OPEN/
|
str_output.string.should =~ /OPEN/
|
||||||
|
@ -1321,7 +1311,7 @@ describe Pry do
|
||||||
str_output = StringIO.new
|
str_output = StringIO.new
|
||||||
Pry.new(:output => str_output,
|
Pry.new(:output => str_output,
|
||||||
:hooks => Pry::Hooks.new.
|
: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
|
).repl
|
||||||
|
|
||||||
str_output.string.should =~ /CLOSE/
|
str_output.string.should =~ /CLOSE/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue