ruby_jard 0.2.0 → 0.2.1
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 +4 -1
- data/CHANGELOG.md +18 -0
- data/CNAME +1 -0
- data/README.md +206 -33
- data/_config.yml +1 -0
- data/docs/_config.yml +8 -0
- data/docs/demo.png +0 -0
- data/docs/index.md +238 -0
- data/docs/logo.jpg +0 -0
- data/docs/screen-backtrace.png +0 -0
- data/docs/screen-repl.png +0 -0
- data/docs/screen-source.png +0 -0
- data/docs/screen-threads.png +0 -0
- data/docs/screen-variables.png +0 -0
- data/images/bg_hr.png +0 -0
- data/images/blacktocat.png +0 -0
- data/images/body-bg.jpg +0 -0
- data/images/download-button.png +0 -0
- data/images/github-button.png +0 -0
- data/images/header-bg.jpg +0 -0
- data/images/highlight-bg.jpg +0 -0
- data/images/icon_download.png +0 -0
- data/images/sidebar-bg.jpg +0 -0
- data/images/sprite_download.png +0 -0
- data/javascripts/main.js +1 -0
- data/lib/ruby_jard.rb +3 -18
- data/lib/ruby_jard/box_drawer.rb +68 -22
- data/lib/ruby_jard/color_scheme.rb +28 -0
- data/lib/ruby_jard/color_schemes.rb +26 -0
- data/lib/ruby_jard/color_schemes/256_color_scheme.rb +64 -0
- data/lib/ruby_jard/color_schemes/deep_space_color_scheme.rb +63 -0
- data/lib/ruby_jard/column.rb +12 -6
- data/lib/ruby_jard/commands/continue_command.rb +1 -0
- data/lib/ruby_jard/commands/list_command.rb +29 -0
- data/lib/ruby_jard/commands/next_command.rb +1 -0
- data/lib/ruby_jard/commands/step_command.rb +1 -0
- data/lib/ruby_jard/commands/step_out_command.rb +1 -0
- data/lib/ruby_jard/console.rb +102 -18
- data/lib/ruby_jard/control_flow.rb +9 -8
- data/lib/ruby_jard/decorators/color_decorator.rb +46 -57
- data/lib/ruby_jard/decorators/inspection_decorator.rb +76 -0
- data/lib/ruby_jard/decorators/loc_decorator.rb +83 -107
- data/lib/ruby_jard/decorators/source_decorator.rb +1 -1
- data/lib/ruby_jard/keys.rb +1 -0
- data/lib/ruby_jard/layout.rb +9 -99
- data/lib/ruby_jard/layout_calculator.rb +151 -0
- data/lib/ruby_jard/layouts/narrow_layout.rb +41 -0
- data/lib/ruby_jard/layouts/wide_layout.rb +17 -103
- data/lib/ruby_jard/repl_processor.rb +5 -1
- data/lib/ruby_jard/repl_proxy.rb +2 -1
- data/lib/ruby_jard/row.rb +5 -5
- data/lib/ruby_jard/row_renderer.rb +108 -0
- data/lib/ruby_jard/screen.rb +20 -115
- data/lib/ruby_jard/screen_drawer.rb +8 -75
- data/lib/ruby_jard/screen_manager.rb +78 -55
- data/lib/ruby_jard/screen_renderer.rb +138 -0
- data/lib/ruby_jard/screens/backtrace_screen.rb +67 -69
- data/lib/ruby_jard/screens/menu_screen.rb +43 -38
- data/lib/ruby_jard/screens/source_screen.rb +43 -27
- data/lib/ruby_jard/screens/threads_screen.rb +91 -39
- data/lib/ruby_jard/screens/variables_screen.rb +72 -56
- data/lib/ruby_jard/session.rb +16 -0
- data/lib/ruby_jard/span.rb +8 -6
- data/lib/ruby_jard/version.rb +1 -1
- data/ruby_jard.gemspec +4 -4
- data/stylesheets/github-light.css +130 -0
- data/stylesheets/normalize.css +424 -0
- data/stylesheets/print.css +228 -0
- data/stylesheets/stylesheet.css +245 -0
- metadata +52 -21
- data/lib/ruby_jard/templates/column_template.rb +0 -17
- data/lib/ruby_jard/templates/row_template.rb +0 -22
- data/lib/ruby_jard/templates/space_template.rb +0 -15
- data/lib/ruby_jard/templates/span_template.rb +0 -25
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
##
|
5
|
+
# Adjust the layout between screens, render row's bitmap by calling RowRenderer,
|
6
|
+
# calculate screen window to ready for putting on the screen.
|
7
|
+
class ScreenRenderer
|
8
|
+
def initialize(screen:, color_scheme:)
|
9
|
+
@screen = screen
|
10
|
+
@color_scheme = color_scheme
|
11
|
+
end
|
12
|
+
|
13
|
+
def render
|
14
|
+
return unless @screen.need_to_render?
|
15
|
+
|
16
|
+
# Move this logic into a class called SreenRenderer
|
17
|
+
calculate_content_lengths
|
18
|
+
column_widths = calculate_column_widths
|
19
|
+
adjust_column_widths(column_widths)
|
20
|
+
render_rows
|
21
|
+
calculate_window
|
22
|
+
@screen.mark_rendered!
|
23
|
+
|
24
|
+
@screen
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def calculate_content_lengths
|
30
|
+
@screen.rows.each do |row|
|
31
|
+
row.columns.each do |column|
|
32
|
+
column.content_length = column.spans.map(&:content_length).inject(&:+)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def calculate_column_widths
|
38
|
+
column_widths = {}
|
39
|
+
total_columns = count_columns
|
40
|
+
|
41
|
+
return column_widths if total_columns == 0
|
42
|
+
|
43
|
+
ideal_column_width = @screen.layout.width / total_columns
|
44
|
+
total_columns.times do |column_index|
|
45
|
+
column_widths[column_index] ||= 0
|
46
|
+
@screen.rows.each do |row|
|
47
|
+
column = row.columns[column_index]
|
48
|
+
if column.content_length > ideal_column_width - 1
|
49
|
+
column_widths[column_index] = nil
|
50
|
+
break
|
51
|
+
elsif column.content_length + 1 > column_widths[column_index]
|
52
|
+
column_widths[column_index] = column.content_length + 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
column_widths
|
57
|
+
end
|
58
|
+
|
59
|
+
def adjust_column_widths(column_widths)
|
60
|
+
dynamic_count = column_widths.values.select(&:nil?).length
|
61
|
+
fixed_width = column_widths.values.inject(0) do |sum, col|
|
62
|
+
col.nil? ? sum : sum + col
|
63
|
+
end
|
64
|
+
|
65
|
+
@screen.rows.each do |row|
|
66
|
+
total_width = 0
|
67
|
+
row.columns.each_with_index do |column, column_index|
|
68
|
+
column.width =
|
69
|
+
if column_index == row.columns.length - 1
|
70
|
+
@screen.layout.width - total_width
|
71
|
+
elsif column_widths[column_index].nil?
|
72
|
+
(@screen.layout.width - fixed_width) / dynamic_count
|
73
|
+
else
|
74
|
+
column_widths[column_index]
|
75
|
+
end
|
76
|
+
total_width += column.width
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def render_rows
|
82
|
+
@screen.rows.each do |row|
|
83
|
+
RubyJard::RowRenderer.new(
|
84
|
+
row: row,
|
85
|
+
width: @screen.layout.width,
|
86
|
+
height: @screen.layout.height,
|
87
|
+
color_scheme: @color_scheme
|
88
|
+
).render
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def calculate_window
|
93
|
+
@screen.window = []
|
94
|
+
|
95
|
+
if @screen.cursor.nil?
|
96
|
+
find_seleted_window
|
97
|
+
else
|
98
|
+
find_cursor_window
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def find_seleted_window
|
103
|
+
@screen.rows.each_with_index do |row, row_index|
|
104
|
+
row.content.each_with_index do |line, line_index|
|
105
|
+
if @screen.window.length < @screen.layout.height
|
106
|
+
@screen.window << line
|
107
|
+
elsif row_index < @screen.selected
|
108
|
+
@screen.window = [line]
|
109
|
+
elsif row_index == @screen.selected
|
110
|
+
if line_index != 0
|
111
|
+
@screen.window.shift
|
112
|
+
@screen.window << line
|
113
|
+
else
|
114
|
+
@screen.window = [line]
|
115
|
+
end
|
116
|
+
else
|
117
|
+
return
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def find_cursor_window
|
124
|
+
cursor_line = -1
|
125
|
+
@screen.rows.each do |row|
|
126
|
+
row.content.each do |line|
|
127
|
+
cursor_line += 1
|
128
|
+
@screen.window << line if cursor_line >= @screen.cursor
|
129
|
+
return if @screen.window.length >= @screen.layout.height
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def count_columns
|
135
|
+
@screen.rows.map { |row| row.columns.count }.max.to_i
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -6,48 +6,51 @@ module RubyJard
|
|
6
6
|
# Backtrace screen implements the content to display current thread's backtrace to the user.
|
7
7
|
class BacktraceScreen < RubyJard::Screen
|
8
8
|
def title
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
9
|
+
['Backtrace', "#{frames_count} frames"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def build
|
13
|
+
@rows = @session.backtrace.map.with_index do |frame, frame_id|
|
14
|
+
RubyJard::Row.new(
|
15
|
+
line_limit: 2,
|
16
|
+
columns: [
|
17
|
+
RubyJard::Column.new(
|
18
|
+
spans: [
|
19
|
+
span_frame_id(frame_id)
|
20
|
+
]
|
21
|
+
),
|
22
|
+
RubyJard::Column.new(
|
23
|
+
spans: [
|
24
|
+
span_class_label(frame),
|
25
|
+
span_label_preposition,
|
26
|
+
span_method_label(frame),
|
27
|
+
span_path(frame)
|
28
|
+
]
|
29
|
+
)
|
30
|
+
]
|
31
|
+
)
|
32
|
+
end
|
33
|
+
@selected = current_frame
|
30
34
|
end
|
31
35
|
|
32
|
-
|
33
|
-
[
|
34
|
-
current_frame?(index) ? '→' : ' ',
|
35
|
-
[:bright_yellow, current_frame?(index) ? :bold : nil]
|
36
|
-
]
|
37
|
-
end
|
36
|
+
private
|
38
37
|
|
39
|
-
def span_frame_id(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
38
|
+
def span_frame_id(frame_id)
|
39
|
+
frame_id_label = frame_id.to_s.rjust(frames_count.to_s.length)
|
40
|
+
if current_frame?(frame_id)
|
41
|
+
RubyJard::Span.new(
|
42
|
+
content: frame_id_label,
|
43
|
+
styles: :frame_id_highlighted
|
44
|
+
)
|
45
|
+
else
|
46
|
+
RubyJard::Span.new(
|
47
|
+
content: frame_id_label,
|
48
|
+
styles: :frame_id
|
49
|
+
)
|
50
|
+
end
|
48
51
|
end
|
49
52
|
|
50
|
-
def
|
53
|
+
def span_class_label(frame)
|
51
54
|
object = frame[1]
|
52
55
|
klass = frame[2]
|
53
56
|
klass_label =
|
@@ -63,18 +66,23 @@ module RubyJard
|
|
63
66
|
else
|
64
67
|
klass.name
|
65
68
|
end
|
66
|
-
c_frame =
|
67
|
-
|
68
|
-
"#{c_frame}#{klass_label}",
|
69
|
-
|
70
|
-
|
69
|
+
c_frame = frame.last.nil? ? '[c] ' : ''
|
70
|
+
RubyJard::Span.new(
|
71
|
+
content: "#{c_frame}#{klass_label}",
|
72
|
+
margin_right: 1,
|
73
|
+
styles: :constant
|
74
|
+
)
|
71
75
|
end
|
72
76
|
|
73
|
-
def span_label_preposition
|
74
|
-
|
77
|
+
def span_label_preposition
|
78
|
+
RubyJard::Span.new(
|
79
|
+
content: 'in',
|
80
|
+
margin_right: 1,
|
81
|
+
styles: :frame_location
|
82
|
+
)
|
75
83
|
end
|
76
84
|
|
77
|
-
def span_method_label(frame
|
85
|
+
def span_method_label(frame)
|
78
86
|
location = frame[0]
|
79
87
|
method_label =
|
80
88
|
if location.label != location.base_label
|
@@ -82,33 +90,31 @@ module RubyJard
|
|
82
90
|
else
|
83
91
|
location.base_label
|
84
92
|
end
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
decorated_path = decorate_path(location.absolute_path, location.lineno)
|
91
|
-
preposition = decorated_path.gem? ? 'in' : 'at'
|
92
|
-
[preposition, current_frame?(index) ? [:bright_white] : [:white]]
|
93
|
+
RubyJard::Span.new(
|
94
|
+
content: method_label,
|
95
|
+
margin_right: 1,
|
96
|
+
styles: :method
|
97
|
+
)
|
93
98
|
end
|
94
99
|
|
95
|
-
def span_path(frame
|
100
|
+
def span_path(frame)
|
96
101
|
location = frame[0]
|
97
102
|
decorated_path = decorate_path(location.absolute_path, location.lineno)
|
98
103
|
|
99
104
|
path_label =
|
100
105
|
if decorated_path.gem?
|
101
|
-
"#{decorated_path.gem} (#{decorated_path.gem_version})"
|
106
|
+
"in #{decorated_path.gem} (#{decorated_path.gem_version})"
|
102
107
|
else
|
103
|
-
"#{decorated_path.path}:#{decorated_path.lineno}"
|
108
|
+
"at #{decorated_path.path}:#{decorated_path.lineno}"
|
104
109
|
end
|
105
|
-
|
110
|
+
RubyJard::Span.new(
|
111
|
+
content: path_label,
|
112
|
+
styles: :frame_location
|
113
|
+
)
|
106
114
|
end
|
107
115
|
|
108
|
-
|
109
|
-
|
110
|
-
def current_frame?(index)
|
111
|
-
index + data_window_start == current_frame
|
116
|
+
def current_frame?(frame_id)
|
117
|
+
frame_id == current_frame
|
112
118
|
end
|
113
119
|
|
114
120
|
def current_frame
|
@@ -119,18 +125,10 @@ module RubyJard
|
|
119
125
|
end
|
120
126
|
end
|
121
127
|
|
122
|
-
def frame_at(index)
|
123
|
-
backtrace[index + data_window_start]
|
124
|
-
end
|
125
|
-
|
126
128
|
def frames_count
|
127
129
|
@session.backtrace.length
|
128
130
|
end
|
129
131
|
|
130
|
-
def backtrace
|
131
|
-
@session.backtrace
|
132
|
-
end
|
133
|
-
|
134
132
|
def decorate_path(path, lineno)
|
135
133
|
RubyJard::Decorators::PathDecorator.new(path, lineno)
|
136
134
|
end
|
@@ -3,49 +3,54 @@
|
|
3
3
|
module RubyJard
|
4
4
|
module Screens
|
5
5
|
class MenuScreen < RubyJard::Screen
|
6
|
-
def
|
7
|
-
RubyJard::
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
6
|
+
def build
|
7
|
+
span_title = RubyJard::Span.new(
|
8
|
+
content: ' REPL Console ',
|
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
|
+
)
|
21
|
+
@rows = [RubyJard::Row.new(
|
22
|
+
line_limit: 1,
|
23
|
+
ellipsis: false,
|
24
|
+
columns: [
|
25
|
+
RubyJard::Column.new(
|
26
|
+
spans: [
|
27
|
+
span_title,
|
28
|
+
span_align,
|
29
|
+
menu_spans
|
30
|
+
].flatten
|
31
|
+
)
|
32
|
+
]
|
33
|
+
)]
|
34
|
+
@selected = 0
|
24
35
|
end
|
25
36
|
|
26
37
|
private
|
27
38
|
|
28
|
-
def
|
29
|
-
[
|
30
|
-
# Fill in later
|
31
|
-
]
|
32
|
-
end
|
33
|
-
|
34
|
-
def generate_right_menu
|
39
|
+
def generate_menu_spans
|
35
40
|
[
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
41
|
+
'Up (F6)',
|
42
|
+
'Down (Shift+F6)',
|
43
|
+
'Step (F7)',
|
44
|
+
'Step Out (Shift+F7)',
|
45
|
+
'Next (F8)',
|
46
|
+
'Continue (F9)'
|
47
|
+
].map do |menu_item|
|
48
|
+
RubyJard::Span.new(
|
49
|
+
content: menu_item,
|
50
|
+
margin_left: 3,
|
51
|
+
styles: :control_buttons
|
52
|
+
)
|
53
|
+
end
|
49
54
|
end
|
50
55
|
end
|
51
56
|
end
|
@@ -8,41 +8,57 @@ module RubyJard
|
|
8
8
|
|
9
9
|
decorated_path = path_decorator(current_file, current_line)
|
10
10
|
if decorated_path.gem?
|
11
|
-
|
11
|
+
['Source', "#{decorated_path.gem} - #{decorated_path.path}:#{decorated_path.lineno}"]
|
12
12
|
else
|
13
|
-
|
13
|
+
['Source', "#{decorated_path.path}:#{decorated_path.lineno}"]
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
def build
|
18
|
+
return if RubyJard.current_session.frame.nil?
|
19
|
+
|
20
|
+
# TODO: screen now supports window.
|
21
|
+
codes = source_decorator.codes
|
22
|
+
@rows = codes.map.with_index do |loc, index|
|
23
|
+
RubyJard::Row.new(
|
24
|
+
line_limit: 3,
|
25
|
+
columns: [
|
26
|
+
RubyJard::Column.new(
|
27
|
+
spans: [
|
28
|
+
span_mark(index),
|
29
|
+
span_lineno(index)
|
30
|
+
]
|
31
|
+
),
|
32
|
+
RubyJard::Column.new(
|
33
|
+
word_wrap: RubyJard::Column::WORD_WRAP_BREAK_WORD,
|
34
|
+
spans: loc_spans(loc)
|
35
|
+
)
|
36
|
+
]
|
37
|
+
)
|
38
|
+
end
|
39
|
+
@selected = 0
|
25
40
|
end
|
26
41
|
|
27
|
-
def span_mark(
|
42
|
+
def span_mark(index)
|
28
43
|
lineno = source_lineno(index)
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
44
|
+
RubyJard::Span.new(
|
45
|
+
margin_right: 1,
|
46
|
+
content: current_line == lineno ? '➠' : ' ',
|
47
|
+
styles: :source_line_mark
|
48
|
+
)
|
33
49
|
end
|
34
50
|
|
35
|
-
def span_lineno(
|
36
|
-
lineno = source_lineno(index)
|
37
|
-
|
38
|
-
lineno
|
39
|
-
current_line == lineno ?
|
40
|
-
|
51
|
+
def span_lineno(index)
|
52
|
+
lineno = source_lineno(index).to_s.rjust(source_decorator.window_end.to_s.length)
|
53
|
+
RubyJard::Span.new(
|
54
|
+
content: lineno,
|
55
|
+
styles: current_line == lineno ? :source_line_mark : :source_lineno
|
56
|
+
)
|
41
57
|
end
|
42
58
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
59
|
+
def loc_spans(loc)
|
60
|
+
spans, _tokens = loc_decorator.decorate(loc, current_file)
|
61
|
+
spans
|
46
62
|
end
|
47
63
|
|
48
64
|
private
|
@@ -68,11 +84,11 @@ module RubyJard
|
|
68
84
|
end
|
69
85
|
|
70
86
|
def source_decorator
|
71
|
-
@source_decorator ||= RubyJard::Decorators::SourceDecorator.new(current_file, current_line,
|
87
|
+
@source_decorator ||= RubyJard::Decorators::SourceDecorator.new(current_file, current_line, @layout.height)
|
72
88
|
end
|
73
89
|
|
74
|
-
def loc_decorator
|
75
|
-
RubyJard::Decorators::LocDecorator.new
|
90
|
+
def loc_decorator
|
91
|
+
@loc_decorator ||= RubyJard::Decorators::LocDecorator.new
|
76
92
|
end
|
77
93
|
|
78
94
|
def source_lineno(index)
|