pry-stack_explorer 0.2.5pre1 → 0.2.6pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +6 -0
- data/lib/pry-stack_explorer.rb +28 -144
- data/lib/pry-stack_explorer/commands.rb +75 -0
- data/lib/pry-stack_explorer/frame_manager.rb +80 -0
- data/lib/pry-stack_explorer/version.rb +1 -1
- metadata +4 -2
data/Rakefile
CHANGED
@@ -61,6 +61,12 @@ task :gems => [:clean, :rmgems, "ruby:gem"]
|
|
61
61
|
desc "remove all platform gems"
|
62
62
|
task :rmgems => ["ruby:clobber_package"]
|
63
63
|
|
64
|
+
desc "reinstall gem"
|
65
|
+
task :reinstall => :gems do
|
66
|
+
sh "gem uninstall pry-exception_explorer" rescue nil
|
67
|
+
sh "gem install #{direc}/pkg/#{PROJECT_NAME}-#{PryStackExplorer::VERSION}.gem"
|
68
|
+
end
|
69
|
+
|
64
70
|
desc "build and push latest gems"
|
65
71
|
task :pushgems => :gems do
|
66
72
|
chdir("#{File.dirname(__FILE__)}/pkg") do
|
data/lib/pry-stack_explorer.rb
CHANGED
@@ -2,169 +2,52 @@
|
|
2
2
|
# (C) John Mair (banisterfiend); MIT license
|
3
3
|
|
4
4
|
require "pry-stack_explorer/version"
|
5
|
+
require "pry-stack_explorer/commands"
|
6
|
+
require "pry-stack_explorer/frame_manager"
|
5
7
|
require "pry"
|
6
8
|
require "binding_of_caller"
|
7
9
|
|
8
10
|
module PryStackExplorer
|
11
|
+
Thread.current[:__pry_frame_managers__] ||= Hash.new { |h, k| h[k] = [] }
|
12
|
+
|
13
|
+
# Create a `Pry::FrameManager` object and push it onto the frame
|
14
|
+
# manager stack for the relevant `_pry_` instance.
|
15
|
+
# @param [Array] bindings The array of bindings (frames)
|
16
|
+
# @param [Pry] _pry_ The Pry instance associated with the frame manager
|
17
|
+
def self.push_and_create_frame_manager(bindings, _pry_)
|
18
|
+
Thread.current[:__pry_frame_managers__][_pry_].push FrameManager.new(bindings, _pry_)
|
19
|
+
end
|
9
20
|
|
10
|
-
|
11
|
-
|
12
|
-
|
21
|
+
# Delete the currently active frame manager
|
22
|
+
# @param [Pry] _pry_ The Pry instance associated with the frame managers
|
23
|
+
def self.pop_frame_manager(_pry_)
|
24
|
+
Thread.current[:__pry_frame_managers__][_pry_].pop
|
13
25
|
end
|
14
26
|
|
15
|
-
|
16
|
-
|
27
|
+
# Clear the stack of frame managers for the Pry instance
|
28
|
+
# @param [Pry] _pry_ The Pry instance associated with the frame managers
|
29
|
+
def self.clear_frame_managers(_pry_)
|
30
|
+
Thread.current[:__pry_frame_managers__][_pry_].clear
|
17
31
|
end
|
18
32
|
|
33
|
+
# @return [PryStackExplorer::FrameManager] The currently active frame manager
|
19
34
|
def self.frame_manager(_pry_)
|
20
|
-
Thread.current[:__pry_frame_managers__][_pry_]
|
35
|
+
Thread.current[:__pry_frame_managers__][_pry_].last
|
21
36
|
end
|
22
37
|
|
38
|
+
# Simple test to check whether two `Binding` objects are equal.
|
39
|
+
# @param [Binding] b1 First binding.
|
40
|
+
# @param [Binding] b2 Second binding.
|
23
41
|
def self.bindings_equal?(b1, b2)
|
24
42
|
(b1.eval('self') == b2.eval('self')) &&
|
25
43
|
(b1.eval('__method__') == b2.eval('__method__')) &&
|
26
44
|
(b1.eval('local_variables').map { |v| b1.eval("#{v}") } ==
|
27
45
|
b2.eval('local_variables').map { |v| b2.eval("#{v}") })
|
28
46
|
end
|
29
|
-
|
30
|
-
class FrameManager
|
31
|
-
attr_reader :binding_index
|
32
|
-
attr_accessor :bindings
|
33
|
-
|
34
|
-
def initialize(bindings, _pry_)
|
35
|
-
@bindings = bindings
|
36
|
-
@binding_index = 0
|
37
|
-
@pry = _pry_
|
38
|
-
end
|
39
|
-
|
40
|
-
def convert_from_one_index(n)
|
41
|
-
if n >= 0
|
42
|
-
n - 1
|
43
|
-
else
|
44
|
-
n
|
45
|
-
end
|
46
|
-
end
|
47
|
-
private :convert_from_one_index
|
48
|
-
|
49
|
-
def signature(b)
|
50
|
-
if b.eval('__method__')
|
51
|
-
"#{closure_type} in #{b.eval('self').class}##{b.eval('__method__')}"
|
52
|
-
else
|
53
|
-
if b.eval('self').is_a?(Module)
|
54
|
-
"#{closure_type} in <class:#{b.eval('self')}>"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def binding_info_for(b)
|
60
|
-
b_self = b.eval('self')
|
61
|
-
b_method = b.eval('__method__')
|
62
|
-
|
63
|
-
if b_method && b_method != :__binding__ && b_method != :__binding_impl__
|
64
|
-
b_method.to_s
|
65
|
-
elsif b_self.instance_of?(Module)
|
66
|
-
"<module:#{b_self}>"
|
67
|
-
elsif b_self.instance_of?(Class)
|
68
|
-
"<class:#{b_self}>"
|
69
|
-
else
|
70
|
-
"<main>"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def change_binding_to(index)
|
75
|
-
index = convert_from_one_index(index)
|
76
|
-
|
77
|
-
if index > bindings.size - 1
|
78
|
-
@pry.output.puts "Warning: At top of stack, cannot go further!"
|
79
|
-
elsif index < 0
|
80
|
-
@pry.output.puts "Warning: At bottom of stack, cannot go further!"
|
81
|
-
else
|
82
|
-
@binding_index = index
|
83
|
-
@pry.binding_stack[-1] = bindings[binding_index]
|
84
|
-
|
85
|
-
@pry.run_command "whereami"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
StackCommands = Pry::CommandSet.new do
|
91
|
-
command "up", "Go up to the caller's context" do |inc_str|
|
92
|
-
inc = inc_str.nil? ? 1 : inc_str.to_i
|
93
|
-
|
94
|
-
if !PryStackExplorer.frame_manager(_pry_)
|
95
|
-
output.puts "Nowhere to go!"
|
96
|
-
else
|
97
|
-
binding_index = PryStackExplorer.frame_manager(_pry_).binding_index
|
98
|
-
PryStackExplorer.frame_manager(_pry_).change_binding_to binding_index + inc + 1
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
command "down", "Go down to the callee's context." do |inc_str|
|
103
|
-
inc = inc_str.nil? ? 1 : inc_str.to_i
|
104
|
-
|
105
|
-
if !PryStackExplorer.frame_manager(_pry_)
|
106
|
-
output.puts "Nowhere to go!"
|
107
|
-
else
|
108
|
-
binding_index = PryStackExplorer.frame_manager(_pry_).binding_index
|
109
|
-
PryStackExplorer.frame_manager(_pry_).change_binding_to binding_index - inc + 1
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
command "show-stack", "Show all frames" do |*args|
|
114
|
-
opts = parse_options!(args) do |opt|
|
115
|
-
opt.banner unindent <<-USAGE
|
116
|
-
Usage: show-stack [OPTIONS]
|
117
|
-
Show all accessible stack frames.
|
118
|
-
e.g: show-stack -v
|
119
|
-
USAGE
|
120
|
-
|
121
|
-
opt.on :v, :verbose, "Include extra information."
|
122
|
-
end
|
123
|
-
|
124
|
-
if !PryStackExplorer.frame_manager(_pry_)
|
125
|
-
output.puts "No caller stack available!"
|
126
|
-
else
|
127
|
-
output.puts "\n#{text.bold('Showing all accessible frames in stack:')}\n--\n"
|
128
|
-
|
129
|
-
PryStackExplorer.frame_manager(_pry_).bindings.each_with_index do |b, i|
|
130
|
-
meth = b.eval('__method__')
|
131
|
-
b_self = b.eval('self')
|
132
|
-
|
133
|
-
desc = b.frame_description ? "#{text.bold('Description:')} #{b.frame_description}".ljust(40) :
|
134
|
-
"#{text.bold('Description:')} #{PryStackExplorer.frame_manager(_pry_).binding_info_for(b)}".ljust(40)
|
135
|
-
sig = meth ? "#{text.bold('Signature:')} #{Pry::Method.new(b_self.method(meth)).signature}".ljust(40) : "".ljust(32)
|
136
|
-
type = b.frame_type ? "#{text.bold('Type:')} #{b.frame_type}".ljust(20) : "".ljust(20)
|
137
|
-
slf = "#{text.bold('Self:')} #{b_self}".ljust(20)
|
138
|
-
path = "#{text.bold("@ File:")} #{b.eval('__FILE__')}:#{b.eval('__LINE__')}"
|
139
|
-
|
140
|
-
info = "##{i + 1} #{desc} #{sig} #{slf if opts[:v]} #{type \
|
141
|
-
if opts[:v]} #{path if opts[:v]}"
|
142
|
-
if i == PryStackExplorer.frame_manager(_pry_).binding_index
|
143
|
-
|
144
|
-
output.puts "=> #{info}"
|
145
|
-
else
|
146
|
-
output.puts " #{info}"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
command "frame", "Switch to a particular frame." do |frame_num|
|
153
|
-
if !PryStackExplorer.frame_manager(_pry_)
|
154
|
-
output.puts "nowhere to go!"
|
155
|
-
else
|
156
|
-
PryStackExplorer.frame_manager(_pry_).change_binding_to frame_num.to_i
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
command "frame-type", "Display current frame type." do
|
161
|
-
output.puts _pry_.binding_stack.last.frame_type
|
162
|
-
end
|
163
|
-
end
|
164
47
|
end
|
165
48
|
|
166
49
|
Pry.config.hooks.add_hook(:after_session, :delete_frame_manager) do |_, _, _pry_|
|
167
|
-
PryStackExplorer.
|
50
|
+
PryStackExplorer.clear_frame_managers(_pry_)
|
168
51
|
end
|
169
52
|
|
170
53
|
Pry.config.hooks.add_hook(:when_started, :save_caller_bindings) do |binding_stack, _pry_|
|
@@ -187,9 +70,10 @@ Pry.config.hooks.add_hook(:when_started, :save_caller_bindings) do |binding_stac
|
|
187
70
|
end
|
188
71
|
|
189
72
|
binding_stack.replace([bindings.first])
|
190
|
-
PryStackExplorer.
|
73
|
+
PryStackExplorer.push_and_create_frame_manager(bindings, _pry_)
|
191
74
|
end
|
192
75
|
|
76
|
+
# Import the StackExplorer commands
|
193
77
|
Pry.config.commands.import PryStackExplorer::StackCommands
|
194
78
|
|
195
79
|
# monkey-patch the whereami command to show some frame information,
|
@@ -200,7 +84,7 @@ Pry.config.commands.before_command("whereami") do |num|
|
|
200
84
|
binding_index = PryStackExplorer.frame_manager(_pry_).binding_index
|
201
85
|
|
202
86
|
output.puts "\n"
|
203
|
-
output.puts "#{Pry::Helpers::Text.bold('Frame number:')} #{binding_index
|
87
|
+
output.puts "#{Pry::Helpers::Text.bold('Frame number:')} #{binding_index}/#{bindings.size - 1}"
|
204
88
|
output.puts "#{Pry::Helpers::Text.bold('Frame type:')} #{bindings[binding_index].frame_type}" if bindings[binding_index].frame_type
|
205
89
|
end
|
206
90
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module PryStackExplorer
|
2
|
+
StackCommands = Pry::CommandSet.new do
|
3
|
+
command "up", "Go up to the caller's context" do |inc_str|
|
4
|
+
inc = inc_str.nil? ? 1 : inc_str.to_i
|
5
|
+
|
6
|
+
if !PryStackExplorer.frame_manager(_pry_)
|
7
|
+
output.puts "Nowhere to go!"
|
8
|
+
else
|
9
|
+
binding_index = PryStackExplorer.frame_manager(_pry_).binding_index
|
10
|
+
PryStackExplorer.frame_manager(_pry_).change_frame_to binding_index + inc
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
command "down", "Go down to the callee's context." do |inc_str|
|
15
|
+
inc = inc_str.nil? ? 1 : inc_str.to_i
|
16
|
+
|
17
|
+
if !PryStackExplorer.frame_manager(_pry_)
|
18
|
+
output.puts "Nowhere to go!"
|
19
|
+
else
|
20
|
+
binding_index = PryStackExplorer.frame_manager(_pry_).binding_index
|
21
|
+
PryStackExplorer.frame_manager(_pry_).change_frame_to binding_index - inc
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
command "show-stack", "Show all frames" do |*args|
|
26
|
+
opts = parse_options!(args) do |opt|
|
27
|
+
opt.banner unindent <<-USAGE
|
28
|
+
Usage: show-stack [OPTIONS]
|
29
|
+
Show all accessible stack frames.
|
30
|
+
e.g: show-stack -v
|
31
|
+
USAGE
|
32
|
+
|
33
|
+
opt.on :v, :verbose, "Include extra information."
|
34
|
+
end
|
35
|
+
|
36
|
+
if !PryStackExplorer.frame_manager(_pry_)
|
37
|
+
output.puts "No caller stack available!"
|
38
|
+
else
|
39
|
+
output.puts "\n#{text.bold('Showing all accessible frames in stack:')}\n--\n"
|
40
|
+
|
41
|
+
PryStackExplorer.frame_manager(_pry_).each_with_index do |b, i|
|
42
|
+
meth = b.eval('__method__')
|
43
|
+
b_self = b.eval('self')
|
44
|
+
|
45
|
+
desc = b.frame_description ? "#{text.bold('Description:')} #{b.frame_description}".ljust(40) :
|
46
|
+
"#{text.bold('Description:')} #{PryStackExplorer.frame_manager(_pry_).frame_info_for(b)}".ljust(40)
|
47
|
+
sig = meth ? "#{text.bold('Signature:')} #{Pry::Method.new(b_self.method(meth)).signature}".ljust(40) : "".ljust(32)
|
48
|
+
type = b.frame_type ? "#{text.bold('Type:')} #{b.frame_type}".ljust(20) : "".ljust(20)
|
49
|
+
slf_class = "#{text.bold('Self.class:')} #{b_self.class}".ljust(20)
|
50
|
+
path = "#{text.bold("@ File:")} #{b.eval('__FILE__')}:#{b.eval('__LINE__')}"
|
51
|
+
|
52
|
+
info = "##{i} #{desc} #{slf_class} #{sig} #{type \
|
53
|
+
if opts[:v]} #{path if opts[:v]}"
|
54
|
+
if i == PryStackExplorer.frame_manager(_pry_).binding_index
|
55
|
+
output.puts "=> #{info}"
|
56
|
+
else
|
57
|
+
output.puts " #{info}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
command "frame", "Switch to a particular frame." do |frame_num|
|
64
|
+
if !PryStackExplorer.frame_manager(_pry_)
|
65
|
+
output.puts "nowhere to go!"
|
66
|
+
else
|
67
|
+
PryStackExplorer.frame_manager(_pry_).change_frame_to frame_num.to_i
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
command "frame-type", "Display current frame type." do
|
72
|
+
output.puts _pry_.binding_stack.last.frame_type
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module PryStackExplorer
|
2
|
+
|
3
|
+
class FrameManager
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_accessor :binding_index
|
7
|
+
attr_accessor :bindings
|
8
|
+
|
9
|
+
# @return [Hash] A hash for user defined data
|
10
|
+
attr_reader :user
|
11
|
+
|
12
|
+
def initialize(bindings, _pry_)
|
13
|
+
self.bindings = bindings
|
14
|
+
self.binding_index = 0
|
15
|
+
@pry = _pry_
|
16
|
+
@user = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
# Replace the current set of bindings (call stack) and binding
|
20
|
+
# index (current frame)
|
21
|
+
# @param [Array] bindings The new call stack (array of bindings)
|
22
|
+
# @param [Fixnum] binding_index The currently 'active' frame (binding).
|
23
|
+
def replace_call_stack(bindings, binding_index = 0)
|
24
|
+
self.bindings = bindings
|
25
|
+
self.binding_index = binding_index
|
26
|
+
end
|
27
|
+
|
28
|
+
# Iterate over all frames
|
29
|
+
def each(&block)
|
30
|
+
bindings.each(&block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return a description of the frame (binding)
|
34
|
+
# @param [Binding] b The binding.
|
35
|
+
# @return [String] A description of the frame (binding).
|
36
|
+
def frame_info_for(b)
|
37
|
+
b_self = b.eval('self')
|
38
|
+
b_method = b.eval('__method__')
|
39
|
+
|
40
|
+
if b_method && b_method != :__binding__ && b_method != :__binding_impl__
|
41
|
+
b_method.to_s
|
42
|
+
elsif b_self.instance_of?(Module)
|
43
|
+
"<module:#{b_self}>"
|
44
|
+
elsif b_self.instance_of?(Class)
|
45
|
+
"<class:#{b_self}>"
|
46
|
+
else
|
47
|
+
"<main>"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Ensure the Pry instance's active binding is the frame manager's
|
52
|
+
# active binding.
|
53
|
+
def refresh_frame
|
54
|
+
change_frame_to binding_index
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Binding] The currently active frame
|
58
|
+
def current_frame
|
59
|
+
bindings[binding_index]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Change active frame to the one indexed by `index`.
|
63
|
+
# Note that indexing base is `0`
|
64
|
+
# @param [Fixnum] index The index of the frame.
|
65
|
+
def change_frame_to(index)
|
66
|
+
|
67
|
+
if index > bindings.size - 1
|
68
|
+
@pry.output.puts "Warning: At top of stack, cannot go further!"
|
69
|
+
elsif index < 0
|
70
|
+
@pry.output.puts "Warning: At bottom of stack, cannot go further!"
|
71
|
+
else
|
72
|
+
self.binding_index = index
|
73
|
+
@pry.binding_stack[-1] = bindings[binding_index]
|
74
|
+
|
75
|
+
@pry.run_command "whereami"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: pry-stack_explorer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 5
|
5
|
-
version: 0.2.
|
5
|
+
version: 0.2.6pre1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- John Mair (banisterfiend)
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-12-
|
13
|
+
date: 2011-12-15 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: binding_of_caller
|
@@ -43,6 +43,8 @@ extensions: []
|
|
43
43
|
extra_rdoc_files: []
|
44
44
|
|
45
45
|
files:
|
46
|
+
- lib/pry-stack_explorer/commands.rb
|
47
|
+
- lib/pry-stack_explorer/frame_manager.rb
|
46
48
|
- lib/pry-stack_explorer/version.rb
|
47
49
|
- lib/pry-stack_explorer.rb
|
48
50
|
- test/test.rb
|