ratatui_ruby 0.3.1 → 0.5.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 +89 -132
- data/CHANGELOG.md +223 -1
- data/README.md +23 -16
- data/REUSE.toml +20 -0
- data/doc/application_architecture.md +176 -0
- data/doc/application_testing.md +17 -10
- data/doc/contributors/design/ruby_frontend.md +11 -7
- data/doc/contributors/developing_examples.md +261 -0
- data/doc/contributors/documentation_style.md +104 -0
- data/doc/contributors/dwim_dx.md +366 -0
- data/doc/contributors/index.md +2 -0
- data/doc/custom.css +14 -0
- data/doc/event_handling.md +125 -0
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_analytics.png +0 -0
- data/doc/images/app_color_picker.png +0 -0
- data/doc/images/app_custom_widget.png +0 -0
- data/doc/images/app_login_form.png +0 -0
- data/doc/images/app_map_demo.png +0 -0
- data/doc/images/app_mouse_events.png +0 -0
- data/doc/images/app_table_select.png +0 -0
- data/doc/images/verify_quickstart_dsl.png +0 -0
- data/doc/images/verify_quickstart_layout.png +0 -0
- data/doc/images/verify_quickstart_lifecycle.png +0 -0
- data/doc/images/verify_readme_usage.png +0 -0
- data/doc/images/widget_barchart_demo.png +0 -0
- data/doc/images/widget_block_padding.png +0 -0
- data/doc/images/widget_block_titles.png +0 -0
- data/doc/images/widget_box_demo.png +0 -0
- data/doc/images/widget_calendar_demo.png +0 -0
- data/doc/images/widget_cell_demo.png +0 -0
- data/doc/images/widget_chart_demo.png +0 -0
- data/doc/images/widget_gauge_demo.png +0 -0
- data/doc/images/widget_layout_split.png +0 -0
- data/doc/images/widget_line_gauge_demo.png +0 -0
- data/doc/images/widget_list_demo.png +0 -0
- data/doc/images/widget_list_styles.png +0 -0
- data/doc/images/widget_popup_demo.png +0 -0
- data/doc/images/widget_ratatui_logo_demo.png +0 -0
- data/doc/images/widget_ratatui_mascot_demo.png +0 -0
- data/doc/images/widget_rect.png +0 -0
- data/doc/images/widget_render.png +0 -0
- data/doc/images/widget_rich_text.png +0 -0
- data/doc/images/widget_scroll_text.png +0 -0
- data/doc/images/widget_scrollbar_demo.png +0 -0
- data/doc/images/widget_sparkline_demo.png +0 -0
- data/doc/images/widget_style_colors.png +0 -0
- data/doc/images/widget_table_flex.png +0 -0
- data/doc/images/widget_tabs_demo.png +0 -0
- data/doc/index.md +1 -0
- data/doc/interactive_design.md +116 -0
- data/doc/quickstart.md +186 -84
- data/examples/app_all_events/README.md +81 -0
- data/examples/app_all_events/app.rb +93 -0
- data/examples/app_all_events/model/event_color_cycle.rb +41 -0
- data/examples/app_all_events/model/event_entry.rb +75 -0
- data/examples/app_all_events/model/events.rb +180 -0
- data/examples/app_all_events/model/highlight.rb +57 -0
- data/examples/app_all_events/model/timestamp.rb +54 -0
- data/examples/app_all_events/test/snapshots/after_focus_lost.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_focus_regained.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_horizontal_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_key_a.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_key_ctrl_x.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_mouse_click.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_mouse_drag.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_multiple_events.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_paste.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_right_click.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_vertical_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/initial_state.txt +24 -0
- data/examples/app_all_events/view/app_view.rb +78 -0
- data/examples/app_all_events/view/controls_view.rb +50 -0
- data/examples/app_all_events/view/counts_view.rb +55 -0
- data/examples/app_all_events/view/live_view.rb +69 -0
- data/examples/app_all_events/view/log_view.rb +60 -0
- data/{lib/ratatui_ruby/output.rb → examples/app_all_events/view.rb} +1 -1
- data/examples/app_all_events/view_state.rb +42 -0
- data/examples/app_color_picker/README.md +94 -0
- data/examples/app_color_picker/app.rb +112 -0
- data/examples/app_color_picker/clipboard.rb +84 -0
- data/examples/app_color_picker/color.rb +191 -0
- data/examples/app_color_picker/copy_dialog.rb +170 -0
- data/examples/app_color_picker/harmony.rb +56 -0
- data/examples/app_color_picker/input.rb +142 -0
- data/examples/app_color_picker/palette.rb +80 -0
- data/examples/app_color_picker/scene.rb +201 -0
- data/examples/app_login_form/app.rb +108 -0
- data/examples/app_map_demo/app.rb +93 -0
- data/examples/app_table_select/app.rb +201 -0
- data/examples/verify_quickstart_dsl/app.rb +45 -0
- data/examples/verify_quickstart_layout/app.rb +69 -0
- data/examples/verify_quickstart_lifecycle/app.rb +48 -0
- data/examples/verify_readme_usage/app.rb +34 -0
- data/examples/widget_barchart_demo/app.rb +238 -0
- data/examples/widget_block_padding/app.rb +67 -0
- data/examples/widget_block_titles/app.rb +69 -0
- data/examples/widget_box_demo/app.rb +250 -0
- data/examples/widget_calendar_demo/app.rb +109 -0
- data/examples/widget_cell_demo/app.rb +104 -0
- data/examples/widget_chart_demo/app.rb +213 -0
- data/examples/widget_gauge_demo/app.rb +212 -0
- data/examples/widget_layout_split/app.rb +246 -0
- data/examples/widget_line_gauge_demo/app.rb +217 -0
- data/examples/widget_list_demo/app.rb +382 -0
- data/examples/widget_list_styles/app.rb +141 -0
- data/examples/widget_popup_demo/app.rb +104 -0
- data/examples/widget_ratatui_logo_demo/app.rb +103 -0
- data/examples/widget_ratatui_mascot_demo/app.rb +93 -0
- data/examples/widget_rect/app.rb +205 -0
- data/examples/widget_render/app.rb +184 -0
- data/examples/widget_rich_text/app.rb +137 -0
- data/examples/widget_scroll_text/app.rb +108 -0
- data/examples/widget_scrollbar_demo/app.rb +153 -0
- data/examples/widget_sparkline_demo/app.rb +274 -0
- data/examples/widget_style_colors/app.rb +102 -0
- data/examples/widget_table_flex/app.rb +95 -0
- data/examples/widget_tabs_demo/app.rb +167 -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 +293 -219
- data/ext/ratatui_ruby/src/frame.rs +115 -0
- data/ext/ratatui_ruby/src/lib.rs +105 -24
- data/ext/ratatui_ruby/src/rendering.rs +94 -10
- data/ext/ratatui_ruby/src/style.rs +357 -93
- data/ext/ratatui_ruby/src/terminal.rs +121 -31
- data/ext/ratatui_ruby/src/text.rs +178 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +99 -24
- data/ext/ratatui_ruby/src/widgets/block.rs +32 -3
- data/ext/ratatui_ruby/src/widgets/calendar.rs +45 -44
- data/ext/ratatui_ruby/src/widgets/canvas.rs +44 -9
- data/ext/ratatui_ruby/src/widgets/chart.rs +79 -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 +223 -15
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +92 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +114 -11
- data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +4 -2
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +35 -13
- data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +40 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +51 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +61 -7
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +73 -6
- data/ext/ratatui_ruby/src/widgets/table.rs +177 -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/none.rb +43 -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 +131 -0
- data/lib/ratatui_ruby/frame.rb +87 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +45 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +23 -0
- data/lib/ratatui_ruby/schema/bar_chart.rb +226 -17
- data/lib/ratatui_ruby/schema/block.rb +178 -11
- data/lib/ratatui_ruby/schema/calendar.rb +70 -14
- data/lib/ratatui_ruby/schema/canvas.rb +213 -46
- data/lib/ratatui_ruby/schema/center.rb +46 -8
- data/lib/ratatui_ruby/schema/chart.rb +134 -32
- data/lib/ratatui_ruby/schema/clear.rb +22 -53
- data/lib/ratatui_ruby/schema/constraint.rb +72 -12
- data/lib/ratatui_ruby/schema/cursor.rb +23 -5
- data/lib/ratatui_ruby/schema/draw.rb +53 -0
- data/lib/ratatui_ruby/schema/gauge.rb +56 -12
- data/lib/ratatui_ruby/schema/layout.rb +91 -9
- data/lib/ratatui_ruby/schema/line_gauge.rb +78 -0
- data/lib/ratatui_ruby/schema/list.rb +92 -16
- data/lib/ratatui_ruby/schema/overlay.rb +29 -3
- data/lib/ratatui_ruby/schema/paragraph.rb +82 -25
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +29 -0
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +34 -0
- data/lib/ratatui_ruby/schema/rect.rb +59 -10
- data/lib/ratatui_ruby/schema/scrollbar.rb +127 -19
- data/lib/ratatui_ruby/schema/shape/label.rb +66 -0
- data/lib/ratatui_ruby/schema/sparkline.rb +120 -12
- data/lib/ratatui_ruby/schema/style.rb +39 -11
- data/lib/ratatui_ruby/schema/table.rb +109 -18
- data/lib/ratatui_ruby/schema/tabs.rb +71 -10
- data/lib/ratatui_ruby/schema/text.rb +90 -0
- data/lib/ratatui_ruby/session/autodoc.rb +417 -0
- data/lib/ratatui_ruby/session.rb +163 -0
- data/lib/ratatui_ruby/test_helper.rb +322 -13
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby.rb +184 -38
- data/sig/examples/app_all_events/app.rbs +11 -0
- data/sig/examples/app_all_events/model/event_entry.rbs +16 -0
- data/sig/examples/app_all_events/model/events.rbs +15 -0
- data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
- data/sig/examples/app_all_events/view/app_view.rbs +8 -0
- data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
- data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
- data/sig/examples/app_all_events/view/live_view.rbs +6 -0
- data/sig/examples/app_all_events/view/log_view.rbs +6 -0
- data/sig/examples/app_all_events/view.rbs +8 -0
- data/sig/examples/app_all_events/view_state.rbs +15 -0
- data/sig/examples/app_color_picker/app.rbs +12 -0
- data/sig/examples/app_login_form/app.rbs +11 -0
- data/sig/examples/app_map_demo/app.rbs +11 -0
- data/sig/examples/app_table_select/app.rbs +11 -0
- data/sig/examples/verify_quickstart_dsl/app.rbs +11 -0
- data/sig/examples/verify_quickstart_lifecycle/app.rbs +11 -0
- data/sig/examples/verify_readme_usage/app.rbs +11 -0
- data/sig/examples/widget_block_padding/app.rbs +11 -0
- data/sig/examples/widget_block_titles/app.rbs +11 -0
- data/sig/examples/widget_box_demo/app.rbs +11 -0
- data/sig/examples/widget_calendar_demo/app.rbs +11 -0
- data/sig/examples/widget_cell_demo/app.rbs +11 -0
- data/sig/examples/widget_chart_demo/app.rbs +11 -0
- data/sig/examples/widget_gauge_demo/app.rbs +11 -0
- data/sig/examples/widget_layout_split/app.rbs +10 -0
- data/sig/examples/widget_line_gauge_demo/app.rbs +11 -0
- data/sig/examples/widget_list_demo/app.rbs +12 -0
- data/sig/examples/widget_list_styles/app.rbs +11 -0
- data/sig/examples/widget_popup_demo/app.rbs +11 -0
- data/sig/examples/widget_ratatui_logo_demo/app.rbs +11 -0
- data/sig/examples/widget_ratatui_mascot_demo/app.rbs +11 -0
- data/sig/examples/widget_rect/app.rbs +12 -0
- data/sig/examples/widget_render/app.rbs +10 -0
- data/sig/examples/widget_rich_text/app.rbs +11 -0
- data/sig/examples/widget_scroll_text/app.rbs +11 -0
- data/sig/examples/widget_scrollbar_demo/app.rbs +11 -0
- data/sig/examples/widget_sparkline_demo/app.rbs +10 -0
- data/sig/examples/widget_style_colors/app.rbs +14 -0
- data/sig/examples/widget_table_flex/app.rbs +11 -0
- data/sig/ratatui_ruby/event.rbs +69 -0
- data/sig/ratatui_ruby/frame.rbs +9 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +5 -3
- 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 +27 -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/sig/ratatui_ruby/schema/ratatui_logo.rbs +8 -0
- 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/sig/ratatui_ruby/session.rbs +94 -0
- data/tasks/autodoc/inventory.rb +61 -0
- data/tasks/autodoc/member.rb +56 -0
- data/tasks/autodoc/name.rb +19 -0
- data/tasks/autodoc/notice.rb +26 -0
- data/tasks/autodoc/rbs.rb +38 -0
- data/tasks/autodoc/rdoc.rb +45 -0
- data/tasks/autodoc.rake +47 -0
- data/tasks/bump/history.rb +2 -2
- data/tasks/doc.rake +600 -6
- data/tasks/example_viewer.html.erb +172 -0
- data/tasks/lint.rake +8 -4
- data/tasks/resources/build.yml.erb +13 -11
- data/tasks/resources/index.html.erb +6 -0
- data/tasks/sourcehut.rake +4 -4
- data/tasks/terminal_preview/app_screenshot.rb +33 -0
- data/tasks/terminal_preview/crash_report.rb +52 -0
- data/tasks/terminal_preview/example_app.rb +25 -0
- data/tasks/terminal_preview/launcher_script.rb +46 -0
- data/tasks/terminal_preview/preview_collection.rb +58 -0
- data/tasks/terminal_preview/preview_timing.rb +22 -0
- data/tasks/terminal_preview/safety_confirmation.rb +56 -0
- data/tasks/terminal_preview/saved_screenshot.rb +53 -0
- data/tasks/terminal_preview/system_appearance.rb +11 -0
- data/tasks/terminal_preview/terminal_window.rb +136 -0
- data/tasks/terminal_preview/window_id.rb +14 -0
- data/tasks/terminal_preview.rake +28 -0
- data/tasks/test.rake +2 -2
- data/tasks/website/index_page.rb +3 -3
- data/tasks/website/version.rb +10 -10
- data/tasks/website/version_menu.rb +10 -12
- data/tasks/website/versioned_documentation.rb +49 -17
- data/tasks/website/website.rb +6 -8
- data/tasks/website.rake +4 -4
- metadata +206 -54
- data/LICENSES/BSD-2-Clause.txt +0 -9
- 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/login_form.rb +0 -115
- data/examples/map_demo.rb +0 -58
- data/examples/mouse_events.rb +0 -95
- data/examples/popup_demo.rb +0 -105
- 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_popup_demo.rb +0 -62
- 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
data/examples/test_login_form.rb
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
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 "login_form"
|
|
11
|
-
|
|
12
|
-
class Minitest::Test
|
|
13
|
-
include RatatuiRuby::TestHelper
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
class TestLoginForm < Minitest::Test
|
|
17
|
-
def setup
|
|
18
|
-
@app = LoginFormApp.new
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def test_render_initial_state
|
|
22
|
-
with_test_terminal(60, 20) do
|
|
23
|
-
@app.render
|
|
24
|
-
assert buffer_content.any? { |line| line.include?("Enter Username:") }
|
|
25
|
-
# Initial cursor position check could be tricky without inspecting cursor state,
|
|
26
|
-
# but we can rely on visual cursor rendering if we had a way to check attributes,
|
|
27
|
-
# or just assume the widget logic puts it there.
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def test_input_handling
|
|
32
|
-
# Type 'a'
|
|
33
|
-
inject_event("key", { code: "a" })
|
|
34
|
-
@app.handle_input
|
|
35
|
-
|
|
36
|
-
with_test_terminal(60, 20) do
|
|
37
|
-
@app.render
|
|
38
|
-
assert buffer_content.any? { |line| line.include?("Enter Username: [ a ]") }
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def test_popup_flow
|
|
43
|
-
# Enter username 'user'
|
|
44
|
-
%w[u s e r].each do |char|
|
|
45
|
-
inject_event("key", { code: char })
|
|
46
|
-
@app.handle_input
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Press Enter
|
|
50
|
-
inject_event("key", { code: "enter" })
|
|
51
|
-
@app.handle_input
|
|
52
|
-
|
|
53
|
-
with_test_terminal(60, 20) do
|
|
54
|
-
@app.render
|
|
55
|
-
assert buffer_content.any? { |line| line.include?("Successful!") }
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Press 'q' to quit popup/app
|
|
59
|
-
inject_event("key", { code: "q" })
|
|
60
|
-
status = @app.handle_input
|
|
61
|
-
assert_equal :quit, status
|
|
62
|
-
end
|
|
63
|
-
end
|
data/examples/test_map_demo.rb
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
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 "map_demo"
|
|
11
|
-
|
|
12
|
-
class TestMapDemo < Minitest::Test
|
|
13
|
-
include RatatuiRuby::TestHelper
|
|
14
|
-
|
|
15
|
-
def test_map_demo_renders
|
|
16
|
-
# Use a specific terminal size to make assertions reliable
|
|
17
|
-
with_test_terminal(20, 10) do
|
|
18
|
-
view = MapDemo.view(0.0)
|
|
19
|
-
RatatuiRuby.draw(view)
|
|
20
|
-
|
|
21
|
-
expected_buffer = [
|
|
22
|
-
"┌World Map Canvas──┐",
|
|
23
|
-
"│⣀⣀⣠⣶⣶⣶⡖⣲⠂⣶⣒⣦⣤⠶⢤⣤⣄⣀│",
|
|
24
|
-
"│⠹⠓⢦ ⠻⣿⡟⠉⣿⡿⣋⡁⠁ ⣴⠿⠋│",
|
|
25
|
-
"│⢀⡀⠘⣆⣴⡏ ⢀⡟⠻⣿⣧⣀⣀⣹⠟ │",
|
|
26
|
-
"│ ⠁ ⠈⢻⠿⣄⠘⢦⡔⢚⡏⠻⣽⣿⣀⡀ │",
|
|
27
|
-
"│⠄ ⠘⡆⣸⠃ ⡇⣼⡆ ⠈⡻⢿⣻⠤│",
|
|
28
|
-
"│ ⣷⠃ ⠙⠃ ⡀ ⠓⢳⢇⡆│",
|
|
29
|
-
"│ ⢀⡀⣻ ⣀⣀⣀⣤⣁⣤⣤⣄⣀⡀│",
|
|
30
|
-
"│⠾⠿⠉⠉⠙⠛⠛⠋⠁ ⠘⠧│",
|
|
31
|
-
"└──────────────────┘",
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
expected_buffer.each_with_index do |line, i|
|
|
35
|
-
assert_equal line, buffer_content[i], "Line #{i} should match"
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def test_quit
|
|
41
|
-
# We need to use with_test_terminal because MapDemo.run calls init_terminal and draw
|
|
42
|
-
with_test_terminal(80, 24) do
|
|
43
|
-
# Inject 'q' event
|
|
44
|
-
inject_event("key", { code: "q" })
|
|
45
|
-
|
|
46
|
-
# MapDemo.run should exit immediately after polling the 'q' event
|
|
47
|
-
# We use Timeout to prevent hanging if it's not quittable
|
|
48
|
-
require "timeout"
|
|
49
|
-
Timeout.timeout(1) do
|
|
50
|
-
MapDemo.run
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def test_map_demo_animation
|
|
56
|
-
# Test that the animation actually happens within the run loop
|
|
57
|
-
with_test_terminal(20, 10) do
|
|
58
|
-
# We want to verify that the radius changes.
|
|
59
|
-
# We'll mock RatatuiRuby.draw to capture the views being drawn.
|
|
60
|
-
draw_calls = []
|
|
61
|
-
|
|
62
|
-
# We need to preserve the original behavior of draw if we want to see it in the test terminal,
|
|
63
|
-
# but for this test, we just want to inspect the view objects.
|
|
64
|
-
|
|
65
|
-
# Using a lambda as a mock for RatatuiRuby.draw
|
|
66
|
-
original_draw = RatatuiRuby.method(:draw)
|
|
67
|
-
RatatuiRuby.define_singleton_method(:draw) do |view|
|
|
68
|
-
draw_calls << view
|
|
69
|
-
original_draw.call(view)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
begin
|
|
73
|
-
MapDemo.stub :sleep, nil do
|
|
74
|
-
# Inject some non-quitting events to let it loop
|
|
75
|
-
# radius starts at 0.0
|
|
76
|
-
# 1st loop: radius becomes 0.5, draws, polls 'up', sleeps
|
|
77
|
-
# 2nd loop: radius becomes 1.0, draws, polls 'up', sleeps
|
|
78
|
-
# 3rd loop: radius becomes 1.5, draws, polls 'q', breaks
|
|
79
|
-
inject_event("key", { code: "up" })
|
|
80
|
-
inject_event("key", { code: "up" })
|
|
81
|
-
inject_event("key", { code: "q" })
|
|
82
|
-
|
|
83
|
-
MapDemo.run
|
|
84
|
-
end
|
|
85
|
-
ensure
|
|
86
|
-
# Restore original draw method
|
|
87
|
-
RatatuiRuby.define_singleton_method(:draw, &original_draw)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
assert_operator draw_calls.size, :>=, 3
|
|
91
|
-
|
|
92
|
-
# Check that the radius in each view is increasing
|
|
93
|
-
radii = draw_calls.map { |v| v.shapes.find { |s| s.is_a?(RatatuiRuby::Circle) }.radius }
|
|
94
|
-
|
|
95
|
-
assert_equal 0.5, radii[0]
|
|
96
|
-
assert_equal 1.0, radii[1]
|
|
97
|
-
assert_equal 1.5, radii[2]
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
data/examples/test_popup_demo.rb
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
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 "popup_demo"
|
|
11
|
-
|
|
12
|
-
class Minitest::Test
|
|
13
|
-
include RatatuiRuby::TestHelper
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
class TestPopupDemo < Minitest::Test
|
|
17
|
-
def setup
|
|
18
|
-
@app = PopupDemo.new
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def test_render_initial_state
|
|
22
|
-
with_test_terminal(60, 20) do
|
|
23
|
-
@app.render
|
|
24
|
-
|
|
25
|
-
# Should have background text
|
|
26
|
-
assert buffer_content.any? { |line| line.include?("BACKGROUND RED") }
|
|
27
|
-
|
|
28
|
-
# Should have popup with "Clear is DISABLED" message
|
|
29
|
-
assert buffer_content.any? { |line| line.include?("Clear is DISABLED") }
|
|
30
|
-
assert buffer_content.any? { |line| line.include?("Style Bleed: Popup is RED!") }
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def test_toggle_clear
|
|
35
|
-
with_test_terminal(60, 20) do
|
|
36
|
-
# Initial state: Clear disabled
|
|
37
|
-
@app.render
|
|
38
|
-
assert buffer_content.any? { |line| line.include?("Clear is DISABLED") }
|
|
39
|
-
|
|
40
|
-
# Toggle Clear on
|
|
41
|
-
inject_event("key", { code: " " })
|
|
42
|
-
@app.handle_input
|
|
43
|
-
|
|
44
|
-
@app.render
|
|
45
|
-
assert buffer_content.any? { |line| line.include?("Clear is ENABLED") }
|
|
46
|
-
assert buffer_content.any? { |line| line.include?("Resets background to default") }
|
|
47
|
-
|
|
48
|
-
# Toggle Clear off
|
|
49
|
-
inject_event("key", { code: " " })
|
|
50
|
-
@app.handle_input
|
|
51
|
-
|
|
52
|
-
@app.render
|
|
53
|
-
assert buffer_content.any? { |line| line.include?("Clear is DISABLED") }
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def test_quit
|
|
58
|
-
inject_event("key", { code: "q" })
|
|
59
|
-
status = @app.handle_input
|
|
60
|
-
assert_equal :quit, status
|
|
61
|
-
end
|
|
62
|
-
end
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
-
|
|
7
|
-
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
8
|
-
require "minitest/autorun"
|
|
9
|
-
require "ratatui_ruby/test_helper"
|
|
10
|
-
|
|
11
|
-
# Load the demo
|
|
12
|
-
require_relative "./scroll_text"
|
|
13
|
-
|
|
14
|
-
class TestScrollText < Minitest::Test
|
|
15
|
-
include RatatuiRuby::TestHelper
|
|
16
|
-
|
|
17
|
-
def setup
|
|
18
|
-
@demo = ScrollTextDemo.new
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def test_demo_initialization
|
|
22
|
-
assert_instance_of ScrollTextDemo, @demo
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def test_initial_rendering
|
|
26
|
-
with_test_terminal(60, 10) do
|
|
27
|
-
@demo.render
|
|
28
|
-
content = buffer_content
|
|
29
|
-
|
|
30
|
-
# Should show Line 1 at the top (inside the block border)
|
|
31
|
-
assert content[1].include?("Line 1")
|
|
32
|
-
# Should show title with scroll position 0, 0
|
|
33
|
-
assert content[0].include?("X: 0, Y: 0")
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def test_scroll_down
|
|
38
|
-
inject_event("key", { code: "down" })
|
|
39
|
-
@demo.handle_input
|
|
40
|
-
|
|
41
|
-
with_test_terminal(60, 10) do
|
|
42
|
-
@demo.render
|
|
43
|
-
content = buffer_content
|
|
44
|
-
|
|
45
|
-
# After scrolling down once, Line 2 should be at the top
|
|
46
|
-
assert content[1].include?("Line 2"), "Expected Line 2 at top, got: #{content[1]}"
|
|
47
|
-
# Line 1 should not be visible (scrolled off)
|
|
48
|
-
refute content.any? { |line| line.include?("Line 1") }, "Line 1 should be scrolled off"
|
|
49
|
-
# Should show Y scroll position 1
|
|
50
|
-
assert content[0].include?("Y: 1")
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def test_scroll_right
|
|
55
|
-
inject_event("key", { code: "right" })
|
|
56
|
-
@demo.handle_input
|
|
57
|
-
|
|
58
|
-
with_test_terminal(60, 10) do
|
|
59
|
-
@demo.render
|
|
60
|
-
content = buffer_content
|
|
61
|
-
|
|
62
|
-
# After scrolling right once, first character should be cut off
|
|
63
|
-
# "Line 1:" becomes "ine 1:"
|
|
64
|
-
assert content[1].include?("ine 1:"), "Expected horizontal scroll, got: #{content[1]}"
|
|
65
|
-
# Should show X scroll position 1
|
|
66
|
-
assert content[0].include?("X: 1")
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def test_scroll_left_at_edge
|
|
71
|
-
# Try to scroll left when already at x=0
|
|
72
|
-
inject_event("key", { code: "left" })
|
|
73
|
-
@demo.handle_input
|
|
74
|
-
|
|
75
|
-
with_test_terminal(60, 10) do
|
|
76
|
-
@demo.render
|
|
77
|
-
content = buffer_content
|
|
78
|
-
|
|
79
|
-
# Should still show full "Line 1:" (can't scroll left past 0)
|
|
80
|
-
assert content[1].include?("Line 1:")
|
|
81
|
-
# Should still show X scroll position 0
|
|
82
|
-
assert content[0].include?("X: 0")
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def test_scroll_up_at_top
|
|
87
|
-
# Try to scroll up when already at top (should stay at 0)
|
|
88
|
-
inject_event("key", { code: "up" })
|
|
89
|
-
@demo.handle_input
|
|
90
|
-
|
|
91
|
-
with_test_terminal(60, 10) do
|
|
92
|
-
@demo.render
|
|
93
|
-
content = buffer_content
|
|
94
|
-
|
|
95
|
-
# Should still show Line 1 at top (can't scroll above 0)
|
|
96
|
-
assert content[1].include?("Line 1")
|
|
97
|
-
# Should still show Y scroll position 0
|
|
98
|
-
assert content[0].include?("Y: 0")
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def test_scroll_both_axes
|
|
103
|
-
# Scroll down 2 times and right 3 times
|
|
104
|
-
2.times do
|
|
105
|
-
inject_event("key", { code: "down" })
|
|
106
|
-
@demo.handle_input
|
|
107
|
-
end
|
|
108
|
-
3.times do
|
|
109
|
-
inject_event("key", { code: "right" })
|
|
110
|
-
@demo.handle_input
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
with_test_terminal(60, 10) do
|
|
114
|
-
@demo.render
|
|
115
|
-
content = buffer_content
|
|
116
|
-
|
|
117
|
-
# After scrolling down 2 and right 3, Line 3 should be at top with first 3 chars cut
|
|
118
|
-
# "Line 3:" becomes " 3:"
|
|
119
|
-
assert content[1].include?(" 3:"), "Expected Line 3 scrolled right by 3, got: #{content[1]}"
|
|
120
|
-
# Should show scroll position X: 3, Y: 2
|
|
121
|
-
assert content[0].include?("X: 3, Y: 2")
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def test_quit
|
|
126
|
-
inject_event("key", { code: "q" })
|
|
127
|
-
status = @demo.handle_input
|
|
128
|
-
assert_equal :quit, status
|
|
129
|
-
end
|
|
130
|
-
end
|
|
@@ -1,39 +0,0 @@
|
|
|
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 "stock_ticker"
|
|
11
|
-
|
|
12
|
-
class Minitest::Test
|
|
13
|
-
include RatatuiRuby::TestHelper
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
class TestStockTicker < Minitest::Test
|
|
17
|
-
def setup
|
|
18
|
-
@app = StockTickerApp.new
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def test_render
|
|
22
|
-
with_test_terminal(60, 20) do
|
|
23
|
-
@app.render
|
|
24
|
-
assert buffer_content.any? { |line| line.include?("Network Activity") }
|
|
25
|
-
assert buffer_content.any? { |line| line.include?("Stock Ticker") }
|
|
26
|
-
# It's a dynamic simulation, so exact content varies,
|
|
27
|
-
# but titles should be stable.
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def test_update
|
|
32
|
-
# Render multiple times to ensure no crash on update
|
|
33
|
-
with_test_terminal(60, 20) do
|
|
34
|
-
@app.render
|
|
35
|
-
@app.render
|
|
36
|
-
assert buffer_content.any? { |line| line.include?("Stock Ticker") }
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
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 "system_monitor"
|
|
11
|
-
|
|
12
|
-
class Minitest::Test
|
|
13
|
-
include RatatuiRuby::TestHelper
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
class TestSystemMonitor < Minitest::Test
|
|
17
|
-
def setup
|
|
18
|
-
@app = SystemMonitorApp.new
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def test_render_initial_state
|
|
22
|
-
with_test_terminal(60, 20) do
|
|
23
|
-
@app.render
|
|
24
|
-
assert buffer_content.any? { |line| line.include?("Processes") }
|
|
25
|
-
assert buffer_content.any? { |line| line.include?("Memory Usage") }
|
|
26
|
-
assert buffer_content.any? { |line| line.include?("50%") }
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def test_interaction
|
|
31
|
-
# Increase percentage
|
|
32
|
-
inject_event("key", { code: "up" })
|
|
33
|
-
@app.handle_input
|
|
34
|
-
|
|
35
|
-
with_test_terminal(60, 20) do
|
|
36
|
-
@app.render
|
|
37
|
-
assert buffer_content.any? { |line| line.include?("55%") }
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
-
|
|
7
|
-
require "test_helper"
|
|
8
|
-
|
|
9
|
-
# Smoke test to ensure the table_select example can be loaded and instantiated
|
|
10
|
-
class TestTableSelect < Minitest::Test
|
|
11
|
-
def test_table_select_smoke
|
|
12
|
-
# Verify the example can create a table with selection
|
|
13
|
-
rows = [["1", "test", "10%"]]
|
|
14
|
-
widths = [
|
|
15
|
-
RatatuiRuby::Constraint.length(8),
|
|
16
|
-
RatatuiRuby::Constraint.length(15),
|
|
17
|
-
RatatuiRuby::Constraint.length(10)
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
table = RatatuiRuby::Table.new(
|
|
21
|
-
header: ["PID", "Name", "CPU"],
|
|
22
|
-
rows: rows,
|
|
23
|
-
widths: widths,
|
|
24
|
-
selected_row: 0,
|
|
25
|
-
highlight_style: RatatuiRuby::Style.new(fg: :yellow),
|
|
26
|
-
highlight_symbol: "> ",
|
|
27
|
-
block: RatatuiRuby::Block.new(title: "Test", borders: :all)
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
# Verify it can be drawn
|
|
31
|
-
with_test_terminal(40, 10) do
|
|
32
|
-
RatatuiRuby.draw(table)
|
|
33
|
-
# Just verify it doesn't crash
|
|
34
|
-
assert true
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
2
|
-
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
-
|
|
4
|
-
use crate::style::parse_style;
|
|
5
|
-
use magnus::prelude::*;
|
|
6
|
-
use magnus::{Error, Ruby, Value};
|
|
7
|
-
use ratatui::buffer::Buffer;
|
|
8
|
-
use std::ffi::CStr;
|
|
9
|
-
|
|
10
|
-
pub struct BufferWrapper {
|
|
11
|
-
ptr: *mut Buffer,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
unsafe impl Send for BufferWrapper {}
|
|
15
|
-
|
|
16
|
-
impl BufferWrapper {
|
|
17
|
-
pub fn new(buffer: &mut Buffer) -> Self {
|
|
18
|
-
Self { ptr: buffer }
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
pub fn set_string(&self, x: u16, y: u16, string: String, style_val: Value) -> Result<(), Error> {
|
|
22
|
-
let style = parse_style(style_val)?;
|
|
23
|
-
let buffer = unsafe { &mut *self.ptr };
|
|
24
|
-
buffer.set_string(x, y, string, style);
|
|
25
|
-
Ok(())
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
pub fn area(&self) -> Value {
|
|
29
|
-
let ruby = Ruby::get().unwrap();
|
|
30
|
-
let module = ruby.define_module("RatatuiRuby").unwrap();
|
|
31
|
-
let class = module.const_get::<_, magnus::RClass>("Rect").unwrap();
|
|
32
|
-
let buffer = unsafe { &*self.ptr };
|
|
33
|
-
let area = buffer.area;
|
|
34
|
-
class.funcall("new", (area.x, area.y, area.width, area.height)).unwrap()
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
unsafe impl magnus::TypedData for BufferWrapper {
|
|
39
|
-
fn class(ruby: &Ruby) -> magnus::RClass {
|
|
40
|
-
ruby.define_module("RatatuiRuby")
|
|
41
|
-
.and_then(|m| m.const_get("Buffer"))
|
|
42
|
-
.unwrap()
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
fn data_type() -> &'static magnus::DataType {
|
|
46
|
-
static DATA_TYPE: magnus::DataType = magnus::DataType::builder::<BufferWrapper>(unsafe {
|
|
47
|
-
CStr::from_bytes_with_nul_unchecked(b"RatatuiRuby::Buffer\0")
|
|
48
|
-
})
|
|
49
|
-
.build();
|
|
50
|
-
&DATA_TYPE
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
impl magnus::DataTypeFunctions for BufferWrapper {}
|
data/lib/ratatui_ruby/dsl.rb
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
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
|
-
module RatatuiRuby
|
|
7
|
-
##
|
|
8
|
-
# A wrapper class that provides a concise DSL for creating widgets and interacting
|
|
9
|
-
# with the terminal within the +main_loop+.
|
|
10
|
-
#
|
|
11
|
-
# This class is yielded to the block provided to {RatatuiRuby.main_loop}.
|
|
12
|
-
# It uses metaprogramming to delegate method calls to {RatatuiRuby} module functions
|
|
13
|
-
# and to act as a factory for {RatatuiRuby} widget classes.
|
|
14
|
-
#
|
|
15
|
-
# == Features
|
|
16
|
-
#
|
|
17
|
-
# 1. **Widget Shorthand**: Provides factory methods for every widget class.
|
|
18
|
-
# Converts snake_case method calls (e.g., +paragraph+) into CamelCase class instantiations
|
|
19
|
-
# (e.g., +RatatuiRuby::Paragraph.new+).
|
|
20
|
-
#
|
|
21
|
-
# 2. **Method Shorthand**: Aliases module functions of {RatatuiRuby}, allowing you
|
|
22
|
-
# to call methods like +draw+ and +poll_event+ directly on the DSL object.
|
|
23
|
-
#
|
|
24
|
-
# == Example
|
|
25
|
-
#
|
|
26
|
-
# RatatuiRuby.main_loop do |tui|
|
|
27
|
-
# # Create UI using shorthand methods
|
|
28
|
-
# view = tui.paragraph(
|
|
29
|
-
# text: "Hello World",
|
|
30
|
-
# block: tui.block(borders: [:all])
|
|
31
|
-
# )
|
|
32
|
-
#
|
|
33
|
-
# # Use module aliases to draw and handle events
|
|
34
|
-
# tui.draw(view)
|
|
35
|
-
# event = tui.poll_event
|
|
36
|
-
#
|
|
37
|
-
# break if event && event[:code] == "q"
|
|
38
|
-
# end
|
|
39
|
-
class DSL
|
|
40
|
-
# Wrap methods directly
|
|
41
|
-
RatatuiRuby.singleton_methods(false).each do |method_name|
|
|
42
|
-
define_method(method_name) do |*args, **kwargs, &block|
|
|
43
|
-
RatatuiRuby.public_send(method_name, *args, **kwargs, &block)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Wrap classes as snake_case factories
|
|
48
|
-
RatatuiRuby.constants.each do |const_name|
|
|
49
|
-
next if const_name == :Buffer
|
|
50
|
-
|
|
51
|
-
klass = RatatuiRuby.const_get(const_name)
|
|
52
|
-
next unless klass.is_a?(Class)
|
|
53
|
-
|
|
54
|
-
method_name = const_name.to_s
|
|
55
|
-
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
56
|
-
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
57
|
-
.downcase
|
|
58
|
-
|
|
59
|
-
define_method(method_name) do |*args, **kwargs, &block|
|
|
60
|
-
klass.new(*args, **kwargs, &block)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|