diff --git a/lib/pry/completion.rb b/lib/pry/completion.rb index c7fc1e0b..0993cdd5 100644 --- a/lib/pry/completion.rb +++ b/lib/pry/completion.rb @@ -43,160 +43,144 @@ class Pry # @param [Array] commands The array of Pry commands. def self.build_completion_proc(target, commands=[""]) proc do |input| - bind = target + begin + bind = target - case input - when /^(\/[^\/]*\/)\.([^.]*)$/ - # Regexp - receiver = $1 - message = Regexp.quote($2) + case input + when /^(\/[^\/]*\/)\.([^.]*)$/ + # Regexp + receiver = $1 + message = Regexp.quote($2) - candidates = Regexp.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, candidates) + candidates = Regexp.instance_methods.collect{|m| m.to_s} + select_message(receiver, message, candidates) - when /^([^\]]*\])\.([^.]*)$/ - # Array - receiver = $1 - message = Regexp.quote($2) + when /^([^\]]*\])\.([^.]*)$/ + # Array + receiver = $1 + message = Regexp.quote($2) - candidates = Array.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, candidates) + candidates = Array.instance_methods.collect{|m| m.to_s} + select_message(receiver, message, candidates) - when /^([^\}]*\})\.([^.]*)$/ - # Proc or Hash - receiver = $1 - message = Regexp.quote($2) + when /^([^\}]*\})\.([^.]*)$/ + # Proc or Hash + receiver = $1 + message = Regexp.quote($2) - candidates = Proc.instance_methods.collect{|m| m.to_s} - candidates |= Hash.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, candidates) + candidates = Proc.instance_methods.collect{|m| m.to_s} + candidates |= Hash.instance_methods.collect{|m| m.to_s} + select_message(receiver, message, candidates) - when /^(:[^:.]*)$/ - # Symbol - if Symbol.respond_to?(:all_symbols) - sym = Regexp.quote($1) - candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name} + when /^(:[^:.]*)$/ + # Symbol + if Symbol.respond_to?(:all_symbols) + sym = Regexp.quote($1) + candidates = Symbol.all_symbols.collect{|s| ":" + s.id2name} - candidates.grep(/^#{sym}/) - else - [] - end + candidates.grep(/^#{sym}/) + else + [] + end - when /^::([A-Z][^:\.\(]*)$/ - # Absolute Constant or class methods - receiver = $1 - candidates = Object.constants.collect{|m| m.to_s} - candidates.grep(/^#{receiver}/).collect{|e| "::" + e} + when /^::([A-Z][^:\.\(]*)$/ + # Absolute Constant or class methods + receiver = $1 + candidates = Object.constants.collect{|m| m.to_s} + candidates.grep(/^#{receiver}/).collect{|e| "::" + e} - when /^([A-Z].*)::([^:.]*)$/ - # Constant or class methods - receiver = $1 - message = Regexp.quote($2) - begin + when /^([A-Z].*)::([^:.]*)$/ + # Constant or class methods + receiver = $1 + message = Regexp.quote($2) candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind) candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind) - rescue RescuableException - candidates = [] - end - candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e} + candidates.grep(/^#{message}/).collect{|e| receiver + "::" + e} - when /^(:[^:.]+)\.([^.]*)$/ - # Symbol - receiver = $1 - message = Regexp.quote($2) + when /^(:[^:.]+)\.([^.]*)$/ + # Symbol + receiver = $1 + message = Regexp.quote($2) - candidates = Symbol.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, candidates) + candidates = Symbol.instance_methods.collect{|m| m.to_s} + select_message(receiver, message, candidates) - when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/ - # Numeric - receiver = $1 - message = Regexp.quote($5) + when /^(-?(0[dbo])?[0-9_]+(\.[0-9_]+)?([eE]-?[0-9]+)?)\.([^.]*)$/ + # Numeric + receiver = $1 + message = Regexp.quote($5) - begin candidates = eval(receiver, bind).methods.collect{|m| m.to_s} - rescue RescuableException - candidates = [] - end - select_message(receiver, message, candidates) + select_message(receiver, message, candidates) - when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/ - # Numeric(0xFFFF) - receiver = $1 - message = Regexp.quote($2) + when /^(-?0x[0-9a-fA-F_]+)\.([^.]*)$/ + # Numeric(0xFFFF) + receiver = $1 + message = Regexp.quote($2) - begin candidates = eval(receiver, bind).methods.collect{|m| m.to_s} - rescue RescuableException - candidates = [] - end - select_message(receiver, message, candidates) + select_message(receiver, message, candidates) - when /^(\$[^.]*)$/ - regmessage = Regexp.new(Regexp.quote($1)) - candidates = global_variables.collect{|m| m.to_s}.grep(regmessage) + when /^(\$[^.]*)$/ + regmessage = Regexp.new(Regexp.quote($1)) + candidates = global_variables.collect{|m| m.to_s}.grep(regmessage) - when /^([^."].*)\.([^.]*)$/ - # variable - receiver = $1 - message = Regexp.quote($2) + when /^([^."].*)\.([^.]*)$/ + # variable + receiver = $1 + message = Regexp.quote($2) - gv = eval("global_variables", bind).collect{|m| m.to_s} - lv = eval("local_variables", bind).collect{|m| m.to_s} - cv = eval("self.class.constants", bind).collect{|m| m.to_s} + gv = eval("global_variables", bind).collect{|m| m.to_s} + lv = eval("local_variables", bind).collect{|m| m.to_s} + cv = eval("self.class.constants", bind).collect{|m| m.to_s} - if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver - # foo.func and foo is local var. OR - # Foo::Bar.func - begin + if (gv | lv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver + # foo.func and foo is local var. OR + # Foo::Bar.func candidates = eval("#{receiver}.methods", bind).collect{|m| m.to_s} - rescue RescuableException + else + # func1.func2 candidates = [] - end - else - # func1.func2 - candidates = [] - ObjectSpace.each_object(Module){|m| - begin + ObjectSpace.each_object(Module){|m| name = m.name.to_s - rescue RescuableException - name = "" - end - next if name != "IRB::Context" and - /^(IRB|SLex|RubyLex|RubyToken)/ =~ name + next if name != "IRB::Context" and + /^(IRB|SLex|RubyLex|RubyToken)/ =~ name - # jruby doesn't always provide #instance_methods() on each - # object. - if m.respond_to?(:instance_methods) - candidates.concat m.instance_methods(false).collect{|x| x.to_s} - end - } - candidates.sort! - candidates.uniq! + # jruby doesn't always provide #instance_methods() on each + # object. + if m.respond_to?(:instance_methods) + candidates.concat m.instance_methods(false).collect{|x| x.to_s} + end + } + candidates.sort! + candidates.uniq! + end + select_message(receiver, message, candidates) + + when /^\.([^.]*)$/ + # unknown(maybe String) + + receiver = "" + message = Regexp.quote($1) + + candidates = String.instance_methods(true).collect{|m| m.to_s} + select_message(receiver, message, candidates) + + else + candidates = eval( + "methods | private_methods | local_variables | " \ + "self.class.constants | instance_variables", + bind + ).collect{|m| m.to_s} + + if eval("respond_to?(:class_variables)", bind) + candidates += eval("class_variables", bind).collect { |m| m.to_s } + end + + (candidates|ReservedWords|commands).grep(/^#{Regexp.quote(input)}/) end - select_message(receiver, message, candidates) - - when /^\.([^.]*)$/ - # unknown(maybe String) - - receiver = "" - message = Regexp.quote($1) - - candidates = String.instance_methods(true).collect{|m| m.to_s} - select_message(receiver, message, candidates) - - else - candidates = eval( - "methods | private_methods | local_variables | " \ - "self.class.constants | instance_variables", - bind - ).collect{|m| m.to_s} - - if eval("respond_to?(:class_variables)", bind) - candidates += eval("class_variables", bind).collect { |m| m.to_s } - end - - (candidates|ReservedWords|commands).grep(/^#{Regexp.quote(input)}/) + rescue RescuableException + [] end end end diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb index fa6fe886..dadb81b7 100644 --- a/lib/pry/pry_instance.rb +++ b/lib/pry/pry_instance.rb @@ -539,6 +539,7 @@ class Pry # Manage switching of input objects on encountering EOFErrors def handle_read_errors should_retry = true + exception_count = 0 begin yield rescue EOFError @@ -565,6 +566,11 @@ class Pry # 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"