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,258 @@
|
|
|
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
|
+
# Analytics Dashboard Example
|
|
10
|
+
# Demonstrates Tabs and BarChart widgets.
|
|
11
|
+
|
|
12
|
+
class AnalyticsApp
|
|
13
|
+
def initialize
|
|
14
|
+
@selected_tab = 0
|
|
15
|
+
@tabs = ["Revenue", "Traffic", "Errors", "Quarterly"]
|
|
16
|
+
@styles = [
|
|
17
|
+
{ name: "Yellow Bold", style: RatatuiRuby::Style.new(fg: :yellow, modifiers: [:bold]) },
|
|
18
|
+
{ name: "Italic Blue on White", style: RatatuiRuby::Style.new(fg: :blue, bg: :white, modifiers: [:italic]) },
|
|
19
|
+
{ name: "Underlined Red", style: RatatuiRuby::Style.new(fg: :red, modifiers: [:underlined]) },
|
|
20
|
+
{ name: "Reversed", style: RatatuiRuby::Style.new(modifiers: [:reversed]) }
|
|
21
|
+
]
|
|
22
|
+
@style_index = 0
|
|
23
|
+
@divider_index = 0
|
|
24
|
+
@dividers = [" | ", " • ", " > ", " / "]
|
|
25
|
+
@base_styles = [
|
|
26
|
+
{ name: "Default", style: nil },
|
|
27
|
+
{ name: "White on Gray", style: RatatuiRuby::Style.new(fg: :white, bg: :dark_gray) },
|
|
28
|
+
{ name: "White on Blue", style: RatatuiRuby::Style.new(fg: :white, bg: :blue) },
|
|
29
|
+
{ name: "Italic", style: RatatuiRuby::Style.new(modifiers: [:italic]) }
|
|
30
|
+
]
|
|
31
|
+
@base_style_index = 0
|
|
32
|
+
@padding_left = 0
|
|
33
|
+
@padding_right = 0
|
|
34
|
+
@direction = :vertical
|
|
35
|
+
@label_style_index = 0
|
|
36
|
+
@value_style_index = 0
|
|
37
|
+
@bar_sets = [
|
|
38
|
+
{ name: "Default", set: nil },
|
|
39
|
+
{ name: "Numbers (Short)", set: { 8 => "8", 7 => "7", 6 => "6", 5 => "5", 4 => "4", 3 => "3", 2 => "2", 1 => "1", 0 => "0" } },
|
|
40
|
+
{ name: "Letters (Long)", set: { full: "H", seven_eighths: "G", three_quarters: "F", five_eighths: "E", half: "D", three_eighths: "C", one_quarter: "B", one_eighth: "A", empty: " " } },
|
|
41
|
+
{ name: "ASCII (Heights)", set: [" ", "_", ".", "-", "=", "+", "*", "#", "@"] }
|
|
42
|
+
]
|
|
43
|
+
@bar_set_index = 0
|
|
44
|
+
@height_mode = :full # :full or :mini
|
|
45
|
+
@group_gap = 0
|
|
46
|
+
|
|
47
|
+
@hotkey_style = RatatuiRuby::Style.new(modifiers: [:bold, :underlined])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def run
|
|
51
|
+
RatatuiRuby.run do
|
|
52
|
+
loop do
|
|
53
|
+
render
|
|
54
|
+
break if handle_input == :quit
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def render
|
|
62
|
+
# Data for different tabs
|
|
63
|
+
data = case @selected_tab
|
|
64
|
+
when 0 # Revenue
|
|
65
|
+
{
|
|
66
|
+
"Q1" => 50, "Q2" => 80, "Q3" => 45, "Q4" => 60,
|
|
67
|
+
"Q1'" => 55, "Q2'" => 85, "Q3'" => 50, "Q4'" => 65
|
|
68
|
+
}
|
|
69
|
+
when 1 # Traffic
|
|
70
|
+
[
|
|
71
|
+
["Mon", 120], ["Tue", 150], ["Wed", 130], ["Thu", 160],
|
|
72
|
+
["Fri", 140],
|
|
73
|
+
["Sat", 110, RatatuiRuby::Style.new(fg: :red)],
|
|
74
|
+
["Sun", 100, RatatuiRuby::Style.new(fg: :red)]
|
|
75
|
+
]
|
|
76
|
+
when 2 # Errors
|
|
77
|
+
{ DB: 5, UI: 2, API: 8, Auth: 3, Net: 4, "I/O": 1, Mem: 6, CPU: 7 }
|
|
78
|
+
when 3 # Quarterly
|
|
79
|
+
[
|
|
80
|
+
RatatuiRuby::BarChart::BarGroup.new(label: "2024", bars: [
|
|
81
|
+
RatatuiRuby::BarChart::Bar.new(value: 40, label: "Q1"),
|
|
82
|
+
RatatuiRuby::BarChart::Bar.new(value: 45, label: "Q2"),
|
|
83
|
+
RatatuiRuby::BarChart::Bar.new(value: 50, label: "Q3"),
|
|
84
|
+
RatatuiRuby::BarChart::Bar.new(value: 55, label: "Q4")
|
|
85
|
+
]),
|
|
86
|
+
RatatuiRuby::BarChart::BarGroup.new(label: "2025", bars: [
|
|
87
|
+
RatatuiRuby::BarChart::Bar.new(value: 60, label: "Q1", style: RatatuiRuby::Style.new(fg: :yellow)),
|
|
88
|
+
RatatuiRuby::BarChart::Bar.new(value: 65, label: "Q2", style: RatatuiRuby::Style.new(fg: :yellow)),
|
|
89
|
+
RatatuiRuby::BarChart::Bar.new(value: 70, label: "Q3", style: RatatuiRuby::Style.new(fg: :yellow)),
|
|
90
|
+
RatatuiRuby::BarChart::Bar.new(value: 75, label: "Q4", style: RatatuiRuby::Style.new(fg: :yellow))
|
|
91
|
+
])
|
|
92
|
+
]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
bar_style = case @selected_tab
|
|
96
|
+
when 0 then RatatuiRuby::Style.new(fg: "green")
|
|
97
|
+
when 1 then RatatuiRuby::Style.new(fg: "blue")
|
|
98
|
+
when 2 then RatatuiRuby::Style.new(fg: "red")
|
|
99
|
+
when 3 then RatatuiRuby::Style.new(fg: "cyan")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Define the BarChart widget
|
|
103
|
+
bar_chart = RatatuiRuby::BarChart.new(
|
|
104
|
+
data:,
|
|
105
|
+
bar_width: @direction == :vertical ? 8 : 1,
|
|
106
|
+
style: bar_style,
|
|
107
|
+
bar_gap: 1,
|
|
108
|
+
group_gap: @group_gap,
|
|
109
|
+
direction: @direction,
|
|
110
|
+
label_style: @styles[@label_style_index][:style],
|
|
111
|
+
value_style: @styles[@value_style_index][:style],
|
|
112
|
+
bar_set: @bar_sets[@bar_set_index][:set],
|
|
113
|
+
block: RatatuiRuby::Block.new(
|
|
114
|
+
title: "Analytics: #{@tabs[@selected_tab]}",
|
|
115
|
+
borders: [:all]
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Wrap chart in a layout to control height if in mini mode
|
|
120
|
+
chart_area = if @height_mode == :mini
|
|
121
|
+
# Height 3: 1 row content + 2 borders
|
|
122
|
+
RatatuiRuby::Layout.new(
|
|
123
|
+
direction: :vertical,
|
|
124
|
+
constraints: [RatatuiRuby::Constraint.length(3), RatatuiRuby::Constraint.fill(1)],
|
|
125
|
+
children: [bar_chart, RatatuiRuby::Block.new] # Empty block to fill rest
|
|
126
|
+
)
|
|
127
|
+
else
|
|
128
|
+
bar_chart
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Build the UI
|
|
132
|
+
ui = RatatuiRuby::Layout.new(
|
|
133
|
+
direction: :vertical,
|
|
134
|
+
constraints: [
|
|
135
|
+
RatatuiRuby::Constraint.fill(1),
|
|
136
|
+
RatatuiRuby::Constraint.length(6),
|
|
137
|
+
],
|
|
138
|
+
children: [
|
|
139
|
+
# Main Area
|
|
140
|
+
RatatuiRuby::Layout.new(
|
|
141
|
+
direction: :vertical,
|
|
142
|
+
constraints: [
|
|
143
|
+
RatatuiRuby::Constraint.new(type: :length, value: 3),
|
|
144
|
+
RatatuiRuby::Constraint.new(type: :min, value: 0),
|
|
145
|
+
],
|
|
146
|
+
children: [
|
|
147
|
+
tabs = RatatuiRuby::Tabs.new(
|
|
148
|
+
titles: @tabs,
|
|
149
|
+
selected_index: @selected_tab,
|
|
150
|
+
block: RatatuiRuby::Block.new(title: "Views", borders: [:all]),
|
|
151
|
+
divider: @dividers[@divider_index],
|
|
152
|
+
highlight_style: @styles[@style_index][:style],
|
|
153
|
+
style: @base_styles[@base_style_index][:style],
|
|
154
|
+
padding_left: @padding_left,
|
|
155
|
+
padding_right: @padding_right
|
|
156
|
+
),
|
|
157
|
+
chart_area
|
|
158
|
+
]
|
|
159
|
+
),
|
|
160
|
+
# Bottom control panel
|
|
161
|
+
RatatuiRuby::Block.new(
|
|
162
|
+
title: "Controls",
|
|
163
|
+
borders: [:all],
|
|
164
|
+
children: [
|
|
165
|
+
RatatuiRuby::Paragraph.new(
|
|
166
|
+
text: [
|
|
167
|
+
# Line 1: Navigation & General
|
|
168
|
+
RatatuiRuby::Text::Line.new(spans: [
|
|
169
|
+
RatatuiRuby::Text::Span.new(content: "←/→", style: @hotkey_style),
|
|
170
|
+
RatatuiRuby::Text::Span.new(content: ": Navigate Tab "),
|
|
171
|
+
RatatuiRuby::Text::Span.new(content: "v", style: @hotkey_style),
|
|
172
|
+
RatatuiRuby::Text::Span.new(content: ": Direction (#{@direction}) "),
|
|
173
|
+
RatatuiRuby::Text::Span.new(content: "q", style: @hotkey_style),
|
|
174
|
+
RatatuiRuby::Text::Span.new(content: ": Quit")
|
|
175
|
+
]),
|
|
176
|
+
# Line 2: Padding & Divider
|
|
177
|
+
RatatuiRuby::Text::Line.new(spans: [
|
|
178
|
+
RatatuiRuby::Text::Span.new(content: "h/l", style: @hotkey_style),
|
|
179
|
+
RatatuiRuby::Text::Span.new(content: ": Pad Left (#{@padding_left}) "),
|
|
180
|
+
RatatuiRuby::Text::Span.new(content: "j/k", style: @hotkey_style),
|
|
181
|
+
RatatuiRuby::Text::Span.new(content: ": Pad Right (#{@padding_right}) "),
|
|
182
|
+
RatatuiRuby::Text::Span.new(content: "d", style: @hotkey_style),
|
|
183
|
+
RatatuiRuby::Text::Span.new(content: ": Divider (#{@dividers[@divider_index]}) "),
|
|
184
|
+
RatatuiRuby::Text::Span.new(content: "Width: #{tabs.width}")
|
|
185
|
+
]),
|
|
186
|
+
# Line 3: Styles
|
|
187
|
+
RatatuiRuby::Text::Line.new(spans: [
|
|
188
|
+
RatatuiRuby::Text::Span.new(content: "space", style: @hotkey_style),
|
|
189
|
+
RatatuiRuby::Text::Span.new(content: ": Highlight (#{@styles[@style_index][:name]}) "),
|
|
190
|
+
RatatuiRuby::Text::Span.new(content: "x", style: @hotkey_style),
|
|
191
|
+
RatatuiRuby::Text::Span.new(content: ": Label (#{@styles[@label_style_index][:name]}) "),
|
|
192
|
+
RatatuiRuby::Text::Span.new(content: "space", style: @hotkey_style),
|
|
193
|
+
RatatuiRuby::Text::Span.new(content: ": Highlight (#{@styles[@style_index][:name]}) "),
|
|
194
|
+
RatatuiRuby::Text::Span.new(content: "x", style: @hotkey_style),
|
|
195
|
+
RatatuiRuby::Text::Span.new(content: ": Label (#{@styles[@label_style_index][:name]})")
|
|
196
|
+
]),
|
|
197
|
+
# Line 4: More Styles
|
|
198
|
+
RatatuiRuby::Text::Line.new(spans: [
|
|
199
|
+
RatatuiRuby::Text::Span.new(content: "z", style: @hotkey_style),
|
|
200
|
+
RatatuiRuby::Text::Span.new(content: ": Value (#{@styles[@value_style_index][:name]}) "),
|
|
201
|
+
RatatuiRuby::Text::Span.new(content: "b", style: @hotkey_style),
|
|
202
|
+
RatatuiRuby::Text::Span.new(content: ": Bar Set (#{@bar_sets[@bar_set_index][:name]}) "),
|
|
203
|
+
RatatuiRuby::Text::Span.new(content: "m", style: @hotkey_style),
|
|
204
|
+
RatatuiRuby::Text::Span.new(content: ": Mode (#{@height_mode == :full ? 'Full' : 'Mini'}) "),
|
|
205
|
+
RatatuiRuby::Text::Span.new(content: "g", style: @hotkey_style),
|
|
206
|
+
RatatuiRuby::Text::Span.new(content: ": Group Gap (#{@group_gap})")
|
|
207
|
+
])
|
|
208
|
+
]
|
|
209
|
+
)
|
|
210
|
+
]
|
|
211
|
+
)
|
|
212
|
+
]
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
RatatuiRuby.draw(ui)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def handle_input
|
|
219
|
+
case RatatuiRuby.poll_event
|
|
220
|
+
in {type: :key, code: "q"} | {type: :key, code: "c", modifiers: ["ctrl"]}
|
|
221
|
+
:quit
|
|
222
|
+
in type: :key, code: "right"
|
|
223
|
+
@selected_tab = (@selected_tab + 1) % @tabs.size
|
|
224
|
+
in type: :key, code: "left"
|
|
225
|
+
@selected_tab = (@selected_tab - 1) % @tabs.size
|
|
226
|
+
in type: :key, code: " "
|
|
227
|
+
@style_index = (@style_index + 1) % @styles.size
|
|
228
|
+
in type: :key, code: "d"
|
|
229
|
+
@divider_index = (@divider_index + 1) % @dividers.size
|
|
230
|
+
in type: :key, code: "s"
|
|
231
|
+
@base_style_index = (@base_style_index + 1) % @base_styles.size
|
|
232
|
+
in type: :key, code: "h"
|
|
233
|
+
@padding_left = [@padding_left - 1, 0].max
|
|
234
|
+
in type: :key, code: "l"
|
|
235
|
+
@padding_left += 1
|
|
236
|
+
in type: :key, code: "v"
|
|
237
|
+
@direction = @direction == :vertical ? :horizontal : :vertical
|
|
238
|
+
in type: :key, code: "j"
|
|
239
|
+
@padding_right = [@padding_right - 1, 0].max
|
|
240
|
+
in type: :key, code: "k"
|
|
241
|
+
@padding_right += 1
|
|
242
|
+
in type: :key, code: "x"
|
|
243
|
+
@label_style_index = (@label_style_index + 1) % @styles.size
|
|
244
|
+
in type: :key, code: "z"
|
|
245
|
+
@value_style_index = (@value_style_index + 1) % @styles.size
|
|
246
|
+
in type: :key, code: "b"
|
|
247
|
+
@bar_set_index = (@bar_set_index + 1) % @bar_sets.size
|
|
248
|
+
in type: :key, code: "m"
|
|
249
|
+
@height_mode = @height_mode == :full ? :mini : :full
|
|
250
|
+
in type: :key, code: "g"
|
|
251
|
+
@group_gap = (@group_gap + 1) % 4
|
|
252
|
+
else
|
|
253
|
+
# Ignore other events
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
AnalyticsApp.new.run if __FILE__ == $0
|
|
@@ -0,0 +1,132 @@
|
|
|
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 TestAnalytics < Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
|
|
15
|
+
def setup
|
|
16
|
+
@app = AnalyticsApp.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_render_initial_state
|
|
20
|
+
with_test_terminal do
|
|
21
|
+
# Queue quit
|
|
22
|
+
inject_key(:q)
|
|
23
|
+
|
|
24
|
+
@app.run
|
|
25
|
+
|
|
26
|
+
# Check Tabs
|
|
27
|
+
assert buffer_content.any? { |line| line.include?("Revenue") }
|
|
28
|
+
assert buffer_content.any? { |line| line.include?("Traffic") }
|
|
29
|
+
assert buffer_content.any? { |line| line.include?("Errors") }
|
|
30
|
+
|
|
31
|
+
# Check initial selected tab content
|
|
32
|
+
assert buffer_content.any? { |line| line.include?("Analytics: Revenue") }
|
|
33
|
+
|
|
34
|
+
# Check help text visibility (join to handle potential wrapping)
|
|
35
|
+
content_str = buffer_content.join("\n")
|
|
36
|
+
assert_includes content_str, "q: Quit"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_navigation_right
|
|
41
|
+
with_test_terminal do
|
|
42
|
+
inject_keys(:right, :q)
|
|
43
|
+
|
|
44
|
+
@app.run
|
|
45
|
+
|
|
46
|
+
assert buffer_content.any? { |line| line.include?("Analytics: Traffic") }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def test_navigation_left
|
|
51
|
+
with_test_terminal do
|
|
52
|
+
# Move right to Traffic
|
|
53
|
+
inject_keys(:a, :b, :c)
|
|
54
|
+
|
|
55
|
+
# Then queue quit
|
|
56
|
+
inject_key(:q)
|
|
57
|
+
|
|
58
|
+
@app.run
|
|
59
|
+
|
|
60
|
+
assert buffer_content.any? { |line| line.include?("Analytics: Revenue") }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_quit
|
|
65
|
+
with_test_terminal do
|
|
66
|
+
inject_key(:q)
|
|
67
|
+
@app.run
|
|
68
|
+
# Success if returns
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_switch_divider
|
|
73
|
+
with_test_terminal do
|
|
74
|
+
# Switch divider (d) then quit (q)
|
|
75
|
+
inject_keys(:d, :q)
|
|
76
|
+
@app.run
|
|
77
|
+
|
|
78
|
+
# Default is " | ", next is " • "
|
|
79
|
+
assert buffer_content.any? { |line| line.include?(" • ") }
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_switch_style
|
|
84
|
+
with_test_terminal do
|
|
85
|
+
# Switch style (space) then quit (q)
|
|
86
|
+
inject_keys(:" ", :q)
|
|
87
|
+
@app.run
|
|
88
|
+
|
|
89
|
+
# Verify it runs without error.
|
|
90
|
+
# Style visual verification is limited with simple string buffer checks,
|
|
91
|
+
# but this ensures the event handling works.
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def test_padding_controls
|
|
96
|
+
with_test_terminal do
|
|
97
|
+
# Increase padding_left (l) and padding_right (k) then quit
|
|
98
|
+
inject_keys(:l, :l, :k, :k, :k, :q)
|
|
99
|
+
@app.run
|
|
100
|
+
|
|
101
|
+
# Verify that padding values are shown in status with hotkeys
|
|
102
|
+
# Use join to match even if wrapped or if "Pad Left" logic changed
|
|
103
|
+
content_str = buffer_content.join("\n")
|
|
104
|
+
assert_includes content_str, "h/l: Pad Left (2)"
|
|
105
|
+
assert_includes content_str, "j/k: Pad Right (3)"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_styling_controls
|
|
110
|
+
with_test_terminal do
|
|
111
|
+
# Cycle label style (x) and value style (z)
|
|
112
|
+
inject_keys(:x, :z, :z, :q)
|
|
113
|
+
@app.run
|
|
114
|
+
# Verify expected content
|
|
115
|
+
content = buffer_content.join
|
|
116
|
+
assert_includes content, "Analytics: Revenue"
|
|
117
|
+
assert_includes content, "Views"
|
|
118
|
+
assert_includes content, "Controls"
|
|
119
|
+
assert_includes content, "Width:"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_direction_toggle
|
|
124
|
+
with_test_terminal do
|
|
125
|
+
# Switch to horizontal (v) then quit
|
|
126
|
+
inject_keys(:v, :q)
|
|
127
|
+
@app.run
|
|
128
|
+
|
|
129
|
+
assert buffer_content.any? { |line| line.include?("v: Direction (horizontal)") }
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
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 showing Block padding capabilities
|
|
10
|
+
class BlockPaddingApp
|
|
11
|
+
def run
|
|
12
|
+
RatatuiRuby.run do |tui|
|
|
13
|
+
loop do
|
|
14
|
+
# 1. Uniform Padding
|
|
15
|
+
block1 = RatatuiRuby::Block.new(
|
|
16
|
+
title: "Uniform Padding (2)",
|
|
17
|
+
borders: [:all],
|
|
18
|
+
padding: 2
|
|
19
|
+
)
|
|
20
|
+
para1 = RatatuiRuby::Paragraph.new(
|
|
21
|
+
text: "This text is padded by 2 on all sides.\nNotice the space between the border and this text.",
|
|
22
|
+
block: block1
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# 2. Directional Padding
|
|
26
|
+
block2 = RatatuiRuby::Block.new(
|
|
27
|
+
title: "Directional Padding [Left: 4, Right: 0, Top: 2, Bottom: 0]",
|
|
28
|
+
borders: [:all],
|
|
29
|
+
padding: [4, 0, 2, 0]
|
|
30
|
+
)
|
|
31
|
+
para2 = RatatuiRuby::Paragraph.new(
|
|
32
|
+
text: "This text has different padding per side.\nLeft: 4, Top: 2.",
|
|
33
|
+
block: block2
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Instructions
|
|
37
|
+
para3 = RatatuiRuby::Paragraph.new(
|
|
38
|
+
text: "Press 'q' to quit."
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Layout
|
|
42
|
+
layout = RatatuiRuby::Layout.new(
|
|
43
|
+
direction: :vertical,
|
|
44
|
+
constraints: [
|
|
45
|
+
RatatuiRuby::Constraint.length(10), # Uniform Padding
|
|
46
|
+
RatatuiRuby::Constraint.length(10), # Directional Padding
|
|
47
|
+
RatatuiRuby::Constraint.min(0)
|
|
48
|
+
],
|
|
49
|
+
children: [para1, para2, para3]
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
tui.draw(layout)
|
|
53
|
+
|
|
54
|
+
event = tui.poll_event
|
|
55
|
+
break if event == "q" || event == :ctrl_c
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if __FILE__ == $0
|
|
62
|
+
BlockPaddingApp.new.run
|
|
63
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
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 TestBlockPadding < Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
|
|
15
|
+
def setup
|
|
16
|
+
@app = BlockPaddingApp.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_render
|
|
20
|
+
with_test_terminal do
|
|
21
|
+
inject_key(:q)
|
|
22
|
+
@app.run
|
|
23
|
+
|
|
24
|
+
content = buffer_content.join("\n")
|
|
25
|
+
assert_includes content, "Uniform Padding (2)"
|
|
26
|
+
assert_includes content, "This text is padded by 2 on all sides."
|
|
27
|
+
assert_includes content, "Directional Padding [Left: 4, Right: 0, Top: 2, Bottom: 0]"
|
|
28
|
+
assert_includes content, "Left: 4, Top: 2."
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
4
|
+
require "ratatui_ruby"
|
|
5
|
+
|
|
6
|
+
# Initialize the terminal
|
|
7
|
+
class BlockTitlesApp
|
|
8
|
+
def run
|
|
9
|
+
RatatuiRuby.run do |tui|
|
|
10
|
+
loop do
|
|
11
|
+
# Create a layout with multiple blocks demonstrating titles
|
|
12
|
+
blocks = [
|
|
13
|
+
tui.block(
|
|
14
|
+
titles: [
|
|
15
|
+
{ content: "Top Left", alignment: :left, position: :top },
|
|
16
|
+
{ content: "Top Right", alignment: :right, position: :top }
|
|
17
|
+
],
|
|
18
|
+
borders: [:all],
|
|
19
|
+
border_color: "cyan"
|
|
20
|
+
),
|
|
21
|
+
tui.block(
|
|
22
|
+
titles: [
|
|
23
|
+
{ content: "Bottom Left", alignment: :left, position: :bottom },
|
|
24
|
+
{ content: "Bottom Center", alignment: :center, position: :bottom },
|
|
25
|
+
{ content: "Bottom Right", alignment: :right, position: :bottom }
|
|
26
|
+
],
|
|
27
|
+
borders: [:all],
|
|
28
|
+
border_color: "magenta"
|
|
29
|
+
),
|
|
30
|
+
tui.block(
|
|
31
|
+
titles: [
|
|
32
|
+
"Simple String Title (Top Left Default)",
|
|
33
|
+
{ content: "Mixed Title", alignment: :center, position: :bottom }
|
|
34
|
+
],
|
|
35
|
+
borders: [:all],
|
|
36
|
+
border_color: "green"
|
|
37
|
+
)
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
layout = tui.layout(
|
|
41
|
+
direction: :vertical,
|
|
42
|
+
constraints: [
|
|
43
|
+
tui.constraint(:length, 10),
|
|
44
|
+
tui.constraint(:length, 10),
|
|
45
|
+
tui.constraint(:length, 10)
|
|
46
|
+
],
|
|
47
|
+
children: blocks
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
tui.draw(layout)
|
|
51
|
+
|
|
52
|
+
event = tui.poll_event
|
|
53
|
+
break if event == "q" || event == :ctrl_c
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if __FILE__ == $0
|
|
60
|
+
BlockTitlesApp.new.run
|
|
61
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
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 TestBlockTitles < Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
|
|
15
|
+
def setup
|
|
16
|
+
@app = BlockTitlesApp.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_render
|
|
20
|
+
with_test_terminal do
|
|
21
|
+
inject_key(:q)
|
|
22
|
+
@app.run
|
|
23
|
+
|
|
24
|
+
content = buffer_content.join("\n")
|
|
25
|
+
assert_includes content, "Top Left"
|
|
26
|
+
assert_includes content, "Top Right"
|
|
27
|
+
assert_includes content, "Bottom Left"
|
|
28
|
+
assert_includes content, "Bottom Center"
|
|
29
|
+
assert_includes content, "Bottom Right"
|
|
30
|
+
assert_includes content, "Simple String Title (Top Left Default)"
|
|
31
|
+
assert_includes content, "Mixed Title"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|