Using a new Pry::CommandProcessor::Result class to manage the way command results are handled.
Behaviour now is: (1) command that has keep_retval => false can replace eval_string() and when the multi-line expression is evaluated it will return value of the multi-line expression (old behaviour did not do this) (2) command that has keep_retval => true will always replace whatever multi-line expression it's invoked in with the return value of the command
This commit is contained in:
parent
d5bbaefd3e
commit
256ddd712e
|
@ -2,6 +2,36 @@ require 'forwardable'
|
|||
|
||||
class Pry
|
||||
class CommandProcessor
|
||||
|
||||
# Wraps the return result of process_commands, indicates if the
|
||||
# result IS a command and what kind of command (e.g void)
|
||||
class Result
|
||||
attr_reader :retval
|
||||
|
||||
def initialize(is_command, keep_retval = false, retval = nil)
|
||||
@is_command, @keep_retval, @retval = is_command, keep_retval, retval
|
||||
end
|
||||
|
||||
# Is the result a command?
|
||||
# @return [Boolean]
|
||||
def command?
|
||||
@is_command
|
||||
end
|
||||
|
||||
# Is the result a command and if it is, is it a void command?
|
||||
# (one that does not return a value)
|
||||
# @return [Boolean]
|
||||
def void_command?
|
||||
(command? && !keep_retval?) || retval == CommandContext::VOID_VALUE
|
||||
end
|
||||
|
||||
# Is the return value kept for this command? (i.e :keep_retval => true)
|
||||
# @return [Boolean]
|
||||
def keep_retval?
|
||||
@keep_retval
|
||||
end
|
||||
end
|
||||
|
||||
extend Forwardable
|
||||
|
||||
attr_accessor :pry_instance
|
||||
|
@ -80,13 +110,17 @@ class Pry
|
|||
# @param [String] eval_string The cumulative lines of input for
|
||||
# multi-line input.
|
||||
# @param [Binding] target The receiver of the commands.
|
||||
# @return [Object] The value returned by the
|
||||
# command.
|
||||
# @return [Pry::CommandProcessor::Result] A wrapper object
|
||||
# containing info about the result of the command processing
|
||||
# (indicating whether it is a command and if it is what kind of
|
||||
# command it is.
|
||||
def process_commands(val, eval_string, target)
|
||||
|
||||
# no command was matched, so return to caller
|
||||
command, captures, pos = command_matched(val, target)
|
||||
return if !command
|
||||
|
||||
# no command was matched, so return to caller
|
||||
return Result.new(false) if !command
|
||||
|
||||
arg_string = val[pos..-1]
|
||||
|
||||
# remove the one leading space if it exists
|
||||
|
@ -104,7 +138,7 @@ class Pry
|
|||
|
||||
ret = execute_command(target, command.name, options, *(captures + args))
|
||||
|
||||
[ret, command.options[:keep_retval]]
|
||||
Result.new(true, command.options[:keep_retval], ret)
|
||||
end
|
||||
|
||||
# Execute a Pry command.
|
||||
|
|
|
@ -246,7 +246,7 @@ class Pry
|
|||
break if valid_expression?(eval_string)
|
||||
end
|
||||
|
||||
@suppress_output = true if eval_string =~ /;\Z/ || null_input?(val)
|
||||
@suppress_output = true if eval_string =~ /;\Z/ || null_input?(eval_string)
|
||||
|
||||
eval_string
|
||||
end
|
||||
|
@ -277,8 +277,9 @@ class Pry
|
|||
# value.
|
||||
# @param [String] val The input string.
|
||||
# @return [Boolean] Whether the input is null.
|
||||
def null_input?(val)
|
||||
val.empty? && Thread.current[:__pry_cmd_ret_value__] == Pry::CommandContext::VOID_VALUE
|
||||
def null_input?(eval_string)
|
||||
result = Thread.current[:__pry_cmd_ret_value__]
|
||||
eval_string.empty? || (eval_string.empty? && result.void_command?)
|
||||
end
|
||||
|
||||
# Read a line of input and check for ^d, also determine prompt to use.
|
||||
|
@ -306,12 +307,21 @@ class Pry
|
|||
# @param [String] eval_string The cumulative lines of input.
|
||||
# @param [Binding] target The target of the Pry session.
|
||||
def process_line(val, eval_string, target)
|
||||
Thread.current[:__pry_cmd_ret_value__], keep_retval = @command_processor.process_commands(val, eval_string, target)
|
||||
result = @command_processor.process_commands(val, eval_string, target)
|
||||
Thread.current[:__pry_cmd_result__] = result
|
||||
|
||||
if keep_retval && Thread.current[:__pry_cmd_ret_value__] != Pry::CommandContext::VOID_VALUE
|
||||
eval_string << "Thread.current[:__pry_cmd_ret_value__]\n"
|
||||
# note that `result` wraps the result of command processing; if a
|
||||
# command was matched and invoked then `result.command?` returns true,
|
||||
# otherwise it returns false.
|
||||
if result.command? && !result.void_command?
|
||||
|
||||
# the command is non-void (has a return value) and so we make
|
||||
# the value of the current expression equal to the return value
|
||||
# of the command.
|
||||
eval_string.replace "Thread.current[:__pry_cmd_result__].retval\n"
|
||||
else
|
||||
# only commands (with no ret_value) should have an empty `val` so this ignores their result
|
||||
# only commands should have an empty `val`
|
||||
# so this ignores their result
|
||||
eval_string << "#{val.rstrip}\n" if !val.empty?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,7 +33,6 @@ describe Pry do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
describe "Pry.binding_for" do
|
||||
|
||||
# regression test for burg's bug (see git history)
|
||||
|
@ -93,6 +92,18 @@ describe Pry do
|
|||
o.instance_variable_get(:@x).should == 10
|
||||
end
|
||||
|
||||
it 'should not output anything for no input' do
|
||||
outp = StringIO.new
|
||||
|
||||
# note i could not use mock_pry() for this test for some
|
||||
# reason, as i'd always get "\n" as output instead of ""
|
||||
redirect_pry_io(StringIO.new(""), outp) do
|
||||
Pry.new.rep(self)
|
||||
end
|
||||
|
||||
outp.string.empty?.should == true
|
||||
end
|
||||
|
||||
it 'should make self evaluate to the receiver of the rep session' do
|
||||
o = :john
|
||||
str_output = StringIO.new
|
||||
|
@ -736,6 +747,43 @@ 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
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "" do
|
||||
eval_string.replace("6")
|
||||
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 =~ /6/
|
||||
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
|
||||
eval_string.replace("6")
|
||||
7
|
||||
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 =~ /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
|
||||
|
|
Loading…
Reference in New Issue