From 02435be016024891b6a64c3c10275c64951cbfd0 Mon Sep 17 00:00:00 2001 From: Jonathan Allard Date: Fri, 26 Jun 2020 20:15:18 -0400 Subject: [PATCH 1/7] Refactor into Frames --- lib/pry-stack_explorer.rb | 1 + lib/pry-stack_explorer/commands.rb | 96 +++++------------------- lib/pry-stack_explorer/frame.rb | 115 +++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 78 deletions(-) create mode 100644 lib/pry-stack_explorer/frame.rb diff --git a/lib/pry-stack_explorer.rb b/lib/pry-stack_explorer.rb index 068ab6a..7bff43e 100755 --- a/lib/pry-stack_explorer.rb +++ b/lib/pry-stack_explorer.rb @@ -4,6 +4,7 @@ require "pry" unless defined?(::Pry) require "pry-stack_explorer/version" require "pry-stack_explorer/commands" +require "pry-stack_explorer/frame" require "pry-stack_explorer/frame_manager" require "pry-stack_explorer/when_started_hook" require "binding_of_caller" diff --git a/lib/pry-stack_explorer/commands.rb b/lib/pry-stack_explorer/commands.rb index d75b902..b487a71 100644 --- a/lib/pry-stack_explorer/commands.rb +++ b/lib/pry-stack_explorer/commands.rb @@ -20,69 +20,6 @@ def prior_context_exists? frame_managers.count > 1 || frame_manager.prior_binding end - # Return a description of the frame (binding). - # This is only useful for regular old bindings that have not been - # enhanced by `#of_caller`. - # @param [Binding] b The binding. - # @return [String] A description of the frame (binding). - def frame_description(b) - b_self = b.eval('self') - b_method = b.eval('__method__') - - if b_method && b_method != :__binding__ && b_method != :__binding_impl__ - b_method.to_s - elsif b_self.instance_of?(Module) - "" - elsif b_self.instance_of?(Class) - "" - else - "
" - end - end - - # Return a description of the passed binding object. Accepts an - # optional `verbose` parameter. - # @param [Binding] b The binding. - # @param [Boolean] verbose Whether to generate a verbose description. - # @return [String] The description of the binding. - def frame_info(b, verbose = false) - meth = b.eval('__method__') - b_self = b.eval('self') - meth_obj = Pry::Method.from_binding(b) if meth - - type = b.frame_type ? "[#{b.frame_type}]".ljust(9) : "" - desc = b.frame_description ? "#{b.frame_description}" : "#{frame_description(b)}" - sig = meth_obj ? "<#{signature_with_owner(meth_obj)}>" : "" - - self_clipped = "#{Pry.view_clip(b_self)}" - path = '@ ' + b.source_location.join(':') - - if !verbose - "#{type} #{desc} #{sig}" - else - "#{type} #{desc} #{sig}\n in #{self_clipped} #{path}" - end - end - - # @param [Pry::Method] meth_obj The method object. - # @return [String] Signature for the method object in Class#method format. - def signature_with_owner(meth_obj) - if !meth_obj.undefined? - args = meth_obj.parameters.inject([]) do |arr, (type, name)| - name ||= (type == :block ? 'block' : "arg#{arr.size + 1}") - arr << case type - when :req then name.to_s - when :opt then "#{name}=?" - when :rest then "*#{name}" - when :block then "&#{name}" - else '?' - end - end - "#{meth_obj.name_with_owner}(#{args.join(', ')})" - else - "#{meth_obj.name_with_owner}(UNKNOWN) (undefined method)" - end - end # Regexp.new(args[0]) def find_frame_by_regex(regex, up_or_down) @@ -225,7 +162,8 @@ def process new_frame_index = find_frame_by_regex(Regexp.new(args[0]), :up) frame_manager.change_frame_to new_frame_index else - output.puts "##{frame_manager.binding_index} #{frame_info(target, true)}" + frame = PryStackExplorer::Frame.make(target) + output.puts "##{frame_manager.binding_index} #{frame.info(verbose: true)}" end end end @@ -250,18 +188,6 @@ def options(opt) opt.on :a, :app, "Display application frames only", optional_argument: true end - def memoized_info(index, b, verbose) - frame_manager.user[:frame_info] ||= Hash.new { |h, k| h[k] = [] } - - if verbose - frame_manager.user[:frame_info][:v][index] ||= frame_info(b, verbose) - else - frame_manager.user[:frame_info][:normal][index] ||= frame_info(b, verbose) - end - end - - private :memoized_info - # @return [Array>] Return tuple of # base_frame_index and the array of frames. def selected_stack_frames @@ -320,11 +246,25 @@ def frames_with_indices end end + ARROW = "=>" + EMPTY = " " + # "=> #0 method_name " def make_stack_line(b, i, active) - arw = active ? "=>" : " " + arrow = active ? ARROW : EMPTY + frame_no = i.to_s.rjust(2) + frame_info = memoized_frame(i, b).info(verbose: opts[:v]) + + [ + arrow, + blue(bold frame_no) + ":", + frame_info, + ].join(" ") + end - "#{arw} ##{i} #{memoized_info(i, b, opts[:v])}" + def memoized_frame(index, b) + frame_manager.user[:frame_info] ||= {} + frame_manager.user[:frame_info][index] ||= PryStackExplorer::Frame.make(b) end def offset_frames diff --git a/lib/pry-stack_explorer/frame.rb b/lib/pry-stack_explorer/frame.rb new file mode 100644 index 0000000..b92a922 --- /dev/null +++ b/lib/pry-stack_explorer/frame.rb @@ -0,0 +1,115 @@ +module PryStackExplorer + class Frame + attr_reader :b + + def self.make(_binding) + new(_binding) + end + + def initialize(_binding) + @b = _binding + end + + # Return a description of the frame (binding). + # This is only useful for regular old bindings that have not been + # enhanced by `#of_caller`. + # @return [String] A description of the frame (binding). + def description + return b.frame_description if b.frame_description + + if is_method? + _method.to_s + elsif b.receiver.instance_of?(Module) + "" + elsif b.receiver.instance_of?(Class) + "" + else + "
" + end + end + + + # Produces a string describing the frame + # @param [Options] verbose: Whether to generate a verbose description. + # @return [String] The description of the binding. + def info(verbose: false) + return @info[!!verbose] if @info + + base = "" + base << faded(pretty_type.ljust(9)) + base << " #{description}" + + if sig + base << faded(" | ") + base << sig + end + + @info = { + false => base, + true => base + "\n in #{self_clipped} #{path}", + } + + @info[!!verbose] + end + + def pretty_type + type ? "[#{type}]" : "" + end + + def type + b.frame_type + end + + def _method + @_method ||= b.eval('__method__') + end + + def is_method? + _method && + _method != :__binding__ && + _method != :__binding_impl__ + end + + def self_clipped + Pry.view_clip(b.receiver) + end + + def path + '@ ' + b.source_location.join(':') + end + + def pry_method + Pry::Method.from_binding(b) if _method + end + + def sig + return unless pry_method + self.class.method_signature_with_owner(pry_method) + end + + # @param [Pry::Method] pry_method The method object. + # @return [String] Signature for the method object in Class#method format. + def self.method_signature_with_owner(pry_method) + if pry_method.undefined? + return "#{pry_method.name_with_owner}(UNKNOWN) (undefined method)" + end + + args = pry_method.parameters.inject([]) do |arr, (type, name)| + name ||= (type == :block ? 'block' : "arg#{arr.size + 1}") + arr << case type + when :req then name.to_s + when :opt then "#{name}=?" + when :rest then "*#{name}" + when :block then "&#{name}" + else '?' + end + end + "#{pry_method.name_with_owner}(#{args.join(', ')})" + end + + # Not in Pry yet + def faded(text) + "\e[2m#{text}\e[0m" + end + end +end From 17cf79c7ef87206d8cb63f13ea7b310adadc025b Mon Sep 17 00:00:00 2001 From: Jonathan Allard Date: Mon, 29 Jun 2020 21:25:42 -0400 Subject: [PATCH 2/7] Break out FrameHelpers --- lib/pry-stack_explorer/commands.rb | 67 ------------------------ lib/pry-stack_explorer/frame_helpers.rb | 68 +++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 67 deletions(-) create mode 100644 lib/pry-stack_explorer/frame_helpers.rb diff --git a/lib/pry-stack_explorer/commands.rb b/lib/pry-stack_explorer/commands.rb index b487a71..3b430b4 100644 --- a/lib/pry-stack_explorer/commands.rb +++ b/lib/pry-stack_explorer/commands.rb @@ -1,71 +1,4 @@ module PryStackExplorer - module FrameHelpers - private - - # @return [PryStackExplorer::FrameManager] The active frame manager for - # the current `Pry` instance. - def frame_manager - PryStackExplorer.frame_manager(pry_instance) - end - - # @return [Array] All the frame - # managers for the current `Pry` instance. - def frame_managers - PryStackExplorer.frame_managers(pry_instance) - end - - # @return [Boolean] Whether there is a context to return to once - # the current `frame_manager` is popped. - def prior_context_exists? - frame_managers.count > 1 || frame_manager.prior_binding - end - - - # Regexp.new(args[0]) - def find_frame_by_regex(regex, up_or_down) - frame_index = find_frame_by_block(up_or_down) do |b| - b.eval("__method__").to_s =~ regex - end - - if frame_index - frame_index - else - raise Pry::CommandError, "No frame that matches #{regex.source} found!" - end - end - - def find_frame_by_object_regex(class_regex, method_regex, up_or_down) - frame_index = find_frame_by_block(up_or_down) do |b| - class_match = b.eval("self.class").to_s =~ class_regex - meth_match = b.eval("__method__").to_s =~ method_regex - - class_match && meth_match - end - - if frame_index - frame_index - else - raise Pry::CommandError, "No frame that matches #{class_regex.source}" + '#' + "#{method_regex.source} found!" - end - end - - def find_frame_by_block(up_or_down) - start_index = frame_manager.binding_index - - if up_or_down == :down - enum = frame_manager.bindings[0..start_index - 1].reverse_each - else - enum = frame_manager.bindings[start_index + 1..-1] - end - - new_frame = enum.find do |b| - yield(b) - end - - frame_manager.bindings.index(new_frame) - end - end - Commands = Pry::CommandSet.new do create_command "up", "Go up to the caller's context." do diff --git a/lib/pry-stack_explorer/frame_helpers.rb b/lib/pry-stack_explorer/frame_helpers.rb new file mode 100644 index 0000000..311f9a9 --- /dev/null +++ b/lib/pry-stack_explorer/frame_helpers.rb @@ -0,0 +1,68 @@ +module PryStackExplorer + module FrameHelpers + private + + # @return [PryStackExplorer::FrameManager] The active frame manager for + # the current `Pry` instance. + def frame_manager + PryStackExplorer.frame_manager(pry_instance) + end + + # @return [Array] All the frame + # managers for the current `Pry` instance. + def frame_managers + PryStackExplorer.frame_managers(pry_instance) + end + + # @return [Boolean] Whether there is a context to return to once + # the current `frame_manager` is popped. + def prior_context_exists? + frame_managers.count > 1 || frame_manager.prior_binding + end + + + # Regexp.new(args[0]) + def find_frame_by_regex(regex, up_or_down) + frame_index = find_frame_by_block(up_or_down) do |b| + b.eval("__method__").to_s =~ regex + end + + if frame_index + frame_index + else + raise Pry::CommandError, "No frame that matches #{regex.source} found!" + end + end + + def find_frame_by_object_regex(class_regex, method_regex, up_or_down) + frame_index = find_frame_by_block(up_or_down) do |b| + class_match = b.eval("self.class").to_s =~ class_regex + meth_match = b.eval("__method__").to_s =~ method_regex + + class_match && meth_match + end + + if frame_index + frame_index + else + raise Pry::CommandError, "No frame that matches #{class_regex.source}" + '#' + "#{method_regex.source} found!" + end + end + + def find_frame_by_block(up_or_down) + start_index = frame_manager.binding_index + + if up_or_down == :down + enum = frame_manager.bindings[0..start_index - 1].reverse_each + else + enum = frame_manager.bindings[start_index + 1..-1] + end + + new_frame = enum.find do |b| + yield(b) + end + + frame_manager.bindings.index(new_frame) + end + end +end From ef801073d0983917a8335f6cba6d611c2be046c6 Mon Sep 17 00:00:00 2001 From: Jonathan Allard Date: Mon, 29 Jun 2020 21:41:03 -0400 Subject: [PATCH 3/7] Move FrameManager#find_frame_by_block --- lib/pry-stack_explorer/frame_helpers.rb | 20 ++------------------ lib/pry-stack_explorer/frame_manager.rb | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/pry-stack_explorer/frame_helpers.rb b/lib/pry-stack_explorer/frame_helpers.rb index 311f9a9..747a8b5 100644 --- a/lib/pry-stack_explorer/frame_helpers.rb +++ b/lib/pry-stack_explorer/frame_helpers.rb @@ -23,7 +23,7 @@ def prior_context_exists? # Regexp.new(args[0]) def find_frame_by_regex(regex, up_or_down) - frame_index = find_frame_by_block(up_or_down) do |b| + frame_index = frame_manager.find_frame_by_block(up_or_down) do |b| b.eval("__method__").to_s =~ regex end @@ -35,7 +35,7 @@ def find_frame_by_regex(regex, up_or_down) end def find_frame_by_object_regex(class_regex, method_regex, up_or_down) - frame_index = find_frame_by_block(up_or_down) do |b| + frame_index = frame_manager.find_frame_by_block(up_or_down) do |b| class_match = b.eval("self.class").to_s =~ class_regex meth_match = b.eval("__method__").to_s =~ method_regex @@ -48,21 +48,5 @@ def find_frame_by_object_regex(class_regex, method_regex, up_or_down) raise Pry::CommandError, "No frame that matches #{class_regex.source}" + '#' + "#{method_regex.source} found!" end end - - def find_frame_by_block(up_or_down) - start_index = frame_manager.binding_index - - if up_or_down == :down - enum = frame_manager.bindings[0..start_index - 1].reverse_each - else - enum = frame_manager.bindings[start_index + 1..-1] - end - - new_frame = enum.find do |b| - yield(b) - end - - frame_manager.bindings.index(new_frame) - end end end diff --git a/lib/pry-stack_explorer/frame_manager.rb b/lib/pry-stack_explorer/frame_manager.rb index 0974a11..d044dc2 100644 --- a/lib/pry-stack_explorer/frame_manager.rb +++ b/lib/pry-stack_explorer/frame_manager.rb @@ -81,5 +81,21 @@ def change_frame_to(index, run_whereami=true) @pry.run_command "whereami" if run_whereami end + + def find_frame_by_block(up_or_down) + start_index = binding_index + + if up_or_down == :down + enum = bindings[0..start_index - 1].reverse_each + else + enum = bindings[start_index + 1..-1] + end + + new_frame = enum.find do |b| + yield(b) + end + + bindings.index(new_frame) + end end end From bb3b5963ef6e02776f576609f2a6193048385467 Mon Sep 17 00:00:00 2001 From: Jonathan Allard Date: Mon, 29 Jun 2020 21:41:18 -0400 Subject: [PATCH 4/7] +FrameManager#travel(steps) --- lib/pry-stack_explorer/commands.rb | 4 ++-- lib/pry-stack_explorer/frame_manager.rb | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/pry-stack_explorer/commands.rb b/lib/pry-stack_explorer/commands.rb index 3b430b4..9349b55 100644 --- a/lib/pry-stack_explorer/commands.rb +++ b/lib/pry-stack_explorer/commands.rb @@ -20,7 +20,7 @@ def process raise Pry::CommandError, "Nowhere to go!" else if inc =~ /\d+/ - frame_manager.change_frame_to frame_manager.binding_index + inc.to_i + frame_manager.travel(+inc.to_i) elsif match = /^([A-Z]+[^#.]*)(#|\.)(.+)$/.match(inc) new_frame_index = find_frame_by_object_regex(Regexp.new(match[1]), Regexp.new(match[3]), :up) frame_manager.change_frame_to new_frame_index @@ -54,7 +54,7 @@ def process if frame_manager.binding_index - inc.to_i < 0 raise Pry::CommandError, "At bottom of stack, cannot go further!" else - frame_manager.change_frame_to frame_manager.binding_index - inc.to_i + frame_manager.travel(-inc.to_i) end elsif match = /^([A-Z]+[^#.]*)(#|\.)(.+)$/.match(inc) new_frame_index = find_frame_by_object_regex(Regexp.new(match[1]), Regexp.new(match[3]), :down) diff --git a/lib/pry-stack_explorer/frame_manager.rb b/lib/pry-stack_explorer/frame_manager.rb index d044dc2..b528260 100644 --- a/lib/pry-stack_explorer/frame_manager.rb +++ b/lib/pry-stack_explorer/frame_manager.rb @@ -65,6 +65,11 @@ def set_binding_index_safely(index) end end + # Travels up or down by `steps`. (Can be positive (up) or negative (down)) + def travel(steps) + change_frame_to(binding_index + steps) + end + # Change active frame to the one indexed by `index`. # Note that indexing base is `0` # @param [Fixnum] index The index of the frame. From 7224b69d4cf03087bf3ddccfc4a066fc19a9e888 Mon Sep 17 00:00:00 2001 From: Jonathan Allard Date: Mon, 29 Jun 2020 22:07:40 -0400 Subject: [PATCH 5/7] Move in FrameManager#find_* --- lib/pry-stack_explorer/frame_helpers.rb | 35 --------------- lib/pry-stack_explorer/frame_manager.rb | 57 ++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/lib/pry-stack_explorer/frame_helpers.rb b/lib/pry-stack_explorer/frame_helpers.rb index 747a8b5..83046ec 100644 --- a/lib/pry-stack_explorer/frame_helpers.rb +++ b/lib/pry-stack_explorer/frame_helpers.rb @@ -13,40 +13,5 @@ def frame_manager def frame_managers PryStackExplorer.frame_managers(pry_instance) end - - # @return [Boolean] Whether there is a context to return to once - # the current `frame_manager` is popped. - def prior_context_exists? - frame_managers.count > 1 || frame_manager.prior_binding - end - - - # Regexp.new(args[0]) - def find_frame_by_regex(regex, up_or_down) - frame_index = frame_manager.find_frame_by_block(up_or_down) do |b| - b.eval("__method__").to_s =~ regex - end - - if frame_index - frame_index - else - raise Pry::CommandError, "No frame that matches #{regex.source} found!" - end - end - - def find_frame_by_object_regex(class_regex, method_regex, up_or_down) - frame_index = frame_manager.find_frame_by_block(up_or_down) do |b| - class_match = b.eval("self.class").to_s =~ class_regex - meth_match = b.eval("__method__").to_s =~ method_regex - - class_match && meth_match - end - - if frame_index - frame_index - else - raise Pry::CommandError, "No frame that matches #{class_regex.source}" + '#' + "#{method_regex.source} found!" - end - end end end diff --git a/lib/pry-stack_explorer/frame_manager.rb b/lib/pry-stack_explorer/frame_manager.rb index b528260..e9922f7 100644 --- a/lib/pry-stack_explorer/frame_manager.rb +++ b/lib/pry-stack_explorer/frame_manager.rb @@ -66,7 +66,9 @@ def set_binding_index_safely(index) end # Travels up or down by `steps`. (Can be positive (up) or negative (down)) - def travel(steps) + def travel(steps, up_or_down = :up) + steps = {up: 1, down: -1}[up_or_down] * steps + change_frame_to(binding_index + steps) end @@ -74,6 +76,7 @@ def travel(steps) # Note that indexing base is `0` # @param [Fixnum] index The index of the frame. def change_frame_to(index, run_whereami=true) + check_destination_in_bounds!(index) set_binding_index_safely(index) @@ -86,6 +89,13 @@ def change_frame_to(index, run_whereami=true) @pry.run_command "whereami" if run_whereami end + def check_destination_in_bounds!(index) + if index < 0 + raise Pry::CommandError, "At bottom of stack, cannot go further!" + # elsif index > n + end + end + def find_frame_by_block(up_or_down) start_index = binding_index @@ -102,5 +112,50 @@ def find_frame_by_block(up_or_down) bindings.index(new_frame) end + + def find_frame_by_regex(regex, up_or_down) + frame_index = find_frame_by_block(up_or_down) do |b| + b.eval("__method__").to_s =~ regex + end + + if frame_index + frame_index + else + raise Pry::CommandError, "No frame that matches #{regex.source} found!" + end + end + + def find_frame_by_object_regex(class_regex, method_regex, up_or_down) + frame_index = find_frame_by_block(up_or_down) do |b| + class_match = b.eval("self.class").to_s =~ class_regex + meth_match = b.eval("__method__").to_s =~ method_regex + + class_match && meth_match + end + + if frame_index + frame_index + else + raise Pry::CommandError, "No frame that matches #{class_regex.source}" + '#' + "#{method_regex.source} found!" + end + end + + def change_frame_by_object_regex(*args) + new_frame_index = find_frame_by_object_regex(*args) + change_frame_to new_frame_index + end + + def change_frame_by_regex(*args) + new_frame_index = find_frame_by_regex(*args) + change_frame_to new_frame_index + end + + # @return [Boolean] Whether there is a context to return to once + # the current `frame_manager` is popped. + # + # Currently unused + def prior_context_exists? + count > 1 || prior_binding + end end end From 10dda59ea04829f53d06ad3bba61e128df404564 Mon Sep 17 00:00:00 2001 From: Jonathan Allard Date: Mon, 29 Jun 2020 22:07:55 -0400 Subject: [PATCH 6/7] Commands: Refactor into #go_updown --- lib/pry-stack_explorer/commands.rb | 45 +++++-------------------- lib/pry-stack_explorer/frame_helpers.rb | 10 ++++++ 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/lib/pry-stack_explorer/commands.rb b/lib/pry-stack_explorer/commands.rb index 9349b55..d37de4b 100644 --- a/lib/pry-stack_explorer/commands.rb +++ b/lib/pry-stack_explorer/commands.rb @@ -19,15 +19,7 @@ def process if !frame_manager raise Pry::CommandError, "Nowhere to go!" else - if inc =~ /\d+/ - frame_manager.travel(+inc.to_i) - elsif match = /^([A-Z]+[^#.]*)(#|\.)(.+)$/.match(inc) - new_frame_index = find_frame_by_object_regex(Regexp.new(match[1]), Regexp.new(match[3]), :up) - frame_manager.change_frame_to new_frame_index - elsif inc =~ /^[^-].*$/ - new_frame_index = find_frame_by_regex(Regexp.new(inc), :up) - frame_manager.change_frame_to new_frame_index - end + go_updown(:up, inc) end end end @@ -50,19 +42,7 @@ def process if !frame_manager raise Pry::CommandError, "Nowhere to go!" else - if inc =~ /\d+/ - if frame_manager.binding_index - inc.to_i < 0 - raise Pry::CommandError, "At bottom of stack, cannot go further!" - else - frame_manager.travel(-inc.to_i) - end - elsif match = /^([A-Z]+[^#.]*)(#|\.)(.+)$/.match(inc) - new_frame_index = find_frame_by_object_regex(Regexp.new(match[1]), Regexp.new(match[3]), :down) - frame_manager.change_frame_to new_frame_index - elsif inc =~ /^[^-].*$/ - new_frame_index = find_frame_by_regex(Regexp.new(inc), :down) - frame_manager.change_frame_to new_frame_index - end + go_updown(:down, inc) end end end @@ -82,22 +62,13 @@ def process BANNER def process - if !frame_manager - raise Pry::CommandError, "nowhere to go!" - else + raise Pry::CommandError, "Nowhere to go!" unless frame_manager - if args[0] =~ /\d+/ - frame_manager.change_frame_to args[0].to_i - elsif match = /^([A-Z]+[^#.]*)(#|\.)(.+)$/.match(args[0]) - new_frame_index = find_frame_by_object_regex(Regexp.new(match[1]), Regexp.new(match[3]), :up) - frame_manager.change_frame_to new_frame_index - elsif args[0] =~ /^[^-].*$/ - new_frame_index = find_frame_by_regex(Regexp.new(args[0]), :up) - frame_manager.change_frame_to new_frame_index - else - frame = PryStackExplorer::Frame.make(target) - output.puts "##{frame_manager.binding_index} #{frame.info(verbose: true)}" - end + if args[0].empty? + frame = PryStackExplorer::Frame.make(target) + output.puts "##{frame_manager.binding_index} #{frame.info(verbose: true)}" + else + go_updown(:up, args[0]) end end end diff --git a/lib/pry-stack_explorer/frame_helpers.rb b/lib/pry-stack_explorer/frame_helpers.rb index 83046ec..54e285b 100644 --- a/lib/pry-stack_explorer/frame_helpers.rb +++ b/lib/pry-stack_explorer/frame_helpers.rb @@ -13,5 +13,15 @@ def frame_manager def frame_managers PryStackExplorer.frame_managers(pry_instance) end + + def go_updown(up_or_down, argument) + if argument =~ /\d+/ + frame_manager.travel(argument.to_i, up_or_down) + elsif match = /^([A-Z]+[^#.]*)(#|\.)(.+)$/.match(argument) + frame_manager.change_frame_by_object_regex(Regexp.new(match[1]), Regexp.new(match[3]), up_or_down) + elsif argument =~ /^[^-].*$/ + frame_manager.change_frame_by_regex(Regexp.new(argument), up_or_down) + end + end end end From 69b388a2b6f1fe1cbcd2f621c63dd74d154ebd81 Mon Sep 17 00:00:00 2001 From: Jonathan Allard Date: Mon, 29 Jun 2020 22:11:41 -0400 Subject: [PATCH 7/7] Commands: Refactor "no stack available" --- lib/pry-stack_explorer/commands.rb | 25 ++++--------------------- lib/pry-stack_explorer/frame_helpers.rb | 6 +++++- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/lib/pry-stack_explorer/commands.rb b/lib/pry-stack_explorer/commands.rb index d37de4b..ae388a7 100644 --- a/lib/pry-stack_explorer/commands.rb +++ b/lib/pry-stack_explorer/commands.rb @@ -15,12 +15,7 @@ module PryStackExplorer def process inc = args.first.nil? ? "1" : args.first - - if !frame_manager - raise Pry::CommandError, "Nowhere to go!" - else - go_updown(:up, inc) - end + go_updown(:up, inc) end end @@ -38,12 +33,7 @@ def process def process inc = args.first.nil? ? "1" : args.first - - if !frame_manager - raise Pry::CommandError, "Nowhere to go!" - else - go_updown(:down, inc) - end + go_updown(:down, inc) end end @@ -62,8 +52,6 @@ def process BANNER def process - raise Pry::CommandError, "Nowhere to go!" unless frame_manager - if args[0].empty? frame = PryStackExplorer::Frame.make(target) output.puts "##{frame_manager.binding_index} #{frame.info(verbose: true)}" @@ -121,9 +109,8 @@ def selected_stack_frames private :selected_stack_frames def process - return no_stack_available! unless frame_manager - - title = "Showing all accessible frames in stack (#{frame_manager.bindings.size} in total):" + stack_size = frame_manager.bindings.size + title = "Showing all accessible frames in stack (#{stack_size} in total):" content = [ bold(title), @@ -179,10 +166,6 @@ def offset_frames end end - def no_stack_available! - output.puts "No caller stack available!" - end - LOCATION_LAMBDA = ->(_binding){ _binding.source_location[0] } def app_frames diff --git a/lib/pry-stack_explorer/frame_helpers.rb b/lib/pry-stack_explorer/frame_helpers.rb index 54e285b..c6a57da 100644 --- a/lib/pry-stack_explorer/frame_helpers.rb +++ b/lib/pry-stack_explorer/frame_helpers.rb @@ -5,7 +5,7 @@ module FrameHelpers # @return [PryStackExplorer::FrameManager] The active frame manager for # the current `Pry` instance. def frame_manager - PryStackExplorer.frame_manager(pry_instance) + PryStackExplorer.frame_manager(pry_instance) || no_stack_available! end # @return [Array] All the frame @@ -23,5 +23,9 @@ def go_updown(up_or_down, argument) frame_manager.change_frame_by_regex(Regexp.new(argument), up_or_down) end end + + def no_stack_available! + raise Pry::CommandError, "No caller stack available!" + end end end