ratatui_ruby 1.4.0-x86_64-linux
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 +7 -0
- data/LICENSE +15 -0
- data/LICENSES/AGPL-3.0-or-later.txt +661 -0
- data/LICENSES/CC-BY-SA-4.0.txt +427 -0
- data/LICENSES/CC0-1.0.txt +121 -0
- data/LICENSES/LGPL-3.0-or-later.txt +304 -0
- data/LICENSES/MIT-0.txt +16 -0
- data/LICENSES/MIT.txt +21 -0
- data/REUSE.toml +42 -0
- data/exe/.gitkeep +0 -0
- data/ext/ratatui_ruby/.cargo/config.toml +13 -0
- data/ext/ratatui_ruby/.gitignore +4 -0
- data/ext/ratatui_ruby/Cargo.lock +1737 -0
- data/ext/ratatui_ruby/Cargo.toml +24 -0
- data/ext/ratatui_ruby/clippy.toml +7 -0
- data/ext/ratatui_ruby/extconf.rb +21 -0
- data/ext/ratatui_ruby/src/color.rs +82 -0
- data/ext/ratatui_ruby/src/errors.rs +28 -0
- data/ext/ratatui_ruby/src/events.rs +700 -0
- data/ext/ratatui_ruby/src/frame.rs +241 -0
- data/ext/ratatui_ruby/src/lib.rs +343 -0
- data/ext/ratatui_ruby/src/lib_header.rs +11 -0
- data/ext/ratatui_ruby/src/rendering.rs +158 -0
- data/ext/ratatui_ruby/src/string_width.rs +101 -0
- data/ext/ratatui_ruby/src/style.rs +469 -0
- data/ext/ratatui_ruby/src/terminal/capabilities.rs +46 -0
- data/ext/ratatui_ruby/src/terminal/init.rs +233 -0
- data/ext/ratatui_ruby/src/terminal/mod.rs +42 -0
- data/ext/ratatui_ruby/src/terminal/mutations.rs +158 -0
- data/ext/ratatui_ruby/src/terminal/queries.rs +231 -0
- data/ext/ratatui_ruby/src/terminal/query.rs +400 -0
- data/ext/ratatui_ruby/src/terminal/storage.rs +109 -0
- data/ext/ratatui_ruby/src/terminal/wrapper.rs +16 -0
- data/ext/ratatui_ruby/src/text.rs +225 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +169 -0
- data/ext/ratatui_ruby/src/widgets/block.rs +41 -0
- data/ext/ratatui_ruby/src/widgets/calendar.rs +84 -0
- data/ext/ratatui_ruby/src/widgets/canvas.rs +183 -0
- data/ext/ratatui_ruby/src/widgets/center.rs +79 -0
- data/ext/ratatui_ruby/src/widgets/chart.rs +222 -0
- data/ext/ratatui_ruby/src/widgets/clear.rs +39 -0
- data/ext/ratatui_ruby/src/widgets/cursor.rs +32 -0
- data/ext/ratatui_ruby/src/widgets/gauge.rs +65 -0
- data/ext/ratatui_ruby/src/widgets/layout.rs +379 -0
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +100 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +378 -0
- data/ext/ratatui_ruby/src/widgets/list_state.rs +173 -0
- data/ext/ratatui_ruby/src/widgets/mod.rs +26 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +24 -0
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +87 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +40 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +55 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +214 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar_state.rs +169 -0
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +127 -0
- data/ext/ratatui_ruby/src/widgets/table.rs +415 -0
- data/ext/ratatui_ruby/src/widgets/table_state.rs +203 -0
- data/ext/ratatui_ruby/src/widgets/tabs.rs +194 -0
- data/lib/ratatui_ruby/backend/window_size.rb +50 -0
- data/lib/ratatui_ruby/backend.rb +59 -0
- data/lib/ratatui_ruby/buffer/cell.rb +212 -0
- data/lib/ratatui_ruby/buffer.rb +149 -0
- data/lib/ratatui_ruby/cell.rb +208 -0
- data/lib/ratatui_ruby/debug.rb +215 -0
- data/lib/ratatui_ruby/draw.rb +63 -0
- data/lib/ratatui_ruby/event/focus_gained.rb +125 -0
- data/lib/ratatui_ruby/event/focus_lost.rb +127 -0
- data/lib/ratatui_ruby/event/key/character.rb +53 -0
- data/lib/ratatui_ruby/event/key/dwim.rb +301 -0
- data/lib/ratatui_ruby/event/key/media.rb +46 -0
- data/lib/ratatui_ruby/event/key/modifier.rb +107 -0
- data/lib/ratatui_ruby/event/key/navigation.rb +72 -0
- data/lib/ratatui_ruby/event/key/system.rb +47 -0
- data/lib/ratatui_ruby/event/key.rb +479 -0
- data/lib/ratatui_ruby/event/mouse.rb +291 -0
- data/lib/ratatui_ruby/event/none.rb +53 -0
- data/lib/ratatui_ruby/event/paste.rb +130 -0
- data/lib/ratatui_ruby/event/resize.rb +221 -0
- data/lib/ratatui_ruby/event/sync.rb +52 -0
- data/lib/ratatui_ruby/event.rb +163 -0
- data/lib/ratatui_ruby/frame.rb +257 -0
- data/lib/ratatui_ruby/labs/a11y.rb +182 -0
- data/lib/ratatui_ruby/labs/frame_a11y_capture.rb +50 -0
- data/lib/ratatui_ruby/labs.rb +47 -0
- data/lib/ratatui_ruby/layout/alignment.rb +91 -0
- data/lib/ratatui_ruby/layout/constraint.rb +337 -0
- data/lib/ratatui_ruby/layout/layout.rb +258 -0
- data/lib/ratatui_ruby/layout/position.rb +81 -0
- data/lib/ratatui_ruby/layout/rect.rb +733 -0
- data/lib/ratatui_ruby/layout/size.rb +62 -0
- data/lib/ratatui_ruby/layout.rb +29 -0
- data/lib/ratatui_ruby/list_state.rb +201 -0
- data/lib/ratatui_ruby/output_guard.rb +171 -0
- data/lib/ratatui_ruby/ratatui_ruby.so +0 -0
- data/lib/ratatui_ruby/scrollbar_state.rb +122 -0
- data/lib/ratatui_ruby/style/color.rb +149 -0
- data/lib/ratatui_ruby/style/style.rb +147 -0
- data/lib/ratatui_ruby/style.rb +19 -0
- data/lib/ratatui_ruby/symbols.rb +435 -0
- data/lib/ratatui_ruby/synthetic_events.rb +106 -0
- data/lib/ratatui_ruby/table_state.rb +251 -0
- data/lib/ratatui_ruby/terminal/capabilities.rb +316 -0
- data/lib/ratatui_ruby/terminal/viewport.rb +80 -0
- data/lib/ratatui_ruby/terminal.rb +66 -0
- data/lib/ratatui_ruby/terminal_lifecycle.rb +303 -0
- data/lib/ratatui_ruby/terminal_lifecycle.rb.bak +197 -0
- data/lib/ratatui_ruby/test_helper/event_injection.rb +241 -0
- data/lib/ratatui_ruby/test_helper/global_state.rb +111 -0
- data/lib/ratatui_ruby/test_helper/snapshot.rb +568 -0
- data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.ansi +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.txt +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.ansi +5 -0
- data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.txt +5 -0
- data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.ansi +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.txt +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/my_snapshot.txt +1 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.ansi +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.txt +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.ansi +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.txt +10 -0
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +449 -0
- data/lib/ratatui_ruby/test_helper/subprocess_timeout.rb +35 -0
- data/lib/ratatui_ruby/test_helper/terminal.rb +187 -0
- data/lib/ratatui_ruby/test_helper/test_doubles.rb +86 -0
- data/lib/ratatui_ruby/test_helper.rb +115 -0
- data/lib/ratatui_ruby/text/line.rb +245 -0
- data/lib/ratatui_ruby/text/span.rb +158 -0
- data/lib/ratatui_ruby/text.rb +99 -0
- data/lib/ratatui_ruby/tui/buffer_factories.rb +22 -0
- data/lib/ratatui_ruby/tui/canvas_factories.rb +149 -0
- data/lib/ratatui_ruby/tui/core.rb +67 -0
- data/lib/ratatui_ruby/tui/layout_factories.rb +153 -0
- data/lib/ratatui_ruby/tui/state_factories.rb +77 -0
- data/lib/ratatui_ruby/tui/style_factories.rb +22 -0
- data/lib/ratatui_ruby/tui/text_factories.rb +86 -0
- data/lib/ratatui_ruby/tui/widget_factories.rb +272 -0
- data/lib/ratatui_ruby/tui.rb +106 -0
- data/lib/ratatui_ruby/version.rb +12 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +51 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +29 -0
- data/lib/ratatui_ruby/widgets/bar_chart.rb +308 -0
- data/lib/ratatui_ruby/widgets/block.rb +266 -0
- data/lib/ratatui_ruby/widgets/calendar.rb +88 -0
- data/lib/ratatui_ruby/widgets/canvas.rb +297 -0
- data/lib/ratatui_ruby/widgets/cell.rb +59 -0
- data/lib/ratatui_ruby/widgets/center.rb +71 -0
- data/lib/ratatui_ruby/widgets/chart.rb +172 -0
- data/lib/ratatui_ruby/widgets/clear.rb +66 -0
- data/lib/ratatui_ruby/widgets/coerceable_widget.rb +77 -0
- data/lib/ratatui_ruby/widgets/cursor.rb +54 -0
- data/lib/ratatui_ruby/widgets/gauge.rb +146 -0
- data/lib/ratatui_ruby/widgets/line_gauge.rb +158 -0
- data/lib/ratatui_ruby/widgets/list.rb +252 -0
- data/lib/ratatui_ruby/widgets/list_item.rb +55 -0
- data/lib/ratatui_ruby/widgets/overlay.rb +55 -0
- data/lib/ratatui_ruby/widgets/paragraph.rb +113 -0
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +35 -0
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +40 -0
- data/lib/ratatui_ruby/widgets/row.rb +123 -0
- data/lib/ratatui_ruby/widgets/scrollbar.rb +147 -0
- data/lib/ratatui_ruby/widgets/shape/label.rb +80 -0
- data/lib/ratatui_ruby/widgets/sparkline.rb +153 -0
- data/lib/ratatui_ruby/widgets/table.rb +213 -0
- data/lib/ratatui_ruby/widgets/tabs.rb +91 -0
- data/lib/ratatui_ruby/widgets.rb +43 -0
- data/lib/ratatui_ruby.rb +555 -0
- data/sig/examples/app_all_events/app.rbs +11 -0
- data/sig/examples/app_all_events/model/app_model.rbs +23 -0
- data/sig/examples/app_all_events/model/event_entry.rbs +23 -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 +14 -0
- data/sig/examples/app_cli_rich_moments/app.rbs +12 -0
- data/sig/examples/app_color_picker/app.rbs +17 -0
- data/sig/examples/app_external_editor/app.rbs +12 -0
- data/sig/examples/app_login_form/app.rbs +11 -0
- data/sig/examples/app_stateful_interaction/app.rbs +39 -0
- data/sig/examples/verify_quickstart_dsl/app.rbs +17 -0
- data/sig/examples/verify_quickstart_lifecycle/app.rbs +17 -0
- data/sig/examples/verify_readme_usage/app.rbs +17 -0
- data/sig/examples/widget_block_demo/app.rbs +38 -0
- data/sig/examples/widget_box_demo/app.rbs +17 -0
- data/sig/examples/widget_calendar_demo/app.rbs +17 -0
- data/sig/examples/widget_cell_demo/app.rbs +17 -0
- data/sig/examples/widget_chart_demo/app.rbs +17 -0
- data/sig/examples/widget_gauge_demo/app.rbs +17 -0
- data/sig/examples/widget_layout_split/app.rbs +16 -0
- data/sig/examples/widget_line_gauge_demo/app.rbs +17 -0
- data/sig/examples/widget_list_demo/app.rbs +17 -0
- data/sig/examples/widget_map_demo/app.rbs +17 -0
- data/sig/examples/widget_popup_demo/app.rbs +17 -0
- data/sig/examples/widget_ratatui_logo_demo/app.rbs +17 -0
- data/sig/examples/widget_ratatui_mascot_demo/app.rbs +17 -0
- data/sig/examples/widget_rect/app.rbs +18 -0
- data/sig/examples/widget_render/app.rbs +16 -0
- data/sig/examples/widget_rich_text/app.rbs +17 -0
- data/sig/examples/widget_scroll_text/app.rbs +17 -0
- data/sig/examples/widget_scrollbar_demo/app.rbs +17 -0
- data/sig/examples/widget_sparkline_demo/app.rbs +16 -0
- data/sig/examples/widget_style_colors/app.rbs +20 -0
- data/sig/examples/widget_table_demo/app.rbs +17 -0
- data/sig/examples/widget_text_width/app.rbs +16 -0
- data/sig/generated/event_key_predicates.rbs +1348 -0
- data/sig/manifest.yaml +5 -0
- data/sig/patches/data.rbs +26 -0
- data/sig/patches/debugger__.rbs +8 -0
- data/sig/ratatui_ruby/backend/window_size.rbs +17 -0
- data/sig/ratatui_ruby/backend.rbs +12 -0
- data/sig/ratatui_ruby/buffer/cell.rbs +46 -0
- data/sig/ratatui_ruby/buffer.rbs +18 -0
- data/sig/ratatui_ruby/cell.rbs +44 -0
- data/sig/ratatui_ruby/clear.rbs +18 -0
- data/sig/ratatui_ruby/constraint.rbs +26 -0
- data/sig/ratatui_ruby/debug.rbs +45 -0
- data/sig/ratatui_ruby/draw.rbs +30 -0
- data/sig/ratatui_ruby/event.rbs +249 -0
- data/sig/ratatui_ruby/frame.rbs +23 -0
- data/sig/ratatui_ruby/interfaces.rbs +25 -0
- data/sig/ratatui_ruby/labs.rbs +90 -0
- data/sig/ratatui_ruby/layout/alignment.rbs +26 -0
- data/sig/ratatui_ruby/layout/constraint.rbs +39 -0
- data/sig/ratatui_ruby/layout/layout.rbs +45 -0
- data/sig/ratatui_ruby/layout/position.rbs +18 -0
- data/sig/ratatui_ruby/layout/rect.rbs +64 -0
- data/sig/ratatui_ruby/layout/size.rbs +18 -0
- data/sig/ratatui_ruby/list_state.rbs +23 -0
- data/sig/ratatui_ruby/output_guard.rbs +23 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +113 -0
- data/sig/ratatui_ruby/rect.rbs +17 -0
- data/sig/ratatui_ruby/scrollbar_state.rbs +24 -0
- data/sig/ratatui_ruby/session.rbs +93 -0
- data/sig/ratatui_ruby/style/color.rbs +22 -0
- data/sig/ratatui_ruby/style/style.rbs +29 -0
- data/sig/ratatui_ruby/symbols.rbs +141 -0
- data/sig/ratatui_ruby/synthetic_events.rbs +24 -0
- data/sig/ratatui_ruby/table_state.rbs +27 -0
- data/sig/ratatui_ruby/terminal/capabilities.rbs +38 -0
- data/sig/ratatui_ruby/terminal/viewport.rbs +33 -0
- data/sig/ratatui_ruby/terminal_lifecycle.rbs +39 -0
- data/sig/ratatui_ruby/test_helper/event_injection.rbs +22 -0
- data/sig/ratatui_ruby/test_helper/snapshot.rbs +37 -0
- data/sig/ratatui_ruby/test_helper/style_assertions.rbs +77 -0
- data/sig/ratatui_ruby/test_helper/terminal.rbs +20 -0
- data/sig/ratatui_ruby/test_helper/test_doubles.rbs +32 -0
- data/sig/ratatui_ruby/test_helper.rbs +18 -0
- data/sig/ratatui_ruby/text/line.rbs +27 -0
- data/sig/ratatui_ruby/text/span.rbs +23 -0
- data/sig/ratatui_ruby/text.rbs +12 -0
- data/sig/ratatui_ruby/tui/buffer_factories.rbs +16 -0
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +38 -0
- data/sig/ratatui_ruby/tui/core.rbs +23 -0
- data/sig/ratatui_ruby/tui/layout_factories.rbs +39 -0
- data/sig/ratatui_ruby/tui/state_factories.rbs +23 -0
- data/sig/ratatui_ruby/tui/style_factories.rbs +18 -0
- data/sig/ratatui_ruby/tui/text_factories.rbs +23 -0
- data/sig/ratatui_ruby/tui/widget_factories.rbs +138 -0
- data/sig/ratatui_ruby/tui.rbs +25 -0
- data/sig/ratatui_ruby/version.rbs +12 -0
- data/sig/ratatui_ruby/widgets/bar_chart.rbs +95 -0
- data/sig/ratatui_ruby/widgets/block.rbs +51 -0
- data/sig/ratatui_ruby/widgets/calendar.rbs +45 -0
- data/sig/ratatui_ruby/widgets/canvas.rbs +95 -0
- data/sig/ratatui_ruby/widgets/chart.rbs +91 -0
- data/sig/ratatui_ruby/widgets/coerceable_widget.rbs +26 -0
- data/sig/ratatui_ruby/widgets/gauge.rbs +44 -0
- data/sig/ratatui_ruby/widgets/line_gauge.rbs +48 -0
- data/sig/ratatui_ruby/widgets/list.rbs +63 -0
- data/sig/ratatui_ruby/widgets/misc.rbs +158 -0
- data/sig/ratatui_ruby/widgets/paragraph.rbs +45 -0
- data/sig/ratatui_ruby/widgets/row.rbs +43 -0
- data/sig/ratatui_ruby/widgets/scrollbar.rbs +53 -0
- data/sig/ratatui_ruby/widgets/shape/label.rbs +37 -0
- data/sig/ratatui_ruby/widgets/sparkline.rbs +45 -0
- data/sig/ratatui_ruby/widgets/table.rbs +78 -0
- data/sig/ratatui_ruby/widgets/tabs.rbs +44 -0
- data/sig/ratatui_ruby/widgets.rbs +16 -0
- data/vendor/goodcop/base.yml +1047 -0
- metadata +729 -0
data/lib/ratatui_ruby.rb
ADDED
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
8
|
+
require_relative "ratatui_ruby/version"
|
|
9
|
+
|
|
10
|
+
# Core types (mirrors ratatui Rust crate)
|
|
11
|
+
require_relative "ratatui_ruby/layout" # Layout::Rect, Layout::Constraint, Layout::Layout
|
|
12
|
+
require_relative "ratatui_ruby/style" # Style::Style
|
|
13
|
+
require_relative "ratatui_ruby/widgets" # Widgets::Block, Widgets::Paragraph, etc.
|
|
14
|
+
require_relative "ratatui_ruby/buffer" # Buffer::Cell (for inspection)
|
|
15
|
+
require_relative "ratatui_ruby/text" # Text::Span, Text::Line, Text.width
|
|
16
|
+
require_relative "ratatui_ruby/draw" # Draw commands
|
|
17
|
+
require_relative "ratatui_ruby/symbols" # Symbols::Shade, etc.
|
|
18
|
+
require_relative "ratatui_ruby/backend" # Backend::WindowSize
|
|
19
|
+
require_relative "ratatui_ruby/terminal/viewport" # Terminal::Viewport
|
|
20
|
+
require_relative "ratatui_ruby/terminal" # Terminal class
|
|
21
|
+
|
|
22
|
+
# Event types
|
|
23
|
+
require_relative "ratatui_ruby/event"
|
|
24
|
+
|
|
25
|
+
# Frame and state objects
|
|
26
|
+
require_relative "ratatui_ruby/frame"
|
|
27
|
+
require_relative "ratatui_ruby/list_state"
|
|
28
|
+
require_relative "ratatui_ruby/table_state"
|
|
29
|
+
require_relative "ratatui_ruby/scrollbar_state"
|
|
30
|
+
|
|
31
|
+
# Behavioral mixins
|
|
32
|
+
require_relative "ratatui_ruby/output_guard"
|
|
33
|
+
require_relative "ratatui_ruby/terminal_lifecycle"
|
|
34
|
+
|
|
35
|
+
# TUI facade (for external instantiation and caching)
|
|
36
|
+
require_relative "ratatui_ruby/tui"
|
|
37
|
+
|
|
38
|
+
# Synthetic events queue (for async synchronization)
|
|
39
|
+
require_relative "ratatui_ruby/synthetic_events"
|
|
40
|
+
|
|
41
|
+
begin
|
|
42
|
+
require "ratatui_ruby/ratatui_ruby"
|
|
43
|
+
rescue LoadError
|
|
44
|
+
# Fallback for development/CI if the bundle is not in the load path
|
|
45
|
+
require_relative "ratatui_ruby/ratatui_ruby"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Debug mode (for Rust backtraces and diagnostic features)
|
|
49
|
+
# Loaded after native extension so _enable_rust_backtrace is defined
|
|
50
|
+
require_relative "ratatui_ruby/debug"
|
|
51
|
+
|
|
52
|
+
# Experimental lab features (RR_LABS env var)
|
|
53
|
+
require_relative "ratatui_ruby/labs"
|
|
54
|
+
|
|
55
|
+
# Main entry point for the library.
|
|
56
|
+
#
|
|
57
|
+
# Terminal UIs require low-level control using C/Rust and high-level abstraction in Ruby.
|
|
58
|
+
#
|
|
59
|
+
# This module bridges the gap. It provides the native methods to initialize the terminal, handle raw mode, and render the widget tree.
|
|
60
|
+
#
|
|
61
|
+
# Use `RatatuiRuby.run` to start your application.
|
|
62
|
+
module RatatuiRuby
|
|
63
|
+
# Base error class for RatatuiRuby.
|
|
64
|
+
#
|
|
65
|
+
# All library-specific exceptions inherit from this class.
|
|
66
|
+
# Catch this to handle any RatatuiRuby error generically.
|
|
67
|
+
#
|
|
68
|
+
# === Example
|
|
69
|
+
#
|
|
70
|
+
#--
|
|
71
|
+
# SPDX-SnippetBegin
|
|
72
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
73
|
+
# SPDX-License-Identifier: MIT-0
|
|
74
|
+
#++
|
|
75
|
+
# begin
|
|
76
|
+
# RatatuiRuby.run { |tui| ... }
|
|
77
|
+
# rescue RatatuiRuby::Error => e
|
|
78
|
+
# puts "RatatuiRuby error: #{e.message}"
|
|
79
|
+
# end
|
|
80
|
+
#--
|
|
81
|
+
# SPDX-SnippetEnd
|
|
82
|
+
#++
|
|
83
|
+
class Error < StandardError
|
|
84
|
+
# Operational failure during terminal I/O.
|
|
85
|
+
#
|
|
86
|
+
# Terminals are finnicky. I/O can fail. Backends can crash.
|
|
87
|
+
# These are runtime problems outside your control.
|
|
88
|
+
#
|
|
89
|
+
# This error signals the terminal operation itself failed.
|
|
90
|
+
# The library tried to do something with the terminal and couldn't.
|
|
91
|
+
#
|
|
92
|
+
# Catch this to handle terminal failures gracefully.
|
|
93
|
+
#
|
|
94
|
+
# === Example
|
|
95
|
+
#
|
|
96
|
+
#--
|
|
97
|
+
# SPDX-SnippetBegin
|
|
98
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
99
|
+
# SPDX-License-Identifier: MIT-0
|
|
100
|
+
#++
|
|
101
|
+
# begin
|
|
102
|
+
# RatatuiRuby.init_terminal
|
|
103
|
+
# rescue RatatuiRuby::Error::Terminal => e
|
|
104
|
+
# puts "Terminal failed: #{e.message}"
|
|
105
|
+
# end
|
|
106
|
+
#--
|
|
107
|
+
# SPDX-SnippetEnd
|
|
108
|
+
#++
|
|
109
|
+
class Terminal < Error; end
|
|
110
|
+
|
|
111
|
+
# Object lifetime violation.
|
|
112
|
+
#
|
|
113
|
+
# Some objects are only valid during specific scopes.
|
|
114
|
+
# Using them after their scope ends causes undefined behavior.
|
|
115
|
+
#
|
|
116
|
+
# This error prevents use-after-scope bugs.
|
|
117
|
+
# The object you're accessing is no longer valid.
|
|
118
|
+
#
|
|
119
|
+
# To resolve, ensure scoped objects are used only within their
|
|
120
|
+
# valid lifetime (e.g., inside the block where they're created).
|
|
121
|
+
#
|
|
122
|
+
# === Example
|
|
123
|
+
#
|
|
124
|
+
#--
|
|
125
|
+
# SPDX-SnippetBegin
|
|
126
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
127
|
+
# SPDX-License-Identifier: MIT-0
|
|
128
|
+
#++
|
|
129
|
+
# stored_frame = nil
|
|
130
|
+
# RatatuiRuby.draw { |frame| stored_frame = frame }
|
|
131
|
+
# stored_frame.area # => raises Error::Safety
|
|
132
|
+
#--
|
|
133
|
+
# SPDX-SnippetEnd
|
|
134
|
+
#++
|
|
135
|
+
class Safety < Error; end
|
|
136
|
+
|
|
137
|
+
# Invariant violation.
|
|
138
|
+
#
|
|
139
|
+
# The library enforces rules about valid states and contracts.
|
|
140
|
+
# Breaking these rules raises this error.
|
|
141
|
+
#
|
|
142
|
+
# Common causes:
|
|
143
|
+
# - Calling methods in the wrong order (e.g., <tt>init_terminal</tt> twice)
|
|
144
|
+
# - Callable return type mismatch (e.g., view returns <tt>nil</tt> instead of a widget)
|
|
145
|
+
#
|
|
146
|
+
# To resolve, check the method's documented contract. Ensure
|
|
147
|
+
# state preconditions are met and return types are correct.
|
|
148
|
+
#
|
|
149
|
+
# === Example
|
|
150
|
+
#
|
|
151
|
+
#--
|
|
152
|
+
# SPDX-SnippetBegin
|
|
153
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
154
|
+
# SPDX-License-Identifier: MIT-0
|
|
155
|
+
#++
|
|
156
|
+
# RatatuiRuby.init_terminal
|
|
157
|
+
# RatatuiRuby.init_terminal # => raises Error::Invariant
|
|
158
|
+
#--
|
|
159
|
+
# SPDX-SnippetEnd
|
|
160
|
+
#++
|
|
161
|
+
class Invariant < Error; end
|
|
162
|
+
|
|
163
|
+
# Framework bug.
|
|
164
|
+
#
|
|
165
|
+
# This error indicates a bug within the RatatuiRuby framework itself.
|
|
166
|
+
# If you encounter this, the framework is broken — please report it.
|
|
167
|
+
#
|
|
168
|
+
# Normal application errors use standard exceptions like ArgumentError.
|
|
169
|
+
# This exception class distinguishes "our bug" from "your bug".
|
|
170
|
+
class Internal < Error; end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Mix in terminal lifecycle and output protection methods
|
|
174
|
+
extend OutputGuard
|
|
175
|
+
extend TerminalLifecycle
|
|
176
|
+
|
|
177
|
+
@experimental_warnings = true
|
|
178
|
+
@tui_session_active = false
|
|
179
|
+
@headless_mode = false
|
|
180
|
+
@deferred_warnings = [] #: Array[String]
|
|
181
|
+
|
|
182
|
+
class << self
|
|
183
|
+
##
|
|
184
|
+
# :attr_accessor: experimental_warnings
|
|
185
|
+
# Whether to show warnings when using experimental features (default: true).
|
|
186
|
+
attr_accessor :experimental_warnings
|
|
187
|
+
|
|
188
|
+
private def queue_warning(message)
|
|
189
|
+
@deferred_warnings << message
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
private def flush_warnings
|
|
193
|
+
return if @deferred_warnings.empty?
|
|
194
|
+
@deferred_warnings.each { |msg| warn msg }
|
|
195
|
+
@deferred_warnings.clear
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
private def flush_panic_info
|
|
199
|
+
return unless Debug.rust_backtrace_enabled?
|
|
200
|
+
panic_info = _get_last_panic
|
|
201
|
+
return unless panic_info
|
|
202
|
+
warn panic_info
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
##
|
|
207
|
+
# :singleton-method: inject_test_event
|
|
208
|
+
# Injects a mock event into the event queue for testing purposes.
|
|
209
|
+
# [event_type] "key" or "mouse"
|
|
210
|
+
# [data] a Hash containing event data
|
|
211
|
+
#
|
|
212
|
+
#--
|
|
213
|
+
# SPDX-SnippetBegin
|
|
214
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
215
|
+
# SPDX-License-Identifier: MIT-0
|
|
216
|
+
#++
|
|
217
|
+
# inject_test_event("key", { code: "a" })
|
|
218
|
+
#
|
|
219
|
+
#--
|
|
220
|
+
# SPDX-SnippetEnd
|
|
221
|
+
#++
|
|
222
|
+
# (Native method implemented in Rust)
|
|
223
|
+
|
|
224
|
+
##
|
|
225
|
+
# Warns about usage of an experimental feature unless warnings are suppressed.
|
|
226
|
+
#
|
|
227
|
+
# [feature_name] String name of the feature (e.g., "Paragraph#line_count")
|
|
228
|
+
#
|
|
229
|
+
# This warns only once per feature name per session.
|
|
230
|
+
def self.warn_experimental_feature(feature_name)
|
|
231
|
+
return unless experimental_warnings
|
|
232
|
+
|
|
233
|
+
@warned_features ||= {} #: Hash[String, bool]
|
|
234
|
+
return if @warned_features[feature_name]
|
|
235
|
+
|
|
236
|
+
message = "WARNING: #{feature_name} is an experimental feature and may change in future versions. Disable this warning with RatatuiRuby.experimental_warnings = false."
|
|
237
|
+
if terminal_active?
|
|
238
|
+
queue_warning(message)
|
|
239
|
+
else
|
|
240
|
+
warn message
|
|
241
|
+
end
|
|
242
|
+
@warned_features[feature_name] = true
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# (Native methods implemented in Rust)
|
|
246
|
+
private_class_method :_init_terminal, :_restore_terminal, :_init_test_terminal, :_enable_rust_backtrace, :_get_last_panic
|
|
247
|
+
|
|
248
|
+
##
|
|
249
|
+
# Enables full debug mode.
|
|
250
|
+
#
|
|
251
|
+
# Convenience alias for Debug.enable!.
|
|
252
|
+
#
|
|
253
|
+
# === Example
|
|
254
|
+
#
|
|
255
|
+
#--
|
|
256
|
+
# SPDX-SnippetBegin
|
|
257
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
258
|
+
# SPDX-License-Identifier: MIT-0
|
|
259
|
+
#++
|
|
260
|
+
# RatatuiRuby.debug_mode!
|
|
261
|
+
#
|
|
262
|
+
#--
|
|
263
|
+
# SPDX-SnippetEnd
|
|
264
|
+
#++
|
|
265
|
+
def self.debug_mode!
|
|
266
|
+
Debug.enable!
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
##
|
|
270
|
+
# Draws the given UI node tree to the terminal.
|
|
271
|
+
#
|
|
272
|
+
# TUI applications need to render widgets to the screen. Rendering could
|
|
273
|
+
# happen all at once with a pre-built tree, or incrementally with direct
|
|
274
|
+
# frame access.
|
|
275
|
+
#
|
|
276
|
+
# This method handles both. Pass a tree for declarative rendering, or
|
|
277
|
+
# pass a block to manipulate the frame directly. The block receives a
|
|
278
|
+
# {Frame} object for imperative drawing.
|
|
279
|
+
#
|
|
280
|
+
# [tree] A widget tree (Widgets::Paragraph, Layout::Layout, etc.) to render. Optional if
|
|
281
|
+
#--
|
|
282
|
+
# SPDX-SnippetBegin
|
|
283
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
284
|
+
# SPDX-License-Identifier: MIT-0
|
|
285
|
+
#++
|
|
286
|
+
# a block is given.
|
|
287
|
+
#
|
|
288
|
+
#--
|
|
289
|
+
# SPDX-SnippetEnd
|
|
290
|
+
#++
|
|
291
|
+
# === Examples
|
|
292
|
+
#
|
|
293
|
+
# Legacy declarative style (tree-based):
|
|
294
|
+
#
|
|
295
|
+
#--
|
|
296
|
+
# SPDX-SnippetBegin
|
|
297
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
298
|
+
# SPDX-License-Identifier: MIT-0
|
|
299
|
+
#++
|
|
300
|
+
# RatatuiRuby.draw(Widgets::Paragraph.new(text: "Hello"))
|
|
301
|
+
#
|
|
302
|
+
#--
|
|
303
|
+
# SPDX-SnippetEnd
|
|
304
|
+
#++
|
|
305
|
+
# New imperative style (block-based):
|
|
306
|
+
#
|
|
307
|
+
#--
|
|
308
|
+
# SPDX-SnippetBegin
|
|
309
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
310
|
+
# SPDX-License-Identifier: MIT-0
|
|
311
|
+
#++
|
|
312
|
+
# RatatuiRuby.draw do |frame|
|
|
313
|
+
# frame.render_widget(Widgets::Paragraph.new(text: "Hello"), frame.area)
|
|
314
|
+
# end
|
|
315
|
+
#
|
|
316
|
+
#--
|
|
317
|
+
# SPDX-SnippetEnd
|
|
318
|
+
#++
|
|
319
|
+
def self.draw(tree = nil, &block)
|
|
320
|
+
if tree && block
|
|
321
|
+
raise ArgumentError, "Cannot provide both a tree and a block to draw"
|
|
322
|
+
end
|
|
323
|
+
unless tree || block
|
|
324
|
+
raise ArgumentError, "Must provide either a tree or a block to draw"
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
if tree
|
|
328
|
+
_draw(tree)
|
|
329
|
+
elsif block
|
|
330
|
+
# Wrap user block to flush A11Y capture after user code
|
|
331
|
+
if Labs.enabled?(:a11y)
|
|
332
|
+
_draw do |frame|
|
|
333
|
+
block.call(frame)
|
|
334
|
+
frame.flush_a11y_capture
|
|
335
|
+
end
|
|
336
|
+
else
|
|
337
|
+
_draw(&block)
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# (Native method _draw implemented in Rust)
|
|
343
|
+
private_class_method :_draw
|
|
344
|
+
|
|
345
|
+
##
|
|
346
|
+
# Checks for user input.
|
|
347
|
+
#
|
|
348
|
+
# Interactive apps must respond to input. Loops need to poll without burning CPU.
|
|
349
|
+
#
|
|
350
|
+
# This method checks for an event. It returns the event if one is found. It returns {RatatuiRuby::Event::None} if the timeout expires.
|
|
351
|
+
#
|
|
352
|
+
# [timeout] Float seconds to wait (default: 0.016).
|
|
353
|
+
#--
|
|
354
|
+
# SPDX-SnippetBegin
|
|
355
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
356
|
+
# SPDX-License-Identifier: MIT-0
|
|
357
|
+
#++
|
|
358
|
+
# Pass <tt>nil</tt> to block indefinitely (wait forever).
|
|
359
|
+
# Pass <tt>0.0</tt> for a non-blocking check.
|
|
360
|
+
#
|
|
361
|
+
#--
|
|
362
|
+
# SPDX-SnippetEnd
|
|
363
|
+
#++
|
|
364
|
+
# === Examples
|
|
365
|
+
#
|
|
366
|
+
#--
|
|
367
|
+
# SPDX-SnippetBegin
|
|
368
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
369
|
+
# SPDX-License-Identifier: MIT-0
|
|
370
|
+
#++
|
|
371
|
+
# # Standard loop (approx 60 FPS)
|
|
372
|
+
# event = RatatuiRuby.poll_event
|
|
373
|
+
#
|
|
374
|
+
# # Block until event (pauses execution)
|
|
375
|
+
# event = RatatuiRuby.poll_event(timeout: nil)
|
|
376
|
+
#
|
|
377
|
+
# # Non-blocking check (returns immediately)
|
|
378
|
+
# event = RatatuiRuby.poll_event(timeout: 0.0)
|
|
379
|
+
#
|
|
380
|
+
#--
|
|
381
|
+
# SPDX-SnippetEnd
|
|
382
|
+
#++
|
|
383
|
+
def self.poll_event(timeout: 0.016)
|
|
384
|
+
raise ArgumentError, "timeout must be non-negative" if timeout && timeout < 0
|
|
385
|
+
|
|
386
|
+
raw = _poll_event(timeout)
|
|
387
|
+
return Event::None.new.freeze if raw.nil?
|
|
388
|
+
|
|
389
|
+
case raw[:type]
|
|
390
|
+
when :key
|
|
391
|
+
Event::Key.new(
|
|
392
|
+
code: raw[:code],
|
|
393
|
+
modifiers: (raw[:modifiers] || []).freeze,
|
|
394
|
+
kind: raw[:kind] || :standard
|
|
395
|
+
).freeze
|
|
396
|
+
when :mouse
|
|
397
|
+
Event::Mouse.new(
|
|
398
|
+
kind: raw[:kind].to_s,
|
|
399
|
+
x: raw[:x],
|
|
400
|
+
y: raw[:y],
|
|
401
|
+
button: raw[:button].to_s,
|
|
402
|
+
modifiers: (raw[:modifiers] || []).freeze
|
|
403
|
+
).freeze
|
|
404
|
+
when :resize
|
|
405
|
+
Event::Resize.new(width: raw[:width], height: raw[:height]).freeze
|
|
406
|
+
when :paste
|
|
407
|
+
Event::Paste.new(content: raw[:content]).freeze
|
|
408
|
+
when :focus_gained
|
|
409
|
+
Event::FocusGained.new.freeze
|
|
410
|
+
when :focus_lost
|
|
411
|
+
Event::FocusLost.new.freeze
|
|
412
|
+
when :sync
|
|
413
|
+
Event::Sync.new.freeze
|
|
414
|
+
else
|
|
415
|
+
# Return None for unknown event types
|
|
416
|
+
Event::None.new.freeze
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
# (Native method _poll_event implemented in Rust)
|
|
421
|
+
private_class_method :_poll_event
|
|
422
|
+
|
|
423
|
+
##
|
|
424
|
+
# Inspects the terminal buffer at specific coordinates.
|
|
425
|
+
#
|
|
426
|
+
# When writing tests, you need to verify that your widget drew the correct characters and styles.
|
|
427
|
+
# This method provides deep inspection of the cell's state (symbol, colors, modifiers).
|
|
428
|
+
#
|
|
429
|
+
# Returns a {Buffer::Cell} object.
|
|
430
|
+
#
|
|
431
|
+
# Values depend on what the backend has rendered. If nothing has been rendered to a cell, it may contain defaults (empty symbol, nil colors).
|
|
432
|
+
#
|
|
433
|
+
# === Example
|
|
434
|
+
#
|
|
435
|
+
#--
|
|
436
|
+
# SPDX-SnippetBegin
|
|
437
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
438
|
+
# SPDX-License-Identifier: MIT-0
|
|
439
|
+
#++
|
|
440
|
+
# cell = RatatuiRuby.get_cell_at(10, 5)
|
|
441
|
+
# expect(cell.symbol).to eq("X")
|
|
442
|
+
# expect(cell.fg).to eq(:red)
|
|
443
|
+
# expect(cell).to be_bold
|
|
444
|
+
#
|
|
445
|
+
#--
|
|
446
|
+
# SPDX-SnippetEnd
|
|
447
|
+
#++
|
|
448
|
+
def self.get_cell_at(x, y)
|
|
449
|
+
raw = _get_cell_at(x, y)
|
|
450
|
+
Buffer::Cell.new(
|
|
451
|
+
char: raw["char"],
|
|
452
|
+
fg: raw["fg"],
|
|
453
|
+
bg: raw["bg"],
|
|
454
|
+
underline_color: raw["underline_color"],
|
|
455
|
+
modifiers: raw["modifiers"] || []
|
|
456
|
+
)
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
##
|
|
460
|
+
# Returns the current terminal viewport area.
|
|
461
|
+
#
|
|
462
|
+
# In inline viewports, this returns the viewport dimensions.
|
|
463
|
+
# In fullscreen mode, this returns the full terminal size.
|
|
464
|
+
#
|
|
465
|
+
# @return [Layout::Rect] The rendering viewport area
|
|
466
|
+
def self.get_viewport_area
|
|
467
|
+
raw = _get_terminal_area
|
|
468
|
+
Layout::Rect.new(
|
|
469
|
+
x: raw["x"],
|
|
470
|
+
y: raw["y"],
|
|
471
|
+
width: raw["width"],
|
|
472
|
+
height: raw["height"]
|
|
473
|
+
)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
##
|
|
477
|
+
# Returns the full terminal backend size.
|
|
478
|
+
#
|
|
479
|
+
# This is always the full terminal dimensions, regardless of viewport mode.
|
|
480
|
+
#
|
|
481
|
+
# === Example
|
|
482
|
+
#
|
|
483
|
+
#--
|
|
484
|
+
# SPDX-SnippetBegin
|
|
485
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
486
|
+
# SPDX-License-Identifier: MIT-0
|
|
487
|
+
#++
|
|
488
|
+
# size = RatatuiRuby.get_terminal_size
|
|
489
|
+
# puts "Terminal: #{size.width}x#{size.height}"
|
|
490
|
+
#
|
|
491
|
+
#--
|
|
492
|
+
# SPDX-SnippetEnd
|
|
493
|
+
#++
|
|
494
|
+
# @return [Layout::Rect] The full terminal size
|
|
495
|
+
def self.get_terminal_size
|
|
496
|
+
raw = _get_terminal_size
|
|
497
|
+
Layout::Rect.new(
|
|
498
|
+
x: raw["x"],
|
|
499
|
+
y: raw["y"],
|
|
500
|
+
width: raw["width"],
|
|
501
|
+
height: raw["height"]
|
|
502
|
+
)
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
# Ruby-idiomatic aliases (TIMTOWTDI)
|
|
506
|
+
class << self
|
|
507
|
+
# Aliases for get_terminal_size (full backend size)
|
|
508
|
+
alias get_terminal_area get_terminal_size
|
|
509
|
+
alias terminal_area get_terminal_size
|
|
510
|
+
alias terminal_size get_terminal_size
|
|
511
|
+
# Aliases for get_viewport_area (viewport rendering area)
|
|
512
|
+
alias get_viewport_size get_viewport_area
|
|
513
|
+
alias viewport_area get_viewport_area
|
|
514
|
+
alias viewport_size get_viewport_area
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
##
|
|
518
|
+
# Number of frames drawn since terminal initialization.
|
|
519
|
+
#
|
|
520
|
+
# TUI applications track render cycles for animations, FPS counters, or
|
|
521
|
+
# debugging. Manually counting draws is error-prone and clutters app logic.
|
|
522
|
+
#
|
|
523
|
+
# This method queries the terminal's internal frame counter. It starts at 0
|
|
524
|
+
# when the terminal initializes and increments by 1 after each successful
|
|
525
|
+
# draw. Restoring and re-initializing resets the counter.
|
|
526
|
+
#
|
|
527
|
+
# Raises RatatuiRuby::Error::Invariant if terminal not initialized.
|
|
528
|
+
def self.frame_count
|
|
529
|
+
_frame_count
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
# (Native methods implemented in Rust)
|
|
533
|
+
private_class_method :_get_cell_at, :_get_terminal_size, :_frame_count
|
|
534
|
+
|
|
535
|
+
# Hide native Layout._split helper
|
|
536
|
+
Layout::Layout.singleton_class.__send__(:private, :_split)
|
|
537
|
+
|
|
538
|
+
# Raw Terminal bindings - use public wrappers (they have timeout guards)
|
|
539
|
+
Terminal.singleton_class.__send__(:private, :_available_color_count)
|
|
540
|
+
Terminal.singleton_class.__send__(:private, :_supports_keyboard_enhancement)
|
|
541
|
+
|
|
542
|
+
# --- Terminal Safety Hooks ---
|
|
543
|
+
# These ensure the terminal is restored even on unexpected exits.
|
|
544
|
+
|
|
545
|
+
at_exit do
|
|
546
|
+
restore_terminal if terminal_active?
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
%i[INT TERM].each do |signal|
|
|
550
|
+
trap(signal) do
|
|
551
|
+
restore_terminal if terminal_active?
|
|
552
|
+
exit(128 + Signal.list[signal.to_s])
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
# MVU application model for the All Events example.
|
|
5
|
+
class AppModel < Data
|
|
6
|
+
HIGHLIGHT_DURATION_MS: Integer
|
|
7
|
+
|
|
8
|
+
attr_reader entries: Array[EventEntry]
|
|
9
|
+
attr_reader focused: bool
|
|
10
|
+
attr_reader window_size: [Integer, Integer]
|
|
11
|
+
attr_reader lit_types: Hash[Symbol, Timestamp]
|
|
12
|
+
attr_reader none_count: Integer
|
|
13
|
+
attr_reader color_cycle_index: Integer
|
|
14
|
+
|
|
15
|
+
def self.initial: () -> instance
|
|
16
|
+
def count: (Symbol type) -> Integer
|
|
17
|
+
def sub_counts: (Symbol type) -> Hash[String, Integer]
|
|
18
|
+
def lit?: (Symbol type) -> bool
|
|
19
|
+
def visible: (Integer max_entries) -> Array[EventEntry]
|
|
20
|
+
def empty?: () -> bool
|
|
21
|
+
def live_event: (Symbol type) -> { time: Time, description: String }?
|
|
22
|
+
def next_color: () -> Symbol
|
|
23
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
# Type alias for any Event subtype.
|
|
5
|
+
type event_type = RatatuiRuby::Event::Key
|
|
6
|
+
| RatatuiRuby::Event::Mouse
|
|
7
|
+
| RatatuiRuby::Event::Resize
|
|
8
|
+
| RatatuiRuby::Event::Paste
|
|
9
|
+
| RatatuiRuby::Event::FocusGained
|
|
10
|
+
| RatatuiRuby::Event::FocusLost
|
|
11
|
+
| RatatuiRuby::Event::None
|
|
12
|
+
|
|
13
|
+
class EventEntry < Data
|
|
14
|
+
attr_reader event: event_type
|
|
15
|
+
attr_reader color: Symbol
|
|
16
|
+
attr_reader timestamp: Timestamp
|
|
17
|
+
|
|
18
|
+
def self.create: (event_type event, Symbol color, Timestamp timestamp) -> instance
|
|
19
|
+
def type: () -> Symbol
|
|
20
|
+
def description: () -> String
|
|
21
|
+
def matches_type?: (Symbol check_type) -> bool
|
|
22
|
+
def live_type: () -> Symbol
|
|
23
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
class Timestamp < Data
|
|
5
|
+
attr_reader milliseconds: Integer
|
|
6
|
+
|
|
7
|
+
def self.now: () -> instance
|
|
8
|
+
def self.current: () -> Integer
|
|
9
|
+
def elapsed?: (Integer duration_ms) -> bool
|
|
10
|
+
def self.new: (?milliseconds: _ToI) -> instance
|
|
11
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
8
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
9
|
+
|
|
10
|
+
module View
|
|
11
|
+
interface _View
|
|
12
|
+
def call: (AppModel model, RatatuiRuby::TUI tui, RatatuiRuby::Frame frame, RatatuiRuby::Layout::Rect area) -> void
|
|
13
|
+
end
|
|
14
|
+
end
|