1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00

Add Pry::Driver to handle the reading and looping

This commit is contained in:
Conrad Irwin 2012-12-20 01:28:04 -08:00
parent 3dfac682c1
commit eeb67684d0
11 changed files with 300 additions and 306 deletions

View file

@ -229,6 +229,7 @@ rescue LoadError
end
require 'pry/version'
require 'pry/driver'
require 'pry/rbx_method'
require 'pry/rbx_path'
require 'pry/code'

197
lib/pry/driver.rb Normal file
View file

@ -0,0 +1,197 @@
require 'forwardable'
class Pry
class Driver
extend Forwardable
attr_accessor :pry
def_delegators :pry, :input, :output, :input_stack
def self.start(options)
new(options).repl
end
def initialize(options)
@pry = Pry.new(options)
@indent = Pry::Indent.new
end
def repl
repl_prologue
# FIXME: move these catchers back into Pry#accept_line
break_data = nil
exception = catch(:raise_up) do
break_data = catch(:breakout) do
repl_body
end
exception = false
end
raise exception if exception
break_data
ensure
repl_epilogue
end
private
def repl_prologue
pry.exec_hook :before_session, pry.output, pry.current_binding, pry
# Clear the line before starting Pry. This fixes the issue discussed here:
# https://github.com/pry/pry/issues/566
if Pry.config.auto_indent
Kernel.print Pry::Helpers::BaseHelpers.windows_ansi? ? "\e[0F" : "\e[0G"
end
end
def repl_body
loop do
case val = retrieve_line
when :control_c
output.puts ""
pry.reset_line
when :end_of_file
output.puts "" if output.tty?
pry.accept_eof
else
pry.accept_line val
end
end
end
# Clean-up after the repl session.
def repl_epilogue
pry.exec_hook :after_session, pry.output, pry.current_binding, pry
Pry.save_history if Pry.config.history.should_save
end
# Read and process a line of input -- check for ^D, determine which prompt to
# use, rewrite the indentation if `Pry.config.auto_indent` is enabled, and,
# if the line is a command, process it and alter the @eval_string accordingly.
#
# @return [String] The line received.
def retrieve_line
@indent.reset if pry.eval_string.empty?
current_prompt = pry.select_prompt
completion_proc = Pry.config.completer.build_completion_proc(pry.current_binding, pry,
pry.instance_eval(&pry.custom_completions))
safe_completion_proc = proc{ |*a| Pry.critical_section{ completion_proc.call(*a) } }
indentation = Pry.config.auto_indent ? @indent.current_prefix : ''
begin
val = readline("#{current_prompt}#{indentation}", safe_completion_proc)
# Handle <Ctrl+C> like Bash, empty the current input buffer but do not quit.
# This is only for ruby-1.9; other versions of ruby do not let you send Interrupt
# from within Readline.
rescue Interrupt
return :control_c
end
# invoke handler if we receive EOF character (^D)
return :end_of_file unless val
if Pry.config.auto_indent && !input.is_a?(StringIO)
original_val = "#{indentation}#{val}"
indented_val = @indent.indent(val)
if output.tty? && Pry::Helpers::BaseHelpers.use_ansi_codes? && Pry.config.correct_indent
output.print @indent.correct_indentation(current_prompt, indented_val, original_val.length - indented_val.length)
output.flush
end
else
indented_val = val
end
Pry.history << indented_val if interactive?
indented_val
end
# Is the user typing into this pry instance directly?
# @return [Boolean]
def interactive?
!input.is_a?(StringIO)
end
# Manage switching of input objects on encountering EOFErrors
def handle_read_errors
should_retry = true
exception_count = 0
begin
yield
rescue EOFError
if input_stack.empty?
pry.input = Pry.config.input
if !should_retry
output.puts "Error: Pry ran out of things to read from! Attempting to break out of REPL."
throw(:breakout)
end
should_retry = false
else
pry.input = input_stack.pop
end
retry
# Interrupts are handled in r() because they need to tweak @eval_string
# TODO: Refactor this baby.
rescue Interrupt
raise
# If we get a random error when trying to read a line we don't want to automatically
# retry, as the user will see a lot of error messages scroll past and be unable to do
# anything about it.
rescue RescuableException => e
puts "Error: #{e.message}"
output.puts e.backtrace
exception_count += 1
if exception_count < 5
retry
end
puts "FATAL: Pry failed to get user input using `#{input}`."
puts "To fix this you may be able to pass input and output file descriptors to pry directly. e.g."
puts " Pry.config.input = STDIN"
puts " Pry.config.output = STDOUT"
puts " binding.pry"
throw(:breakout)
end
end
# Returns the next line of input to be used by the pry instance.
# This method should not need to be invoked directly.
# @param [String] current_prompt The prompt to use for input.
# @return [String] The next line of input.
def readline(current_prompt="> ", completion_proc=nil)
handle_read_errors do
if defined? Coolline and input.is_a? Coolline
input.completion_proc = proc do |cool|
completions = completion_proc.call cool.completed_word
completions.compact
end
elsif input.respond_to? :completion_proc=
input.completion_proc = completion_proc
end
if input == Readline
input.readline(current_prompt, false) # false since we'll add it manually
elsif defined? Coolline and input.is_a? Coolline
input.readline(current_prompt)
else
if input.method(:readline).arity == 1
input.readline(current_prompt)
else
input.readline
end
end
end
end
end
end

View file

@ -148,8 +148,11 @@ class Pry
end
end
driver = options[:driver] || Pry::Driver
# Enter the matrix
new(options).repl
driver.new(options).repl
rescue Pry::TooSafeException
puts "ERROR: Pry cannot work with $SAFE > 0"
raise

View file

@ -231,48 +231,18 @@ class Pry
Pry.save_history if Pry.config.history.should_save
end
# Start a read-eval-print-loop in the current context.
def repl
repl_prologue
break_data = nil
exception = catch(:raise_up) do
break_data = catch(:breakout) do
r
end
exception = false
end
raise exception if exception
break_data
ensure
repl_epilogue
def reset_line
@eval_string = ""
end
def r
loop do
throw(:breakout) if current_binding.nil?
@suppress_output = false
inject_sticky_locals!
case val = retrieve_line
when :control_c
output.puts ""
@eval_string = ""
when :end_of_file
output.puts "" if output.tty?
Pry.config.control_d_handler.call(@eval_string, self)
else
ensure_correct_encoding!(val)
accept_line(val)
end
exec_hook :after_read, @eval_string, self
end
def accept_eof
Pry.config.control_d_handler.call(@eval_string, self)
end
def accept_line(line)
@suppress_output = false
inject_sticky_locals!
ensure_correct_encoding!(line)
begin
if !process_command_safely(line.lstrip)
@eval_string << "#{line.chomp}\n" unless line.empty?
@ -287,6 +257,10 @@ class Pry
return
end
# This hook is supposed to be executed after each line of ruby code
# has been read (regardless of whether eval_string is yet a complete expression)
exec_hook :after_read, eval_string, self
begin
complete_expr = Pry::Code.complete_expression?(@eval_string)
rescue SyntaxError => e
@ -312,6 +286,8 @@ class Pry
show_result(result)
end
end
throw(:breakout) if current_binding.nil?
end
def evaluate_ruby(code)
@ -360,52 +336,6 @@ class Pry
end
private :ensure_correct_encoding!
# Read and process a line of input -- check for ^D, determine which prompt to
# use, rewrite the indentation if `Pry.config.auto_indent` is enabled, and,
# if the line is a command, process it and alter the @eval_string accordingly.
#
# @return [String] The line received.
def retrieve_line
@indent.reset if @eval_string.empty?
current_prompt = select_prompt
completion_proc = Pry.config.completer.build_completion_proc(current_binding, self,
instance_eval(&custom_completions))
safe_completion_proc = proc{ |*a| Pry.critical_section{ completion_proc.call(*a) } }
indentation = Pry.config.auto_indent ? @indent.current_prefix : ''
begin
val = readline("#{current_prompt}#{indentation}", safe_completion_proc)
# Handle <Ctrl+C> like Bash, empty the current input buffer but do not quit.
# This is only for ruby-1.9; other versions of ruby do not let you send Interrupt
# from within Readline.
rescue Interrupt
return :control_c
end
# invoke handler if we receive EOF character (^D)
return :end_of_file unless val
if Pry.config.auto_indent && !input.is_a?(StringIO)
original_val = "#{indentation}#{val}"
indented_val = @indent.indent(val)
if output.tty? && Pry::Helpers::BaseHelpers.use_ansi_codes? && Pry.config.correct_indent
output.print @indent.correct_indentation(current_prompt, indented_val, original_val.length - indented_val.length)
output.flush
end
else
indented_val = val
end
Pry.history << indented_val if interactive?
indented_val
end
# Is the user typing into this pry instance directly?
# @return [Boolean]
def interactive?
@ -543,81 +473,6 @@ class Pry
@last_result_is_exception
end
# Manage switching of input objects on encountering EOFErrors
def handle_read_errors
should_retry = true
exception_count = 0
begin
yield
rescue EOFError
if input_stack.empty?
self.input = Pry.config.input
if !should_retry
output.puts "Error: Pry ran out of things to read from! Attempting to break out of REPL."
throw(:breakout)
end
should_retry = false
else
self.input = input_stack.pop
end
retry
# Interrupts are handled in r() because they need to tweak @eval_string
# TODO: Refactor this baby.
rescue Interrupt
raise
# If we get a random error when trying to read a line we don't want to automatically
# retry, as the user will see a lot of error messages scroll past and be unable to do
# anything about it.
rescue RescuableException => e
puts "Error: #{e.message}"
output.puts e.backtrace
exception_count += 1
if exception_count < 5
retry
end
puts "FATAL: Pry failed to get user input using `#{input}`."
puts "To fix this you may be able to pass input and output file descriptors to pry directly. e.g."
puts " Pry.config.input = STDIN"
puts " Pry.config.output = STDOUT"
puts " binding.pry"
throw(:breakout)
end
end
private :handle_read_errors
# Returns the next line of input to be used by the pry instance.
# This method should not need to be invoked directly.
# @param [String] current_prompt The prompt to use for input.
# @return [String] The next line of input.
def readline(current_prompt="> ", completion_proc=nil)
handle_read_errors do
if defined? Coolline and input.is_a? Coolline
input.completion_proc = proc do |cool|
completions = completion_proc.call cool.completed_word
completions.compact
end
elsif input.respond_to? :completion_proc=
input.completion_proc = completion_proc
end
if input == Readline
input.readline(current_prompt, false) # false since we'll add it manually
elsif defined? Coolline and input.is_a? Coolline
input.readline(current_prompt)
else
if input.method(:readline).arity == 1
input.readline(current_prompt)
else
input.readline
end
end
end
end
# Whether the print proc should be invoked.
# Currently only invoked if the output is not suppressed.
# @return [Boolean] Whether the print proc should be invoked.

View file

@ -28,6 +28,7 @@ describe "commands" do
after do
Pad.clear
Pry.reset_defaults
end
describe "alias_command" do
@ -356,11 +357,7 @@ describe "commands" do
end
it 'should create a command in a nested context and that command should be accessible from the parent' do
redirect_pry_io(StringIO.new("@x=nil\ncd 7\n_pry_.commands.instance_eval {\ncommand('bing') { |arg| run arg }\n}\ncd ..\nbing ls\nexit-all"), @str_output) do
Pry.new(:target => 0).repl
end
pry_tester(0).eval(*(<<-RUBY.split("\n"))).should =~ /instance variables:\s+@x/m
pry_tester(Object.new).eval(*(<<-RUBY.split("\n"))).should =~ /instance variables:\s+@x/m
@x = nil
cd 7
_pry_.commands.instance_eval { command('bing') { |arg| run arg } }
@ -459,21 +456,15 @@ describe "commands" do
end
end
Pry.commands = klass
Pry.new(:input => InputTester.new("hello"), :output => @str_output).repl
@str_output.string.should =~ /hello world/
other_klass = Pry::CommandSet.new do
command "goodbye", "" do
output.puts "goodbye world"
end
end
@str_output = StringIO.new
Pry.new(:input => InputTester.new("goodbye"), :output => @str_output, :commands => other_klass).repl
@str_output.string.should =~ /goodbye world/
Pry.commands = klass
pry_tester.eval("hello").should == "hello world\n"
pry_tester(:commands => other_klass).eval("goodbye").should == "goodbye world\n"
end
it 'should inherit commands from Pry::Commands' do
@ -554,19 +545,9 @@ describe "commands" do
end
end
# suppress evaluation output
Pry.print = proc {}
Pry.new(:input => InputTester.new("jump-to"), :output => @str_output, :commands => klass).repl
@str_output.string.rstrip.should == "jump-to the music"
@str_output = StringIO.new
Pry.new(:input => InputTester.new("help"), :output => @str_output, :commands => klass).repl
@str_output.string.should == "help to the music\n"
Pry.reset_defaults
Pry.color = false
t = pry_tester(:commands => klass)
t.eval('jump-to').should == "jump-to the music\n"
t.eval('help').should == "help to the music\n"
end
it 'should run a command with no parameter' do

View file

@ -13,13 +13,13 @@ describe "raise-up" do
it "should raise the exception with raise-up" do
redirect_pry_io(InputTester.new("raise NoMethodError", "raise-up NoMethodError")) do
lambda { Pry.new(:target => 0).repl }.should.raise NoMethodError
lambda { Object.new.pry }.should.raise NoMethodError
end
end
it "should raise an unamed exception with raise-up" do
redirect_pry_io(InputTester.new("raise 'stop'","raise-up 'noreally'")) do
lambda { Pry.new(:target => 0).repl }.should.raise RuntimeError, "noreally"
lambda { Object.new.pry }.should.raise RuntimeError, "noreally"
end
end

View file

@ -17,28 +17,25 @@ describe Pry::DEFAULT_CONTROL_D_HANDLER do
describe 'at top-level session' do
it 'should break out of a REPL loop' do
instance = nil
redirect_pry_io(InputTester.new(@control_d)) do
instance = Pry.new
instance.repl
end
instance = Pry.new
instance.binding_stack.should.not.be.empty
called = false
catch(:breakout) {
instance.accept_eof
called = true
}
called.should == false
instance.binding_stack.should.be.empty
end
end
describe 'in a nested session' do
it 'should pop last binding from the binding stack' do
base = OpenStruct.new
base.obj = OpenStruct.new
redirect_pry_io(InputTester.new("cd obj", "self.stack_size = _pry_.binding_stack.size",
@control_d, "self.stack_size = _pry_.binding_stack.size", "exit-all")) do
Pry.start(base)
end
base.obj.stack_size.should == 2
base.stack_size.should == 1
t = pry_tester
t.eval "cd Object.new"
t.eval("_pry_.binding_stack.size").should == 2
t.eval("_pry_.accept_eof")
t.eval("_pry_.binding_stack.size").should == 1
end
end
end

View file

@ -17,13 +17,12 @@ describe "Pry#input_stack" do
Pry.config.input_stack = []
end
it 'should read from all input objects on stack and exit session (usingn repl)' do
it 'should read from all input objects on stack and exit session' do
stack = [b = StringIO.new(":cloister\nexit\n"), c = StringIO.new(":baron\n")]
instance = Pry.new(:input => StringIO.new(":alex\n"),
:output => @str_output,
:input_stack => stack)
Object.new.pry :input => StringIO.new(":alex\n"),
:output => @str_output,
:input_stack => stack
instance.repl
@str_output.string.should =~ /:alex/
@str_output.string.should =~ /:baron/
@str_output.string.should =~ /:cloister/
@ -31,28 +30,25 @@ describe "Pry#input_stack" do
it 'input objects should be popped off stack as they are used up' do
stack = [StringIO.new(":cloister\n"), StringIO.new(":baron\n")]
instance = Pry.new(:input => StringIO.new(":alex\n"),
:output => @str_output,
:input_stack => stack)
instance.push_binding binding
driver = Pry::Driver.new :input => StringIO.new(":alex\n"),
:output => @str_output,
:input_stack => stack
stack.size.should == 2
instance.retrieve_line.should == ":alex\n"
driver.send(:retrieve_line).should == ":alex\n"
stack.size.should == 2
instance.retrieve_line.should == ":baron\n"
driver.send(:retrieve_line).should == ":baron\n"
stack.size.should == 1
instance.retrieve_line.should == ":cloister\n"
driver.send(:retrieve_line).should == ":cloister\n"
stack.size.should == 0
end
it 'should revert to Pry.config.input when it runs out of input objects in input_stack' do
redirect_pry_io(StringIO.new(":rimbaud\nexit\n"), StringIO.new) do
stack = [StringIO.new(":cloister\n"), StringIO.new(":baron\n")]
instance = Pry.new(:input => StringIO.new(":alex\n"),
:output => @str_output,
:input_stack => stack)
Object.new.pry :input => StringIO.new(":alex\n"),
:output => @str_output,
:input_stack => stack
instance.repl
@str_output.string.should =~ /:alex/
@str_output.string.should =~ /:baron/
@str_output.string.should =~ /:cloister/
@ -63,7 +59,7 @@ describe "Pry#input_stack" do
it 'should display error and throw(:breakout) if at end of input after using up input_stack objects' do
catch(:breakout) do
redirect_pry_io(StringIO.new(":rimbaud\n"), @str_output) do
Pry.new(:input_stack => [StringIO.new(":a\n"), StringIO.new(":b\n")]).repl
Object.new.pry :input_stack => [StringIO.new(":a\n"), StringIO.new(":b\n")]
end
end
@str_output.string.should =~ /Error: Pry ran out of things to read/

View file

@ -21,10 +21,11 @@ describe "test Pry defaults" do
it 'should set the input default, and the default should be overridable' do
Pry.input = InputTester.new("5")
Pry.output = @str_output
Pry.new.repl
Object.new.pry
@str_output.string.should =~ /5/
Pry.new(:input => InputTester.new("6")).repl
Pry.output = @str_output
Object.new.pry :input => InputTester.new("6")
@str_output.string.should =~ /6/
end
@ -77,16 +78,16 @@ describe "test Pry defaults" do
Pry.output = @str_output
Pry.input = InputTester.new("5")
Pry.new.repl
Object.new.pry
@str_output.string.should =~ /5/
Pry.input = InputTester.new("6")
Pry.new.repl
Object.new.pry
@str_output.string.should =~ /5\n.*6/
Pry.input = InputTester.new("7")
@str_output = StringIO.new
Pry.new(:output => @str_output).repl
Object.new.pry :output => @str_output
@str_output.string.should.not =~ /5\n.*6/
@str_output.string.should =~ /7/
end
@ -96,17 +97,17 @@ describe "test Pry defaults" do
Pry.print = new_print
Pry.new.print.should == Pry.print
Pry.new(:input => InputTester.new("\"test\""), :output => @str_output).repl
Object.new.pry :input => InputTester.new("\"test\""), :output => @str_output
@str_output.string.should == "=> LOL\n"
@str_output = StringIO.new
Pry.new(:input => InputTester.new("\"test\""), :output => @str_output,
:print => proc { |out, value| out.puts value.reverse }).repl
Object.new.pry :input => InputTester.new("\"test\""), :output => @str_output,
:print => proc { |out, value| out.puts value.reverse }
@str_output.string.should == "=> tset\n"
Pry.new.print.should == Pry.print
@str_output = StringIO.new
Pry.new(:input => InputTester.new("\"test\""), :output => @str_output).repl
Object.new.pry :input => InputTester.new("\"test\""), :output => @str_output
@str_output.string.should == "=> LOL\n"
end
@ -381,18 +382,17 @@ describe "test Pry defaults" do
add_hook(:before_session, :my_name) { |out,_,_| out.puts "HELLO" }.
add_hook(:after_session, :my_name) { |out,_,_| out.puts "BYE" }
Pry.new(:output => @str_output).repl
Object.new.pry :output => @str_output
@str_output.string.should =~ /HELLO/
@str_output.string.should =~ /BYE/
Pry.input.rewind
@str_output = StringIO.new
Pry.new(:output => @str_output,
:hooks => Pry::Hooks.new.
add_hook( :before_session, :my_name) { |out,_,_| out.puts "MORNING" }.
add_hook(:after_session, :my_name) { |out,_,_| out.puts "EVENING" }
).repl
Object.new.pry :output => @str_output,
:hooks => Pry::Hooks.new.
add_hook( :before_session, :my_name) { |out,_,_| out.puts "MORNING" }.
add_hook(:after_session, :my_name) { |out,_,_| out.puts "EVENING" }
@str_output.string.should =~ /MORNING/
@str_output.string.should =~ /EVENING/
@ -400,19 +400,17 @@ describe "test Pry defaults" do
# try below with just defining one hook
Pry.input.rewind
@str_output = StringIO.new
Pry.new(:output => @str_output,
:hooks => Pry::Hooks.new.
add_hook(:before_session, :my_name) { |out,_,_| out.puts "OPEN" }
).repl
Object.new.pry :output => @str_output,
:hooks => Pry::Hooks.new.
add_hook(:before_session, :my_name) { |out,_,_| out.puts "OPEN" }
@str_output.string.should =~ /OPEN/
Pry.input.rewind
@str_output = StringIO.new
Pry.new(:output => @str_output,
:hooks => Pry::Hooks.new.
add_hook(:after_session, :my_name) { |out,_,_| out.puts "CLOSE" }
).repl
Object.new.pry :output => @str_output,
:hooks => Pry::Hooks.new.
add_hook(:after_session, :my_name) { |out,_,_| out.puts "CLOSE" }
@str_output.string.should =~ /CLOSE/

View file

@ -101,7 +101,7 @@ describe Pry do
it 'should display error if Pry instance runs out of input' do
redirect_pry_io(StringIO.new, @str_output) do
Pry.new.repl
Pry.start
end
@str_output.string.should =~ /Error: Pry ran out of things to read/
end
@ -176,50 +176,39 @@ describe Pry do
describe "history arrays" do
it 'sets _ to the last result' do
res = []
input = InputTester.new *[":foo", "self << _", "42", "self << _"]
Pry.new(:input => input, :output => StringIO.new, :target => res).repl
res.should == [:foo, 42]
t = pry_tester
t.eval ":foo"
t.eval("_").should == :foo
t.eval "42"
t.eval("_").should == 42
end
it 'sets out to an array with the result' do
res = {}
input = InputTester.new *[":foo", "42", "self[:res] = _out_"]
Pry.new(:input => input, :output => StringIO.new, :target => res).repl
t = pry_tester
t.eval ":foo"
t.eval "42"
res = t.eval "_out_"
res[:res].should.be.kind_of Pry::HistoryArray
res[:res][1..2].should == [:foo, 42]
res.should.be.kind_of Pry::HistoryArray
res[1..2].should == [:foo, 42]
end
it 'sets _in_ to an array with the entered lines' do
res = {}
input = InputTester.new *[":foo", "42", "self[:res] = _in_"]
Pry.new(:input => input, :output => StringIO.new, :target => res).repl
t = pry_tester
t.eval ":foo"
t.eval "42"
res = t.eval "_in_"
res[:res].should.be.kind_of Pry::HistoryArray
res[:res][1..2].should == [":foo\n", "42\n"]
res.should.be.kind_of Pry::HistoryArray
res[1..2].should == [":foo\n", "42\n"]
end
it 'uses 100 as the size of _in_ and _out_' do
res = []
input = InputTester.new *["self << _out_.max_size << _in_.max_size"]
Pry.new(:input => input, :output => StringIO.new, :target => res).repl
res.should == [100, 100]
pry_tester.eval("[_in_.max_size, _out_.max_size]").should == [100, 100]
end
it 'can change the size of the history arrays' do
res = []
input = InputTester.new *["self << _out_.max_size << _in_.max_size"]
Pry.new(
:input => input,
:output => StringIO.new,
:memory_size => 1000,
:target => res
).repl
res.should == [1000, 1000]
pry_tester(:memory_size => 1000).eval("[_out_, _in_].map(&:max_size)").should == [1000, 1000]
end
it 'store exceptions' do
@ -296,18 +285,6 @@ describe Pry do
Object.const_defined?(:TEST_RC).should == false
end
it "should not load the rc file if #repl method invoked" do
Pry.config.should_load_rc = true
Pry.new(
:input => StringIO.new("exit-all\n"),
:output => StringIO.new
).repl
Object.const_defined?(:TEST_RC).should == false
Pry.config.should_load_rc = false
end
describe "that raise exceptions" do
before do
Pry::HOME_RC_FILE = "spec/fixtures/testrcbad"

View file

@ -122,27 +122,16 @@ describe "Sticky locals (_file_ and friends)" do
end
it 'should create a new sticky local' do
o = Object.new
pry = Pry.new(:target => o)
pry.add_sticky_local(:test_local) { :test_value }
pry.input = InputTester.new("@value = test_local", "exit-all")
pry.output = StringIO.new
pry.repl
o.instance_variable_get(:@value).should == :test_value
t = pry_tester
t.eval "_pry_.add_sticky_local(:test_local){ :test_value }"
t.eval("test_local").should == :test_value
end
it 'should still exist after cd-ing into new binding' do
o = Object.new
o2 = Object.new
o.instance_variable_set(:@o2, o2)
pry = Pry.new(:target => o)
pry.add_sticky_local(:test_local) { :test_value }
pry.input = InputTester.new("cd @o2\n", "@value = test_local", "exit-all")
pry.output = StringIO.new
pry.repl
o2.instance_variable_get(:@value).should == :test_value
t = pry_tester
t.eval "_pry_.add_sticky_local(:test_local){ :test_value }"
t.eval "cd Object.new"
t.eval("test_local").should == :test_value
end
it 'should provide different values for successive block invocations' do