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
|
@@ -0,0 +1,291 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
9
|
+
class Event
|
|
10
|
+
# Reports a mouse interaction.
|
|
11
|
+
#
|
|
12
|
+
# Modern terminals support rich pointer input, but the protocols are complex and varied.
|
|
13
|
+
# Handling clicks, drags, and scrolls requires robust parsing.
|
|
14
|
+
#
|
|
15
|
+
# This event simplifies the complexity. It tells you exactly *what* happened (+kind+),
|
|
16
|
+
# *where* it happened (+x+, +y+), and *which* button was involved.
|
|
17
|
+
#
|
|
18
|
+
# Use this to build interactive UIs. Implement click handlers, draggable sliders, or
|
|
19
|
+
# scrollable viewports with confidence.
|
|
20
|
+
#
|
|
21
|
+
# === Example
|
|
22
|
+
#
|
|
23
|
+
#--
|
|
24
|
+
# SPDX-SnippetBegin
|
|
25
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
26
|
+
# SPDX-License-Identifier: MIT-0
|
|
27
|
+
#++
|
|
28
|
+
# if event.mouse? && event.down? && event.button == "left"
|
|
29
|
+
# puts "Left click at #{event.x}, #{event.y}"
|
|
30
|
+
# end
|
|
31
|
+
#--
|
|
32
|
+
# SPDX-SnippetEnd
|
|
33
|
+
#++
|
|
34
|
+
class Mouse < Event
|
|
35
|
+
# The kind of event (<tt>"down"</tt>, <tt>"up"</tt>, <tt>"drag"</tt>, <tt>"moved"</tt>, <tt>"scroll_up"</tt>, <tt>"scroll_down"</tt>).
|
|
36
|
+
#
|
|
37
|
+
# puts event.kind # => "down"
|
|
38
|
+
attr_reader :kind
|
|
39
|
+
# X coordinate (column).
|
|
40
|
+
#
|
|
41
|
+
# puts event.x # => 10
|
|
42
|
+
attr_reader :x
|
|
43
|
+
# Y coordinate (row).
|
|
44
|
+
#
|
|
45
|
+
# puts event.y # => 5
|
|
46
|
+
attr_reader :y
|
|
47
|
+
# The button pressed (<tt>"left"</tt>, <tt>"right"</tt>, <tt>"middle"</tt>, <tt>"none"</tt>).
|
|
48
|
+
#
|
|
49
|
+
#--
|
|
50
|
+
# SPDX-SnippetBegin
|
|
51
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
52
|
+
# SPDX-License-Identifier: MIT-0
|
|
53
|
+
#++
|
|
54
|
+
# puts event.button # => "left"
|
|
55
|
+
#
|
|
56
|
+
#--
|
|
57
|
+
# SPDX-SnippetEnd
|
|
58
|
+
#++
|
|
59
|
+
# Can be <tt>nil</tt>, which is treated as <tt>"none"</tt>.
|
|
60
|
+
attr_reader :button
|
|
61
|
+
# List of active modifiers.
|
|
62
|
+
#
|
|
63
|
+
# puts event.modifiers # => ["ctrl"]
|
|
64
|
+
attr_reader :modifiers
|
|
65
|
+
|
|
66
|
+
# Returns true for Mouse events.
|
|
67
|
+
#
|
|
68
|
+
#--
|
|
69
|
+
# SPDX-SnippetBegin
|
|
70
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
71
|
+
# SPDX-License-Identifier: MIT-0
|
|
72
|
+
#++
|
|
73
|
+
# event.mouse? # => true
|
|
74
|
+
# event.key? # => false
|
|
75
|
+
# event.resize? # => false
|
|
76
|
+
#--
|
|
77
|
+
# SPDX-SnippetEnd
|
|
78
|
+
#++
|
|
79
|
+
def mouse?
|
|
80
|
+
true
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Creates a new Mouse event.
|
|
84
|
+
#
|
|
85
|
+
# [kind]
|
|
86
|
+
# Event kind (String).
|
|
87
|
+
# [x]
|
|
88
|
+
# X coordinate (Integer).
|
|
89
|
+
# [y]
|
|
90
|
+
# Y coordinate (Integer).
|
|
91
|
+
# [button]
|
|
92
|
+
# Button name (String or <tt>nil</tt>).
|
|
93
|
+
# [modifiers]
|
|
94
|
+
# List of modifiers (Array<String>).
|
|
95
|
+
def initialize(kind:, x:, y:, button:, modifiers: [])
|
|
96
|
+
@kind = kind.freeze
|
|
97
|
+
@x = x
|
|
98
|
+
@y = y
|
|
99
|
+
@button = (button || "none").freeze
|
|
100
|
+
@modifiers = modifiers.map(&:freeze).sort.freeze
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Returns true if mouse button was pressed down.
|
|
104
|
+
def down?
|
|
105
|
+
@kind == "down"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Returns true if mouse button was released.
|
|
109
|
+
def up?
|
|
110
|
+
@kind == "up"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
alias mouse_down? down?
|
|
114
|
+
alias mouse_up? up?
|
|
115
|
+
|
|
116
|
+
# Returns true if mouse is being dragged.
|
|
117
|
+
def drag?
|
|
118
|
+
@kind == "drag"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Returns true if scroll wheel moved up.
|
|
122
|
+
def scroll_up?
|
|
123
|
+
@kind == "scroll_up"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Returns true if scroll wheel moved down.
|
|
127
|
+
#
|
|
128
|
+
#--
|
|
129
|
+
# SPDX-SnippetBegin
|
|
130
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
131
|
+
# SPDX-License-Identifier: MIT-0
|
|
132
|
+
#++
|
|
133
|
+
# if event.scroll_down?
|
|
134
|
+
# scroll_offset += 1
|
|
135
|
+
# end
|
|
136
|
+
#--
|
|
137
|
+
# SPDX-SnippetEnd
|
|
138
|
+
#++
|
|
139
|
+
def scroll_down?
|
|
140
|
+
@kind == "scroll_down"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Returns true if event involves the left mouse button.
|
|
144
|
+
def left?
|
|
145
|
+
@button == "left"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Returns true if event involves the right mouse button.
|
|
149
|
+
def right?
|
|
150
|
+
@button == "right"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Returns true if event involves the middle mouse button.
|
|
154
|
+
def middle?
|
|
155
|
+
@button == "middle"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
alias left_button? left?
|
|
159
|
+
alias right_button? right?
|
|
160
|
+
alias middle_button? middle?
|
|
161
|
+
|
|
162
|
+
# Deconstructs the event for pattern matching.
|
|
163
|
+
#
|
|
164
|
+
#--
|
|
165
|
+
# SPDX-SnippetBegin
|
|
166
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
167
|
+
# SPDX-License-Identifier: MIT-0
|
|
168
|
+
#++
|
|
169
|
+
# case event
|
|
170
|
+
# in type: :mouse, kind: "down", x:, y:
|
|
171
|
+
# puts "Click at #{x}, #{y}"
|
|
172
|
+
# end
|
|
173
|
+
#--
|
|
174
|
+
# SPDX-SnippetEnd
|
|
175
|
+
#++
|
|
176
|
+
def deconstruct_keys(keys)
|
|
177
|
+
{ type: :mouse, kind: @kind, x: @x, y: @y, button: @button, modifiers: @modifiers }
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
##
|
|
181
|
+
# Converts the event to a Symbol representation.
|
|
182
|
+
#
|
|
183
|
+
# The format varies by event type:
|
|
184
|
+
#
|
|
185
|
+
# [Left Button]
|
|
186
|
+
# <tt>:mouse_left_down</tt>, <tt>:mouse_left_up</tt>, <tt>:mouse_left_drag</tt>
|
|
187
|
+
# [Right Button]
|
|
188
|
+
# <tt>:mouse_right_down</tt>, <tt>:mouse_right_up</tt>, <tt>:mouse_right_drag</tt>
|
|
189
|
+
# [Middle Button]
|
|
190
|
+
# <tt>:mouse_middle_down</tt>, <tt>:mouse_middle_up</tt>, <tt>:mouse_middle_drag</tt>
|
|
191
|
+
# [Scroll]
|
|
192
|
+
# <tt>:scroll_up</tt>, <tt>:scroll_down</tt>
|
|
193
|
+
# [Move]
|
|
194
|
+
#--
|
|
195
|
+
# SPDX-SnippetBegin
|
|
196
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
197
|
+
# SPDX-License-Identifier: MIT-0
|
|
198
|
+
#++
|
|
199
|
+
# <tt>:mouse_moved</tt>
|
|
200
|
+
#
|
|
201
|
+
#--
|
|
202
|
+
# SPDX-SnippetEnd
|
|
203
|
+
#++
|
|
204
|
+
# === Example
|
|
205
|
+
#
|
|
206
|
+
#--
|
|
207
|
+
# SPDX-SnippetBegin
|
|
208
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
209
|
+
# SPDX-License-Identifier: MIT-0
|
|
210
|
+
#++
|
|
211
|
+
# event = Event::Mouse.new(kind: "down", x: 10, y: 5, button: "left")
|
|
212
|
+
# event.to_sym # => :mouse_left_down
|
|
213
|
+
#
|
|
214
|
+
# scroll = Event::Mouse.new(kind: "scroll_up", x: 0, y: 0, button: "none")
|
|
215
|
+
# scroll.to_sym # => :scroll_up
|
|
216
|
+
#--
|
|
217
|
+
# SPDX-SnippetEnd
|
|
218
|
+
#++
|
|
219
|
+
def to_sym
|
|
220
|
+
if @kind.start_with?("scroll")
|
|
221
|
+
@kind.to_sym
|
|
222
|
+
elsif @button == "none"
|
|
223
|
+
:"mouse_#{@kind}"
|
|
224
|
+
else
|
|
225
|
+
:"mouse_#{@button}_#{@kind}"
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
##
|
|
230
|
+
# Compares the event with another object.
|
|
231
|
+
#
|
|
232
|
+
# - If +other+ is a +Symbol+, compares against #to_sym.
|
|
233
|
+
# - If +other+ is a +Mouse+, compares as a value object.
|
|
234
|
+
# - Otherwise, returns +false+.
|
|
235
|
+
#
|
|
236
|
+
# === Example
|
|
237
|
+
#
|
|
238
|
+
#--
|
|
239
|
+
# SPDX-SnippetBegin
|
|
240
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
241
|
+
# SPDX-License-Identifier: MIT-0
|
|
242
|
+
#++
|
|
243
|
+
# if event == :mouse_left_down
|
|
244
|
+
# handle_click(event)
|
|
245
|
+
# end
|
|
246
|
+
#--
|
|
247
|
+
# SPDX-SnippetEnd
|
|
248
|
+
#++
|
|
249
|
+
def ==(other)
|
|
250
|
+
case other
|
|
251
|
+
when Symbol then to_sym == other
|
|
252
|
+
when Mouse then kind == other.kind && x == other.x && y == other.y && button == other.button && modifiers == other.modifiers
|
|
253
|
+
else false
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
alias wheel_up? scroll_up?
|
|
258
|
+
alias wheel_down? scroll_down?
|
|
259
|
+
|
|
260
|
+
# Returns true for any scroll event.
|
|
261
|
+
#
|
|
262
|
+
# event.scroll? # => true for scroll_up or scroll_down
|
|
263
|
+
def scroll?
|
|
264
|
+
scroll_up? || scroll_down?
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
alias primary? left?
|
|
268
|
+
alias secondary? right?
|
|
269
|
+
alias context_menu? right?
|
|
270
|
+
alias aux? middle?
|
|
271
|
+
alias auxiliary? aux?
|
|
272
|
+
|
|
273
|
+
# Returns true for mouse movement without button press.
|
|
274
|
+
#
|
|
275
|
+
# event.moved? # => true for moved (no button)
|
|
276
|
+
def moved?
|
|
277
|
+
@kind == "moved"
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
alias hover? moved?
|
|
281
|
+
alias hovering? moved?
|
|
282
|
+
alias move? moved?
|
|
283
|
+
alias dragging? drag?
|
|
284
|
+
|
|
285
|
+
alias release? up?
|
|
286
|
+
alias released? up?
|
|
287
|
+
alias press? down?
|
|
288
|
+
alias pressed? down?
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
9
|
+
class Event
|
|
10
|
+
# {Null object}[https://en.wikipedia.org/wiki/Null_object_pattern] for absent events.
|
|
11
|
+
#
|
|
12
|
+
# Event loops poll for input 60 times per second. Usually nothing is happening.
|
|
13
|
+
# If <tt>RatatuiRuby.poll_event</tt> returned <tt>nil</tt>, you would need
|
|
14
|
+
# nil-checks: <tt>event&.key?</tt>, <tt>next unless event</tt>.
|
|
15
|
+
#
|
|
16
|
+
# This class eliminates that friction. It responds to every predicate with
|
|
17
|
+
# <tt>false</tt>. Call <tt>none?</tt> to detect it explicitly. Pattern-match on
|
|
18
|
+
# <tt>type: :none</tt> for exhaustive dispatch.
|
|
19
|
+
#
|
|
20
|
+
# Use it to simplify your event loop. No guards. Optional `else` clauses.
|
|
21
|
+
#
|
|
22
|
+
# See Martin Fowler's {Special Case}[https://martinfowler.com/eaaCatalog/specialCase.html] pattern.
|
|
23
|
+
#
|
|
24
|
+
# === Predicate Example
|
|
25
|
+
#
|
|
26
|
+
#--
|
|
27
|
+
# SPDX-SnippetBegin
|
|
28
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
29
|
+
# SPDX-License-Identifier: MIT-0
|
|
30
|
+
#++
|
|
31
|
+
# event = RatatuiRuby.poll_event
|
|
32
|
+
# break if event.ctrl_c?
|
|
33
|
+
# redraw if event.none?
|
|
34
|
+
#
|
|
35
|
+
#--
|
|
36
|
+
# SPDX-SnippetEnd
|
|
37
|
+
#++
|
|
38
|
+
# === Pattern Matching Example
|
|
39
|
+
#
|
|
40
|
+
# redraw if RatatuiRuby.poll_event in type: :none
|
|
41
|
+
class None < Event
|
|
42
|
+
# Returns true for None events.
|
|
43
|
+
def none?
|
|
44
|
+
true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Deconstructs the event for pattern matching.
|
|
48
|
+
def deconstruct_keys(keys)
|
|
49
|
+
{ type: :none }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
9
|
+
class Event
|
|
10
|
+
# Encapsulates pasted text.
|
|
11
|
+
#
|
|
12
|
+
# Users frequently paste text into terminals. Without specific handling, a paste appears as
|
|
13
|
+
# a flood of rapid keystrokes, often triggering accidental commands or confusing the input state.
|
|
14
|
+
#
|
|
15
|
+
# This event makes pasting safe. It groups the entire inserted block into a single atomic action.
|
|
16
|
+
#
|
|
17
|
+
# Handle this event to support bulk text insertion cleanly. Insert the +content+ directly into
|
|
18
|
+
# your field or buffer without triggering per-character logic.
|
|
19
|
+
#
|
|
20
|
+
# === Examples
|
|
21
|
+
#
|
|
22
|
+
# Using predicates:
|
|
23
|
+
#--
|
|
24
|
+
# SPDX-SnippetBegin
|
|
25
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
26
|
+
# SPDX-License-Identifier: MIT-0
|
|
27
|
+
#++
|
|
28
|
+
# if event.paste?
|
|
29
|
+
# puts "Pasted: #{event.content}"
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
#--
|
|
33
|
+
# SPDX-SnippetEnd
|
|
34
|
+
#++
|
|
35
|
+
# Using pattern matching:
|
|
36
|
+
#--
|
|
37
|
+
# SPDX-SnippetBegin
|
|
38
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
39
|
+
# SPDX-License-Identifier: MIT-0
|
|
40
|
+
#++
|
|
41
|
+
# case event
|
|
42
|
+
# in type: :paste, content:
|
|
43
|
+
# puts "Pasted: #{content}"
|
|
44
|
+
# end
|
|
45
|
+
#--
|
|
46
|
+
# SPDX-SnippetEnd
|
|
47
|
+
#++
|
|
48
|
+
class Paste < Event
|
|
49
|
+
# The pasted content.
|
|
50
|
+
#
|
|
51
|
+
# puts event.content # => "https://example.com"
|
|
52
|
+
attr_reader :content
|
|
53
|
+
|
|
54
|
+
# Returns true for Paste events.
|
|
55
|
+
#
|
|
56
|
+
#--
|
|
57
|
+
# SPDX-SnippetBegin
|
|
58
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
59
|
+
# SPDX-License-Identifier: MIT-0
|
|
60
|
+
#++
|
|
61
|
+
# event.paste? # => true
|
|
62
|
+
# event.key? # => false
|
|
63
|
+
# event.resize? # => false
|
|
64
|
+
#--
|
|
65
|
+
# SPDX-SnippetEnd
|
|
66
|
+
#++
|
|
67
|
+
def paste?
|
|
68
|
+
true
|
|
69
|
+
end
|
|
70
|
+
alias clipboard? paste?
|
|
71
|
+
alias pasteboard? paste?
|
|
72
|
+
alias pasted? paste?
|
|
73
|
+
|
|
74
|
+
# Creates a new Paste event.
|
|
75
|
+
#
|
|
76
|
+
# [content]
|
|
77
|
+
# Pasted text (String).
|
|
78
|
+
def initialize(content:)
|
|
79
|
+
@content = content.freeze
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Deconstructs the event for pattern matching.
|
|
83
|
+
#
|
|
84
|
+
#--
|
|
85
|
+
# SPDX-SnippetBegin
|
|
86
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
87
|
+
# SPDX-License-Identifier: MIT-0
|
|
88
|
+
#++
|
|
89
|
+
# case event
|
|
90
|
+
# in type: :paste, content:
|
|
91
|
+
# puts "User pasted: #{content}"
|
|
92
|
+
# end
|
|
93
|
+
#--
|
|
94
|
+
# SPDX-SnippetEnd
|
|
95
|
+
#++
|
|
96
|
+
def deconstruct_keys(keys)
|
|
97
|
+
{ type: :paste, content: @content }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
##
|
|
101
|
+
# Compares this event with another for equality.
|
|
102
|
+
def ==(other)
|
|
103
|
+
return false unless other.is_a?(Paste)
|
|
104
|
+
content == other.content
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Returns true if the pasted content is empty.
|
|
108
|
+
def empty?
|
|
109
|
+
@content.empty?
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns true if the pasted content is empty or whitespace-only.
|
|
113
|
+
def blank?
|
|
114
|
+
@content.strip.empty?
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Returns true if the pasted content spans multiple lines.
|
|
118
|
+
def multiline?
|
|
119
|
+
@content.include?("\n")
|
|
120
|
+
end
|
|
121
|
+
alias multi_line? multiline?
|
|
122
|
+
|
|
123
|
+
# Returns true if the pasted content is a single line.
|
|
124
|
+
def single_line?
|
|
125
|
+
!multiline?
|
|
126
|
+
end
|
|
127
|
+
alias singleline? single_line?
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,221 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
9
|
+
class Event
|
|
10
|
+
# Signals a change in terminal dimensions.
|
|
11
|
+
#
|
|
12
|
+
# The terminal window is dynamic, not static. The user changes its dimensions at will,
|
|
13
|
+
# usually breaking a fixed layout.
|
|
14
|
+
#
|
|
15
|
+
# This event captures the new state. It delivers the updated +width+ and +height+
|
|
16
|
+
# immediately after the change.
|
|
17
|
+
#
|
|
18
|
+
# Use these dimensions to drive your layout logic. Recalculate constraints. Reallocate space.
|
|
19
|
+
# Fill the new canvas completely to maintain a responsive design.
|
|
20
|
+
#
|
|
21
|
+
# === Examples
|
|
22
|
+
#
|
|
23
|
+
# Using predicates:
|
|
24
|
+
#--
|
|
25
|
+
# SPDX-SnippetBegin
|
|
26
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
27
|
+
# SPDX-License-Identifier: MIT-0
|
|
28
|
+
#++
|
|
29
|
+
# if event.resize?
|
|
30
|
+
# puts "Resized to #{event.width}x#{event.height}"
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
#--
|
|
34
|
+
# SPDX-SnippetEnd
|
|
35
|
+
#++
|
|
36
|
+
# Using pattern matching:
|
|
37
|
+
#--
|
|
38
|
+
# SPDX-SnippetBegin
|
|
39
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
40
|
+
# SPDX-License-Identifier: MIT-0
|
|
41
|
+
#++
|
|
42
|
+
# case event
|
|
43
|
+
# in type: :resize, width:, height:
|
|
44
|
+
# puts "Resized to #{width}x#{height}"
|
|
45
|
+
# end
|
|
46
|
+
#--
|
|
47
|
+
# SPDX-SnippetEnd
|
|
48
|
+
#++
|
|
49
|
+
class Resize < Event
|
|
50
|
+
# New terminal width in columns.
|
|
51
|
+
#
|
|
52
|
+
# puts event.width # => 80
|
|
53
|
+
attr_reader :width
|
|
54
|
+
|
|
55
|
+
# New terminal height in rows.
|
|
56
|
+
#
|
|
57
|
+
# puts event.height # => 24
|
|
58
|
+
attr_reader :height
|
|
59
|
+
|
|
60
|
+
# Returns true for Resize events.
|
|
61
|
+
#
|
|
62
|
+
#--
|
|
63
|
+
# SPDX-SnippetBegin
|
|
64
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
65
|
+
# SPDX-License-Identifier: MIT-0
|
|
66
|
+
#++
|
|
67
|
+
# event.resize? # => true
|
|
68
|
+
# event.key? # => false
|
|
69
|
+
# event.mouse? # => false
|
|
70
|
+
#--
|
|
71
|
+
# SPDX-SnippetEnd
|
|
72
|
+
#++
|
|
73
|
+
def resize?
|
|
74
|
+
true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Creates a new Resize event.
|
|
78
|
+
#
|
|
79
|
+
# [width]
|
|
80
|
+
# New width (Integer).
|
|
81
|
+
# [height]
|
|
82
|
+
# New height (Integer).
|
|
83
|
+
def initialize(width:, height:)
|
|
84
|
+
@width = width
|
|
85
|
+
@height = height
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Deconstructs the event for pattern matching.
|
|
89
|
+
#
|
|
90
|
+
#--
|
|
91
|
+
# SPDX-SnippetBegin
|
|
92
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
93
|
+
# SPDX-License-Identifier: MIT-0
|
|
94
|
+
#++
|
|
95
|
+
# case event
|
|
96
|
+
# in type: :resize, width:, height:
|
|
97
|
+
# puts "Resized to #{width}x#{height}"
|
|
98
|
+
# end
|
|
99
|
+
#--
|
|
100
|
+
# SPDX-SnippetEnd
|
|
101
|
+
#++
|
|
102
|
+
def deconstruct_keys(keys)
|
|
103
|
+
{ type: :resize, width: @width, height: @height }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
##
|
|
107
|
+
# Converts the event to a Symbol representation.
|
|
108
|
+
#
|
|
109
|
+
# Always returns <tt>:resize</tt>.
|
|
110
|
+
#
|
|
111
|
+
# === Example
|
|
112
|
+
#
|
|
113
|
+
#--
|
|
114
|
+
# SPDX-SnippetBegin
|
|
115
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
116
|
+
# SPDX-License-Identifier: MIT-0
|
|
117
|
+
#++
|
|
118
|
+
# event = Event::Resize.new(width: 80, height: 24)
|
|
119
|
+
# event.to_sym # => :resize
|
|
120
|
+
#--
|
|
121
|
+
# SPDX-SnippetEnd
|
|
122
|
+
#++
|
|
123
|
+
def to_sym
|
|
124
|
+
:resize
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# Compares the event with another object.
|
|
129
|
+
#
|
|
130
|
+
# - If +other+ is a +Symbol+, compares against #to_sym.
|
|
131
|
+
# - If +other+ is a +Resize+, compares as a value object.
|
|
132
|
+
# - Otherwise, returns +false+.
|
|
133
|
+
#
|
|
134
|
+
# === Example
|
|
135
|
+
#
|
|
136
|
+
#--
|
|
137
|
+
# SPDX-SnippetBegin
|
|
138
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
139
|
+
# SPDX-License-Identifier: MIT-0
|
|
140
|
+
#++
|
|
141
|
+
# if event == :resize
|
|
142
|
+
# handle_resize(event)
|
|
143
|
+
# end
|
|
144
|
+
#--
|
|
145
|
+
# SPDX-SnippetEnd
|
|
146
|
+
#++
|
|
147
|
+
def ==(other)
|
|
148
|
+
case other
|
|
149
|
+
when Symbol then to_sym == other
|
|
150
|
+
when Resize then width == other.width && height == other.height
|
|
151
|
+
else false
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Returns true. Unix <tt>SIGWINCH</tt> triggers terminal resize.
|
|
156
|
+
#
|
|
157
|
+
# event.sigwinch? # => true
|
|
158
|
+
def sigwinch?
|
|
159
|
+
true
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
alias winch? sigwinch?
|
|
163
|
+
alias sig_winch? sigwinch?
|
|
164
|
+
|
|
165
|
+
alias terminal_resize? resize?
|
|
166
|
+
alias window_resize? resize?
|
|
167
|
+
alias window_change? resize?
|
|
168
|
+
alias viewport_resize? resize?
|
|
169
|
+
alias viewport_change? resize?
|
|
170
|
+
alias size_change? resize?
|
|
171
|
+
alias resized? resize?
|
|
172
|
+
|
|
173
|
+
VT100_WIDTH = 80 # :nodoc:
|
|
174
|
+
VT100_HEIGHT = 24 # :nodoc:
|
|
175
|
+
|
|
176
|
+
# Returns true if width exceeds height.
|
|
177
|
+
#
|
|
178
|
+
# Event::Resize.new(width: 120, height: 24).landscape? # => true
|
|
179
|
+
def landscape?
|
|
180
|
+
@width > @height
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Returns true if height exceeds or equals width.
|
|
184
|
+
#
|
|
185
|
+
# Event::Resize.new(width: 40, height: 80).portrait? # => true
|
|
186
|
+
def portrait?
|
|
187
|
+
@height >= @width
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Returns true if dimensions are exactly 80x24.
|
|
191
|
+
#
|
|
192
|
+
# Event::Resize.new(width: 80, height: 24).vt100? # => true
|
|
193
|
+
def vt100?
|
|
194
|
+
@width == VT100_WIDTH && @height == VT100_HEIGHT
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Returns true if both dimensions meet or exceed 80x24.
|
|
198
|
+
#
|
|
199
|
+
# Event::Resize.new(width: 120, height: 40).at_least_vt100? # => true
|
|
200
|
+
def at_least_vt100?
|
|
201
|
+
@width >= VT100_WIDTH && @height >= VT100_HEIGHT
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Returns true if both dimensions exceed 80x24.
|
|
205
|
+
#
|
|
206
|
+
# Event::Resize.new(width: 81, height: 25).over_vt100? # => true
|
|
207
|
+
def over_vt100?
|
|
208
|
+
@width > VT100_WIDTH && @height > VT100_HEIGHT
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Returns true if either dimension falls below VT100 standard.
|
|
212
|
+
#
|
|
213
|
+
# Event::Resize.new(width: 60, height: 24).cramped? # => true
|
|
214
|
+
def cramped?
|
|
215
|
+
@width < VT100_WIDTH || @height < VT100_HEIGHT
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
alias constrained? cramped?
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|