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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/CHANGELOG.md +18 -0
  4. data/CNAME +1 -0
  5. data/README.md +206 -33
  6. data/_config.yml +1 -0
  7. data/docs/_config.yml +8 -0
  8. data/docs/demo.png +0 -0
  9. data/docs/index.md +238 -0
  10. data/docs/logo.jpg +0 -0
  11. data/docs/screen-backtrace.png +0 -0
  12. data/docs/screen-repl.png +0 -0
  13. data/docs/screen-source.png +0 -0
  14. data/docs/screen-threads.png +0 -0
  15. data/docs/screen-variables.png +0 -0
  16. data/images/bg_hr.png +0 -0
  17. data/images/blacktocat.png +0 -0
  18. data/images/body-bg.jpg +0 -0
  19. data/images/download-button.png +0 -0
  20. data/images/github-button.png +0 -0
  21. data/images/header-bg.jpg +0 -0
  22. data/images/highlight-bg.jpg +0 -0
  23. data/images/icon_download.png +0 -0
  24. data/images/sidebar-bg.jpg +0 -0
  25. data/images/sprite_download.png +0 -0
  26. data/javascripts/main.js +1 -0
  27. data/lib/ruby_jard.rb +3 -18
  28. data/lib/ruby_jard/box_drawer.rb +68 -22
  29. data/lib/ruby_jard/color_scheme.rb +28 -0
  30. data/lib/ruby_jard/color_schemes.rb +26 -0
  31. data/lib/ruby_jard/color_schemes/256_color_scheme.rb +64 -0
  32. data/lib/ruby_jard/color_schemes/deep_space_color_scheme.rb +63 -0
  33. data/lib/ruby_jard/column.rb +12 -6
  34. data/lib/ruby_jard/commands/continue_command.rb +1 -0
  35. data/lib/ruby_jard/commands/list_command.rb +29 -0
  36. data/lib/ruby_jard/commands/next_command.rb +1 -0
  37. data/lib/ruby_jard/commands/step_command.rb +1 -0
  38. data/lib/ruby_jard/commands/step_out_command.rb +1 -0
  39. data/lib/ruby_jard/console.rb +102 -18
  40. data/lib/ruby_jard/control_flow.rb +9 -8
  41. data/lib/ruby_jard/decorators/color_decorator.rb +46 -57
  42. data/lib/ruby_jard/decorators/inspection_decorator.rb +76 -0
  43. data/lib/ruby_jard/decorators/loc_decorator.rb +83 -107
  44. data/lib/ruby_jard/decorators/source_decorator.rb +1 -1
  45. data/lib/ruby_jard/keys.rb +1 -0
  46. data/lib/ruby_jard/layout.rb +9 -99
  47. data/lib/ruby_jard/layout_calculator.rb +151 -0
  48. data/lib/ruby_jard/layouts/narrow_layout.rb +41 -0
  49. data/lib/ruby_jard/layouts/wide_layout.rb +17 -103
  50. data/lib/ruby_jard/repl_processor.rb +5 -1
  51. data/lib/ruby_jard/repl_proxy.rb +2 -1
  52. data/lib/ruby_jard/row.rb +5 -5
  53. data/lib/ruby_jard/row_renderer.rb +108 -0
  54. data/lib/ruby_jard/screen.rb +20 -115
  55. data/lib/ruby_jard/screen_drawer.rb +8 -75
  56. data/lib/ruby_jard/screen_manager.rb +78 -55
  57. data/lib/ruby_jard/screen_renderer.rb +138 -0
  58. data/lib/ruby_jard/screens/backtrace_screen.rb +67 -69
  59. data/lib/ruby_jard/screens/menu_screen.rb +43 -38
  60. data/lib/ruby_jard/screens/source_screen.rb +43 -27
  61. data/lib/ruby_jard/screens/threads_screen.rb +91 -39
  62. data/lib/ruby_jard/screens/variables_screen.rb +72 -56
  63. data/lib/ruby_jard/session.rb +16 -0
  64. data/lib/ruby_jard/span.rb +8 -6
  65. data/lib/ruby_jard/version.rb +1 -1
  66. data/ruby_jard.gemspec +4 -4
  67. data/stylesheets/github-light.css +130 -0
  68. data/stylesheets/normalize.css +424 -0
  69. data/stylesheets/print.css +228 -0
  70. data/stylesheets/stylesheet.css +245 -0
  71. metadata +52 -21
  72. data/lib/ruby_jard/templates/column_template.rb +0 -17
  73. data/lib/ruby_jard/templates/row_template.rb +0 -22
  74. data/lib/ruby_jard/templates/space_template.rb +0 -15
  75. 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
@@ -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
- STDIN.getch(min: 0, time: KEYPRESS_POLLING)
84
+ RubyJard::Console.getch(STDIN, KEYPRESS_POLLING)
84
85
  end
85
86
 
86
87
  def repl(current_binding)
@@ -4,13 +4,13 @@ module RubyJard
4
4
  class Row
5
5
  extend Forwardable
6
6
 
7
- attr_accessor :row_template, :columns
7
+ attr_accessor :columns, :line_limit, :content
8
8
 
9
- def_delegators :@row_template, :line_limit
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
@@ -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 :output, :rows, :width, :height, :x, :y
9
+ attr_accessor :layout, :rows, :color_scheme, :window, :cursor, :selected
10
10
 
11
- def initialize(screen_template:, session: nil, width:, height:, x:, y:)
11
+ def initialize(session: nil, layout:, color_scheme:)
12
12
  @session = session || RubyJard.current_session
13
- @screen_template = screen_template
14
- @width = width
15
- @height = height
16
- @x = x
17
- @y = y
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
- row_template = @screen_template.row_template
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
- private
22
+ def move_down; end
50
23
 
51
- def calculate_column_widths(row_template, rows)
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 fill_column_widths(rows, column_widths)
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
- rows.each do |row|
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 create_row(row_template, data_row, index)
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 create_column(column_template, data_row, index)
100
- column = Column.new(column_template: column_template)
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 create_span(span_template, data_row, index)
112
- span = Span.new(span_template: span_template)
113
- span_content_method = "span_#{span_template.name}".to_sym
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
- span
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
- attr_reader :output
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
- @original_x = @x
23
- @screen.rows.each do |row|
24
- draw_columns(row, row.columns)
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
- end
29
-
30
- private
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
- require 'ruby_jard/screens'
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/row'
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.hard_clear_screen(@output)
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!(@output)
90
- RubyJard::Console.echo!(@output)
91
- RubyJard::Console.show_cursor(@output)
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.hide_cursor(@output)
106
- clear_screen
113
+ RubyJard::Console.disable_cursor!
107
114
  width, height = RubyJard::Console.screen_size(@output)
108
- screen_layouts = calculate_layouts(width, height)
109
- draw_screens(screen_layouts)
110
- jump_to_prompt(screen_layouts)
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!(@output)
118
- RubyJard::Console.echo!(@output)
119
- RubyJard::Console.show_cursor(@output)
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(height - 5)
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::Layout.calculate(
143
- layout: layout,
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(screen_layouts)
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
- screen.draw(@output)
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 jump_to_prompt(screen_layouts)
173
- prompt_y = screen_layouts.map { |_template, _width, screen_height, _x, y| y + screen_height }.max
174
- RubyJard::Console.move_to(@output, 0, prompt_y)
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