ruby_jard 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +40 -0
- data/Gemfile +1 -1
- data/README.md +65 -2
- data/docs/guide-ui.png +0 -0
- data/lib/ruby_jard.rb +49 -12
- data/lib/ruby_jard/box_drawer.rb +126 -0
- data/lib/ruby_jard/column.rb +18 -0
- data/lib/ruby_jard/commands/continue_command.rb +1 -6
- data/lib/ruby_jard/commands/down_command.rb +1 -4
- data/lib/ruby_jard/commands/frame_command.rb +12 -11
- data/lib/ruby_jard/commands/next_command.rb +1 -4
- data/lib/ruby_jard/commands/step_command.rb +1 -4
- data/lib/ruby_jard/commands/step_out_command.rb +28 -0
- data/lib/ruby_jard/commands/up_command.rb +1 -4
- data/lib/ruby_jard/console.rb +86 -0
- data/lib/ruby_jard/control_flow.rb +71 -0
- data/lib/ruby_jard/decorators/color_decorator.rb +78 -0
- data/lib/ruby_jard/decorators/loc_decorator.rb +41 -28
- data/lib/ruby_jard/decorators/source_decorator.rb +1 -1
- data/lib/ruby_jard/key_binding.rb +14 -0
- data/lib/ruby_jard/key_bindings.rb +96 -0
- data/lib/ruby_jard/keys.rb +49 -0
- data/lib/ruby_jard/layout.rb +67 -55
- data/lib/ruby_jard/layouts/wide_layout.rb +138 -0
- data/lib/ruby_jard/repl_processor.rb +80 -90
- data/lib/ruby_jard/repl_proxy.rb +232 -0
- data/lib/ruby_jard/row.rb +16 -0
- data/lib/ruby_jard/screen.rb +114 -36
- data/lib/ruby_jard/screen_drawer.rb +89 -0
- data/lib/ruby_jard/screen_manager.rb +157 -56
- data/lib/ruby_jard/screens/backtrace_screen.rb +88 -97
- data/lib/ruby_jard/screens/menu_screen.rb +23 -31
- data/lib/ruby_jard/screens/source_screen.rb +42 -90
- data/lib/ruby_jard/screens/threads_screen.rb +50 -64
- data/lib/ruby_jard/screens/variables_screen.rb +96 -99
- data/lib/ruby_jard/session.rb +13 -7
- data/lib/ruby_jard/span.rb +18 -0
- data/lib/ruby_jard/templates/column_template.rb +17 -0
- data/lib/ruby_jard/templates/layout_template.rb +35 -0
- data/lib/ruby_jard/templates/row_template.rb +22 -0
- data/lib/ruby_jard/templates/screen_template.rb +35 -0
- data/lib/ruby_jard/templates/space_template.rb +15 -0
- data/lib/ruby_jard/templates/span_template.rb +25 -0
- data/lib/ruby_jard/version.rb +1 -1
- data/ruby_jard.gemspec +1 -4
- metadata +29 -41
- data/lib/ruby_jard/commands/finish_command.rb +0 -31
- data/lib/ruby_jard/decorators/text_decorator.rb +0 -61
- data/lib/ruby_jard/layout_template.rb +0 -101
- data/lib/ruby_jard/screens/breakpoints_screen.rb +0 -23
- data/lib/ruby_jard/screens/expressions_sreen.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94dbda134fd22365f583f71fa2aaddffae206045cc8da4fd6ee51e2eeaebfca7
|
4
|
+
data.tar.gz: af8c443ac2c40619cead142c3e77dd3b7f7ad59c19993966edcdd1eae8c31a3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d18a6894bcb24bae3bf30244dfcf1f39412e9804df5897e7adac6b74cdb8929b3353a8a0999ec55b687bfa60e87890a5db637bfe7d046b30a470b0d5158c46e
|
7
|
+
data.tar.gz: 7eaacc77cd4eaa4fdb7e183292872cef01217e5c92f75bea1882d454dad1ad1ae97ff3790ca129e76de4f893167d1b1b81b6deb7eb44b6931d67a23cca03f7f5
|
data/.rubocop.yml
CHANGED
@@ -1,9 +1,19 @@
|
|
1
|
+
Naming/MethodParameterName:
|
2
|
+
Enabled: false
|
1
3
|
Style/SymbolArray:
|
2
4
|
Enabled: false
|
5
|
+
Style/GuardClause:
|
6
|
+
Enabled: false
|
7
|
+
Style/NumericPredicate:
|
8
|
+
Enabled: false
|
9
|
+
Style/IfUnlessModifier:
|
10
|
+
Enabled: false
|
3
11
|
Metrics/MethodLength:
|
4
12
|
Max: 20
|
5
13
|
Metrics/PerceivedComplexity:
|
6
14
|
Max: 15
|
15
|
+
Metrics/AbcSize:
|
16
|
+
Enabled: false
|
7
17
|
Metrics/ParameterLists:
|
8
18
|
Enabled: false
|
9
19
|
Metrics/ClassLength:
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [0.2.0 - Alpha 2] - UI completeness
|
4
|
+
|
5
|
+
### UX/UI
|
6
|
+
- Improve box drawing.
|
7
|
+
- Isolate jard-related UI in an alternative termnial, just like Vim or Less.
|
8
|
+
- Restore printed information from STDOUT and STDERR after jard exits.
|
9
|
+
- Support keyboard shortcut.
|
10
|
+
- Support erb, haml highlighting.
|
11
|
+
- Increase contrast and enhance color scheme.
|
12
|
+
- Remove `finish` command.
|
13
|
+
- Add `frame` command.
|
14
|
+
- Add `step-out` command.
|
15
|
+
- Remove useless inline variables.
|
16
|
+
- Indicate types and inline variables in variable screen.
|
17
|
+
|
18
|
+
### Bug fixes
|
19
|
+
- Fix line number and loc mismatching if the current source viewport is at the start of the file.
|
20
|
+
- Multiple layout broken, overlapping text glitches.
|
21
|
+
|
22
|
+
### Internal & Refactoring
|
23
|
+
- Refactor screen's data flow.
|
24
|
+
- Standardize control flow.
|
25
|
+
- Replace `tty-cursor`, `tty-screen` by native Ruby alternative.
|
26
|
+
- Replace `tty-box` by home-growing solution.
|
27
|
+
- Remove text decorator.
|
28
|
+
- Implement color decorator
|
29
|
+
- Implement keybinding register and matching mechanism.
|
30
|
+
- Implement ReplProxy to wrap around Pry instance.
|
31
|
+
- Utility to debug and benchmark.
|
32
|
+
|
33
|
+
## [0.1.0 - Alpha] - Alpha initial version
|
34
|
+
**Release date**: July 1st 2020
|
35
|
+
|
36
|
+
- Default Terminal UI, in which the layout and display are responsive to support different screen size.
|
37
|
+
- Highlighted source code screen.
|
38
|
+
- Stacktrace visulization and navigation.
|
39
|
+
- Auto explore and display variables in the current context.
|
40
|
+
- Multi-thread exploration and debugging.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,73 @@
|
|
1
1
|
# RubyJard
|
2
2
|
|
3
|
-
Just
|
3
|
+
Jard stands for Just Another Ruby Debugger. It implements a layer of UI wrapping around byebug, aims to provide a unified experience when debugging Ruby source code. Ruby Jard supports the following major features at the moment:
|
4
|
+
|
5
|
+
- Default Terminal UI, in which the layout and display are responsive to support different screen sizes.
|
6
|
+
- Highlighted source code screen.
|
7
|
+
- Stacktrace visualization and navigation.
|
8
|
+
- Auto explore and display variables in the current context.
|
9
|
+
- Multi-thread exploration and debugging.
|
10
|
+
|
11
|
+
In the roadmap:
|
12
|
+
- Dynamic breakpoints.
|
13
|
+
- Watch expressions.
|
14
|
+
- Support different screen sizes.
|
15
|
+
- Minimal layout configuration.
|
16
|
+
- Fully layout configuration with Tmux.
|
17
|
+
- Integrate with Vim.
|
18
|
+
- Integrate with Visual Studio Code.
|
19
|
+
- Encrypted remote debugging.
|
20
|
+
- Some handful debug tools and data visualization.
|
21
|
+
|
22
|
+
Ruby Jard's core is Byebug, an awesome de factor debugger for Ruby. Therefore, Ruby Jard supports most of Byebug's functionalities.
|
23
|
+
|
24
|
+
If you still don't know what it is, let's watch this video. This is a record of debugging Code Ray - A syntax highlighter for Ruby.
|
25
|
+
|
26
|
+
[![asciicast](https://asciinema.org/a/ejWK3Px55QNQmhM4nbd1lSigW.svg)](https://asciinema.org/a/ejWK3Px55QNQmhM4nbd1lSigW)
|
27
|
+
|
28
|
+
## Getting Started
|
29
|
+
|
30
|
+
**Warning**: Ruby Jard is still under heavy development. Bugs and weird behaviors are expected. If you see one, please don't hesitate to open an issue. I'll try my best to fix.
|
31
|
+
|
32
|
+
Add `ruby_jard` to your Gemfile, recommend to put it in test or development environment.
|
33
|
+
|
34
|
+
``` ruby
|
35
|
+
gem 'ruby_jard'
|
36
|
+
```
|
37
|
+
|
38
|
+
Add magic method `jard` before the line you want to debug, just like `byebug`
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
def test_method
|
42
|
+
a = 1
|
43
|
+
b = 2
|
44
|
+
jard # Debugger will stop here
|
45
|
+
c = a + b
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
## Guides
|
50
|
+
|
51
|
+
![Guide UI](./docs/guide-ui.png)
|
52
|
+
|
53
|
+
The main page of the debugging UI includes 4 screens:
|
54
|
+
- Source: Show the current file, surrounding the source code of the executing line.
|
55
|
+
- Stacktrace: Show the current thread's stack trace. You can use `up`, `down`, `frame` to navigate through the stack trace.
|
56
|
+
- Variables: Show all the variables in the current context, including local variables, instance variables, and constants.
|
57
|
+
- Threads: Show all the threads of the process. This screen is valuable in case you are debugging a multi-threaded program.
|
58
|
+
|
59
|
+
At this alpha state, Ruby Jard support some basic commands:
|
60
|
+
- `next`: continue the execution to the next line.
|
61
|
+
- `step`: continue the execution, do deep into the implementation of methods in the current line.
|
62
|
+
- `continue`: continue the execution. The program gonna stops at the next breakpoint.
|
63
|
+
- `finish`: Finish the execution of the current frame, and go back.
|
64
|
+
- `up`: explore the stack trace, jump to the upper frame of the current program
|
65
|
+
- `down`: explore the stack trace, jump to the lower frame of the current program
|
66
|
+
- `frame`: explore the stack trace, jump to a precise frame in the stack trace.
|
4
67
|
|
5
68
|
## Contributing
|
6
69
|
|
7
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
70
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/nguyenquangminh0711/ruby_jard. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/nguyenquangminh0711/ruby_jard/blob/master/CODE_OF_CONDUCT.md).
|
8
71
|
|
9
72
|
|
10
73
|
## License
|
data/docs/guide-ui.png
ADDED
Binary file
|
data/lib/ruby_jard.rb
CHANGED
@@ -1,21 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'pry'
|
4
|
-
require 'coderay'
|
5
4
|
require 'byebug/core'
|
6
5
|
require 'byebug/attacher'
|
7
|
-
require '
|
8
|
-
require '
|
9
|
-
require 'tty-screen'
|
10
|
-
|
11
|
-
require 'ruby_jard/commands/continue_command'
|
12
|
-
require 'ruby_jard/commands/up_command'
|
13
|
-
require 'ruby_jard/commands/down_command'
|
14
|
-
require 'ruby_jard/commands/next_command'
|
15
|
-
require 'ruby_jard/commands/step_command'
|
16
|
-
require 'ruby_jard/commands/finish_command'
|
17
|
-
require 'ruby_jard/commands/frame_command'
|
6
|
+
require 'forwardable'
|
7
|
+
require 'benchmark'
|
18
8
|
|
9
|
+
require 'ruby_jard/control_flow'
|
10
|
+
require 'ruby_jard/keys'
|
11
|
+
require 'ruby_jard/key_binding'
|
12
|
+
require 'ruby_jard/key_bindings'
|
13
|
+
require 'ruby_jard/repl_proxy'
|
19
14
|
require 'ruby_jard/repl_processor'
|
20
15
|
require 'ruby_jard/screen_manager'
|
21
16
|
|
@@ -46,9 +41,51 @@ require 'ruby_jard/version'
|
|
46
41
|
module RubyJard
|
47
42
|
class Error < StandardError; end
|
48
43
|
|
44
|
+
DEFAULT_LAYOUT_TEMPLATES = [
|
45
|
+
RubyJard::Layouts::WideLayout
|
46
|
+
].freeze
|
47
|
+
|
49
48
|
def self.current_session
|
50
49
|
@current_session ||= RubyJard::Session.new
|
51
50
|
end
|
51
|
+
|
52
|
+
def self.benchmark(name)
|
53
|
+
@benchmark_depth ||= 0
|
54
|
+
@benchmark_depth += 1
|
55
|
+
return_value = nil
|
56
|
+
time = Benchmark.realtime { return_value = yield }
|
57
|
+
debug("#{' ' * @benchmark_depth}Benchmark `#{name}`: #{time}")
|
58
|
+
@benchmark_depth -= 1
|
59
|
+
return_value
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.debug(*info)
|
63
|
+
@debug_info ||= []
|
64
|
+
@debug_info += info
|
65
|
+
File.open('./jard_debugs.txt', 'a') do |f|
|
66
|
+
info.each do |line|
|
67
|
+
f.puts line
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.debug_info
|
73
|
+
@debug_info ||= []
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.clear_debug
|
77
|
+
@debug_info = []
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.global_key_bindings
|
81
|
+
return @global_key_bindings if defined?(@global_key_bindings)
|
82
|
+
|
83
|
+
@global_key_bindings = RubyJard::KeyBindings.new
|
84
|
+
RubyJard::Keys::DEFAULT_KEY_BINDINGS.each do |sequence, action|
|
85
|
+
@global_key_bindings.push(sequence, action)
|
86
|
+
end
|
87
|
+
@global_key_bindings
|
88
|
+
end
|
52
89
|
end
|
53
90
|
|
54
91
|
##
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
##
|
5
|
+
# Drawer to draw a nice single-line box that maximize screen area
|
6
|
+
#
|
7
|
+
# Each screen has 4 corners and clock-wise corresponding ID:
|
8
|
+
# - Top-left => 1
|
9
|
+
# - Top-right => 2
|
10
|
+
# - Bottom-right => 3
|
11
|
+
# - Bottom-left => 4
|
12
|
+
#
|
13
|
+
# For each screen, add each point to a coordinator hash.
|
14
|
+
# - If a point is occupied by 1 screen, draw normal box corner symbol.
|
15
|
+
# - If a point is occupied by 2 screens, look up in a map, and draw corresponding intersection corner symbol.
|
16
|
+
# - If a point is occupied by 3 or more screens, it's definitely a + symbol.
|
17
|
+
#
|
18
|
+
# The corner list at each point (x, y) is unique. If 2 screens overlap a point with same corner ID, it means
|
19
|
+
# 2 screens overlap, and have same corner symbol.
|
20
|
+
class BoxDrawer
|
21
|
+
CORNERS = [
|
22
|
+
TOP_LEFT = 1,
|
23
|
+
TOP_RIGHT = 2,
|
24
|
+
BOTTOM_RIGHT = 3,
|
25
|
+
BOTTOM_LEFT = 4
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
HORIZONTAL_LINE = '─'
|
29
|
+
VERTICAL_LINE = '│'
|
30
|
+
CROSS_CORNER = '┼'
|
31
|
+
|
32
|
+
NORMALS_CORNERS = {
|
33
|
+
TOP_LEFT => '┌',
|
34
|
+
TOP_RIGHT => '┐',
|
35
|
+
BOTTOM_RIGHT => '┘',
|
36
|
+
BOTTOM_LEFT => '└'
|
37
|
+
}.freeze
|
38
|
+
|
39
|
+
OVERLAPPED_CORNERS = {
|
40
|
+
[TOP_LEFT, TOP_RIGHT] => '┬',
|
41
|
+
[TOP_LEFT, BOTTOM_RIGHT] => '┼',
|
42
|
+
[TOP_LEFT, BOTTOM_LEFT] => '├',
|
43
|
+
[TOP_RIGHT, BOTTOM_RIGHT] => '┤',
|
44
|
+
[TOP_RIGHT, BOTTOM_LEFT] => '┼',
|
45
|
+
[BOTTOM_RIGHT, BOTTOM_LEFT] => '┴'
|
46
|
+
}.freeze
|
47
|
+
|
48
|
+
def initialize(output:, screens:)
|
49
|
+
@output = output
|
50
|
+
@screens = screens
|
51
|
+
@color_decorator = RubyJard::Decorators::ColorDecorator.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def draw
|
55
|
+
draw_basic_lines
|
56
|
+
corners = calculate_corners
|
57
|
+
draw_corners(corners)
|
58
|
+
draw_titles
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def draw_basic_lines
|
64
|
+
# Exclude the corners
|
65
|
+
@screens.each do |screen|
|
66
|
+
RubyJard::Console.move_to(@output, screen.x + 1, screen.y)
|
67
|
+
@output.print HORIZONTAL_LINE * (screen.width - 2)
|
68
|
+
|
69
|
+
RubyJard::Console.move_to(@output, screen.x + 1, screen.y + screen.height - 1)
|
70
|
+
@output.print HORIZONTAL_LINE * (screen.width - 2)
|
71
|
+
|
72
|
+
(screen.y + 1..screen.y + screen.height - 2).each do |moving_y|
|
73
|
+
RubyJard::Console.move_to(@output, screen.x, moving_y)
|
74
|
+
@output.print VERTICAL_LINE
|
75
|
+
RubyJard::Console.move_to(@output, screen.x + screen.width - 1, moving_y)
|
76
|
+
@output.print VERTICAL_LINE
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def draw_corners(corners)
|
82
|
+
corners.each do |x, corners_x|
|
83
|
+
corners_x.each do |y, ids|
|
84
|
+
RubyJard::Console.move_to(@output, x, y)
|
85
|
+
|
86
|
+
case ids.length
|
87
|
+
when 1
|
88
|
+
@output.print NORMALS_CORNERS[ids.first]
|
89
|
+
when 2
|
90
|
+
ids = ids.sort
|
91
|
+
@output.print OVERLAPPED_CORNERS[ids]
|
92
|
+
else
|
93
|
+
@output.print CROSS_CORNER
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def draw_titles
|
100
|
+
@screens.each do |screen|
|
101
|
+
next unless screen.respond_to?(:title)
|
102
|
+
RubyJard::Console.move_to(@output, screen.x + 2, screen.y)
|
103
|
+
@output.print ' '
|
104
|
+
@output.print @color_decorator.decorate(screen.title, :bright_yellow, :bold)
|
105
|
+
@output.print ' '
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def calculate_corners
|
110
|
+
corners = {}
|
111
|
+
@screens.each do |screen|
|
112
|
+
mark_corner(corners, screen.x, screen.y, TOP_LEFT)
|
113
|
+
mark_corner(corners, screen.x + screen.width - 1, screen.y, TOP_RIGHT)
|
114
|
+
mark_corner(corners, screen.x + screen.width - 1, screen.y + screen.height - 1, BOTTOM_RIGHT)
|
115
|
+
mark_corner(corners, screen.x, screen.y + screen.height - 1, BOTTOM_LEFT)
|
116
|
+
end
|
117
|
+
corners
|
118
|
+
end
|
119
|
+
|
120
|
+
def mark_corner(corners, x, y, id)
|
121
|
+
corners[x] ||= {}
|
122
|
+
corners[x][y] ||= []
|
123
|
+
corners[x][y] << id unless corners[x][y].include?(id)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
class Column
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
attr_accessor :column_template, :spans, :content_length, :width
|
8
|
+
|
9
|
+
def_delegators :@column_template, :margin_left, :margin_right
|
10
|
+
|
11
|
+
def initialize(column_template:)
|
12
|
+
@column_template = column_template
|
13
|
+
@spans = []
|
14
|
+
@width = 0
|
15
|
+
@content_length = 0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -3,9 +3,6 @@
|
|
3
3
|
module RubyJard
|
4
4
|
module Commands
|
5
5
|
# Command used to continue program execution.
|
6
|
-
# Data attached in the throw:
|
7
|
-
# * command: constant symbol (:continue)
|
8
|
-
# * pry: current context pry instance
|
9
6
|
class ContinueCommand < Pry::ClassCommand
|
10
7
|
group 'RubyJard'
|
11
8
|
description 'Continue program execution.'
|
@@ -22,9 +19,7 @@ module RubyJard
|
|
22
19
|
BANNER
|
23
20
|
|
24
21
|
def process
|
25
|
-
|
26
|
-
ensure
|
27
|
-
Byebug.stop if Byebug.stoppable?
|
22
|
+
RubyJard::ControlFlow.dispatch(:continue)
|
28
23
|
end
|
29
24
|
end
|
30
25
|
end
|
@@ -3,9 +3,6 @@
|
|
3
3
|
module RubyJard
|
4
4
|
module Commands
|
5
5
|
# Command used to explore stacktrace.
|
6
|
-
# Data attached in the throw:
|
7
|
-
# * command: constant symbol (:down)
|
8
|
-
# * pry: current context pry instance
|
9
6
|
class DownCommand < Pry::ClassCommand
|
10
7
|
group 'RubyJard'
|
11
8
|
description 'Explore the frames bellow the current stopped line in the backtrace'
|
@@ -22,7 +19,7 @@ module RubyJard
|
|
22
19
|
BANNER
|
23
20
|
|
24
21
|
def process
|
25
|
-
|
22
|
+
RubyJard::ControlFlow.dispatch(:down)
|
26
23
|
end
|
27
24
|
end
|
28
25
|
end
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module RubyJard
|
4
4
|
module Commands
|
5
5
|
# Command used to explore stacktrace.
|
6
|
-
# Data attached in the throw:
|
7
|
-
# * command: constant symbol (:frame)
|
8
|
-
# * pry: current context pry instance
|
9
|
-
# * frame (optional): frame id of the destination frame
|
10
6
|
class FrameCommand < Pry::ClassCommand
|
11
7
|
group 'RubyJard'
|
12
8
|
description 'Explore to any frame of current stacktrace.'
|
@@ -14,20 +10,25 @@ module RubyJard
|
|
14
10
|
match 'frame'
|
15
11
|
|
16
12
|
banner <<-BANNER
|
17
|
-
Usage: frame
|
13
|
+
Usage: frame [FRAME_ID]
|
18
14
|
|
19
15
|
Explore to any frame of current stacktrace.
|
20
16
|
|
21
17
|
Examples:
|
22
|
-
frame
|
18
|
+
frame 4 # Jump to frame 4 in the backtrace
|
23
19
|
BANNER
|
24
20
|
|
25
21
|
def process
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
frame = args.first
|
23
|
+
raise Pry::CommandError, 'Frame ID is required' if frame.nil?
|
24
|
+
raise Pry::CommandError, 'Frame ID must be numeric' unless frame =~ /^\d+$/i
|
25
|
+
|
26
|
+
frame = frame.to_i
|
27
|
+
if frame >= RubyJard.current_session.backtrace.length || frame < 0
|
28
|
+
raise Pry::CommandError, "Frame #{frame} does not exist!"
|
29
|
+
else
|
30
|
+
RubyJard::ControlFlow.dispatch(:frame, frame: args.first)
|
31
|
+
end
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|