summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Fitzgerald <rwfitzge@gmail.com>2014-04-27 17:28:56 -0700
committerRyan Fitzgerald <rwfitzge@gmail.com>2014-04-27 17:28:56 -0700
commit24678711694f4057985cc41526bda2452222dd82 (patch)
tree8deb0feedafa51be1a94406a5bc90815362be3c3
parent249dbabe59bc6f6576780cbcab45fbfa9ac96c32 (diff)
downloadpry-24678711694f4057985cc41526bda2452222dd82.tar.gz
Extract object path resolution into a class
-rw-r--r--lib/pry.rb1
-rw-r--r--lib/pry/commands/cd.rb3
-rw-r--r--lib/pry/helpers/base_helpers.rb67
-rw-r--r--lib/pry/input_completer.rb2
-rw-r--r--lib/pry/object_path.rb89
5 files changed, 93 insertions, 69 deletions
diff --git a/lib/pry.rb b/lib/pry.rb
index 9a79d8e1..2b1460be 100644
--- a/lib/pry.rb
+++ b/lib/pry.rb
@@ -169,3 +169,4 @@ require "pry/indent"
require "pry/last_exception"
require "pry/prompt"
require "pry/inspector"
+require 'pry/object_path'
diff --git a/lib/pry/commands/cd.rb b/lib/pry/commands/cd.rb
index b628176e..8e8cddb3 100644
--- a/lib/pry/commands/cd.rb
+++ b/lib/pry/commands/cd.rb
@@ -21,7 +21,8 @@ class Pry
def process
state.old_stack ||= []
- stack, state.old_stack = context_from_object_path(arg_string, _pry_, state.old_stack)
+ stack, state.old_stack =
+ ObjectPath.new(arg_string, _pry_.binding_stack, state.old_stack).resolve
_pry_.binding_stack = stack if stack
end
end
diff --git a/lib/pry/helpers/base_helpers.rb b/lib/pry/helpers/base_helpers.rb
index 771535a8..b4b3f13d 100644
--- a/lib/pry/helpers/base_helpers.rb
+++ b/lib/pry/helpers/base_helpers.rb
@@ -119,73 +119,6 @@ class Pry
Pry::Pager.page(text, out)
end
-
- # @param [String] arg_string The object path expressed as a string.
- # @param [Pry] _pry_ The relevant Pry instance.
- # @param [Array<Binding>] old_stack The state of the old binding stack
- # @return [Array<Array<Binding>, Array<Binding>>] An array
- # containing two elements: The new `binding_stack` and the old `binding_stack`.
- def context_from_object_path(arg_string, _pry_=nil, old_stack=[])
-
- # Extract command arguments. Delete blank arguments like " ", but
- # don't delete empty strings like "".
- path = arg_string.split(/\//).delete_if { |a| a =~ /\A\s+\z/ }
- stack = _pry_.binding_stack.dup
- state_old_stack = old_stack
-
- # Special case when we only get a single "/", return to root.
- if path.empty?
- state_old_stack = stack.dup unless old_stack.empty?
- stack = [stack.first]
- end
-
- path.each_with_index do |context, i|
- begin
- case context.chomp
- when ""
- state_old_stack = stack.dup
- stack = [stack.first]
- when "::"
- state_old_stack = stack.dup
- stack.push(TOPLEVEL_BINDING)
- when "."
- next
- when ".."
- unless stack.size == 1
- # Don't rewrite old_stack if we're in complex expression
- # (e.g.: `cd 1/2/3/../4).
- state_old_stack = stack.dup if path.first == ".."
- stack.pop
- end
- when "-"
- unless old_stack.empty?
- # Interchange current stack and old stack with each other.
- stack, state_old_stack = state_old_stack, stack
- end
- else
- state_old_stack = stack.dup if i == 0
- stack.push(Pry.binding_for(stack.last.eval(context)))
- end
-
- rescue RescuableException => e
- # Restore old stack to its initial values.
- state_old_stack = old_stack
-
- msg = [
- "Bad object path: #{arg_string}.",
- "Failed trying to resolve: #{context}.",
- e.inspect
- ].join(' ')
-
- CommandError.new(msg).tap do |err|
- err.set_backtrace e.backtrace
- raise err
- end
- end
- end
- return stack, state_old_stack
- end
-
end
end
end
diff --git a/lib/pry/input_completer.rb b/lib/pry/input_completer.rb
index 74a249f9..86f9abf0 100644
--- a/lib/pry/input_completer.rb
+++ b/lib/pry/input_completer.rb
@@ -60,7 +60,7 @@ class Pry::InputCompleter
if path.call.empty?
target = options[:target]
else
- target, _ = Pry::Helpers::BaseHelpers.context_from_object_path(path.call, @pry)
+ target, _ = Pry::ObjectPath.new(path.call, @pry.binding_stack).resolve
target = target.last
end
diff --git a/lib/pry/object_path.rb b/lib/pry/object_path.rb
new file mode 100644
index 00000000..b669d3ec
--- /dev/null
+++ b/lib/pry/object_path.rb
@@ -0,0 +1,89 @@
+class Pry
+ # `ObjectPath` implements the resolution of "object paths", which are strings
+ # that are similar to filesystem paths but meant for traversing Ruby objects.
+ # Examples of valid object paths include:
+ #
+ # x
+ # @foo/@bar
+ # "string"/upcase
+ # Pry/Method
+ #
+ # Object paths are mostly relevant in the context of the `cd` command.
+ # @see https://github.com/pry/pry/wiki/State-navigation
+ class ObjectPath
+ # @param [String] path_string The object path expressed as a string.
+ # @param [Array<Binding>] current_stack The current state of the binding
+ # stack.
+ # @param [Array<Binding>] old_stack The previous state of the binding
+ # stack, if applicable.
+ def initialize(path_string, current_stack, old_stack=[])
+ @path_string = path_string
+ @current_stack = current_stack
+ @old_stack = old_stack
+ end
+
+ # @return [Array(Array<Binding>, Array<Binding>)] an array
+ # containing two elements, the new binding stack and the old binding
+ # stack.
+ def resolve
+ # Extract command arguments. Delete blank arguments like " ", but
+ # don't delete empty strings like "".
+ path = @path_string.split(/\//).delete_if { |a| a =~ /\A\s+\z/ }
+ stack = @current_stack.dup
+ state_old_stack = @old_stack
+
+ # Special case when we only get a single "/", return to root.
+ if path.empty?
+ state_old_stack = stack.dup unless @old_stack.empty?
+ stack = [stack.first]
+ end
+
+ path.each_with_index do |context, i|
+ begin
+ case context.chomp
+ when ""
+ state_old_stack = stack.dup
+ stack = [stack.first]
+ when "::"
+ state_old_stack = stack.dup
+ stack.push(TOPLEVEL_BINDING)
+ when "."
+ next
+ when ".."
+ unless stack.size == 1
+ # Don't rewrite old_stack if we're in complex expression
+ # (e.g.: `cd 1/2/3/../4).
+ state_old_stack = stack.dup if path.first == ".."
+ stack.pop
+ end
+ when "-"
+ unless @old_stack.empty?
+ # Interchange current stack and old stack with each other.
+ stack, state_old_stack = state_old_stack, stack
+ end
+ else
+ state_old_stack = stack.dup if i == 0
+ stack.push(Pry.binding_for(stack.last.eval(context)))
+ end
+
+ rescue RescuableException => e
+ # Restore old stack to its initial values.
+ state_old_stack = @old_stack
+
+ msg = [
+ "Bad object path: #{@path_string}.",
+ "Failed trying to resolve: #{context}.",
+ e.inspect
+ ].join(' ')
+
+ CommandError.new(msg).tap do |err|
+ err.set_backtrace e.backtrace
+ raise err
+ end
+ end
+ end
+
+ [stack, state_old_stack]
+ end
+ end
+end