summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConrad Irwin <conrad.irwin@gmail.com>2012-11-13 21:59:59 -0800
committerConrad Irwin <conrad.irwin@gmail.com>2012-11-13 21:59:59 -0800
commit6de594fef39fbef5678d4c54266d2c0f9ca50ba3 (patch)
treeed16530755b0e1217b2182cd982aa8bf524aa0c7
parent1ffae5ebddcfdc96ea10f9a43ce0caf7fef7b00c (diff)
downloadpry-6de594fef39fbef5678d4c54266d2c0f9ca50ba3.tar.gz
Add Pry.critical_section to break pry inside pry [Fixes #729]
-rw-r--r--lib/pry/pry_class.rb18
-rw-r--r--lib/pry/pry_instance.rb21
-rw-r--r--test/test_pry.rb11
3 files changed, 42 insertions, 8 deletions
diff --git a/lib/pry/pry_class.rb b/lib/pry/pry_class.rb
index 2d2be5a2..6f87cd57 100644
--- a/lib/pry/pry_class.rb
+++ b/lib/pry/pry_class.rb
@@ -128,6 +128,13 @@ class Pry
# Pry.start(Object.new, :input => MyInput.new)
def self.start(target=nil, options={})
return if ENV['DISABLE_PRY']
+
+ if in_critical_section?
+ output.puts "ERROR: Pry started inside Pry."
+ output.puts "This can happen if you have a binding.pry inside a #to_s or #inspect function."
+ return
+ end
+
target = Pry.binding_for(target || toplevel_binding)
initial_session_setup
@@ -416,6 +423,17 @@ class Pry
@toplevel_binding.eval('private')
@toplevel_binding
end
+
+ def self.in_critical_section?
+ @critical_section.to_i > 0
+ end
+
+ def self.critical_section(&block)
+ @critical_section = @critical_section.to_i + 1
+ yield
+ ensure
+ @critical_section -= 1
+ end
end
Pry.init
diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb
index 9bc81f29..21b3acbe 100644
--- a/lib/pry/pry_instance.rb
+++ b/lib/pry/pry_instance.rb
@@ -253,7 +253,9 @@ class Pry
target = Pry.binding_for(target)
result = re(target)
- show_result(result)
+ Pry.critical_section do
+ show_result(result)
+ end
end
# Perform a read-eval
@@ -374,11 +376,12 @@ class Pry
completion_proc = Pry.config.completer.build_completion_proc(target, 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}", completion_proc)
+ 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
@@ -659,13 +662,15 @@ class Pry
:eval_string => eval_string,
:cont => !eval_string.empty?)
- # If input buffer is empty then use normal prompt
- if eval_string.empty?
- generate_prompt(Array(prompt).first, c)
+ Pry.critical_section do
+ # If input buffer is empty then use normal prompt
+ if eval_string.empty?
+ generate_prompt(Array(prompt).first, c)
- # Otherwise use the wait prompt (indicating multi-line expression)
- else
- generate_prompt(Array(prompt).last, c)
+ # Otherwise use the wait prompt (indicating multi-line expression)
+ else
+ generate_prompt(Array(prompt).last, c)
+ end
end
end
diff --git a/test/test_pry.rb b/test/test_pry.rb
index 781027c1..aee20530 100644
--- a/test/test_pry.rb
+++ b/test/test_pry.rb
@@ -38,6 +38,17 @@ describe Pry do
end
end
+ describe "Pry.critical_section" do
+ it "should prevent Pry being called" do
+ output = StringIO.new
+ Pry.output = output
+ Pry.critical_section do
+ Pry.start
+ end
+ output.string.should =~ /Pry started inside Pry/
+ end
+ end
+
describe "Pry.binding_for" do
# regression test for burg's bug (see git history)