pry-stack_explorer 0.2.5pre1 → 0.2.6pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|