From 09774a034aefed3a0ccb923c1c6ec94933e42073 Mon Sep 17 00:00:00 2001 From: John Mair Date: Sun, 21 Aug 2011 18:22:45 +1200 Subject: [PATCH] migrated to a binding_stack approach from nested instances --- lib/pry/command_processor.rb | 3 +- lib/pry/default_commands/context.rb | 25 ++++++------ lib/pry/pry_class.rb | 17 -------- lib/pry/pry_instance.rb | 61 ++++++----------------------- test/test_pry.rb | 2 +- 5 files changed, 28 insertions(+), 80 deletions(-) diff --git a/lib/pry/command_processor.rb b/lib/pry/command_processor.rb index e3ffc759..fa30ac7b 100644 --- a/lib/pry/command_processor.rb +++ b/lib/pry/command_processor.rb @@ -10,7 +10,7 @@ class Pry @pry_instance = pry_instance end - def_delegators :@pry_instance, :commands, :nesting, :output + def_delegators :@pry_instance, :commands, :output # Is the string a valid command? # @param [String] val The string passed in from the Pry prompt. @@ -96,7 +96,6 @@ class Pry :val => val, :arg_string => arg_string, :eval_string => eval_string, - :nesting => nesting, :commands => commands.commands, :captures => captures } diff --git a/lib/pry/default_commands/context.rb b/lib/pry/default_commands/context.rb index 60bb746f..b5553da7 100644 --- a/lib/pry/default_commands/context.rb +++ b/lib/pry/default_commands/context.rb @@ -12,15 +12,17 @@ class Pry output.puts "Must provide an object." next when ".." - throw(:breakout, opts[:nesting].level) + _pry_.binding_stack.pop.eval('self') + # throw(:breakout, opts[:nesting].level) when "/" - throw(:breakout, 1) if opts[:nesting].level > 0 - next + _pry_.binding_stack = [_pry_.binding_stack.first] + nil when "::" TOPLEVEL_BINDING.pry next else - Pry.start target.eval(arg_string) + _pry_.binding_stack.push Pry.binding_for(target.eval(arg_string)) + nil end end @@ -29,11 +31,11 @@ class Pry output.puts "Nesting status:" output.puts "--" - nesting.each do |level, obj| + _pry_.binding_stack.each_with_index do |obj, level| if level == 0 - output.puts "#{level}. #{Pry.view_clip(obj)} (Pry top level)" + output.puts "#{level}. #{Pry.view_clip(obj.eval('self'))} (Pry top level)" else - output.puts "#{level}. #{Pry.view_clip(obj)}" + output.puts "#{level}. #{Pry.view_clip(obj.eval('self'))}" end end end @@ -53,12 +55,13 @@ class Pry end end - command "exit", "End the current Pry session. Accepts optional return value. Aliases: quit, back" do - throw(:breakout, [opts[:nesting].level, target.eval(arg_string)]) + command "quit", "End the current Pry session. Accepts optional return value. Aliases: exit-all, !!@" do + throw(:breakout, target.eval(arg_string)) end - alias_command "quit", "exit", "" - alias_command "back", "exit", "" + alias_command "!!@", "quit", "" + alias_command "exit", "quit", "" + alias_command "exit-all", "quit", "" command "exit-all", "End all nested Pry sessions. Accepts optional return value. Aliases: !!@" do throw(:breakout, [0, target.eval(arg_string)]) diff --git a/lib/pry/pry_class.rb b/lib/pry/pry_class.rb index bed7b73d..e6e7da2f 100644 --- a/lib/pry/pry_class.rb +++ b/lib/pry/pry_class.rb @@ -18,11 +18,6 @@ class Pry def_delegators delagatee, *names.map { |v| "#{v}=" } end - # Get nesting data. - # This method should not need to be accessed directly. - # @return [Array] The unparsed nesting information. - attr_reader :nesting - # Get last value evaluated by Pry. # This method should not need to be accessed directly. # @return [Object] The last result. @@ -263,18 +258,6 @@ class Pry locate_plugins end - @nesting = [] - def @nesting.level - last.is_a?(Array) ? last.first : nil - end - - # Return all active Pry sessions. - # @return [Array] Active Pry sessions. - def self.sessions - # last element in nesting array is the pry instance - nesting.map(&:last) - end - # Return a `Binding` object for `target` or return `target` if it is # already a `Binding`. # In the case where `target` is top-level then return `TOPLEVEL_BINDING` diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb index 649b0773..f2ac2f74 100644 --- a/lib/pry/pry_instance.rb +++ b/lib/pry/pry_instance.rb @@ -10,10 +10,7 @@ class Pry attr_accessor :hooks attr_accessor :custom_completions - # Returns the target binding for the session. Note that altering this - # attribute will not change the target binding. - # @return [Binding] The target object for the session - attr_accessor :session_target + attr_accessor :binding_stack # Create a new `Pry` object. # @param [Hash] options The optional configuration parameters. @@ -28,6 +25,7 @@ class Pry refresh(options) @command_processor = CommandProcessor.new(self) + @binding_stack = [] end # Refresh the Pry instance settings from the Pry class. @@ -84,32 +82,6 @@ class Pry @output_array = Pry::HistoryArray.new(size) end - # Get nesting data. - # This method should not need to be accessed directly. - # @return [Array] The unparsed nesting information. - def nesting - self.class.nesting - end - - # Set nesting data. - # This method should not need to be accessed directly. - # @param v nesting data. - def nesting=(v) - self.class.nesting = v - end - - # @return [Boolean] Whether top-level session has ended. - def finished_top_level_session? - nesting.empty? - end - - # Return parent of current Pry session. - # @return [Pry] The parent of the current Pry session. - def parent - idx = Pry.sessions.index(self) - Pry.sessions[idx - 1] if idx && idx > 0 - end - # Execute the hook `hook_name`, if it is defined. # @param [Symbol] hook_name The hook to execute # @param [Array] args The arguments to pass to the hook. @@ -131,25 +103,21 @@ class Pry @input_array << nil # add empty input so inp and out match set_last_result(Pry.last_result, target) - self.session_target = target + binding_stack.push target end # Clean-up after the repl session. # @param [Binding] target The target binding for the session. # @return [Object] The return value of the repl session (if one exists). - def repl_epilogue(target, nesting_level, break_data) - nesting.pop + def repl_epilogue(target, break_data) exec_hook :after_session, output, target # If break_data is an array, then the last element is the return value - break_level, return_value = Array(break_data) + return_value = break_data - # keep throwing until we reach the desired nesting level - if nesting_level != break_level - throw :breakout, break_data - end + binding_stack.pop - Pry.save_history if Pry.config.history.should_save && finished_top_level_session? + Pry.save_history if Pry.config.history.should_save return_value end @@ -168,18 +136,13 @@ class Pry repl_prologue(target) - # cannot rely on nesting.level as - # nesting.level changes with new sessions - nesting_level = nesting.size - break_data = catch(:breakout) do - nesting.push [nesting.size, target_self, self] loop do - rep(target) + rep(@binding_stack.last) end end - return_value = repl_epilogue(target, nesting_level, break_data) + return_value = repl_epilogue(target, break_data) return_value || target_self end @@ -287,7 +250,7 @@ class Pry # exit session if we receive EOF character if !val output.puts - throw(:breakout, nesting.level) + throw :breakout end val @@ -424,9 +387,9 @@ class Pry def select_prompt(first_line, target_self) if first_line - Array(prompt).first.call(target_self, nesting.level) + Array(prompt).first.call(target_self, binding_stack.size - 1) else - Array(prompt).last.call(target_self, nesting.level) + Array(prompt).last.call(target_self, binding_stack.size - 1) end end diff --git a/test/test_pry.rb b/test/test_pry.rb index 52c596a4..0cc57f1e 100644 --- a/test/test_pry.rb +++ b/test/test_pry.rb @@ -292,7 +292,7 @@ describe Pry do end it 'should nest properly' do - Pry.input = InputTester.new("pry", "pry", "pry", "\"nest:\#\{Pry.nesting.level\}\"", "exit_all") + Pry.input = InputTester.new("cd 1", "cd 2", "cd 3", "\"nest:\#\{(_pry_.binding_stack.size - 1)\}\"", "exit_all") str_output = StringIO.new Pry.output = str_output