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,127 @@
|
|
|
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 that the application is in the background.
|
|
11
|
+
#
|
|
12
|
+
# The user has switched context. Your application is no longer the primary focus.
|
|
13
|
+
#
|
|
14
|
+
# This event warns of inactivity. It fires when the terminal window loses focus.
|
|
15
|
+
#
|
|
16
|
+
# Respond by conserving resources. Pause animations. Stop heavy polling. dim the UI to
|
|
17
|
+
# indicate a background state.
|
|
18
|
+
#
|
|
19
|
+
# Only supported by some terminals (e.g. iTerm2, Kitty, newer xterm).
|
|
20
|
+
#
|
|
21
|
+
# === Example
|
|
22
|
+
#
|
|
23
|
+
#--
|
|
24
|
+
# SPDX-SnippetBegin
|
|
25
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
26
|
+
# SPDX-License-Identifier: MIT-0
|
|
27
|
+
#++
|
|
28
|
+
# if event.focus_lost?
|
|
29
|
+
# puts "Focus lost"
|
|
30
|
+
# end
|
|
31
|
+
#--
|
|
32
|
+
# SPDX-SnippetEnd
|
|
33
|
+
#++
|
|
34
|
+
class FocusLost < Event
|
|
35
|
+
# Returns true for FocusLost events.
|
|
36
|
+
#
|
|
37
|
+
#--
|
|
38
|
+
# SPDX-SnippetBegin
|
|
39
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
40
|
+
# SPDX-License-Identifier: MIT-0
|
|
41
|
+
#++
|
|
42
|
+
# event.focus_lost? # => true
|
|
43
|
+
# event.key? # => false
|
|
44
|
+
#--
|
|
45
|
+
# SPDX-SnippetEnd
|
|
46
|
+
#++
|
|
47
|
+
def focus_lost?
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Deconstructs the event for pattern matching.
|
|
52
|
+
#
|
|
53
|
+
#--
|
|
54
|
+
# SPDX-SnippetBegin
|
|
55
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long
|
|
56
|
+
# SPDX-License-Identifier: MIT-0
|
|
57
|
+
#++
|
|
58
|
+
# case event
|
|
59
|
+
# in type: :focus_lost
|
|
60
|
+
# puts "Application lost focus"
|
|
61
|
+
# end
|
|
62
|
+
#--
|
|
63
|
+
# SPDX-SnippetEnd
|
|
64
|
+
#++
|
|
65
|
+
def deconstruct_keys(keys)
|
|
66
|
+
{ type: :focus_lost }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Compares this event with another for equality.
|
|
71
|
+
def ==(other)
|
|
72
|
+
other.is_a?(FocusLost)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# =========================================================================
|
|
76
|
+
# DWIM Predicates
|
|
77
|
+
# =========================================================================
|
|
78
|
+
|
|
79
|
+
# Returns true. The terminal has lost focus (blur).
|
|
80
|
+
#
|
|
81
|
+
# event.blur? # => true
|
|
82
|
+
def blur?
|
|
83
|
+
true
|
|
84
|
+
end
|
|
85
|
+
alias blurred? blur?
|
|
86
|
+
|
|
87
|
+
# Returns true. The application lost focus.
|
|
88
|
+
#
|
|
89
|
+
# event.lost? # => true
|
|
90
|
+
def lost?
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
alias unfocused? lost?
|
|
94
|
+
|
|
95
|
+
# Returns false. This is not a focus gained event.
|
|
96
|
+
#
|
|
97
|
+
# event.focus? # => false
|
|
98
|
+
def focus?
|
|
99
|
+
false
|
|
100
|
+
end
|
|
101
|
+
alias focused? focus?
|
|
102
|
+
|
|
103
|
+
# Returns false. This is not a gained event.
|
|
104
|
+
#
|
|
105
|
+
# event.gained? # => false
|
|
106
|
+
def gained?
|
|
107
|
+
false
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Returns true. The application is inactive.
|
|
111
|
+
#
|
|
112
|
+
# event.inactive? # => true
|
|
113
|
+
def inactive?
|
|
114
|
+
true
|
|
115
|
+
end
|
|
116
|
+
alias background? inactive?
|
|
117
|
+
|
|
118
|
+
# Returns false. The application is not active.
|
|
119
|
+
#
|
|
120
|
+
# event.active? # => false
|
|
121
|
+
def active?
|
|
122
|
+
false
|
|
123
|
+
end
|
|
124
|
+
alias foreground? active?
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
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
|
+
class Key < Event
|
|
11
|
+
# Methods for handling printable characters.
|
|
12
|
+
module Character
|
|
13
|
+
# Returns true if the key represents a single printable character.
|
|
14
|
+
#
|
|
15
|
+
#--
|
|
16
|
+
# SPDX-SnippetBegin
|
|
17
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
18
|
+
# SPDX-License-Identifier: MIT-0
|
|
19
|
+
#++
|
|
20
|
+
# RatatuiRuby::Event::Key.new(code: "a").text? # => true
|
|
21
|
+
# RatatuiRuby::Event::Key.new(code: "enter").text? # => false
|
|
22
|
+
# RatatuiRuby::Event::Key.new(code: "space").text? # => false ("space" is not 1 char, " " is)
|
|
23
|
+
#--
|
|
24
|
+
# SPDX-SnippetEnd
|
|
25
|
+
#++
|
|
26
|
+
def text?
|
|
27
|
+
@code.length == 1
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns the key as a printable character (if applicable).
|
|
31
|
+
#
|
|
32
|
+
# [Printable Characters]
|
|
33
|
+
# Returns the character itself (e.g., <tt>"a"</tt>, <tt>"1"</tt>, <tt>" "</tt>).
|
|
34
|
+
# [Special Keys]
|
|
35
|
+
#--
|
|
36
|
+
# SPDX-SnippetBegin
|
|
37
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
38
|
+
# SPDX-License-Identifier: MIT-0
|
|
39
|
+
#++
|
|
40
|
+
# Returns <tt>nil</tt> (e.g., <tt>"enter"</tt>, <tt>"up"</tt>, <tt>"f1"</tt>).
|
|
41
|
+
#
|
|
42
|
+
# RatatuiRuby::Event::Key.new(code: "a").char # => "a"
|
|
43
|
+
# RatatuiRuby::Event::Key.new(code: "enter").char # => nil
|
|
44
|
+
#--
|
|
45
|
+
# SPDX-SnippetEnd
|
|
46
|
+
#++
|
|
47
|
+
def char
|
|
48
|
+
text? ? @code : nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,301 @@
|
|
|
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
|
+
class Key < Event
|
|
11
|
+
# DWIM predicates for common key patterns.
|
|
12
|
+
#
|
|
13
|
+
# These predicates anticipate what developers intuitively try. Space bars,
|
|
14
|
+
# character categories, Unix signals, and Vim-style navigation.
|
|
15
|
+
module Dwim
|
|
16
|
+
# Returns true if the key is a space character.
|
|
17
|
+
#
|
|
18
|
+
# event.space? # => true for " "
|
|
19
|
+
def space?
|
|
20
|
+
@code == " " && @modifiers.empty?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
alias spacebar? space?
|
|
24
|
+
|
|
25
|
+
# Returns true if the key is Enter. Alias for carriage return.
|
|
26
|
+
#
|
|
27
|
+
# event.cr? # => true for enter
|
|
28
|
+
def cr?
|
|
29
|
+
@code == "enter" && @modifiers.empty?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
alias carriagereturn? cr?
|
|
33
|
+
alias linefeed? cr?
|
|
34
|
+
alias newline? cr?
|
|
35
|
+
alias lf? cr?
|
|
36
|
+
|
|
37
|
+
# Returns true if the key is a single letter (a-z, A-Z).
|
|
38
|
+
#
|
|
39
|
+
# Event::Key.new(code: "a").letter? # => true
|
|
40
|
+
def letter?
|
|
41
|
+
@code.length == 1 && @code.match?(/\A[A-Za-z]\z/)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Returns true if the key is a digit (0-9).
|
|
45
|
+
#
|
|
46
|
+
# Event::Key.new(code: "5").digit? # => true
|
|
47
|
+
def digit?
|
|
48
|
+
@code.length == 1 && @code.match?(/\A[0-9]\z/)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns true if the key is alphanumeric.
|
|
52
|
+
#
|
|
53
|
+
# Event::Key.new(code: "a").alphanumeric? # => true
|
|
54
|
+
def alphanumeric?
|
|
55
|
+
letter? || digit?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns true if the key is punctuation.
|
|
59
|
+
#
|
|
60
|
+
# Event::Key.new(code: "@", modifiers: ["shift"]).punctuation? # => true
|
|
61
|
+
def punctuation?
|
|
62
|
+
return false unless @code.length == 1
|
|
63
|
+
!letter? && !digit? && !whitespace?
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Returns true if the key is whitespace (space, enter, tab).
|
|
67
|
+
#
|
|
68
|
+
# Event::Key.new(code: " ").whitespace? # => true
|
|
69
|
+
def whitespace?
|
|
70
|
+
@code == " " || @code == "enter" || @code == "tab"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns true for interrupt (Ctrl+C).
|
|
74
|
+
#
|
|
75
|
+
# event.interrupt? # => true for Ctrl+C
|
|
76
|
+
def interrupt?
|
|
77
|
+
@code == "c" && @modifiers == ["ctrl"]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Returns true for end-of-file (Ctrl+D).
|
|
81
|
+
#
|
|
82
|
+
# event.eof? # => true for Ctrl+D
|
|
83
|
+
def eof?
|
|
84
|
+
@code == "d" && @modifiers == ["ctrl"]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Returns true for cancel (Esc or Ctrl+C).
|
|
88
|
+
#
|
|
89
|
+
# event.cancel? # => true for Esc or Ctrl+C
|
|
90
|
+
def cancel?
|
|
91
|
+
(@code == "esc" && @modifiers.empty?) || interrupt?
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Returns true for SIGINT (Ctrl+C).
|
|
95
|
+
#
|
|
96
|
+
# event.sigint? # => true for Ctrl+C
|
|
97
|
+
def sigint?
|
|
98
|
+
interrupt?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
alias int? sigint?
|
|
102
|
+
|
|
103
|
+
# Returns true for SIGTSTP (Ctrl+Z) - suspend/stop.
|
|
104
|
+
#
|
|
105
|
+
# event.suspend? # => true for Ctrl+Z
|
|
106
|
+
def suspend?
|
|
107
|
+
@code == "z" && @modifiers == ["ctrl"]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
alias sigtstp? suspend?
|
|
111
|
+
alias tstp? suspend?
|
|
112
|
+
|
|
113
|
+
# Returns true for SIGQUIT (Ctrl+\).
|
|
114
|
+
#
|
|
115
|
+
# event.quit? # => true for Ctrl+\
|
|
116
|
+
def quit?
|
|
117
|
+
@code == "\\" && @modifiers == ["ctrl"]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
alias sigquit? quit?
|
|
121
|
+
|
|
122
|
+
NAVIGATION_KEYS = %w[up down left right home end page_up page_down].freeze # :nodoc:
|
|
123
|
+
|
|
124
|
+
# Returns true if key is a navigation key.
|
|
125
|
+
#
|
|
126
|
+
# Event::Key.new(code: "up").navigation? # => true
|
|
127
|
+
def navigation?
|
|
128
|
+
NAVIGATION_KEYS.include?(@code) && @modifiers.empty?
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
ARROW_KEYS = %w[up down left right].freeze # :nodoc:
|
|
132
|
+
|
|
133
|
+
# Returns true if key is an arrow key.
|
|
134
|
+
#
|
|
135
|
+
# Event::Key.new(code: "up").arrow? # => true
|
|
136
|
+
def arrow?
|
|
137
|
+
ARROW_KEYS.include?(@code) && @modifiers.empty?
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
VIM_MOVEMENT_KEYS = %w[h j k l w b g G].freeze # :nodoc:
|
|
141
|
+
|
|
142
|
+
# Returns true if key is a Vim movement key.
|
|
143
|
+
#
|
|
144
|
+
# Event::Key.new(code: "j").vim? # => true
|
|
145
|
+
def vim?
|
|
146
|
+
return true if VIM_MOVEMENT_KEYS.include?(@code) && @modifiers.empty?
|
|
147
|
+
@code == "G" && @modifiers == ["shift"]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Returns true for Vim left (h).
|
|
151
|
+
def vim_left?
|
|
152
|
+
@code == "h" && @modifiers.empty?
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Returns true for Vim down (j).
|
|
156
|
+
def vim_down?
|
|
157
|
+
@code == "j" && @modifiers.empty?
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Returns true for Vim up (k).
|
|
161
|
+
def vim_up?
|
|
162
|
+
@code == "k" && @modifiers.empty?
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Returns true for Vim right (l).
|
|
166
|
+
def vim_right?
|
|
167
|
+
@code == "l" && @modifiers.empty?
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Returns true for Vim word forward (w).
|
|
171
|
+
def vim_word_forward?
|
|
172
|
+
@code == "w" && @modifiers.empty?
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Returns true for Vim word backward (b).
|
|
176
|
+
def vim_word_backward?
|
|
177
|
+
@code == "b" && @modifiers.empty?
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Returns true for Vim go to top (gg pattern, here just g).
|
|
181
|
+
def vim_top?
|
|
182
|
+
@code == "g" && @modifiers.empty?
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Returns true for Vim go to bottom (G).
|
|
186
|
+
def vim_bottom?
|
|
187
|
+
@code == "G" && @modifiers == ["shift"]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Punctuation name predicates - generated at load time for performance.
|
|
191
|
+
# Maps intuitive names to their symbol characters.
|
|
192
|
+
# :nodoc:
|
|
193
|
+
PUNCTUATION_NAMES = {
|
|
194
|
+
# Navigation shortcuts (the original use case!)
|
|
195
|
+
tilde: "~",
|
|
196
|
+
slash: "/",
|
|
197
|
+
forwardslash: "/",
|
|
198
|
+
backslash: "\\",
|
|
199
|
+
|
|
200
|
+
# Common punctuation
|
|
201
|
+
comma: ",",
|
|
202
|
+
period: ".",
|
|
203
|
+
dot: ".",
|
|
204
|
+
colon: ":",
|
|
205
|
+
semicolon: ";",
|
|
206
|
+
|
|
207
|
+
# Question and exclamation
|
|
208
|
+
question: "?",
|
|
209
|
+
questionmark: "?",
|
|
210
|
+
exclamation: "!",
|
|
211
|
+
exclamationmark: "!",
|
|
212
|
+
exclamationpoint: "!",
|
|
213
|
+
bang: "!",
|
|
214
|
+
|
|
215
|
+
# Programming symbols
|
|
216
|
+
at: "@",
|
|
217
|
+
atsign: "@",
|
|
218
|
+
hash: "#",
|
|
219
|
+
pound: "#",
|
|
220
|
+
numbersign: "#",
|
|
221
|
+
dollar: "$",
|
|
222
|
+
dollarsign: "$",
|
|
223
|
+
percent: "%",
|
|
224
|
+
caret: "^",
|
|
225
|
+
circumflex: "^",
|
|
226
|
+
ampersand: "&",
|
|
227
|
+
asterisk: "*",
|
|
228
|
+
star: "*",
|
|
229
|
+
|
|
230
|
+
# Arithmetic and comparison
|
|
231
|
+
underscore: "_",
|
|
232
|
+
hyphen: "-",
|
|
233
|
+
dash: "-",
|
|
234
|
+
minus: "-",
|
|
235
|
+
plus: "+",
|
|
236
|
+
equals: "=",
|
|
237
|
+
equalsign: "=",
|
|
238
|
+
pipe: "|",
|
|
239
|
+
bar: "|",
|
|
240
|
+
lessthan: "<",
|
|
241
|
+
lt: "<",
|
|
242
|
+
greaterthan: ">",
|
|
243
|
+
gt: ">",
|
|
244
|
+
|
|
245
|
+
# Brackets and parens
|
|
246
|
+
lparen: "(",
|
|
247
|
+
leftparen: "(",
|
|
248
|
+
openparen: "(",
|
|
249
|
+
leftparenthesis: "(",
|
|
250
|
+
openparenthesis: "(",
|
|
251
|
+
rparen: ")",
|
|
252
|
+
rightparen: ")",
|
|
253
|
+
closeparen: ")",
|
|
254
|
+
rightparenthesis: ")",
|
|
255
|
+
closeparenthesis: ")",
|
|
256
|
+
lbracket: "[",
|
|
257
|
+
leftbracket: "[",
|
|
258
|
+
openbracket: "[",
|
|
259
|
+
leftsquarebracket: "[",
|
|
260
|
+
opensquarebracket: "[",
|
|
261
|
+
rbracket: "]",
|
|
262
|
+
rightbracket: "]",
|
|
263
|
+
closebracket: "]",
|
|
264
|
+
rightsquarebracket: "]",
|
|
265
|
+
closesquarebracket: "]",
|
|
266
|
+
lbrace: "{",
|
|
267
|
+
leftbrace: "{",
|
|
268
|
+
openbrace: "{",
|
|
269
|
+
leftcurlybrace: "{",
|
|
270
|
+
opencurlybrace: "{",
|
|
271
|
+
rbrace: "}",
|
|
272
|
+
rightbrace: "}",
|
|
273
|
+
closebrace: "}",
|
|
274
|
+
rightcurlybrace: "}",
|
|
275
|
+
closecurlybrace: "}",
|
|
276
|
+
|
|
277
|
+
# Quotes
|
|
278
|
+
backtick: "`",
|
|
279
|
+
grave: "`",
|
|
280
|
+
singlequote: "'",
|
|
281
|
+
apostrophe: "'",
|
|
282
|
+
doublequote: "\"",
|
|
283
|
+
}.freeze
|
|
284
|
+
|
|
285
|
+
# Generate predicate methods at load time (faster than method_missing)
|
|
286
|
+
PUNCTUATION_NAMES.each do |name, char|
|
|
287
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
288
|
+
def #{name}?
|
|
289
|
+
@code == #{char.inspect}
|
|
290
|
+
end
|
|
291
|
+
RUBY
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# quote? matches both single and double quotes
|
|
295
|
+
def quote?
|
|
296
|
+
@code == "'" || @code == "\""
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
class Key < Event
|
|
11
|
+
# Methods and logic for media keys.
|
|
12
|
+
module Media
|
|
13
|
+
# Returns true if this is a media key.
|
|
14
|
+
#
|
|
15
|
+
# Media keys include: play, pause, stop, track controls, volume controls.
|
|
16
|
+
# These are only available in terminals supporting the Kitty keyboard protocol.
|
|
17
|
+
#
|
|
18
|
+
# event.media? # => true for media_play, media_pause, etc.
|
|
19
|
+
def media?
|
|
20
|
+
@kind == :media
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Handles media-specific DWIM logic for method_missing.
|
|
24
|
+
private def match_media_dwim?(key_name)
|
|
25
|
+
return false unless @kind == :media
|
|
26
|
+
|
|
27
|
+
# Allow unprefixed predicate
|
|
28
|
+
# e.g., pause? returns true for media_pause
|
|
29
|
+
if @code.start_with?("media_")
|
|
30
|
+
base_code = @code.delete_prefix("media_")
|
|
31
|
+
return true if key_name == base_code
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Bidirectional media overlaps
|
|
35
|
+
# e.g., play? and pause? both match media_play_pause
|
|
36
|
+
return true if @code == "media_play_pause" && (key_name == "play" || key_name == "pause")
|
|
37
|
+
|
|
38
|
+
# e.g., play_pause? matches media_play or media_pause
|
|
39
|
+
return true if key_name == "play_pause" && (@code == "media_play" || @code == "media_pause")
|
|
40
|
+
|
|
41
|
+
false
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
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
|
+
class Key < Event
|
|
11
|
+
# Methods and logic for modifier keys.
|
|
12
|
+
module Modifier
|
|
13
|
+
# Returns true if CTRL is held OR if this is a left_control/right_control key event.
|
|
14
|
+
def ctrl?
|
|
15
|
+
@modifiers.include?("ctrl") || @code == "left_control" || @code == "right_control"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Alias for {#ctrl?}.
|
|
19
|
+
alias control? ctrl?
|
|
20
|
+
|
|
21
|
+
# Returns true if ALT is held OR if this is a left_alt/right_alt key event.
|
|
22
|
+
def alt?
|
|
23
|
+
@modifiers.include?("alt") || @code == "left_alt" || @code == "right_alt"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Alias for {#alt?}.
|
|
27
|
+
alias option? alt?
|
|
28
|
+
|
|
29
|
+
# Returns true if SHIFT is held OR if this is a left_shift/right_shift key event.
|
|
30
|
+
def shift?
|
|
31
|
+
@modifiers.include?("shift") || @code == "left_shift" || @code == "right_shift"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns true if SUPER is held OR if this is a left_super/right_super key event.
|
|
35
|
+
# Also responds to platform aliases: win?, command?, cmd?, tux?
|
|
36
|
+
def super?
|
|
37
|
+
@modifiers.include?("super") || @code == "left_super" || @code == "right_super"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Alias for {#super?}.
|
|
41
|
+
alias win? super?
|
|
42
|
+
# Alias for {#super?}.
|
|
43
|
+
alias windows? super?
|
|
44
|
+
# Alias for {#super?}.
|
|
45
|
+
alias command? super?
|
|
46
|
+
# Alias for {#super?}.
|
|
47
|
+
alias cmd? super?
|
|
48
|
+
# Alias for {#super?}.
|
|
49
|
+
alias tux? super?
|
|
50
|
+
|
|
51
|
+
# Returns true if HYPER is held OR if this is a left_hyper/right_hyper key event.
|
|
52
|
+
def hyper?
|
|
53
|
+
@modifiers.include?("hyper") || @code == "left_hyper" || @code == "right_hyper"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns true if META is held OR if this is a left_meta/right_meta key event.
|
|
57
|
+
def meta?
|
|
58
|
+
@modifiers.include?("meta") || @code == "left_meta" || @code == "right_meta"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Returns true if this is a modifier key event.
|
|
62
|
+
#
|
|
63
|
+
# Some applications need to know if an event represents a generic key
|
|
64
|
+
# press or a specific modifier key (like CTRL or ALT) being pressed on
|
|
65
|
+
# its own.
|
|
66
|
+
#
|
|
67
|
+
# This method identifies if the key event itself is a modifier key.
|
|
68
|
+
#
|
|
69
|
+
# === Example
|
|
70
|
+
#
|
|
71
|
+
#--
|
|
72
|
+
# SPDX-SnippetBegin
|
|
73
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
74
|
+
# SPDX-License-Identifier: MIT-0
|
|
75
|
+
#++
|
|
76
|
+
# if event.modifier?
|
|
77
|
+
# # Handle solo modifier key press
|
|
78
|
+
# end
|
|
79
|
+
#--
|
|
80
|
+
# SPDX-SnippetEnd
|
|
81
|
+
#++
|
|
82
|
+
def modifier?
|
|
83
|
+
@kind == :modifier
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Handles modifier-specific DWIM logic for method_missing.
|
|
87
|
+
private def match_modifier_dwim?(key_name, key_sym)
|
|
88
|
+
# Platform modifier aliases
|
|
89
|
+
modifier_aliases = {
|
|
90
|
+
win: "super",
|
|
91
|
+
command: "super",
|
|
92
|
+
cmd: "super",
|
|
93
|
+
tux: "super",
|
|
94
|
+
}.freeze
|
|
95
|
+
|
|
96
|
+
target_modifier = modifier_aliases[key_sym]
|
|
97
|
+
if target_modifier
|
|
98
|
+
return true if @modifiers.include?(target_modifier)
|
|
99
|
+
return true if @code == "left_#{target_modifier}" || @code == "right_#{target_modifier}"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
false
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
class Key < Event
|
|
11
|
+
# Methods and logic for navigation keys.
|
|
12
|
+
module Navigation
|
|
13
|
+
# Returns true if this is a standard key.
|
|
14
|
+
#
|
|
15
|
+
# Standard keys include: characters, Enter, Tab, arrow keys, navigation keys.
|
|
16
|
+
#
|
|
17
|
+
# event.standard? # => true for "a", "enter", "up", etc.
|
|
18
|
+
def standard?
|
|
19
|
+
@kind == :standard
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Alias for {#standard?}.
|
|
23
|
+
#
|
|
24
|
+
# Provided for semantic clarity when checking if a key has no special category.
|
|
25
|
+
#
|
|
26
|
+
# event.unmodified? # => true for standard keys like "a", "enter", "up"
|
|
27
|
+
alias unmodified? standard?
|
|
28
|
+
|
|
29
|
+
# Handles navigation-specific DWIM logic for method_missing.
|
|
30
|
+
private def match_navigation_dwim?(key_name, key_sym)
|
|
31
|
+
# DWIM: back_tab?/backtab? matches back_tab code even with shift modifier
|
|
32
|
+
# (since back_tab semantically implies shift)
|
|
33
|
+
if (key_name == "back_tab" || key_name == "backtab") && @code == "back_tab" && (@modifiers.empty? || @modifiers == ["shift"])
|
|
34
|
+
return true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# DWIM: reverse_tab? matches both BackTab key and Shift+Tab combo
|
|
38
|
+
if key_name == "reverse_tab"
|
|
39
|
+
return true if @code == "back_tab"
|
|
40
|
+
return true if @code == "tab" && @modifiers.include?("shift")
|
|
41
|
+
end
|
|
42
|
+
# DWIM: Check explicit aliases
|
|
43
|
+
navigation_aliases = {
|
|
44
|
+
# Arrow key aliases (disambiguate from Mouse#up? and Mouse#down?)
|
|
45
|
+
arrow_up: "up",
|
|
46
|
+
up_arrow: "up",
|
|
47
|
+
arrow_down: "down",
|
|
48
|
+
down_arrow: "down",
|
|
49
|
+
arrow_left: "left",
|
|
50
|
+
left_arrow: "left",
|
|
51
|
+
arrow_right: "right",
|
|
52
|
+
right_arrow: "right",
|
|
53
|
+
# Other navigation aliases
|
|
54
|
+
return: "enter",
|
|
55
|
+
back: "backspace",
|
|
56
|
+
del: "delete",
|
|
57
|
+
ins: "insert",
|
|
58
|
+
pgup: "page_up",
|
|
59
|
+
pageup: "page_up",
|
|
60
|
+
pgdn: "page_down",
|
|
61
|
+
pagedown: "page_down",
|
|
62
|
+
}.freeze
|
|
63
|
+
|
|
64
|
+
target_code = navigation_aliases[key_sym]
|
|
65
|
+
return true if target_code && @code == target_code && @modifiers.empty?
|
|
66
|
+
|
|
67
|
+
false
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|