ratatui_ruby 0.3.1 → 0.4.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/.builds/ruby-3.2.yml +14 -12
- data/.builds/ruby-3.3.yml +14 -12
- data/.builds/ruby-3.4.yml +14 -12
- data/.builds/ruby-4.0.0.yml +14 -12
- data/AGENTS.md +54 -13
- data/CHANGELOG.md +186 -1
- data/README.md +17 -15
- data/doc/application_architecture.md +116 -0
- data/doc/application_testing.md +12 -7
- data/doc/contributors/better_dx.md +543 -0
- data/doc/contributors/design/ruby_frontend.md +1 -1
- data/doc/contributors/developing_examples.md +203 -0
- data/doc/contributors/documentation_style.md +97 -0
- data/doc/contributors/dwim_dx.md +366 -0
- data/doc/contributors/example_analysis.md +82 -0
- data/doc/custom.css +14 -0
- data/doc/event_handling.md +119 -0
- data/doc/images/all_events.png +0 -0
- data/doc/images/analytics.png +0 -0
- data/doc/images/block_padding.png +0 -0
- data/doc/images/block_titles.png +0 -0
- data/doc/images/box_demo.png +0 -0
- data/doc/images/calendar_demo.png +0 -0
- data/doc/images/cell_demo.png +0 -0
- data/doc/images/chart_demo.png +0 -0
- data/doc/images/custom_widget.png +0 -0
- data/doc/images/flex_layout.png +0 -0
- data/doc/images/gauge_demo.png +0 -0
- data/doc/images/hit_test.png +0 -0
- data/doc/images/line_gauge_demo.png +0 -0
- data/doc/images/list_demo.png +0 -0
- data/doc/images/list_styles.png +0 -0
- data/doc/images/login_form.png +0 -0
- data/doc/images/map_demo.png +0 -0
- data/doc/images/mouse_events.png +0 -0
- data/doc/images/popup_demo.png +0 -0
- data/doc/images/quickstart_dsl.png +0 -0
- data/doc/images/quickstart_lifecycle.png +0 -0
- data/doc/images/ratatui_logo_demo.png +0 -0
- data/doc/images/readme_usage.png +0 -0
- data/doc/images/rich_text.png +0 -0
- data/doc/images/scroll_text.png +0 -0
- data/doc/images/scrollbar_demo.png +0 -0
- data/doc/images/sparkline_demo.png +0 -0
- data/doc/images/table_flex.png +0 -0
- data/doc/images/table_select.png +0 -0
- data/doc/images/widget_style_colors.png +0 -0
- data/doc/index.md +1 -0
- data/doc/interactive_design.md +121 -0
- data/doc/quickstart.md +147 -72
- data/examples/all_events/app.rb +169 -0
- data/examples/all_events/app.rbs +7 -0
- data/examples/all_events/test_app.rb +139 -0
- data/examples/analytics/app.rb +258 -0
- data/examples/analytics/app.rbs +7 -0
- data/examples/analytics/test_app.rb +132 -0
- data/examples/block_padding/app.rb +63 -0
- data/examples/block_padding/app.rbs +7 -0
- data/examples/block_padding/test_app.rb +31 -0
- data/examples/block_titles/app.rb +61 -0
- data/examples/block_titles/app.rbs +7 -0
- data/examples/block_titles/test_app.rb +34 -0
- data/examples/box_demo/app.rb +216 -0
- data/examples/box_demo/app.rbs +7 -0
- data/examples/box_demo/test_app.rb +88 -0
- data/examples/calendar_demo/app.rb +101 -0
- data/examples/calendar_demo/app.rbs +7 -0
- data/examples/calendar_demo/test_app.rb +108 -0
- data/examples/cell_demo/app.rb +108 -0
- data/examples/cell_demo/app.rbs +7 -0
- data/examples/cell_demo/test_app.rb +36 -0
- data/examples/chart_demo/app.rb +203 -0
- data/examples/chart_demo/app.rbs +7 -0
- data/examples/chart_demo/test_app.rb +102 -0
- data/examples/custom_widget/app.rb +51 -0
- data/examples/custom_widget/app.rbs +7 -0
- data/examples/custom_widget/test_app.rb +30 -0
- data/examples/flex_layout/app.rb +156 -0
- data/examples/flex_layout/app.rbs +7 -0
- data/examples/flex_layout/test_app.rb +65 -0
- data/examples/gauge_demo/app.rb +182 -0
- data/examples/gauge_demo/app.rbs +7 -0
- data/examples/gauge_demo/test_app.rb +120 -0
- data/examples/hit_test/app.rb +175 -0
- data/examples/hit_test/app.rbs +7 -0
- data/examples/hit_test/test_app.rb +102 -0
- data/examples/line_gauge_demo/app.rb +190 -0
- data/examples/line_gauge_demo/app.rbs +7 -0
- data/examples/line_gauge_demo/test_app.rb +129 -0
- data/examples/list_demo/app.rb +253 -0
- data/examples/list_demo/app.rbs +12 -0
- data/examples/list_demo/test_app.rb +237 -0
- data/examples/list_styles/app.rb +140 -0
- data/examples/list_styles/app.rbs +7 -0
- data/examples/list_styles/test_app.rb +157 -0
- data/examples/{login_form.rb → login_form/app.rb} +12 -16
- data/examples/login_form/app.rbs +7 -0
- data/examples/login_form/test_app.rb +51 -0
- data/examples/map_demo/app.rb +90 -0
- data/examples/map_demo/app.rbs +7 -0
- data/examples/map_demo/test_app.rb +149 -0
- data/examples/{mouse_events.rb → mouse_events/app.rb} +29 -27
- data/examples/mouse_events/app.rbs +7 -0
- data/examples/mouse_events/test_app.rb +53 -0
- data/examples/{popup_demo.rb → popup_demo/app.rb} +15 -17
- data/examples/popup_demo/app.rbs +7 -0
- data/examples/{test_popup_demo.rb → popup_demo/test_app.rb} +18 -26
- data/examples/quickstart_dsl/app.rb +36 -0
- data/examples/quickstart_dsl/app.rbs +7 -0
- data/examples/quickstart_dsl/test_app.rb +29 -0
- data/examples/quickstart_lifecycle/app.rb +39 -0
- data/examples/quickstart_lifecycle/app.rbs +7 -0
- data/examples/quickstart_lifecycle/test_app.rb +29 -0
- data/examples/ratatui_logo_demo/app.rb +79 -0
- data/examples/ratatui_logo_demo/app.rbs +7 -0
- data/examples/ratatui_logo_demo/test_app.rb +51 -0
- data/examples/ratatui_mascot_demo/app.rb +84 -0
- data/examples/ratatui_mascot_demo/app.rbs +7 -0
- data/examples/ratatui_mascot_demo/test_app.rb +47 -0
- data/examples/readme_usage/app.rb +29 -0
- data/examples/readme_usage/app.rbs +7 -0
- data/examples/readme_usage/test_app.rb +29 -0
- data/examples/rich_text/app.rb +141 -0
- data/examples/rich_text/app.rbs +7 -0
- data/examples/rich_text/test_app.rb +166 -0
- data/examples/scroll_text/app.rb +103 -0
- data/examples/scroll_text/app.rbs +7 -0
- data/examples/scroll_text/test_app.rb +110 -0
- data/examples/scrollbar_demo/app.rb +143 -0
- data/examples/scrollbar_demo/app.rbs +7 -0
- data/examples/scrollbar_demo/test_app.rb +77 -0
- data/examples/sparkline_demo/app.rb +240 -0
- data/examples/sparkline_demo/app.rbs +10 -0
- data/examples/sparkline_demo/test_app.rb +107 -0
- data/examples/table_flex/app.rb +65 -0
- data/examples/table_flex/app.rbs +7 -0
- data/examples/table_flex/test_app.rb +36 -0
- data/examples/table_select/app.rb +198 -0
- data/examples/table_select/app.rbs +7 -0
- data/examples/table_select/test_app.rb +180 -0
- data/examples/widget_style_colors/app.rb +104 -0
- data/examples/widget_style_colors/app.rbs +14 -0
- data/examples/widget_style_colors/test_app.rb +48 -0
- data/ext/ratatui_ruby/Cargo.lock +889 -115
- data/ext/ratatui_ruby/Cargo.toml +4 -3
- data/ext/ratatui_ruby/clippy.toml +7 -0
- data/ext/ratatui_ruby/extconf.rb +7 -0
- data/ext/ratatui_ruby/src/events.rs +218 -229
- data/ext/ratatui_ruby/src/lib.rs +38 -10
- data/ext/ratatui_ruby/src/rendering.rs +90 -10
- data/ext/ratatui_ruby/src/style.rs +281 -98
- data/ext/ratatui_ruby/src/terminal.rs +119 -25
- data/ext/ratatui_ruby/src/text.rs +171 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +97 -24
- data/ext/ratatui_ruby/src/widgets/block.rs +31 -3
- data/ext/ratatui_ruby/src/widgets/calendar.rs +45 -44
- data/ext/ratatui_ruby/src/widgets/canvas.rs +46 -29
- data/ext/ratatui_ruby/src/widgets/chart.rs +69 -27
- data/ext/ratatui_ruby/src/widgets/clear.rs +3 -1
- data/ext/ratatui_ruby/src/widgets/gauge.rs +11 -4
- data/ext/ratatui_ruby/src/widgets/layout.rs +218 -15
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +92 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +91 -11
- data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +3 -2
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +35 -13
- data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +29 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +44 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +59 -7
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +70 -6
- data/ext/ratatui_ruby/src/widgets/table.rs +173 -64
- data/ext/ratatui_ruby/src/widgets/tabs.rs +105 -5
- data/lib/ratatui_ruby/cell.rb +166 -0
- data/lib/ratatui_ruby/event/focus_gained.rb +49 -0
- data/lib/ratatui_ruby/event/focus_lost.rb +50 -0
- data/lib/ratatui_ruby/event/key.rb +211 -0
- data/lib/ratatui_ruby/event/mouse.rb +124 -0
- data/lib/ratatui_ruby/event/paste.rb +71 -0
- data/lib/ratatui_ruby/event/resize.rb +80 -0
- data/lib/ratatui_ruby/event.rb +79 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +45 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +27 -0
- data/lib/ratatui_ruby/schema/bar_chart.rb +228 -19
- data/lib/ratatui_ruby/schema/block.rb +186 -14
- data/lib/ratatui_ruby/schema/calendar.rb +74 -17
- data/lib/ratatui_ruby/schema/canvas.rb +215 -48
- data/lib/ratatui_ruby/schema/center.rb +49 -11
- data/lib/ratatui_ruby/schema/chart.rb +151 -41
- data/lib/ratatui_ruby/schema/clear.rb +41 -72
- data/lib/ratatui_ruby/schema/constraint.rb +82 -22
- data/lib/ratatui_ruby/schema/cursor.rb +27 -9
- data/lib/ratatui_ruby/schema/draw.rb +53 -0
- data/lib/ratatui_ruby/schema/gauge.rb +59 -15
- data/lib/ratatui_ruby/schema/layout.rb +95 -13
- data/lib/ratatui_ruby/schema/line_gauge.rb +78 -0
- data/lib/ratatui_ruby/schema/list.rb +93 -19
- data/lib/ratatui_ruby/schema/overlay.rb +34 -8
- data/lib/ratatui_ruby/schema/paragraph.rb +87 -30
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +25 -0
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +29 -0
- data/lib/ratatui_ruby/schema/rect.rb +64 -15
- data/lib/ratatui_ruby/schema/scrollbar.rb +132 -24
- data/lib/ratatui_ruby/schema/shape/label.rb +66 -0
- data/lib/ratatui_ruby/schema/sparkline.rb +122 -15
- data/lib/ratatui_ruby/schema/style.rb +49 -21
- data/lib/ratatui_ruby/schema/table.rb +119 -21
- data/lib/ratatui_ruby/schema/tabs.rb +75 -13
- data/lib/ratatui_ruby/schema/text.rb +90 -0
- data/lib/ratatui_ruby/session.rb +146 -0
- data/lib/ratatui_ruby/test_helper.rb +156 -13
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby.rb +143 -23
- data/sig/ratatui_ruby/event.rbs +69 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +2 -1
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +16 -0
- data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +13 -0
- data/sig/ratatui_ruby/schema/bar_chart.rbs +20 -2
- data/sig/ratatui_ruby/schema/block.rbs +5 -4
- data/sig/ratatui_ruby/schema/calendar.rbs +6 -2
- data/sig/ratatui_ruby/schema/canvas.rbs +52 -39
- data/sig/ratatui_ruby/schema/center.rbs +3 -3
- data/sig/ratatui_ruby/schema/chart.rbs +8 -5
- data/sig/ratatui_ruby/schema/constraint.rbs +8 -5
- data/sig/ratatui_ruby/schema/cursor.rbs +1 -1
- data/sig/ratatui_ruby/schema/draw.rbs +23 -0
- data/sig/ratatui_ruby/schema/gauge.rbs +4 -2
- data/sig/ratatui_ruby/schema/layout.rbs +11 -1
- data/sig/ratatui_ruby/schema/line_gauge.rbs +16 -0
- data/sig/ratatui_ruby/schema/list.rbs +5 -1
- data/sig/ratatui_ruby/schema/paragraph.rbs +4 -1
- data/{lib/ratatui_ruby/output.rb → sig/ratatui_ruby/schema/ratatui_logo.rbs} +3 -2
- data/sig/ratatui_ruby/{buffer.rbs → schema/ratatui_mascot.rbs} +4 -3
- data/sig/ratatui_ruby/schema/rect.rbs +2 -1
- data/sig/ratatui_ruby/schema/scrollbar.rbs +18 -2
- data/sig/ratatui_ruby/schema/sparkline.rbs +6 -2
- data/sig/ratatui_ruby/schema/table.rbs +8 -1
- data/sig/ratatui_ruby/schema/tabs.rbs +5 -1
- data/sig/ratatui_ruby/schema/text.rbs +22 -0
- data/tasks/resources/build.yml.erb +13 -11
- data/tasks/terminal_preview/app_screenshot.rb +35 -0
- data/tasks/terminal_preview/crash_report.rb +54 -0
- data/tasks/terminal_preview/example_app.rb +25 -0
- data/tasks/terminal_preview/launcher_script.rb +48 -0
- data/tasks/terminal_preview/preview_collection.rb +60 -0
- data/tasks/terminal_preview/preview_timing.rb +22 -0
- data/tasks/terminal_preview/safety_confirmation.rb +58 -0
- data/tasks/terminal_preview/saved_screenshot.rb +55 -0
- data/tasks/terminal_preview/system_appearance.rb +11 -0
- data/tasks/terminal_preview/terminal_window.rb +138 -0
- data/tasks/terminal_preview/window_id.rb +14 -0
- data/tasks/terminal_preview.rake +28 -0
- data/tasks/test.rake +1 -1
- metadata +174 -53
- data/doc/images/examples-analytics.rb.png +0 -0
- data/doc/images/examples-box_demo.rb.png +0 -0
- data/doc/images/examples-calendar_demo.rb.png +0 -0
- data/doc/images/examples-chart_demo.rb.png +0 -0
- data/doc/images/examples-custom_widget.rb.png +0 -0
- data/doc/images/examples-dashboard.rb.png +0 -0
- data/doc/images/examples-list_styles.rb.png +0 -0
- data/doc/images/examples-login_form.rb.png +0 -0
- data/doc/images/examples-map_demo.rb.png +0 -0
- data/doc/images/examples-mouse_events.rb.png +0 -0
- data/doc/images/examples-popup_demo.rb.gif +0 -0
- data/doc/images/examples-quickstart_lifecycle.rb.png +0 -0
- data/doc/images/examples-scroll_text.rb.png +0 -0
- data/doc/images/examples-scrollbar_demo.rb.png +0 -0
- data/doc/images/examples-stock_ticker.rb.png +0 -0
- data/doc/images/examples-system_monitor.rb.png +0 -0
- data/doc/images/examples-table_select.rb.png +0 -0
- data/examples/analytics.rb +0 -88
- data/examples/box_demo.rb +0 -71
- data/examples/calendar_demo.rb +0 -55
- data/examples/chart_demo.rb +0 -84
- data/examples/custom_widget.rb +0 -43
- data/examples/dashboard.rb +0 -72
- data/examples/list_styles.rb +0 -66
- data/examples/map_demo.rb +0 -58
- data/examples/quickstart_dsl.rb +0 -30
- data/examples/quickstart_lifecycle.rb +0 -40
- data/examples/readme_usage.rb +0 -21
- data/examples/scroll_text.rb +0 -74
- data/examples/scrollbar_demo.rb +0 -75
- data/examples/stock_ticker.rb +0 -93
- data/examples/system_monitor.rb +0 -94
- data/examples/table_select.rb +0 -70
- data/examples/test_analytics.rb +0 -65
- data/examples/test_box_demo.rb +0 -38
- data/examples/test_calendar_demo.rb +0 -66
- data/examples/test_dashboard.rb +0 -38
- data/examples/test_list_styles.rb +0 -61
- data/examples/test_login_form.rb +0 -63
- data/examples/test_map_demo.rb +0 -100
- data/examples/test_scroll_text.rb +0 -130
- data/examples/test_stock_ticker.rb +0 -39
- data/examples/test_system_monitor.rb +0 -40
- data/examples/test_table_select.rb +0 -37
- data/ext/ratatui_ruby/src/buffer.rs +0 -54
- data/lib/ratatui_ruby/dsl.rb +0 -64
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
|
|
9
|
+
class BoxDemoApp
|
|
10
|
+
def initialize
|
|
11
|
+
# Border Types (ratatui native styles)
|
|
12
|
+
@border_types = [
|
|
13
|
+
{ name: "Plain", type: :plain },
|
|
14
|
+
{ name: "Rounded", type: :rounded },
|
|
15
|
+
{ name: "Double", type: :double },
|
|
16
|
+
{ name: "Thick", type: :thick },
|
|
17
|
+
{ name: "Quadrant Inside", type: :quadrant_inside },
|
|
18
|
+
{ name: "Quadrant Outside", type: :quadrant_outside }
|
|
19
|
+
]
|
|
20
|
+
@border_type_index = 0
|
|
21
|
+
|
|
22
|
+
# Custom Border Sets
|
|
23
|
+
# NOTE: We define these ONCE in initialize for efficiency.
|
|
24
|
+
@border_sets = [
|
|
25
|
+
{ name: "None", set: nil },
|
|
26
|
+
{ name: "Digits (Short)", set: {
|
|
27
|
+
tl: "1", tr: "2", bl: "3", br: "4",
|
|
28
|
+
vl: "5", vr: "6", ht: "7", hb: "8"
|
|
29
|
+
}},
|
|
30
|
+
{ name: "Letters (Long)", set: {
|
|
31
|
+
top_left: "A", top_right: "B", bottom_left: "C", bottom_right: "D",
|
|
32
|
+
vertical_left: "E", vertical_right: "F", horizontal_top: "G", horizontal_bottom: "H"
|
|
33
|
+
}}
|
|
34
|
+
]
|
|
35
|
+
@border_set_index = 0
|
|
36
|
+
|
|
37
|
+
@colors = [
|
|
38
|
+
{ name: "Green", color: "green" },
|
|
39
|
+
{ name: "Red", color: "red" },
|
|
40
|
+
{ name: "Blue", color: "blue" },
|
|
41
|
+
{ name: "Yellow", color: "yellow" },
|
|
42
|
+
{ name: "Magenta", color: "magenta" }
|
|
43
|
+
]
|
|
44
|
+
@color_index = 0
|
|
45
|
+
|
|
46
|
+
@title_alignments = [
|
|
47
|
+
{ name: "Left", alignment: :left },
|
|
48
|
+
{ name: "Center", alignment: :center },
|
|
49
|
+
{ name: "Right", alignment: :right }
|
|
50
|
+
]
|
|
51
|
+
@title_alignment_index = 0
|
|
52
|
+
|
|
53
|
+
@styles = [
|
|
54
|
+
{ name: "Default", style: nil },
|
|
55
|
+
{ name: "Blue on White", style: { fg: "blue", bg: "white", modifiers: [:bold] } }
|
|
56
|
+
]
|
|
57
|
+
@style_index = 0
|
|
58
|
+
|
|
59
|
+
@title_styles = [
|
|
60
|
+
{ name: "Default", style: nil },
|
|
61
|
+
{ name: "Yellow Bold Underlined", style: { fg: "yellow", modifiers: [:bold, :underlined] } }
|
|
62
|
+
]
|
|
63
|
+
@title_style_index = 0
|
|
64
|
+
|
|
65
|
+
@border_styles = [
|
|
66
|
+
{ name: "Default (no border style)", style: nil },
|
|
67
|
+
{ name: "Bold Red", style: { fg: "red", modifiers: [:bold] } },
|
|
68
|
+
{ name: "Cyan Italic", style: { fg: "cyan", modifiers: [:italic] } },
|
|
69
|
+
{ name: "Magenta Dim", style: { fg: "magenta", modifiers: [:dim] } }
|
|
70
|
+
]
|
|
71
|
+
@border_style_index = 0
|
|
72
|
+
|
|
73
|
+
@hotkey_style = RatatuiRuby::Style.new(modifiers: [:bold, :underlined])
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def run
|
|
77
|
+
RatatuiRuby.run do
|
|
78
|
+
loop do
|
|
79
|
+
render
|
|
80
|
+
break if handle_input == :quit
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def render
|
|
88
|
+
# Get current values
|
|
89
|
+
border_type_config = @border_types[@border_type_index]
|
|
90
|
+
border_set_config = @border_sets[@border_set_index]
|
|
91
|
+
|
|
92
|
+
color_config = @colors[@color_index]
|
|
93
|
+
title_alignment_config = @title_alignments[@title_alignment_index]
|
|
94
|
+
style_config = @styles[@style_index]
|
|
95
|
+
title_style_config = @title_styles[@title_style_index]
|
|
96
|
+
border_style_config = @border_styles[@border_style_index]
|
|
97
|
+
|
|
98
|
+
# 1. State/View
|
|
99
|
+
# Use border_style if provided, otherwise fall back to border_color
|
|
100
|
+
effective_border_style = border_style_config[:style]
|
|
101
|
+
effective_border_color = effective_border_style ? nil : (style_config[:style] ? nil : color_config[:color])
|
|
102
|
+
|
|
103
|
+
# Show overridden status if border_set is active
|
|
104
|
+
type_display = border_type_config[:name]
|
|
105
|
+
if border_set_config[:set]
|
|
106
|
+
type_display += " (Overridden)"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
block = RatatuiRuby::Block.new(
|
|
110
|
+
title: "Box Demo",
|
|
111
|
+
title_alignment: title_alignment_config[:alignment],
|
|
112
|
+
title_style: title_style_config[:style],
|
|
113
|
+
borders: [:all],
|
|
114
|
+
border_color: effective_border_color,
|
|
115
|
+
border_style: effective_border_style,
|
|
116
|
+
border_type: border_type_config[:type],
|
|
117
|
+
border_set: border_set_config[:set],
|
|
118
|
+
style: style_config[:style]
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Main content
|
|
122
|
+
main_panel = RatatuiRuby::Paragraph.new(
|
|
123
|
+
text: "Arrow Keys: Change Color\n\nCurrent Color: #{color_config[:name]}",
|
|
124
|
+
block: block,
|
|
125
|
+
fg: style_config[:style] ? nil : color_config[:color],
|
|
126
|
+
style: style_config[:style],
|
|
127
|
+
alignment: :center
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Bottom control panel
|
|
131
|
+
control_panel = RatatuiRuby::Block.new(
|
|
132
|
+
title: "Controls",
|
|
133
|
+
borders: [:all],
|
|
134
|
+
children: [
|
|
135
|
+
RatatuiRuby::Paragraph.new(
|
|
136
|
+
text: [
|
|
137
|
+
# Line 1: Main Controls
|
|
138
|
+
RatatuiRuby::Text::Line.new(spans: [
|
|
139
|
+
RatatuiRuby::Text::Span.new(content: "↑↓←→", style: @hotkey_style),
|
|
140
|
+
RatatuiRuby::Text::Span.new(content: ": Color (#{color_config[:name]}) "),
|
|
141
|
+
RatatuiRuby::Text::Span.new(content: "q", style: @hotkey_style),
|
|
142
|
+
RatatuiRuby::Text::Span.new(content: ": Quit")
|
|
143
|
+
]),
|
|
144
|
+
# Line 2: Borders
|
|
145
|
+
RatatuiRuby::Text::Line.new(spans: [
|
|
146
|
+
RatatuiRuby::Text::Span.new(content: "space", style: @hotkey_style),
|
|
147
|
+
RatatuiRuby::Text::Span.new(content: ": Border Type (#{type_display}) "),
|
|
148
|
+
RatatuiRuby::Text::Span.new(content: "c", style: @hotkey_style),
|
|
149
|
+
RatatuiRuby::Text::Span.new(content: ": Border Set (#{border_set_config[:name]})")
|
|
150
|
+
]),
|
|
151
|
+
# Line 3: Styles
|
|
152
|
+
RatatuiRuby::Text::Line.new(spans: [
|
|
153
|
+
RatatuiRuby::Text::Span.new(content: "s", style: @hotkey_style),
|
|
154
|
+
RatatuiRuby::Text::Span.new(content: ": Style (#{style_config[:name]}) "),
|
|
155
|
+
RatatuiRuby::Text::Span.new(content: "b", style: @hotkey_style),
|
|
156
|
+
RatatuiRuby::Text::Span.new(content: ": Border Style (#{border_style_config[:name]})")
|
|
157
|
+
]),
|
|
158
|
+
# Line 4: Title
|
|
159
|
+
RatatuiRuby::Text::Line.new(spans: [
|
|
160
|
+
RatatuiRuby::Text::Span.new(content: "enter", style: @hotkey_style),
|
|
161
|
+
RatatuiRuby::Text::Span.new(content: ": Align Title (#{title_alignment_config[:name]}) "),
|
|
162
|
+
RatatuiRuby::Text::Span.new(content: "t", style: @hotkey_style),
|
|
163
|
+
RatatuiRuby::Text::Span.new(content: ": Title Style (#{title_style_config[:name]})")
|
|
164
|
+
])
|
|
165
|
+
]
|
|
166
|
+
)
|
|
167
|
+
]
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Vertical Layout
|
|
171
|
+
layout = RatatuiRuby::Layout.new(
|
|
172
|
+
direction: :vertical,
|
|
173
|
+
constraints: [
|
|
174
|
+
RatatuiRuby::Constraint.fill(1),
|
|
175
|
+
RatatuiRuby::Constraint.length(6),
|
|
176
|
+
],
|
|
177
|
+
children: [main_panel, control_panel]
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# 2. Render
|
|
181
|
+
RatatuiRuby.draw(layout)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def handle_input
|
|
185
|
+
# 3. Events
|
|
186
|
+
case RatatuiRuby.poll_event
|
|
187
|
+
in {type: :key, code: "q"} | {type: :key, code: "c", modifiers: ["ctrl"]}
|
|
188
|
+
:quit
|
|
189
|
+
in type: :key, code: "up"
|
|
190
|
+
@color_index = (@color_index - 1) % @colors.size
|
|
191
|
+
in type: :key, code: "down"
|
|
192
|
+
@color_index = (@color_index + 1) % @colors.size
|
|
193
|
+
in type: :key, code: "left"
|
|
194
|
+
@color_index = (@color_index - 1) % @colors.size
|
|
195
|
+
in type: :key, code: "right"
|
|
196
|
+
@color_index = (@color_index + 1) % @colors.size
|
|
197
|
+
in type: :key, code: " "
|
|
198
|
+
@border_type_index = (@border_type_index + 1) % @border_types.size
|
|
199
|
+
in type: :key, code: "c"
|
|
200
|
+
@border_set_index = (@border_set_index + 1) % @border_sets.size
|
|
201
|
+
in type: :key, code: "enter"
|
|
202
|
+
@title_alignment_index = (@title_alignment_index + 1) % @title_alignments.size
|
|
203
|
+
in type: :key, code: "s"
|
|
204
|
+
@style_index = (@style_index + 1) % @styles.size
|
|
205
|
+
in type: :key, code: "t"
|
|
206
|
+
@title_style_index = (@title_style_index + 1) % @title_styles.size
|
|
207
|
+
in type: :key, code: "b"
|
|
208
|
+
@border_style_index = (@border_style_index + 1) % @border_styles.size
|
|
209
|
+
else
|
|
210
|
+
nil
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
BoxDemoApp.new.run if __FILE__ == $0
|
|
216
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
require "ratatui_ruby/test_helper"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
require_relative "app"
|
|
11
|
+
|
|
12
|
+
class TestBoxDemo < Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
|
|
15
|
+
def setup
|
|
16
|
+
@app = BoxDemoApp.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_render_initial_state
|
|
20
|
+
with_test_terminal do
|
|
21
|
+
inject_key(:q)
|
|
22
|
+
@app.run
|
|
23
|
+
|
|
24
|
+
assert buffer_content.any? { |line| line.include?("Box Demo") }
|
|
25
|
+
assert buffer_content.any? { |line| line.include?("Controls") }
|
|
26
|
+
assert buffer_content.any? { |line| line.include?("Green") }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_color_cycling_changes_color
|
|
31
|
+
with_test_terminal do
|
|
32
|
+
# Pressing up should cycle colors backwards
|
|
33
|
+
inject_keys(:up, :q)
|
|
34
|
+
@app.run
|
|
35
|
+
|
|
36
|
+
# At least the Controls section should be rendered
|
|
37
|
+
assert buffer_content.any? { |line| line.include?("Controls") }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_border_type_cycling
|
|
42
|
+
with_test_terminal do
|
|
43
|
+
inject_keys(" ", :q)
|
|
44
|
+
@app.run
|
|
45
|
+
|
|
46
|
+
assert buffer_content.any? { |line| line.include?("Rounded") }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def test_title_alignment_cycling
|
|
51
|
+
with_test_terminal do
|
|
52
|
+
inject_keys(:enter, :q)
|
|
53
|
+
@app.run
|
|
54
|
+
|
|
55
|
+
assert buffer_content.any? { |line| line.include?("Center") }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_content_style_changes
|
|
60
|
+
with_test_terminal do
|
|
61
|
+
inject_keys(:s, :q)
|
|
62
|
+
@app.run
|
|
63
|
+
|
|
64
|
+
# At least the Controls section should be rendered
|
|
65
|
+
assert buffer_content.any? { |line| line.include?("Controls") }
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_title_style_changes
|
|
70
|
+
with_test_terminal do
|
|
71
|
+
inject_keys(:t, :q)
|
|
72
|
+
@app.run
|
|
73
|
+
|
|
74
|
+
# At least the Controls section should be rendered
|
|
75
|
+
assert buffer_content.any? { |line| line.include?("Controls") }
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_border_style_cycling
|
|
80
|
+
with_test_terminal do
|
|
81
|
+
inject_keys(:b, :q)
|
|
82
|
+
@app.run
|
|
83
|
+
|
|
84
|
+
# At least the Controls section should be rendered
|
|
85
|
+
assert buffer_content.any? { |line| line.include?("Controls") }
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
|
|
9
|
+
# A demo application for the Calendar widget.
|
|
10
|
+
class CalendarDemoApp
|
|
11
|
+
def run
|
|
12
|
+
RatatuiRuby.run do
|
|
13
|
+
show_header = true
|
|
14
|
+
show_weekdays = true
|
|
15
|
+
show_surrounding = false
|
|
16
|
+
show_events = true
|
|
17
|
+
|
|
18
|
+
loop do
|
|
19
|
+
now = Time.now
|
|
20
|
+
surrounding_style = if show_surrounding
|
|
21
|
+
RatatuiRuby::Style.new(fg: "gray", modifiers: [:dim])
|
|
22
|
+
else
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
events_map = if show_events
|
|
27
|
+
{
|
|
28
|
+
now => RatatuiRuby::Style.new(fg: "green", modifiers: [:bold]),
|
|
29
|
+
(now + 86400 * 2) => RatatuiRuby::Style.new(fg: "red", modifiers: [:underlined]),
|
|
30
|
+
(now - 86400 * 5) => RatatuiRuby::Style.new(fg: "blue", bg: "white"),
|
|
31
|
+
}
|
|
32
|
+
else
|
|
33
|
+
{}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
calendar = RatatuiRuby::Calendar.new(
|
|
37
|
+
year: now.year,
|
|
38
|
+
month: now.month,
|
|
39
|
+
events: events_map,
|
|
40
|
+
header_style: RatatuiRuby::Style.new(fg: "yellow", modifiers: [:bold]),
|
|
41
|
+
show_month_header: show_header,
|
|
42
|
+
show_weekdays_header: show_weekdays,
|
|
43
|
+
show_surrounding: surrounding_style,
|
|
44
|
+
block: RatatuiRuby::Block.new(borders: [:top, :left, :right])
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
controls_text = [
|
|
48
|
+
RatatuiRuby::Text::Line.new(
|
|
49
|
+
spans: [
|
|
50
|
+
RatatuiRuby::Text::Span.new(content: " h/w/s/e", style: RatatuiRuby::Style.new(modifiers: [:bold])),
|
|
51
|
+
RatatuiRuby::Text::Span.new(content: ": Toggle Header/Weekdays/Surrounding/Events "),
|
|
52
|
+
RatatuiRuby::Text::Span.new(content: "q", style: RatatuiRuby::Style.new(modifiers: [:bold])),
|
|
53
|
+
RatatuiRuby::Text::Span.new(content: ": Quit"),
|
|
54
|
+
]
|
|
55
|
+
),
|
|
56
|
+
RatatuiRuby::Text::Line.new(
|
|
57
|
+
spans: [
|
|
58
|
+
RatatuiRuby::Text::Span.new(content: " Events: ", style: RatatuiRuby::Style.new(modifiers: [:bold])),
|
|
59
|
+
RatatuiRuby::Text::Span.new(content: "Today (Green), +2d (Red), -5d (Blue) (#{show_events ? "On" : "Off"})"),
|
|
60
|
+
]
|
|
61
|
+
)
|
|
62
|
+
]
|
|
63
|
+
controls = RatatuiRuby::Paragraph.new(
|
|
64
|
+
text: controls_text,
|
|
65
|
+
block: RatatuiRuby::Block.new(title: " Controls ", borders: [:all])
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
RatatuiRuby.draw(
|
|
69
|
+
RatatuiRuby::Layout.new(
|
|
70
|
+
direction: :vertical,
|
|
71
|
+
constraints: [
|
|
72
|
+
RatatuiRuby::Constraint.min(0),
|
|
73
|
+
RatatuiRuby::Constraint.length(4),
|
|
74
|
+
],
|
|
75
|
+
children: [calendar, controls]
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
event = RatatuiRuby.poll_event
|
|
80
|
+
case event
|
|
81
|
+
in {type: :key, code: "q"} | {type: :key, code: "c", modifiers: ["ctrl"]}
|
|
82
|
+
break
|
|
83
|
+
in type: :key, code: "h"
|
|
84
|
+
show_header = !show_header
|
|
85
|
+
in type: :key, code: "w"
|
|
86
|
+
show_weekdays = !show_weekdays
|
|
87
|
+
in type: :key, code: "s"
|
|
88
|
+
show_surrounding = !show_surrounding
|
|
89
|
+
in type: :key, code: "e"
|
|
90
|
+
show_events = !show_events
|
|
91
|
+
else
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
sleep 0.05
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
CalendarDemoApp.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
7
|
+
require "minitest/autorun"
|
|
8
|
+
require "ratatui_ruby"
|
|
9
|
+
require "ratatui_ruby/test_helper"
|
|
10
|
+
require_relative "app"
|
|
11
|
+
|
|
12
|
+
class TestCalendarDemoApp < Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
|
|
15
|
+
def setup
|
|
16
|
+
@app = CalendarDemoApp.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_demo_renders
|
|
20
|
+
with_test_terminal do
|
|
21
|
+
inject_keys(:down, :down, :q)
|
|
22
|
+
|
|
23
|
+
@app.run
|
|
24
|
+
|
|
25
|
+
content = buffer_content
|
|
26
|
+
rendered_text = content.join("\n")
|
|
27
|
+
|
|
28
|
+
# Verify the bottom controls are present
|
|
29
|
+
assert_match(/h\/w\/s\/e: Toggle Header\/Weekdays\/Surrounding\/Events/, rendered_text)
|
|
30
|
+
assert_match(/q: Quit/, rendered_text)
|
|
31
|
+
|
|
32
|
+
# Verify the calendar content is present
|
|
33
|
+
assert_match(/#{Time.now.year}/, rendered_text)
|
|
34
|
+
|
|
35
|
+
# Verify layout structure (calendar taking up most space, controls at bottom)
|
|
36
|
+
# The controls are on the last line (index 23 for 24 lines) if the terminal is 24 lines high
|
|
37
|
+
# but standard terminal might be different. with_test_terminal defaults to 80x24.
|
|
38
|
+
# assert_match(/q: Quit/, content[23]) if content[23]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_toggle_weekdays_header
|
|
43
|
+
with_test_terminal do
|
|
44
|
+
inject_keys("w", :q)
|
|
45
|
+
|
|
46
|
+
@app.run
|
|
47
|
+
|
|
48
|
+
content = buffer_content
|
|
49
|
+
rendered_text = content.join("\n")
|
|
50
|
+
|
|
51
|
+
# The app should render successfully with weekdays toggled
|
|
52
|
+
assert_match(/#{Time.now.year}/, rendered_text)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_toggle_header
|
|
57
|
+
with_test_terminal do
|
|
58
|
+
inject_keys("h", :q)
|
|
59
|
+
|
|
60
|
+
@app.run
|
|
61
|
+
|
|
62
|
+
content = buffer_content
|
|
63
|
+
rendered_text = content.join("\n")
|
|
64
|
+
|
|
65
|
+
# The app should render successfully with header toggled (hidden)
|
|
66
|
+
refute_match(/#{Time.now.year}/, rendered_text)
|
|
67
|
+
|
|
68
|
+
# Inject h again to show it (h -> off, h -> on)
|
|
69
|
+
inject_keys("h", "h", :q)
|
|
70
|
+
@app.run
|
|
71
|
+
content = buffer_content
|
|
72
|
+
rendered_text = content.join("\n")
|
|
73
|
+
assert_match(/#{Time.now.year}/, rendered_text)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_toggle_surrounding
|
|
78
|
+
with_test_terminal do
|
|
79
|
+
inject_keys("s", :q)
|
|
80
|
+
|
|
81
|
+
@app.run
|
|
82
|
+
|
|
83
|
+
content = buffer_content
|
|
84
|
+
rendered_text = content.join("\n")
|
|
85
|
+
|
|
86
|
+
# The app should render successfully with surrounding toggled
|
|
87
|
+
assert_match(/#{Time.now.year}/, rendered_text)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_events_render
|
|
92
|
+
with_test_terminal do
|
|
93
|
+
inject_keys("e", :q)
|
|
94
|
+
|
|
95
|
+
@app.run
|
|
96
|
+
|
|
97
|
+
content = buffer_content
|
|
98
|
+
# We just check that the app runs without crashing and renders the calendar.
|
|
99
|
+
# Verifying specific color codes in the buffer content is harder without
|
|
100
|
+
# exposing the underlying buffer cells' style.
|
|
101
|
+
# But we can at least assert the content is still correct.
|
|
102
|
+
assert_match(/#{Time.now.year}/, content.join("\n"))
|
|
103
|
+
|
|
104
|
+
# Verify the legend is present and shows Off status after toggle
|
|
105
|
+
assert_match(/Events: .* \(Off\)/, content.join("\n"))
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
4
|
+
require "ratatui_ruby"
|
|
5
|
+
|
|
6
|
+
# A custom widget that fills its area with a checkered pattern using Cell objects.
|
|
7
|
+
class CheckeredBackground
|
|
8
|
+
def render(area)
|
|
9
|
+
cell = RatatuiRuby::Cell.new(char: "░", fg: :dark_gray)
|
|
10
|
+
commands = []
|
|
11
|
+
area.height.times do |y|
|
|
12
|
+
area.width.times do |x|
|
|
13
|
+
# Checkerboard logic
|
|
14
|
+
if (x + y).even?
|
|
15
|
+
# Use a dim cell for the background pattern
|
|
16
|
+
commands << RatatuiRuby::Draw.cell(area.x + x, area.y + y, cell)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
commands
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class CellDemoApp
|
|
25
|
+
def main
|
|
26
|
+
RatatuiRuby.run do |tui|
|
|
27
|
+
# Define some reusable cells for our table
|
|
28
|
+
ok_cell = RatatuiRuby::Cell.new(char: "OK", fg: :green)
|
|
29
|
+
fail_cell = RatatuiRuby::Cell.new(char: "FAIL", fg: :red, modifiers: ["bold"])
|
|
30
|
+
pending_cell = RatatuiRuby::Cell.new(char: "...", fg: :yellow, modifiers: ["dim"])
|
|
31
|
+
|
|
32
|
+
# A mix of Strings and Cells in rows
|
|
33
|
+
rows = [
|
|
34
|
+
["Database", ok_cell],
|
|
35
|
+
["Cache", ok_cell],
|
|
36
|
+
["Worker", fail_cell],
|
|
37
|
+
["Analytics", pending_cell],
|
|
38
|
+
["Web Server", RatatuiRuby::Cell.new(char: "RESTARTING", fg: :blue, modifiers: ["rapid_blink"])]
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
table = RatatuiRuby::Table.new(
|
|
42
|
+
header: ["Service", RatatuiRuby::Cell.new(char: "Status", modifiers: ["underlined"])],
|
|
43
|
+
rows: rows,
|
|
44
|
+
widths: [
|
|
45
|
+
RatatuiRuby::Constraint.percentage(70),
|
|
46
|
+
RatatuiRuby::Constraint.percentage(30)
|
|
47
|
+
],
|
|
48
|
+
block: RatatuiRuby::Block.new(title: "System Status", borders: :all),
|
|
49
|
+
column_spacing: 1
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Main loop
|
|
53
|
+
loop do
|
|
54
|
+
# Create a layout that holds both widgets
|
|
55
|
+
# We use a vertical layout:
|
|
56
|
+
# Top: Custom CheckeredBackground with specific height
|
|
57
|
+
# Bottom: Table using remaining space
|
|
58
|
+
|
|
59
|
+
# Note: CheckeredBackground renders to the area implicitly if passed as a child.
|
|
60
|
+
# However, to overlay the paragraph, we might need a more complex structure or
|
|
61
|
+
# wrapper. RatatuiRuby::Layout handles non-overlapping children.
|
|
62
|
+
# To get the "Overlay" effect from my previous code (Paragraph over Background),
|
|
63
|
+
# we would need to composite them. For now, let's just show them stacked or
|
|
64
|
+
# using 'Overlay' widget if it exists.
|
|
65
|
+
|
|
66
|
+
# Checking schema: Overlay exists? Yes: require_relative "ratatui_ruby/schema/overlay" in lib/ratatui_ruby.rb
|
|
67
|
+
|
|
68
|
+
layout = RatatuiRuby::Layout.new(
|
|
69
|
+
direction: :vertical,
|
|
70
|
+
constraints: [
|
|
71
|
+
RatatuiRuby::Constraint.length(10), # Top section
|
|
72
|
+
RatatuiRuby::Constraint.min(0) # Bottom section
|
|
73
|
+
],
|
|
74
|
+
children: [
|
|
75
|
+
# Top Child: An Overlay of Paragraph on top of CheckeredBackground
|
|
76
|
+
RatatuiRuby::Overlay.new(
|
|
77
|
+
layers: [
|
|
78
|
+
CheckeredBackground.new,
|
|
79
|
+
RatatuiRuby::Center.new(
|
|
80
|
+
width_percent: 50,
|
|
81
|
+
height_percent: 50,
|
|
82
|
+
child: RatatuiRuby::Paragraph.new(
|
|
83
|
+
text: "Custom Widget Demo\n(CheckeredBackground)",
|
|
84
|
+
alignment: :center,
|
|
85
|
+
block: RatatuiRuby::Block.new(borders: :all, title: "Overlay")
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
]
|
|
89
|
+
),
|
|
90
|
+
# Bottom Child: The Table
|
|
91
|
+
table
|
|
92
|
+
]
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
tui.draw(layout)
|
|
96
|
+
|
|
97
|
+
event = RatatuiRuby.poll_event
|
|
98
|
+
if event.is_a?(RatatuiRuby::Event::Key)
|
|
99
|
+
break if event.code == "q" || (event.code == "c" && event.modifiers.include?("ctrl"))
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
if __FILE__ == $0
|
|
107
|
+
CellDemoApp.new.main
|
|
108
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require "minitest/autorun"
|
|
2
|
+
require "ratatui_ruby"
|
|
3
|
+
require "ratatui_ruby/test_helper"
|
|
4
|
+
require_relative "app"
|
|
5
|
+
|
|
6
|
+
class TestCellDemoApp < Minitest::Test
|
|
7
|
+
include RatatuiRuby::TestHelper
|
|
8
|
+
|
|
9
|
+
include RatatuiRuby::TestHelper
|
|
10
|
+
|
|
11
|
+
def test_cell_demo_output
|
|
12
|
+
# Run the demo in a test terminal
|
|
13
|
+
# We'll inject a 'q' key to exit the loop immediately after the first draw
|
|
14
|
+
with_test_terminal(timeout: 5) do
|
|
15
|
+
inject_key("q")
|
|
16
|
+
CellDemoApp.new.main
|
|
17
|
+
|
|
18
|
+
# Verify Custom Widget Output
|
|
19
|
+
# Check for "░" character from CheckeredBackground
|
|
20
|
+
# It should be visible around the centered widget
|
|
21
|
+
assert_includes buffer_content.join("\n"), "░"
|
|
22
|
+
|
|
23
|
+
# Verify Table Output
|
|
24
|
+
# Content strings
|
|
25
|
+
assert_includes buffer_content.join("\n"), "System Status"
|
|
26
|
+
assert_includes buffer_content.join("\n"), "Database"
|
|
27
|
+
assert_includes buffer_content.join("\n"), "Worker"
|
|
28
|
+
|
|
29
|
+
# We can't easily grep for "FAIL" with color in simple string content check,
|
|
30
|
+
# but we can check the text presence.
|
|
31
|
+
assert_includes buffer_content.join("\n"), "FAIL"
|
|
32
|
+
assert_includes buffer_content.join("\n"), "OK"
|
|
33
|
+
assert_includes buffer_content.join("\n"), "RESTARTING"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|