ruby_jard 0.2.2 → 0.2.3
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/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/ruby.yml +85 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +70 -1
- data/CHANGELOG.md +31 -0
- data/Gemfile +6 -3
- data/README.md +122 -8
- data/bin/console +1 -2
- data/docs/color_schemes/256-light.png +0 -0
- data/docs/color_schemes/gruvbox.png +0 -0
- data/docs/color_schemes/one-half-dark.png +0 -0
- data/docs/color_schemes/one-half-light.png +0 -0
- data/lib/ruby_jard.rb +5 -5
- data/lib/ruby_jard/box_drawer.rb +4 -1
- data/lib/ruby_jard/color_schemes.rb +31 -15
- data/lib/ruby_jard/color_schemes/256_color_scheme.rb +37 -37
- data/lib/ruby_jard/color_schemes/256_light_color_scheme.rb +62 -0
- data/lib/ruby_jard/color_schemes/deep_space_color_scheme.rb +36 -36
- data/lib/ruby_jard/color_schemes/gruvbox_color_scheme.rb +62 -0
- data/lib/ruby_jard/color_schemes/one_half_dark_color_scheme.rb +61 -0
- data/lib/ruby_jard/color_schemes/one_half_light_color_scheme.rb +62 -0
- data/lib/ruby_jard/column.rb +3 -1
- data/lib/ruby_jard/commands/continue_command.rb +2 -3
- data/lib/ruby_jard/commands/down_command.rb +9 -5
- data/lib/ruby_jard/commands/exit_command.rb +27 -0
- data/lib/ruby_jard/commands/frame_command.rb +11 -10
- data/lib/ruby_jard/commands/jard/color_scheme_command.rb +52 -0
- data/lib/ruby_jard/commands/jard/hide_command.rb +40 -0
- data/lib/ruby_jard/commands/jard/output_command.rb +28 -0
- data/lib/ruby_jard/commands/jard/show_command.rb +41 -0
- data/lib/ruby_jard/commands/jard_command.rb +50 -0
- data/lib/ruby_jard/commands/list_command.rb +5 -4
- data/lib/ruby_jard/commands/next_command.rb +10 -5
- data/lib/ruby_jard/commands/step_command.rb +10 -5
- data/lib/ruby_jard/commands/step_out_command.rb +10 -5
- data/lib/ruby_jard/commands/up_command.rb +10 -5
- data/lib/ruby_jard/commands/validation_helpers.rb +50 -0
- data/lib/ruby_jard/config.rb +7 -3
- data/lib/ruby_jard/console.rb +10 -22
- data/lib/ruby_jard/control_flow.rb +3 -3
- data/lib/ruby_jard/decorators/color_decorator.rb +11 -5
- data/lib/ruby_jard/decorators/loc_decorator.rb +1 -1
- data/lib/ruby_jard/decorators/path_decorator.rb +20 -7
- data/lib/ruby_jard/decorators/source_decorator.rb +2 -0
- data/lib/ruby_jard/frame.rb +55 -0
- data/lib/ruby_jard/keys.rb +0 -3
- data/lib/ruby_jard/layout.rb +9 -2
- data/lib/ruby_jard/layout_calculator.rb +29 -12
- data/lib/ruby_jard/layout_picker.rb +34 -0
- data/lib/ruby_jard/layouts.rb +52 -0
- data/lib/ruby_jard/layouts/narrow_horizontal_layout.rb +28 -0
- data/lib/ruby_jard/layouts/narrow_vertical_layout.rb +32 -0
- data/lib/ruby_jard/layouts/tiny_layout.rb +25 -0
- data/lib/ruby_jard/layouts/wide_layout.rb +13 -15
- data/lib/ruby_jard/pager.rb +96 -0
- data/lib/ruby_jard/repl_processor.rb +61 -31
- data/lib/ruby_jard/repl_proxy.rb +193 -89
- data/lib/ruby_jard/row.rb +16 -1
- data/lib/ruby_jard/row_renderer.rb +51 -42
- data/lib/ruby_jard/screen.rb +2 -12
- data/lib/ruby_jard/screen_adjuster.rb +104 -0
- data/lib/ruby_jard/screen_drawer.rb +3 -0
- data/lib/ruby_jard/screen_manager.rb +32 -54
- data/lib/ruby_jard/screen_renderer.rb +30 -16
- data/lib/ruby_jard/screens.rb +31 -12
- data/lib/ruby_jard/screens/backtrace_screen.rb +23 -26
- data/lib/ruby_jard/screens/menu_screen.rb +53 -22
- data/lib/ruby_jard/screens/source_screen.rb +65 -37
- data/lib/ruby_jard/screens/threads_screen.rb +14 -14
- data/lib/ruby_jard/screens/variables_screen.rb +59 -34
- data/lib/ruby_jard/session.rb +19 -10
- data/lib/ruby_jard/span.rb +3 -0
- data/lib/ruby_jard/templates/layout_template.rb +1 -1
- data/lib/ruby_jard/templates/screen_template.rb +3 -4
- data/lib/ruby_jard/version.rb +1 -1
- data/ruby_jard.gemspec +1 -1
- metadata +38 -9
- data/lib/ruby_jard/commands/color_scheme_command.rb +0 -42
- data/lib/ruby_jard/layouts/narrow_layout.rb +0 -41
- data/lib/ruby_jard/screens/empty_screen.rb +0 -13
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RubyJard
|
4
|
-
|
4
|
+
class Screens
|
5
5
|
##
|
6
6
|
# Backtrace screen implements the content to display current thread's backtrace to the user.
|
7
7
|
class BacktraceScreen < RubyJard::Screen
|
@@ -10,7 +10,7 @@ module RubyJard
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def build
|
13
|
-
@rows = @session.
|
13
|
+
@rows = @session.current_backtrace.map.with_index do |frame, frame_id|
|
14
14
|
RubyJard::Row.new(
|
15
15
|
line_limit: 2,
|
16
16
|
columns: [
|
@@ -39,36 +39,35 @@ module RubyJard
|
|
39
39
|
frame_id_label = frame_id.to_s.rjust(frames_count.to_s.length)
|
40
40
|
if current_frame?(frame_id)
|
41
41
|
RubyJard::Span.new(
|
42
|
-
content: frame_id_label,
|
42
|
+
content: "➠ #{frame_id_label}",
|
43
43
|
styles: :frame_id_highlighted
|
44
44
|
)
|
45
45
|
else
|
46
46
|
RubyJard::Span.new(
|
47
|
-
content: frame_id_label,
|
47
|
+
content: " #{frame_id_label}",
|
48
48
|
styles: :frame_id
|
49
49
|
)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
53
|
def span_class_label(frame)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if object.is_a?(Class)
|
59
|
-
object.name
|
54
|
+
class_label =
|
55
|
+
if frame.frame_class.nil? || frame.frame_self.class == frame.frame_class
|
56
|
+
if frame.frame_self.is_a?(Class)
|
57
|
+
frame.frame_self.name
|
60
58
|
else
|
61
|
-
|
59
|
+
frame.frame_self.class.name
|
62
60
|
end
|
63
|
-
elsif
|
61
|
+
elsif frame.frame_class.singleton_class?
|
64
62
|
# No easy way to get the original class of a singleton class
|
65
|
-
|
63
|
+
frame.frame_self.respond_to?(:name) ? frame.frame_self.name : frame.frame_self.to_s
|
66
64
|
else
|
67
|
-
|
65
|
+
frame.frame_class.name
|
68
66
|
end
|
69
|
-
|
67
|
+
|
68
|
+
c_frame = frame.c_frame? ? '[c] ' : ''
|
70
69
|
RubyJard::Span.new(
|
71
|
-
content: "#{c_frame}#{
|
70
|
+
content: "#{c_frame}#{class_label}",
|
72
71
|
margin_right: 1,
|
73
72
|
styles: :constant
|
74
73
|
)
|
@@ -83,12 +82,11 @@ module RubyJard
|
|
83
82
|
end
|
84
83
|
|
85
84
|
def span_method_label(frame)
|
86
|
-
location = frame[0]
|
87
85
|
method_label =
|
88
|
-
if
|
89
|
-
"#{
|
86
|
+
if frame.frame_location.label != frame.frame_location.base_label
|
87
|
+
"#{frame.frame_location.base_label} (#{frame.frame_location.label.split(' ').first})"
|
90
88
|
else
|
91
|
-
|
89
|
+
frame.frame_location.base_label
|
92
90
|
end
|
93
91
|
RubyJard::Span.new(
|
94
92
|
content: method_label,
|
@@ -98,8 +96,7 @@ module RubyJard
|
|
98
96
|
end
|
99
97
|
|
100
98
|
def span_path(frame)
|
101
|
-
|
102
|
-
decorated_path = decorate_path(location.absolute_path, location.lineno)
|
99
|
+
decorated_path = decorate_path(frame.frame_location.absolute_path, frame.frame_location.lineno)
|
103
100
|
|
104
101
|
path_label =
|
105
102
|
if decorated_path.gem?
|
@@ -118,15 +115,15 @@ module RubyJard
|
|
118
115
|
end
|
119
116
|
|
120
117
|
def current_frame
|
121
|
-
if @session.
|
118
|
+
if @session.current_frame.nil?
|
122
119
|
0
|
123
120
|
else
|
124
|
-
@session.
|
121
|
+
@session.current_frame.pos.to_i
|
125
122
|
end
|
126
123
|
end
|
127
124
|
|
128
125
|
def frames_count
|
129
|
-
@session.
|
126
|
+
@session.current_backtrace.length
|
130
127
|
end
|
131
128
|
|
132
129
|
def decorate_path(path, lineno)
|
@@ -136,4 +133,4 @@ module RubyJard
|
|
136
133
|
end
|
137
134
|
end
|
138
135
|
|
139
|
-
RubyJard::Screens.add_screen(
|
136
|
+
RubyJard::Screens.add_screen('backtrace', RubyJard::Screens::BacktraceScreen)
|
@@ -1,32 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RubyJard
|
4
|
-
|
4
|
+
class Screens
|
5
|
+
##
|
6
|
+
# Display key binding guidelines and shortcuts.
|
5
7
|
class MenuScreen < RubyJard::Screen
|
6
8
|
def build
|
7
|
-
|
8
|
-
|
9
|
-
styles: :title_highlighted
|
10
|
-
)
|
11
|
-
menu_spans = generate_menu_spans
|
12
|
-
|
13
|
-
alignment =
|
14
|
-
@layout.width -
|
15
|
-
span_title.content_length -
|
16
|
-
menu_spans.map(&:content_length).sum
|
17
|
-
span_align = RubyJard::Span.new(
|
18
|
-
content: ' ' * (alignment < 0 ? 0 : alignment),
|
19
|
-
styles: :background
|
20
|
-
)
|
9
|
+
left_spans = generate_left_spans
|
10
|
+
right_spans = generate_right_spans
|
21
11
|
@rows = [RubyJard::Row.new(
|
22
12
|
line_limit: 1,
|
23
|
-
ellipsis: false,
|
24
13
|
columns: [
|
25
14
|
RubyJard::Column.new(
|
15
|
+
word_wrap: RubyJard::Column::WORD_WRAP_BREAK_WORD,
|
26
16
|
spans: [
|
27
|
-
|
28
|
-
|
29
|
-
|
17
|
+
left_spans,
|
18
|
+
align(left_spans, right_spans),
|
19
|
+
right_spans
|
30
20
|
].flatten
|
31
21
|
)
|
32
22
|
]
|
@@ -36,7 +26,37 @@ module RubyJard
|
|
36
26
|
|
37
27
|
private
|
38
28
|
|
39
|
-
def
|
29
|
+
def generate_left_spans
|
30
|
+
[
|
31
|
+
RubyJard::Span.new(
|
32
|
+
content: ' REPL ',
|
33
|
+
styles: :title_highlighted
|
34
|
+
)
|
35
|
+
]
|
36
|
+
# [
|
37
|
+
# RubyJard::Span.new(
|
38
|
+
# content: ' Mode (F2) ',
|
39
|
+
# styles: :title_highlighted
|
40
|
+
# ),
|
41
|
+
# RubyJard::Span.new(
|
42
|
+
# margin_left: 1,
|
43
|
+
# content: 'All gems',
|
44
|
+
# styles: :menu_mode
|
45
|
+
# ),
|
46
|
+
# RubyJard::Span.new(
|
47
|
+
# margin_left: 1,
|
48
|
+
# content: '|',
|
49
|
+
# styles: :menu_tips
|
50
|
+
# ),
|
51
|
+
# RubyJard::Span.new(
|
52
|
+
# margin_left: 1,
|
53
|
+
# content: 'Application only',
|
54
|
+
# styles: :menu_tips
|
55
|
+
# )
|
56
|
+
# ]
|
57
|
+
end
|
58
|
+
|
59
|
+
def generate_right_spans
|
40
60
|
[
|
41
61
|
'Up (F6)',
|
42
62
|
'Down (Shift+F6)',
|
@@ -48,12 +68,23 @@ module RubyJard
|
|
48
68
|
RubyJard::Span.new(
|
49
69
|
content: menu_item,
|
50
70
|
margin_left: 3,
|
51
|
-
styles: :
|
71
|
+
styles: :menu_tips
|
52
72
|
)
|
53
73
|
end
|
54
74
|
end
|
75
|
+
|
76
|
+
def align(left_spans, right_spans)
|
77
|
+
alignment =
|
78
|
+
@layout.width -
|
79
|
+
right_spans.map(&:content_length).sum -
|
80
|
+
left_spans.map(&:content_length).sum
|
81
|
+
RubyJard::Span.new(
|
82
|
+
content: ' ' * (alignment < 0 ? 0 : alignment),
|
83
|
+
styles: :background
|
84
|
+
)
|
85
|
+
end
|
55
86
|
end
|
56
87
|
end
|
57
88
|
end
|
58
89
|
|
59
|
-
RubyJard::Screens.add_screen(
|
90
|
+
RubyJard::Screens.add_screen('menu', RubyJard::Screens::MenuScreen)
|
@@ -1,12 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RubyJard
|
4
|
-
|
4
|
+
class Screens
|
5
|
+
##
|
6
|
+
# Display source code of current stopping line and surrounding lines
|
5
7
|
class SourceScreen < RubyJard::Screen
|
8
|
+
ANONYMOUS_SIGNATURES = [
|
9
|
+
'(eval)', '-e'
|
10
|
+
].freeze
|
11
|
+
|
6
12
|
def title
|
7
|
-
return 'Source' if
|
13
|
+
return 'Source' if @session.current_frame.nil?
|
8
14
|
|
9
|
-
decorated_path = path_decorator(
|
15
|
+
decorated_path = path_decorator(@session.current_frame.frame_file, @session.current_frame.frame_line)
|
10
16
|
if decorated_path.gem?
|
11
17
|
['Source', "#{decorated_path.gem} - #{decorated_path.path}:#{decorated_path.lineno}"]
|
12
18
|
else
|
@@ -15,35 +21,73 @@ module RubyJard
|
|
15
21
|
end
|
16
22
|
|
17
23
|
def build
|
18
|
-
return if
|
24
|
+
return if @session.current_frame.nil?
|
25
|
+
|
26
|
+
if ANONYMOUS_SIGNATURES.include? @session.current_frame.frame_file
|
27
|
+
# (eval) is hard-coded in Ruby source code for in-code evaluation
|
28
|
+
handle_anonymous_evaluation
|
29
|
+
else
|
30
|
+
# TODO: screen now supports window.
|
31
|
+
codes = source_decorator.codes
|
32
|
+
@rows = codes.map.with_index do |loc, index|
|
33
|
+
RubyJard::Row.new(
|
34
|
+
line_limit: 3,
|
35
|
+
columns: [
|
36
|
+
RubyJard::Column.new(
|
37
|
+
spans: [
|
38
|
+
span_mark(index),
|
39
|
+
span_lineno(index)
|
40
|
+
]
|
41
|
+
),
|
42
|
+
RubyJard::Column.new(
|
43
|
+
word_wrap: RubyJard::Column::WORD_WRAP_BREAK_WORD,
|
44
|
+
spans: loc_spans(loc)
|
45
|
+
)
|
46
|
+
]
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@selected = 0
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
19
54
|
|
20
|
-
|
21
|
-
|
22
|
-
@rows = codes.map.with_index do |loc, index|
|
55
|
+
def handle_anonymous_evaluation
|
56
|
+
@rows = [
|
23
57
|
RubyJard::Row.new(
|
24
58
|
line_limit: 3,
|
25
59
|
columns: [
|
26
60
|
RubyJard::Column.new(
|
27
61
|
spans: [
|
28
|
-
|
29
|
-
|
62
|
+
RubyJard::Span.new(
|
63
|
+
content: 'This section is anonymous!',
|
64
|
+
styles: :normal_token
|
65
|
+
)
|
30
66
|
]
|
31
|
-
)
|
67
|
+
)
|
68
|
+
]
|
69
|
+
),
|
70
|
+
RubyJard::Row.new(
|
71
|
+
line_limit: 3,
|
72
|
+
columns: [
|
32
73
|
RubyJard::Column.new(
|
33
|
-
|
34
|
-
|
74
|
+
spans: [
|
75
|
+
RubyJard::Span.new(
|
76
|
+
content: 'Maybe it is dynamically evaluated, or called via ruby-e, without file information.',
|
77
|
+
styles: :source_lineno
|
78
|
+
)
|
79
|
+
]
|
35
80
|
)
|
36
81
|
]
|
37
82
|
)
|
38
|
-
|
39
|
-
@selected = 0
|
83
|
+
]
|
40
84
|
end
|
41
85
|
|
42
86
|
def span_mark(index)
|
43
87
|
lineno = source_lineno(index)
|
44
88
|
RubyJard::Span.new(
|
45
89
|
margin_right: 1,
|
46
|
-
content:
|
90
|
+
content: @session.current_frame.frame_line == lineno ? '➠' : ' ',
|
47
91
|
styles: :source_line_mark
|
48
92
|
)
|
49
93
|
end
|
@@ -52,39 +96,23 @@ module RubyJard
|
|
52
96
|
lineno = source_lineno(index).to_s.rjust(source_decorator.window_end.to_s.length)
|
53
97
|
RubyJard::Span.new(
|
54
98
|
content: lineno,
|
55
|
-
styles:
|
99
|
+
styles: @session.current_frame.frame_line == lineno ? :source_line_mark : :source_lineno
|
56
100
|
)
|
57
101
|
end
|
58
102
|
|
59
103
|
def loc_spans(loc)
|
60
|
-
spans, _tokens = loc_decorator.decorate(loc,
|
104
|
+
spans, _tokens = loc_decorator.decorate(loc, @session.current_frame.frame_file)
|
61
105
|
spans
|
62
106
|
end
|
63
107
|
|
64
|
-
private
|
65
|
-
|
66
|
-
def current_binding
|
67
|
-
RubyJard.current_session.frame._binding
|
68
|
-
end
|
69
|
-
|
70
|
-
def current_frame_scope
|
71
|
-
RubyJard.current_session.backtrace[RubyJard.current_session.frame.pos][1]
|
72
|
-
end
|
73
|
-
|
74
|
-
def current_file
|
75
|
-
RubyJard.current_session.frame.file
|
76
|
-
end
|
77
|
-
|
78
|
-
def current_line
|
79
|
-
RubyJard.current_session.frame.line
|
80
|
-
end
|
81
|
-
|
82
108
|
def path_decorator(path, lineno)
|
83
109
|
@path_decorator ||= RubyJard::Decorators::PathDecorator.new(path, lineno)
|
84
110
|
end
|
85
111
|
|
86
112
|
def source_decorator
|
87
|
-
@source_decorator ||= RubyJard::Decorators::SourceDecorator.new(
|
113
|
+
@source_decorator ||= RubyJard::Decorators::SourceDecorator.new(
|
114
|
+
@session.current_frame.frame_file, @session.current_frame.frame_line, @layout.height
|
115
|
+
)
|
88
116
|
end
|
89
117
|
|
90
118
|
def loc_decorator
|
@@ -98,4 +126,4 @@ module RubyJard
|
|
98
126
|
end
|
99
127
|
end
|
100
128
|
|
101
|
-
RubyJard::Screens.add_screen(
|
129
|
+
RubyJard::Screens.add_screen('source', RubyJard::Screens::SourceScreen)
|
@@ -1,14 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RubyJard
|
4
|
-
|
4
|
+
class Screens
|
5
|
+
##
|
6
|
+
# Display all current alive threads, excluding internal threads
|
5
7
|
class ThreadsScreen < RubyJard::Screen
|
6
8
|
def title
|
7
|
-
['Threads', "#{
|
9
|
+
['Threads', "#{@session.threads.length} threads"]
|
8
10
|
end
|
9
11
|
|
10
12
|
def build
|
11
|
-
contexts =
|
13
|
+
contexts = @session.threads.select { |c| c.thread.alive? }
|
12
14
|
contexts = sort_contexts(contexts)
|
13
15
|
@rows = contexts.map do |context|
|
14
16
|
RubyJard::Row.new(
|
@@ -40,10 +42,11 @@ module RubyJard
|
|
40
42
|
private
|
41
43
|
|
42
44
|
def span_mark(context)
|
45
|
+
style = thread_status_style(context.thread)
|
43
46
|
RubyJard::Span.new(
|
44
47
|
margin_right: 1,
|
45
|
-
content: '•',
|
46
|
-
styles:
|
48
|
+
content: style == :thread_status_run ? '►' : '•',
|
49
|
+
styles: style
|
47
50
|
)
|
48
51
|
end
|
49
52
|
|
@@ -72,11 +75,11 @@ module RubyJard
|
|
72
75
|
def span_thread_location(context)
|
73
76
|
return unknown_thread_location if
|
74
77
|
context.thread.backtrace_locations.nil? ||
|
75
|
-
|
78
|
+
@session.current_frame.frame_location.nil?
|
76
79
|
|
77
80
|
last_backtrace =
|
78
81
|
if current_thread?(context)
|
79
|
-
|
82
|
+
@session.current_frame.frame_location
|
80
83
|
else
|
81
84
|
context.thread.backtrace_locations[1]
|
82
85
|
end
|
@@ -112,14 +115,10 @@ module RubyJard
|
|
112
115
|
contexts.sort do |a, b|
|
113
116
|
[
|
114
117
|
bool_to_int(current_thread?(a)),
|
115
|
-
bool_to_int(b.ignored?),
|
116
|
-
bool_to_int(b.suspended?),
|
117
118
|
bool_to_int(b.thread.name.nil?),
|
118
119
|
a.thread.object_id
|
119
120
|
] <=> [
|
120
121
|
bool_to_int(current_thread?(b)),
|
121
|
-
bool_to_int(a.ignored?),
|
122
|
-
bool_to_int(a.suspended?),
|
123
122
|
bool_to_int(a.thread.name.nil?),
|
124
123
|
b.thread.object_id
|
125
124
|
]
|
@@ -139,9 +138,10 @@ module RubyJard
|
|
139
138
|
end
|
140
139
|
|
141
140
|
def thread_status_style(thread)
|
142
|
-
|
141
|
+
case thread.status
|
142
|
+
when 'run'
|
143
143
|
:thread_status_run
|
144
|
-
|
144
|
+
when 'sleep'
|
145
145
|
:thread_status_sleep
|
146
146
|
else
|
147
147
|
:thread_status_other
|
@@ -151,4 +151,4 @@ module RubyJard
|
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
|
-
RubyJard::Screens.add_screen(
|
154
|
+
RubyJard::Screens.add_screen('threads', RubyJard::Screens::ThreadsScreen)
|