ruby_jard 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -120,7 +120,7 @@ module RubyJard
|
|
120
120
|
# Do nothing
|
121
121
|
end
|
122
122
|
|
123
|
-
def handle_key_binding_command(options)
|
123
|
+
def handle_key_binding_command(options = {})
|
124
124
|
method_name = "handle_#{options[:action]}_command"
|
125
125
|
if respond_to?(method_name, true)
|
126
126
|
send(method_name)
|
@@ -129,5 +129,9 @@ module RubyJard
|
|
129
129
|
"Fail to handle key binding `#{options[:action]}`"
|
130
130
|
end
|
131
131
|
end
|
132
|
+
|
133
|
+
def handle_list_command(_options = {})
|
134
|
+
process_commands
|
135
|
+
end
|
132
136
|
end
|
133
137
|
end
|
data/lib/ruby_jard/repl_proxy.rb
CHANGED
@@ -7,6 +7,7 @@ require 'ruby_jard/commands/next_command'
|
|
7
7
|
require 'ruby_jard/commands/step_command'
|
8
8
|
require 'ruby_jard/commands/step_out_command'
|
9
9
|
require 'ruby_jard/commands/frame_command'
|
10
|
+
require 'ruby_jard/commands/list_command'
|
10
11
|
|
11
12
|
module RubyJard
|
12
13
|
##
|
@@ -80,7 +81,7 @@ module RubyJard
|
|
80
81
|
end
|
81
82
|
|
82
83
|
def read_key
|
83
|
-
|
84
|
+
RubyJard::Console.getch(STDIN, KEYPRESS_POLLING)
|
84
85
|
end
|
85
86
|
|
86
87
|
def repl(current_binding)
|
data/lib/ruby_jard/row.rb
CHANGED
@@ -4,13 +4,13 @@ module RubyJard
|
|
4
4
|
class Row
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
attr_accessor :
|
7
|
+
attr_accessor :columns, :line_limit, :content
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(row_template:, columns: [])
|
12
|
-
@row_template = row_template
|
9
|
+
def initialize(line_limit: 1, columns: [], ellipsis: true)
|
10
|
+
@content = []
|
13
11
|
@columns = columns
|
12
|
+
@ellipsis = ellipsis
|
13
|
+
@line_limit = line_limit
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
##
|
5
|
+
# Generate bitmap lines from a row's data
|
6
|
+
class RowRenderer
|
7
|
+
ELLIPSIS = ' »'
|
8
|
+
|
9
|
+
def initialize(row:, width:, height:, color_scheme:)
|
10
|
+
@row = row
|
11
|
+
@width = width
|
12
|
+
@height = height
|
13
|
+
@color_decorator = RubyJard::Decorators::ColorDecorator.new(color_scheme)
|
14
|
+
end
|
15
|
+
|
16
|
+
def render
|
17
|
+
@x = 0
|
18
|
+
@y = 0
|
19
|
+
@content_map = []
|
20
|
+
|
21
|
+
original_x = 0
|
22
|
+
@row.columns.each_with_index do |column, index|
|
23
|
+
@y = 0
|
24
|
+
@x = original_x
|
25
|
+
content_width = column.width
|
26
|
+
content_width -= 1 if index < @row.columns.length - 1
|
27
|
+
render_column(column, original_x, content_width)
|
28
|
+
|
29
|
+
original_x += column.width
|
30
|
+
end
|
31
|
+
|
32
|
+
generate_bitmap
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_column(column, original_x, content_width)
|
36
|
+
width = 0
|
37
|
+
lines = 1
|
38
|
+
|
39
|
+
column.spans.each do |span|
|
40
|
+
line_content = span.content
|
41
|
+
|
42
|
+
until line_content.nil? || line_content.empty?
|
43
|
+
if column.word_wrap == RubyJard::Column::WORD_WRAP_NORMAL
|
44
|
+
if content_width - width < line_content.length && width != 0
|
45
|
+
width = 0
|
46
|
+
lines += 1
|
47
|
+
@y += 1
|
48
|
+
@x = original_x
|
49
|
+
end
|
50
|
+
elsif column.word_wrap == RubyJard::Column::WORD_WRAP_BREAK_WORD
|
51
|
+
if content_width - width <= 0
|
52
|
+
width = 0
|
53
|
+
lines += 1
|
54
|
+
@y += 1
|
55
|
+
@x = original_x
|
56
|
+
end
|
57
|
+
elsif content_width - width <= 0
|
58
|
+
return
|
59
|
+
end
|
60
|
+
drawing_content = line_content[0..content_width - width - 1]
|
61
|
+
line_content = line_content[content_width - width..-1]
|
62
|
+
width += drawing_content.length
|
63
|
+
|
64
|
+
if !@row.line_limit.nil? && lines >= @row.line_limit && !line_content.nil? && !line_content.empty?
|
65
|
+
drawing_content[drawing_content.length - ELLIPSIS.length..-1] = ELLIPSIS
|
66
|
+
draw_content(drawing_content, span.styles)
|
67
|
+
return
|
68
|
+
else
|
69
|
+
draw_content(drawing_content, span.styles)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def draw_content(drawing_content, styles)
|
76
|
+
return if @y < 0 || @y >= @height
|
77
|
+
|
78
|
+
@content_map[@y] ||= []
|
79
|
+
@content_map[@y][@x] = [styles, drawing_content]
|
80
|
+
@x += drawing_content.length
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate_bitmap
|
84
|
+
@row.content = []
|
85
|
+
@content_map.each do |line|
|
86
|
+
line_content = ''
|
87
|
+
pending_content = ''
|
88
|
+
|
89
|
+
cell_index = 0
|
90
|
+
while cell_index < @width
|
91
|
+
cell = line[cell_index]
|
92
|
+
if cell.nil? || cell[1].empty?
|
93
|
+
pending_content += ' '
|
94
|
+
cell_index += 1
|
95
|
+
else
|
96
|
+
line_content += @color_decorator.decorate(:background, pending_content)
|
97
|
+
line_content += @color_decorator.decorate(cell[0], cell[1])
|
98
|
+
pending_content = ''
|
99
|
+
cell_index += cell[1].length
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
line_content += @color_decorator.decorate(:background, pending_content) unless pending_content.empty?
|
104
|
+
@row.content << line_content
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/ruby_jard/screen.rb
CHANGED
@@ -6,134 +6,39 @@ module RubyJard
|
|
6
6
|
# generated based on input layout specifiation, screen data, and top-left
|
7
7
|
# corner cordination.
|
8
8
|
class Screen
|
9
|
-
attr_accessor :
|
9
|
+
attr_accessor :layout, :rows, :color_scheme, :window, :cursor, :selected
|
10
10
|
|
11
|
-
def initialize(
|
11
|
+
def initialize(session: nil, layout:, color_scheme:)
|
12
12
|
@session = session || RubyJard.current_session
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
18
|
-
end
|
19
|
-
|
20
|
-
def draw(output)
|
21
|
-
calculate
|
22
|
-
drawer = RubyJard::ScreenDrawer.new(
|
23
|
-
output: output,
|
24
|
-
screen: self,
|
25
|
-
x: @x,
|
26
|
-
y: @y
|
27
|
-
)
|
28
|
-
drawer.draw
|
29
|
-
end
|
30
|
-
|
31
|
-
def data_size
|
32
|
-
raise NotImplementedError, "#{self.class} must implement #data_size method"
|
33
|
-
end
|
34
|
-
|
35
|
-
def data_window
|
36
|
-
raise NotImplementedError, "#{self.class} must implement #data_window method"
|
37
|
-
end
|
38
|
-
|
39
|
-
def calculate
|
13
|
+
@layout = layout
|
14
|
+
@color_scheme = color_scheme
|
15
|
+
@window = []
|
16
|
+
@cursor = nil
|
17
|
+
@selected = 0
|
40
18
|
@rows = []
|
41
|
-
|
42
|
-
@rows = data_window.map.with_index do |data_row, index|
|
43
|
-
create_row(row_template, data_row, index)
|
44
|
-
end
|
45
|
-
column_widths = calculate_column_widths(row_template, @rows)
|
46
|
-
fill_column_widths(@rows, column_widths)
|
19
|
+
@need_to_render = true
|
47
20
|
end
|
48
21
|
|
49
|
-
|
22
|
+
def move_down; end
|
50
23
|
|
51
|
-
def
|
52
|
-
column_widths = {}
|
53
|
-
ideal_column_width = @width / row_template.columns.length
|
54
|
-
row_template.columns.each_with_index do |_column_template, column_index|
|
55
|
-
column_widths[column_index] ||= 0
|
56
|
-
rows.each do |row|
|
57
|
-
column = row.columns[column_index]
|
58
|
-
if column.content_length > ideal_column_width
|
59
|
-
column_widths[column_index] = nil
|
60
|
-
break
|
61
|
-
elsif column.content_length > column_widths[column_index]
|
62
|
-
column_widths[column_index] = column.content_length
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
column_widths
|
67
|
-
end
|
24
|
+
def move_up; end
|
68
25
|
|
69
|
-
def
|
70
|
-
fixed_count = column_widths.length
|
71
|
-
fixed_width = column_widths.values.inject(0) do |sum, col|
|
72
|
-
col.nil? ? sum : sum + col
|
73
|
-
end
|
26
|
+
def page_up; end
|
74
27
|
|
75
|
-
|
76
|
-
total_width = 0
|
77
|
-
row.columns.each_with_index do |column, column_index|
|
78
|
-
column.width =
|
79
|
-
if column_index == row.columns.length - 1
|
80
|
-
@width - total_width
|
81
|
-
elsif column_widths[column_index].nil?
|
82
|
-
(@width - fixed_width) / fixed_count
|
83
|
-
else
|
84
|
-
column_widths[column_index]
|
85
|
-
end
|
86
|
-
total_width += column.width
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
28
|
+
def page_down; end
|
90
29
|
|
91
|
-
def
|
92
|
-
row = Row.new(row_template: row_template)
|
93
|
-
row.columns = row_template.columns.map do |column_template|
|
94
|
-
create_column(column_template, data_row, index)
|
95
|
-
end
|
96
|
-
row
|
97
|
-
end
|
30
|
+
def click(relative_x, relative_y); end
|
98
31
|
|
99
|
-
def
|
100
|
-
|
101
|
-
column.spans = column_template.spans.map do |span_template|
|
102
|
-
create_span(span_template, data_row, index)
|
103
|
-
end.flatten
|
104
|
-
column.content_length =
|
105
|
-
column.spans.map(&:content_length).inject(&:+) +
|
106
|
-
column.margin_left +
|
107
|
-
column.margin_right
|
108
|
-
column
|
32
|
+
def build
|
33
|
+
raise NotImplementedError, "#{self.class} should implement this method."
|
109
34
|
end
|
110
35
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
if respond_to?(span_content_method)
|
116
|
-
content, styles = send(span_content_method, data_row, index)
|
117
|
-
if content.nil?
|
118
|
-
span.content = ''
|
119
|
-
span.content_length = 0
|
120
|
-
elsif content.is_a?(Array)
|
121
|
-
content.each do |sub_span|
|
122
|
-
sub_span.styles += Array(styles).flatten.compact
|
123
|
-
end
|
124
|
-
return content
|
125
|
-
else
|
126
|
-
content = ' ' * span_template.margin_left + content if span_template.margin_left
|
127
|
-
content += ' ' * span_template.margin_right if span_template.margin_right
|
128
|
-
span.content = content
|
129
|
-
span.styles = Array(styles).flatten.compact
|
130
|
-
span.content_length = span.content.length
|
131
|
-
end
|
132
|
-
else
|
133
|
-
raise NotImplementedError, "#{self.class} must implement #{span_content_method} method"
|
134
|
-
end
|
36
|
+
def need_to_render?
|
37
|
+
@need_to_render == true
|
38
|
+
end
|
135
39
|
|
136
|
-
|
40
|
+
def mark_rendered!
|
41
|
+
@need_to_render = false
|
137
42
|
end
|
138
43
|
end
|
139
44
|
end
|
@@ -1,89 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RubyJard
|
4
|
-
##
|
5
|
-
# Draw a screen and its rows into the output interface.
|
6
4
|
class ScreenDrawer
|
7
|
-
|
8
|
-
|
9
|
-
ELLIPSIS = ' »'
|
10
|
-
|
11
|
-
def initialize(output:, screen:, x:, y:)
|
5
|
+
def initialize(output:, screen:, color_scheme:)
|
12
6
|
@output = output
|
13
|
-
@color_decorator = RubyJard::Decorators::ColorDecorator.new
|
14
|
-
@x = x
|
15
|
-
@y = y
|
16
|
-
@original_x = x
|
17
|
-
@original_y = y
|
18
7
|
@screen = screen
|
8
|
+
@color_decorator = RubyJard::Decorators::ColorDecorator.new(color_scheme)
|
19
9
|
end
|
20
10
|
|
21
11
|
def draw
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
@y += 1
|
26
|
-
@x = @original_x
|
12
|
+
@screen.window.each_with_index do |line, index|
|
13
|
+
RubyJard::Console.move_to(@output, @screen.layout.x, @screen.layout.y + index)
|
14
|
+
@output.print line
|
27
15
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
def draw_columns(row, columns)
|
33
|
-
columns.each do |column|
|
34
|
-
width = 0
|
35
|
-
lines = 1
|
36
|
-
column_content_width = column.width - column.margin_left - column.margin_right
|
37
|
-
@x += column.margin_left
|
38
|
-
RubyJard::Console.move_to(@output, @x, @y)
|
39
|
-
|
40
|
-
column.spans.each do |span|
|
41
|
-
line_content = span.content
|
42
|
-
|
43
|
-
until line_content.nil? || line_content.empty?
|
44
|
-
if column_content_width - width <= 0
|
45
|
-
width = 0
|
46
|
-
lines += 1
|
47
|
-
@y += 1
|
48
|
-
RubyJard::Console.move_to(@output, @x, @y)
|
49
|
-
end
|
50
|
-
drawing_content = line_content[0..column_content_width - width - 1]
|
51
|
-
line_content = line_content[column_content_width - width..-1]
|
52
|
-
width += drawing_content.length
|
53
|
-
|
54
|
-
if !row.line_limit.nil? && lines >= row.line_limit && !line_content.nil? && !line_content.empty?
|
55
|
-
drawing_content[drawing_content.length - ELLIPSIS.length..-1] = ELLIPSIS
|
56
|
-
protected_print @color_decorator.decorate(drawing_content, *span.styles)
|
57
|
-
break
|
58
|
-
else
|
59
|
-
protected_print @color_decorator.decorate(drawing_content, *span.styles)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
@x += column_content_width + column.margin_right
|
16
|
+
(@screen.window.length..@screen.layout.height - 1).each do |index|
|
17
|
+
RubyJard::Console.move_to(@output, @screen.layout.x, @screen.layout.y + index)
|
18
|
+
@output.print @color_decorator.decorate(:background, ' ' * @screen.layout.width)
|
64
19
|
end
|
65
20
|
end
|
66
|
-
|
67
|
-
def protected_print(content)
|
68
|
-
# TODO: currently, only row overflow is detected. Definitely should handle column overflow
|
69
|
-
return if @y < @original_y || @y > @original_y + @screen.height - 1
|
70
|
-
|
71
|
-
@output.print content
|
72
|
-
end
|
73
|
-
|
74
|
-
def default_frame_styles
|
75
|
-
{
|
76
|
-
style: {
|
77
|
-
fg: :white
|
78
|
-
},
|
79
|
-
border: {
|
80
|
-
bottom_left: false,
|
81
|
-
bottom_right: false,
|
82
|
-
bottom: false,
|
83
|
-
left: :line,
|
84
|
-
right: false
|
85
|
-
}
|
86
|
-
}
|
87
|
-
end
|
88
21
|
end
|
89
22
|
end
|
@@ -6,11 +6,24 @@ require 'ruby_jard/decorators/color_decorator'
|
|
6
6
|
require 'ruby_jard/decorators/path_decorator'
|
7
7
|
require 'ruby_jard/decorators/loc_decorator'
|
8
8
|
require 'ruby_jard/decorators/source_decorator'
|
9
|
+
require 'ruby_jard/decorators/inspection_decorator'
|
9
10
|
|
10
11
|
require 'ruby_jard/screen'
|
12
|
+
require 'ruby_jard/screens'
|
13
|
+
|
14
|
+
require 'ruby_jard/color_scheme'
|
15
|
+
require 'ruby_jard/color_schemes'
|
16
|
+
require 'ruby_jard/color_schemes/deep_space_color_scheme'
|
17
|
+
require 'ruby_jard/color_schemes/256_color_scheme'
|
18
|
+
|
19
|
+
require 'ruby_jard/row'
|
20
|
+
require 'ruby_jard/column'
|
21
|
+
require 'ruby_jard/span'
|
22
|
+
require 'ruby_jard/row_renderer'
|
23
|
+
require 'ruby_jard/screen_renderer'
|
11
24
|
require 'ruby_jard/box_drawer'
|
12
25
|
require 'ruby_jard/screen_drawer'
|
13
|
-
|
26
|
+
|
14
27
|
require 'ruby_jard/screens/source_screen'
|
15
28
|
require 'ruby_jard/screens/backtrace_screen'
|
16
29
|
require 'ruby_jard/screens/threads_screen'
|
@@ -19,16 +32,11 @@ require 'ruby_jard/screens/menu_screen'
|
|
19
32
|
|
20
33
|
require 'ruby_jard/templates/layout_template'
|
21
34
|
require 'ruby_jard/templates/screen_template'
|
22
|
-
require 'ruby_jard/templates/row_template'
|
23
|
-
require 'ruby_jard/templates/column_template'
|
24
|
-
require 'ruby_jard/templates/span_template'
|
25
|
-
require 'ruby_jard/templates/space_template'
|
26
35
|
|
27
36
|
require 'ruby_jard/layouts/wide_layout'
|
37
|
+
require 'ruby_jard/layouts/narrow_layout'
|
28
38
|
require 'ruby_jard/layout'
|
29
|
-
require 'ruby_jard/
|
30
|
-
require 'ruby_jard/column'
|
31
|
-
require 'ruby_jard/span'
|
39
|
+
require 'ruby_jard/layout_calculator'
|
32
40
|
|
33
41
|
module RubyJard
|
34
42
|
##
|
@@ -59,7 +67,7 @@ module RubyJard
|
|
59
67
|
return if started?
|
60
68
|
|
61
69
|
RubyJard::Console.start_alternative_terminal(@output)
|
62
|
-
RubyJard::Console.
|
70
|
+
RubyJard::Console.clear_screen(@output)
|
63
71
|
|
64
72
|
def $stdout.write(string)
|
65
73
|
if !RubyJard::ScreenManager.updating? && RubyJard::ScreenManager.started?
|
@@ -86,9 +94,9 @@ module RubyJard
|
|
86
94
|
@started = false
|
87
95
|
|
88
96
|
RubyJard::Console.stop_alternative_terminal(@output)
|
89
|
-
RubyJard::Console.cooked!
|
90
|
-
RubyJard::Console.
|
91
|
-
RubyJard::Console.
|
97
|
+
RubyJard::Console.cooked!
|
98
|
+
RubyJard::Console.enable_echo!
|
99
|
+
RubyJard::Console.enable_cursor!
|
92
100
|
|
93
101
|
unless @output_storage.string.empty?
|
94
102
|
@output.puts ''
|
@@ -102,25 +110,35 @@ module RubyJard
|
|
102
110
|
start unless started?
|
103
111
|
@updating = true
|
104
112
|
|
105
|
-
RubyJard::Console.
|
106
|
-
clear_screen
|
113
|
+
RubyJard::Console.disable_cursor!
|
107
114
|
width, height = RubyJard::Console.screen_size(@output)
|
108
|
-
|
109
|
-
|
110
|
-
|
115
|
+
|
116
|
+
@layouts = calculate_layouts(width, height)
|
117
|
+
@screens = build_screens(@layouts)
|
118
|
+
draw_box(@screens)
|
119
|
+
draw_screens(@screens)
|
120
|
+
|
121
|
+
RubyJard::Console.move_to(@output, 0, total_screen_height(@layouts) + 1)
|
122
|
+
RubyJard::Console.clear_screen_to_end(@output)
|
123
|
+
|
111
124
|
draw_debug(width, height)
|
112
125
|
rescue StandardError => e
|
113
|
-
clear_screen
|
126
|
+
RubyJard::Console.clear_screen(@output)
|
114
127
|
draw_error(e, height)
|
115
128
|
ensure
|
116
129
|
# You don't want to mess up previous user TTY no matter happens
|
117
|
-
RubyJard::Console.cooked!
|
118
|
-
RubyJard::Console.
|
119
|
-
RubyJard::Console.
|
130
|
+
RubyJard::Console.cooked!
|
131
|
+
RubyJard::Console.enable_echo!
|
132
|
+
RubyJard::Console.enable_cursor!
|
120
133
|
@updating = false
|
121
134
|
end
|
122
135
|
|
136
|
+
def scroll; end
|
137
|
+
|
138
|
+
def click; end
|
139
|
+
|
123
140
|
def draw_error(exception, height = 0)
|
141
|
+
@output.print RubyJard::Decorators::ColorDecorator::CSI_RESET
|
124
142
|
@output.puts '--- Error ---'
|
125
143
|
@output.puts "Internal error from Jard. I'm sorry to mess up your debugging experience."
|
126
144
|
@output.puts 'It would be great if you can submit an issue in https://github.com/nguyenquangminh0711/ruby_jard/issues'
|
@@ -129,52 +147,62 @@ module RubyJard
|
|
129
147
|
if height == 0
|
130
148
|
@output.puts exception.backtrace
|
131
149
|
else
|
132
|
-
@output.puts exception.backtrace.first(
|
150
|
+
@output.puts exception.backtrace.first(10)
|
133
151
|
end
|
134
152
|
@output.puts '-------------'
|
135
153
|
end
|
136
154
|
|
137
|
-
|
138
155
|
private
|
139
156
|
|
140
157
|
def calculate_layouts(width, height)
|
141
158
|
layout = pick_layout(width, height)
|
142
|
-
RubyJard::
|
143
|
-
|
159
|
+
RubyJard::LayoutCalculator.calculate(
|
160
|
+
layout_template: layout,
|
144
161
|
width: width, height: height,
|
145
162
|
x: 0, y: 0
|
146
163
|
)
|
147
164
|
end
|
148
165
|
|
166
|
+
def build_screens(layouts)
|
167
|
+
layouts.map do |layout|
|
168
|
+
screen_class = fetch_screen(layout.template.screen)
|
169
|
+
screen = screen_class.new(
|
170
|
+
layout: layout,
|
171
|
+
color_scheme: pick_color_scheme
|
172
|
+
)
|
173
|
+
screen.build
|
174
|
+
render_screen(screen)
|
175
|
+
screen
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
149
179
|
def draw_box(screens)
|
150
180
|
RubyJard::BoxDrawer.new(
|
151
181
|
output: @output,
|
152
|
-
screens: screens
|
182
|
+
screens: screens,
|
183
|
+
color_scheme: pick_color_scheme
|
153
184
|
).draw
|
154
185
|
end
|
155
186
|
|
156
|
-
def draw_screens(
|
157
|
-
screens = screen_layouts.map do |screen_template, width, height, x, y|
|
158
|
-
screen = fetch_screen(screen_template.screen)
|
159
|
-
screen&.new(
|
160
|
-
screen_template: screen_template,
|
161
|
-
width: width, height: height,
|
162
|
-
x: x, y: y
|
163
|
-
)
|
164
|
-
end
|
165
|
-
draw_box(screens)
|
166
|
-
adjust_screen_contents(screens)
|
187
|
+
def draw_screens(screens)
|
167
188
|
screens.each do |screen|
|
168
|
-
|
189
|
+
RubyJard::ScreenDrawer.new(
|
190
|
+
output: @output,
|
191
|
+
screen: screen,
|
192
|
+
color_scheme: pick_color_scheme
|
193
|
+
).draw
|
169
194
|
end
|
170
195
|
end
|
171
196
|
|
172
|
-
def
|
173
|
-
|
174
|
-
|
197
|
+
def render_screen(screen)
|
198
|
+
RubyJard::ScreenRenderer.new(
|
199
|
+
screen: screen,
|
200
|
+
color_scheme: pick_color_scheme
|
201
|
+
).render
|
175
202
|
end
|
176
203
|
|
177
204
|
def draw_debug(_width, height)
|
205
|
+
@output.print RubyJard::Decorators::ColorDecorator::CSI_RESET
|
178
206
|
unless RubyJard.debug_info.empty?
|
179
207
|
@output.puts '--- Debug ---'
|
180
208
|
RubyJard.debug_info.first(height - 2).each do |line|
|
@@ -185,24 +213,14 @@ module RubyJard
|
|
185
213
|
RubyJard.clear_debug
|
186
214
|
end
|
187
215
|
|
188
|
-
def adjust_screen_contents(screens)
|
189
|
-
# After drawing the box, screen sizes should be updated to reflect content-only area
|
190
|
-
screens.each do |screen|
|
191
|
-
screen.width -= 2
|
192
|
-
screen.height -= 2
|
193
|
-
screen.x += 1
|
194
|
-
screen.y += 1
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def clear_screen
|
199
|
-
RubyJard::Console.clear_screen(@output)
|
200
|
-
end
|
201
|
-
|
202
216
|
def fetch_screen(name)
|
203
217
|
RubyJard::Screens[name]
|
204
218
|
end
|
205
219
|
|
220
|
+
def total_screen_height(layouts)
|
221
|
+
layouts.map { |layout| layout.y + layout.height }.max
|
222
|
+
end
|
223
|
+
|
206
224
|
def pick_layout(width, height)
|
207
225
|
RubyJard::DEFAULT_LAYOUT_TEMPLATES.each do |template|
|
208
226
|
matched = true
|
@@ -218,5 +236,10 @@ module RubyJard
|
|
218
236
|
end
|
219
237
|
RubyJard::DEFAULT_LAYOUT_TEMPLATES.first
|
220
238
|
end
|
239
|
+
|
240
|
+
def pick_color_scheme
|
241
|
+
# TODO: Fallback to a default color scheme if not found
|
242
|
+
RubyJard::ColorSchemes[RubyJard::DEFAULT_COLOR_SCHEME].new
|
243
|
+
end
|
221
244
|
end
|
222
245
|
end
|