Class: Pry::ObjectPath

Inherits:
Object show all
Defined in:
lib/pry/object_path.rb

Overview

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.

Constant Summary collapse

SPECIAL_TERMS =
["", "::", ".", ".."].freeze

Instance Method Summary collapse

Constructor Details

#initialize(path_string, current_stack) ⇒ ObjectPath

Returns a new instance of ObjectPath.

Parameters:

  • path_string (String)

    The object path expressed as a string.

  • current_stack (Array<Binding>)

    The current state of the binding stack.


23
24
25
26
# File 'lib/pry/object_path.rb', line 23

def initialize(path_string, current_stack)
  @path_string   = path_string
  @current_stack = current_stack
end

Instance Method Details

#complete?(segment) ⇒ Boolean (private)

Returns:

  • (Boolean)

74
75
76
# File 'lib/pry/object_path.rb', line 74

def complete?(segment)
  SPECIAL_TERMS.include?(segment) || Pry::Code.complete_expression?(segment)
end

#handle_failure(context, err) ⇒ Object (private)


78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/pry/object_path.rb', line 78

def handle_failure(context, err)
  msg = [
    "Bad object path: #{@path_string.inspect}",
    "Failed trying to resolve: #{context.inspect}",
    "Exception: #{err.inspect}"
  ].join("\n")

  command_error = CommandError.new(msg)
  command_error.set_backtrace(err.backtrace)

  raise command_error
end

#resolveArray<Binding>

Returns a new stack resulting from applying the given path to the current stack.

Returns:

  • (Array<Binding>)

    a new stack resulting from applying the given path to the current stack.


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/pry/object_path.rb', line 30

def resolve
  scanner = StringScanner.new(@path_string.strip)
  stack   = @current_stack.dup

  loop do
    begin
      next_segment = ""

      loop do
        # Scan for as long as we don't see a slash
        next_segment += scanner.scan(%r{[^/]*})

        if complete?(next_segment) || scanner.eos?
          scanner.getch # consume the slash
          break
        else
          next_segment += scanner.getch # append the slash
        end
      end

      case next_segment.chomp
      when ""
        stack = [stack.first]
      when "::"
        stack.push(TOPLEVEL_BINDING)
      when "."
        next
      when ".."
        stack.pop unless stack.size == 1
      else
        stack.push(Pry.binding_for(stack.last.eval(next_segment)))
      end
    rescue RescuableException => e
      return handle_failure(next_segment, e)
    end

    break if scanner.eos?
  end

  stack
end