diff options
author | Conrad Irwin <conrad.irwin@gmail.com> | 2012-11-13 21:59:59 -0800 |
---|---|---|
committer | Conrad Irwin <conrad.irwin@gmail.com> | 2012-11-13 21:59:59 -0800 |
commit | 6de594fef39fbef5678d4c54266d2c0f9ca50ba3 (patch) | |
tree | ed16530755b0e1217b2182cd982aa8bf524aa0c7 | |
parent | 1ffae5ebddcfdc96ea10f9a43ce0caf7fef7b00c (diff) | |
download | pry-6de594fef39fbef5678d4c54266d2c0f9ca50ba3.tar.gz |
Add Pry.critical_section to break pry inside pry [Fixes #729]
-rw-r--r-- | lib/pry/pry_class.rb | 18 | ||||
-rw-r--r-- | lib/pry/pry_instance.rb | 21 | ||||
-rw-r--r-- | test/test_pry.rb | 11 |
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) |