ruby_jard 0.1.0 → 0.2.0
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.
- 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
|
+
[](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
|
+

|
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
|