diff --git a/CHANGELOG b/CHANGELOG index 9405e52a..ea1260ed 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ * changed `exit` command so that it now called Kernel#exit (after saving history) * 'quit' now behaves like 'exit-all' (and aliased to exit-all) - it breaks out of the repl loop and sets empties the binding_stack * 'cd ..' just pops a binding off the binding_stack with special behaviour when only one binding in stack - it breaks out of the repl loop +* added switch-to command (like jump-to but doesnt unwind the stack) * show-method and show-doc now accept multiple method names * control_d hook added (Pry.config.control_d_handler) * behaviour of ^d is now to break out of current expr if in multi-line expr, or break out of current context if nested, or break out of pry repl loop if at top-level diff --git a/lib/pry/default_commands/introspection.rb b/lib/pry/default_commands/introspection.rb index e6dca1a5..a365d7ee 100644 --- a/lib/pry/default_commands/introspection.rb +++ b/lib/pry/default_commands/introspection.rb @@ -131,12 +131,10 @@ class Pry should_reload = opts[:r] if opts.ex? - last_exception = target.eval("_ex_") + next output.puts "No Exception found." if _pry_.last_exception.nil? - next output.puts "No Exception found." if last_exception.nil? - - file_name = last_exception.file - line = last_exception.line + file_name = _pry_.last_exception.file + line = _pry_.last_exception.line next output.puts "Exception has no associated file." if file_name.nil? next output.puts "Cannot edit exceptions raised in REPL." if Pry.eval_path == file_name elsif opts.t? diff --git a/lib/pry/default_commands/shell.rb b/lib/pry/default_commands/shell.rb index 02295873..cebb4e9d 100644 --- a/lib/pry/default_commands/shell.rb +++ b/lib/pry/default_commands/shell.rb @@ -38,7 +38,6 @@ class Pry start_line = 0 end_line = -1 file_name = nil - last_exception = target.eval("_ex_") opts = Slop.parse!(args) do |opt| opt.on :s, :start, "Start line (defaults to start of file)Line 1 is the first line.", true, :as => Integer do |line| @@ -51,7 +50,7 @@ class Pry opt.on :ex, "Show a window of N lines either side of the last exception (defaults to 5).", :optional => true, :as => Integer do |window_size| window_size ||= 5 - ex = last_exception + ex = _pry_.last_exception next if !ex start_line = (ex.line - 1) - window_size start_line = start_line < 0 ? 0 : start_line @@ -94,7 +93,7 @@ class Pry contents = contents.lines.each_with_index.map do |line, idx| l = idx + start_line - if l == (last_exception.line - 1) + if l == (_pry_.last_exception.line - 1) " =>#{line}" else " #{line}" @@ -102,8 +101,8 @@ class Pry end.join # header for exceptions - output.puts "\n#{Pry::Helpers::Text.bold('Exception:')}: #{last_exception.class}: #{last_exception.message}" - output.puts "#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{last_exception.line}\n\n" + output.puts "\n#{Pry::Helpers::Text.bold('Exception:')}: #{_pry_.last_exception.class}: #{_pry_.last_exception.message}" + output.puts "#{Pry::Helpers::Text.bold('From:')} #{file_name} @ line #{_pry_.last_exception.line}\n\n" end set_file_and_dir_locals(file_name) diff --git a/lib/pry/helpers/base_helpers.rb b/lib/pry/helpers/base_helpers.rb index acb7068f..7536815f 100644 --- a/lib/pry/helpers/base_helpers.rb +++ b/lib/pry/helpers/base_helpers.rb @@ -36,8 +36,11 @@ class Pry def set_file_and_dir_locals(file_name) return if !target - _pry_.inject_local("_file_", File.expand_path(file_name), target) - _pry_.inject_local("_dir_", File.dirname(File.expand_path(file_name)), target) + _pry_.last_file = File.expand_path(file_name) + _pry_.inject_local("_file_", _pry_.last_file, target) + + _pry_.last_dir = File.dirname(_pry_.last_file) + _pry_.inject_local("_dir_", _pry_.last_dir, target) end def stub_proc(name, options) diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb index 927fdbb9..a1b511be 100644 --- a/lib/pry/pry_instance.rb +++ b/lib/pry/pry_instance.rb @@ -12,6 +12,11 @@ class Pry attr_accessor :binding_stack + attr_accessor :last_result + attr_accessor :last_exception + attr_accessor :last_file + attr_accessor :last_dir + # Create a new `Pry` object. # @param [Hash] options The optional configuration parameters. # @option options [#readline] :input The object to use for input. @@ -101,19 +106,36 @@ class Pry hooks[hook_name].call(*args, &block) if hooks[hook_name] end - # Initialize the repl session. - # @param [Binding] target The target binding for the session. - def repl_prologue(target) - exec_hook :before_session, output, target - - # Make sure special locals exist + # Make sure special locals exist at start of session + def initialize_special_locals(target) inject_local("inp", @input_array, target) inject_local("out", @output_array, target) inject_local("_pry_", self, target) inject_local("_ex_", nil, target) - inject_local("file_", nil, target) + inject_local("_file_", nil, target) inject_local("_dir_", nil, target) + + # without this line we get 1 test failure, ask Mon_Ouie set_last_result(nil, target) + inject_local("_", nil, target) + end + private :initialize_special_locals + + def inject_special_locals(target) + inject_local("inp", @input_array, target) + inject_local("out", @output_array, target) + inject_local("_pry_", self, target) + inject_local("_ex_", self.last_exception, target) + inject_local("_file_", self.last_file, target) + inject_local("_dir_", self.last_dir, target) + inject_local("_", self.last_result, target) + end + + # Initialize the repl session. + # @param [Binding] target The target binding for the session. + def repl_prologue(target) + exec_hook :before_session, output, target + initialize_special_locals(target) @input_array << nil # add empty input so inp and out match @@ -185,14 +207,14 @@ class Pry Readline.completion_proc = Pry::InputCompleter.build_completion_proc target, instance_eval(&custom_completions) end - inject_local("inp", @input_array, target) - inject_local("out", @output_array, target) - inject_local("_pry_", self, target) + # It's not actually redundant to inject them continually as we may have + # moved into the scope of a new Binding (e.g the user typed `cd`) + inject_special_locals(target) code = r(target) - res = set_last_result(target.eval(code, Pry.eval_path, Pry.current_line), target) - res + result = set_last_result(target.eval(code, Pry.eval_path, Pry.current_line), target) + result rescue RescuableException => e set_last_exception(e, target) ensure @@ -299,7 +321,7 @@ class Pry @last_result_is_exception = false @output_array << result - inject_local("_", result, target) + self.last_result = result end # Set the last exception for a session. @@ -317,7 +339,7 @@ class Pry @last_result_is_exception = true @output_array << ex - inject_local("_ex_", ex, target) + self.last_exception = ex end # Update Pry's internal state after evalling code. diff --git a/test/helper.rb b/test/helper.rb index 26167365..a0a611e7 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -27,6 +27,11 @@ end Pry.reset_defaults +# this is to test exception code (cat --ex) +def broken_method + this method is broken +end + # sample doc def sample_method :sample