ratatui_ruby 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.builds/ruby-3.2.yml +14 -12
- data/.builds/ruby-3.3.yml +14 -12
- data/.builds/ruby-3.4.yml +14 -12
- data/.builds/ruby-4.0.0.yml +14 -12
- data/AGENTS.md +89 -132
- data/CHANGELOG.md +223 -1
- data/README.md +23 -16
- data/REUSE.toml +20 -0
- data/doc/application_architecture.md +176 -0
- data/doc/application_testing.md +17 -10
- data/doc/contributors/design/ruby_frontend.md +11 -7
- data/doc/contributors/developing_examples.md +261 -0
- data/doc/contributors/documentation_style.md +104 -0
- data/doc/contributors/dwim_dx.md +366 -0
- data/doc/contributors/index.md +2 -0
- data/doc/custom.css +14 -0
- data/doc/event_handling.md +125 -0
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_analytics.png +0 -0
- data/doc/images/app_color_picker.png +0 -0
- data/doc/images/app_custom_widget.png +0 -0
- data/doc/images/app_login_form.png +0 -0
- data/doc/images/app_map_demo.png +0 -0
- data/doc/images/app_mouse_events.png +0 -0
- data/doc/images/app_table_select.png +0 -0
- data/doc/images/verify_quickstart_dsl.png +0 -0
- data/doc/images/verify_quickstart_layout.png +0 -0
- data/doc/images/verify_quickstart_lifecycle.png +0 -0
- data/doc/images/verify_readme_usage.png +0 -0
- data/doc/images/widget_barchart_demo.png +0 -0
- data/doc/images/widget_block_padding.png +0 -0
- data/doc/images/widget_block_titles.png +0 -0
- data/doc/images/widget_box_demo.png +0 -0
- data/doc/images/widget_calendar_demo.png +0 -0
- data/doc/images/widget_cell_demo.png +0 -0
- data/doc/images/widget_chart_demo.png +0 -0
- data/doc/images/widget_gauge_demo.png +0 -0
- data/doc/images/widget_layout_split.png +0 -0
- data/doc/images/widget_line_gauge_demo.png +0 -0
- data/doc/images/widget_list_demo.png +0 -0
- data/doc/images/widget_list_styles.png +0 -0
- data/doc/images/widget_popup_demo.png +0 -0
- data/doc/images/widget_ratatui_logo_demo.png +0 -0
- data/doc/images/widget_ratatui_mascot_demo.png +0 -0
- data/doc/images/widget_rect.png +0 -0
- data/doc/images/widget_render.png +0 -0
- data/doc/images/widget_rich_text.png +0 -0
- data/doc/images/widget_scroll_text.png +0 -0
- data/doc/images/widget_scrollbar_demo.png +0 -0
- data/doc/images/widget_sparkline_demo.png +0 -0
- data/doc/images/widget_style_colors.png +0 -0
- data/doc/images/widget_table_flex.png +0 -0
- data/doc/images/widget_tabs_demo.png +0 -0
- data/doc/index.md +1 -0
- data/doc/interactive_design.md +116 -0
- data/doc/quickstart.md +186 -84
- data/examples/app_all_events/README.md +81 -0
- data/examples/app_all_events/app.rb +93 -0
- data/examples/app_all_events/model/event_color_cycle.rb +41 -0
- data/examples/app_all_events/model/event_entry.rb +75 -0
- data/examples/app_all_events/model/events.rb +180 -0
- data/examples/app_all_events/model/highlight.rb +57 -0
- data/examples/app_all_events/model/timestamp.rb +54 -0
- data/examples/app_all_events/test/snapshots/after_focus_lost.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_focus_regained.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_horizontal_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_key_a.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_key_ctrl_x.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_mouse_click.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_mouse_drag.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_multiple_events.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_paste.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_right_click.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_vertical_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/initial_state.txt +24 -0
- data/examples/app_all_events/view/app_view.rb +78 -0
- data/examples/app_all_events/view/controls_view.rb +50 -0
- data/examples/app_all_events/view/counts_view.rb +55 -0
- data/examples/app_all_events/view/live_view.rb +69 -0
- data/examples/app_all_events/view/log_view.rb +60 -0
- data/{lib/ratatui_ruby/output.rb → examples/app_all_events/view.rb} +1 -1
- data/examples/app_all_events/view_state.rb +42 -0
- data/examples/app_color_picker/README.md +94 -0
- data/examples/app_color_picker/app.rb +112 -0
- data/examples/app_color_picker/clipboard.rb +84 -0
- data/examples/app_color_picker/color.rb +191 -0
- data/examples/app_color_picker/copy_dialog.rb +170 -0
- data/examples/app_color_picker/harmony.rb +56 -0
- data/examples/app_color_picker/input.rb +142 -0
- data/examples/app_color_picker/palette.rb +80 -0
- data/examples/app_color_picker/scene.rb +201 -0
- data/examples/app_login_form/app.rb +108 -0
- data/examples/app_map_demo/app.rb +93 -0
- data/examples/app_table_select/app.rb +201 -0
- data/examples/verify_quickstart_dsl/app.rb +45 -0
- data/examples/verify_quickstart_layout/app.rb +69 -0
- data/examples/verify_quickstart_lifecycle/app.rb +48 -0
- data/examples/verify_readme_usage/app.rb +34 -0
- data/examples/widget_barchart_demo/app.rb +238 -0
- data/examples/widget_block_padding/app.rb +67 -0
- data/examples/widget_block_titles/app.rb +69 -0
- data/examples/widget_box_demo/app.rb +250 -0
- data/examples/widget_calendar_demo/app.rb +109 -0
- data/examples/widget_cell_demo/app.rb +104 -0
- data/examples/widget_chart_demo/app.rb +213 -0
- data/examples/widget_gauge_demo/app.rb +212 -0
- data/examples/widget_layout_split/app.rb +246 -0
- data/examples/widget_line_gauge_demo/app.rb +217 -0
- data/examples/widget_list_demo/app.rb +382 -0
- data/examples/widget_list_styles/app.rb +141 -0
- data/examples/widget_popup_demo/app.rb +104 -0
- data/examples/widget_ratatui_logo_demo/app.rb +103 -0
- data/examples/widget_ratatui_mascot_demo/app.rb +93 -0
- data/examples/widget_rect/app.rb +205 -0
- data/examples/widget_render/app.rb +184 -0
- data/examples/widget_rich_text/app.rb +137 -0
- data/examples/widget_scroll_text/app.rb +108 -0
- data/examples/widget_scrollbar_demo/app.rb +153 -0
- data/examples/widget_sparkline_demo/app.rb +274 -0
- data/examples/widget_style_colors/app.rb +102 -0
- data/examples/widget_table_flex/app.rb +95 -0
- data/examples/widget_tabs_demo/app.rb +167 -0
- data/ext/ratatui_ruby/Cargo.lock +889 -115
- data/ext/ratatui_ruby/Cargo.toml +4 -3
- data/ext/ratatui_ruby/clippy.toml +7 -0
- data/ext/ratatui_ruby/extconf.rb +7 -0
- data/ext/ratatui_ruby/src/events.rs +293 -219
- data/ext/ratatui_ruby/src/frame.rs +115 -0
- data/ext/ratatui_ruby/src/lib.rs +105 -24
- data/ext/ratatui_ruby/src/rendering.rs +94 -10
- data/ext/ratatui_ruby/src/style.rs +357 -93
- data/ext/ratatui_ruby/src/terminal.rs +121 -31
- data/ext/ratatui_ruby/src/text.rs +178 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +99 -24
- data/ext/ratatui_ruby/src/widgets/block.rs +32 -3
- data/ext/ratatui_ruby/src/widgets/calendar.rs +45 -44
- data/ext/ratatui_ruby/src/widgets/canvas.rs +44 -9
- data/ext/ratatui_ruby/src/widgets/chart.rs +79 -27
- data/ext/ratatui_ruby/src/widgets/clear.rs +3 -1
- data/ext/ratatui_ruby/src/widgets/gauge.rs +11 -4
- data/ext/ratatui_ruby/src/widgets/layout.rs +223 -15
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +92 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +114 -11
- data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +4 -2
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +35 -13
- data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +40 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +51 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +61 -7
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +73 -6
- data/ext/ratatui_ruby/src/widgets/table.rs +177 -64
- data/ext/ratatui_ruby/src/widgets/tabs.rs +105 -5
- data/lib/ratatui_ruby/cell.rb +166 -0
- data/lib/ratatui_ruby/event/focus_gained.rb +49 -0
- data/lib/ratatui_ruby/event/focus_lost.rb +50 -0
- data/lib/ratatui_ruby/event/key.rb +211 -0
- data/lib/ratatui_ruby/event/mouse.rb +124 -0
- data/lib/ratatui_ruby/event/none.rb +43 -0
- data/lib/ratatui_ruby/event/paste.rb +71 -0
- data/lib/ratatui_ruby/event/resize.rb +80 -0
- data/lib/ratatui_ruby/event.rb +131 -0
- data/lib/ratatui_ruby/frame.rb +87 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +45 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +23 -0
- data/lib/ratatui_ruby/schema/bar_chart.rb +226 -17
- data/lib/ratatui_ruby/schema/block.rb +178 -11
- data/lib/ratatui_ruby/schema/calendar.rb +70 -14
- data/lib/ratatui_ruby/schema/canvas.rb +213 -46
- data/lib/ratatui_ruby/schema/center.rb +46 -8
- data/lib/ratatui_ruby/schema/chart.rb +134 -32
- data/lib/ratatui_ruby/schema/clear.rb +22 -53
- data/lib/ratatui_ruby/schema/constraint.rb +72 -12
- data/lib/ratatui_ruby/schema/cursor.rb +23 -5
- data/lib/ratatui_ruby/schema/draw.rb +53 -0
- data/lib/ratatui_ruby/schema/gauge.rb +56 -12
- data/lib/ratatui_ruby/schema/layout.rb +91 -9
- data/lib/ratatui_ruby/schema/line_gauge.rb +78 -0
- data/lib/ratatui_ruby/schema/list.rb +92 -16
- data/lib/ratatui_ruby/schema/overlay.rb +29 -3
- data/lib/ratatui_ruby/schema/paragraph.rb +82 -25
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +29 -0
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +34 -0
- data/lib/ratatui_ruby/schema/rect.rb +59 -10
- data/lib/ratatui_ruby/schema/scrollbar.rb +127 -19
- data/lib/ratatui_ruby/schema/shape/label.rb +66 -0
- data/lib/ratatui_ruby/schema/sparkline.rb +120 -12
- data/lib/ratatui_ruby/schema/style.rb +39 -11
- data/lib/ratatui_ruby/schema/table.rb +109 -18
- data/lib/ratatui_ruby/schema/tabs.rb +71 -10
- data/lib/ratatui_ruby/schema/text.rb +90 -0
- data/lib/ratatui_ruby/session/autodoc.rb +417 -0
- data/lib/ratatui_ruby/session.rb +163 -0
- data/lib/ratatui_ruby/test_helper.rb +322 -13
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby.rb +184 -38
- data/sig/examples/app_all_events/app.rbs +11 -0
- data/sig/examples/app_all_events/model/event_entry.rbs +16 -0
- data/sig/examples/app_all_events/model/events.rbs +15 -0
- data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
- data/sig/examples/app_all_events/view/app_view.rbs +8 -0
- data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
- data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
- data/sig/examples/app_all_events/view/live_view.rbs +6 -0
- data/sig/examples/app_all_events/view/log_view.rbs +6 -0
- data/sig/examples/app_all_events/view.rbs +8 -0
- data/sig/examples/app_all_events/view_state.rbs +15 -0
- data/sig/examples/app_color_picker/app.rbs +12 -0
- data/sig/examples/app_login_form/app.rbs +11 -0
- data/sig/examples/app_map_demo/app.rbs +11 -0
- data/sig/examples/app_table_select/app.rbs +11 -0
- data/sig/examples/verify_quickstart_dsl/app.rbs +11 -0
- data/sig/examples/verify_quickstart_lifecycle/app.rbs +11 -0
- data/sig/examples/verify_readme_usage/app.rbs +11 -0
- data/sig/examples/widget_block_padding/app.rbs +11 -0
- data/sig/examples/widget_block_titles/app.rbs +11 -0
- data/sig/examples/widget_box_demo/app.rbs +11 -0
- data/sig/examples/widget_calendar_demo/app.rbs +11 -0
- data/sig/examples/widget_cell_demo/app.rbs +11 -0
- data/sig/examples/widget_chart_demo/app.rbs +11 -0
- data/sig/examples/widget_gauge_demo/app.rbs +11 -0
- data/sig/examples/widget_layout_split/app.rbs +10 -0
- data/sig/examples/widget_line_gauge_demo/app.rbs +11 -0
- data/sig/examples/widget_list_demo/app.rbs +12 -0
- data/sig/examples/widget_list_styles/app.rbs +11 -0
- data/sig/examples/widget_popup_demo/app.rbs +11 -0
- data/sig/examples/widget_ratatui_logo_demo/app.rbs +11 -0
- data/sig/examples/widget_ratatui_mascot_demo/app.rbs +11 -0
- data/sig/examples/widget_rect/app.rbs +12 -0
- data/sig/examples/widget_render/app.rbs +10 -0
- data/sig/examples/widget_rich_text/app.rbs +11 -0
- data/sig/examples/widget_scroll_text/app.rbs +11 -0
- data/sig/examples/widget_scrollbar_demo/app.rbs +11 -0
- data/sig/examples/widget_sparkline_demo/app.rbs +10 -0
- data/sig/examples/widget_style_colors/app.rbs +14 -0
- data/sig/examples/widget_table_flex/app.rbs +11 -0
- data/sig/ratatui_ruby/event.rbs +69 -0
- data/sig/ratatui_ruby/frame.rbs +9 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +5 -3
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +16 -0
- data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +13 -0
- data/sig/ratatui_ruby/schema/bar_chart.rbs +20 -2
- data/sig/ratatui_ruby/schema/block.rbs +5 -4
- data/sig/ratatui_ruby/schema/calendar.rbs +6 -2
- data/sig/ratatui_ruby/schema/canvas.rbs +52 -39
- data/sig/ratatui_ruby/schema/center.rbs +3 -3
- data/sig/ratatui_ruby/schema/chart.rbs +8 -5
- data/sig/ratatui_ruby/schema/constraint.rbs +8 -5
- data/sig/ratatui_ruby/schema/cursor.rbs +1 -1
- data/sig/ratatui_ruby/schema/draw.rbs +27 -0
- data/sig/ratatui_ruby/schema/gauge.rbs +4 -2
- data/sig/ratatui_ruby/schema/layout.rbs +11 -1
- data/sig/ratatui_ruby/schema/line_gauge.rbs +16 -0
- data/sig/ratatui_ruby/schema/list.rbs +5 -1
- data/sig/ratatui_ruby/schema/paragraph.rbs +4 -1
- data/sig/ratatui_ruby/schema/ratatui_logo.rbs +8 -0
- data/sig/ratatui_ruby/{buffer.rbs → schema/ratatui_mascot.rbs} +4 -3
- data/sig/ratatui_ruby/schema/rect.rbs +2 -1
- data/sig/ratatui_ruby/schema/scrollbar.rbs +18 -2
- data/sig/ratatui_ruby/schema/sparkline.rbs +6 -2
- data/sig/ratatui_ruby/schema/table.rbs +8 -1
- data/sig/ratatui_ruby/schema/tabs.rbs +5 -1
- data/sig/ratatui_ruby/schema/text.rbs +22 -0
- data/sig/ratatui_ruby/session.rbs +94 -0
- data/tasks/autodoc/inventory.rb +61 -0
- data/tasks/autodoc/member.rb +56 -0
- data/tasks/autodoc/name.rb +19 -0
- data/tasks/autodoc/notice.rb +26 -0
- data/tasks/autodoc/rbs.rb +38 -0
- data/tasks/autodoc/rdoc.rb +45 -0
- data/tasks/autodoc.rake +47 -0
- data/tasks/bump/history.rb +2 -2
- data/tasks/doc.rake +600 -6
- data/tasks/example_viewer.html.erb +172 -0
- data/tasks/lint.rake +8 -4
- data/tasks/resources/build.yml.erb +13 -11
- data/tasks/resources/index.html.erb +6 -0
- data/tasks/sourcehut.rake +4 -4
- data/tasks/terminal_preview/app_screenshot.rb +33 -0
- data/tasks/terminal_preview/crash_report.rb +52 -0
- data/tasks/terminal_preview/example_app.rb +25 -0
- data/tasks/terminal_preview/launcher_script.rb +46 -0
- data/tasks/terminal_preview/preview_collection.rb +58 -0
- data/tasks/terminal_preview/preview_timing.rb +22 -0
- data/tasks/terminal_preview/safety_confirmation.rb +56 -0
- data/tasks/terminal_preview/saved_screenshot.rb +53 -0
- data/tasks/terminal_preview/system_appearance.rb +11 -0
- data/tasks/terminal_preview/terminal_window.rb +136 -0
- data/tasks/terminal_preview/window_id.rb +14 -0
- data/tasks/terminal_preview.rake +28 -0
- data/tasks/test.rake +2 -2
- data/tasks/website/index_page.rb +3 -3
- data/tasks/website/version.rb +10 -10
- data/tasks/website/version_menu.rb +10 -12
- data/tasks/website/versioned_documentation.rb +49 -17
- data/tasks/website/website.rb +6 -8
- data/tasks/website.rake +4 -4
- metadata +206 -54
- data/LICENSES/BSD-2-Clause.txt +0 -9
- data/doc/images/examples-analytics.rb.png +0 -0
- data/doc/images/examples-box_demo.rb.png +0 -0
- data/doc/images/examples-calendar_demo.rb.png +0 -0
- data/doc/images/examples-chart_demo.rb.png +0 -0
- data/doc/images/examples-custom_widget.rb.png +0 -0
- data/doc/images/examples-dashboard.rb.png +0 -0
- data/doc/images/examples-list_styles.rb.png +0 -0
- data/doc/images/examples-login_form.rb.png +0 -0
- data/doc/images/examples-map_demo.rb.png +0 -0
- data/doc/images/examples-mouse_events.rb.png +0 -0
- data/doc/images/examples-popup_demo.rb.gif +0 -0
- data/doc/images/examples-quickstart_lifecycle.rb.png +0 -0
- data/doc/images/examples-scroll_text.rb.png +0 -0
- data/doc/images/examples-scrollbar_demo.rb.png +0 -0
- data/doc/images/examples-stock_ticker.rb.png +0 -0
- data/doc/images/examples-system_monitor.rb.png +0 -0
- data/doc/images/examples-table_select.rb.png +0 -0
- data/examples/analytics.rb +0 -88
- data/examples/box_demo.rb +0 -71
- data/examples/calendar_demo.rb +0 -55
- data/examples/chart_demo.rb +0 -84
- data/examples/custom_widget.rb +0 -43
- data/examples/dashboard.rb +0 -72
- data/examples/list_styles.rb +0 -66
- data/examples/login_form.rb +0 -115
- data/examples/map_demo.rb +0 -58
- data/examples/mouse_events.rb +0 -95
- data/examples/popup_demo.rb +0 -105
- data/examples/quickstart_dsl.rb +0 -30
- data/examples/quickstart_lifecycle.rb +0 -40
- data/examples/readme_usage.rb +0 -21
- data/examples/scroll_text.rb +0 -74
- data/examples/scrollbar_demo.rb +0 -75
- data/examples/stock_ticker.rb +0 -93
- data/examples/system_monitor.rb +0 -94
- data/examples/table_select.rb +0 -70
- data/examples/test_analytics.rb +0 -65
- data/examples/test_box_demo.rb +0 -38
- data/examples/test_calendar_demo.rb +0 -66
- data/examples/test_dashboard.rb +0 -38
- data/examples/test_list_styles.rb +0 -61
- data/examples/test_login_form.rb +0 -63
- data/examples/test_map_demo.rb +0 -100
- data/examples/test_popup_demo.rb +0 -62
- data/examples/test_scroll_text.rb +0 -130
- data/examples/test_stock_ticker.rb +0 -39
- data/examples/test_system_monitor.rb +0 -40
- data/examples/test_table_select.rb +0 -37
- data/ext/ratatui_ruby/src/buffer.rs +0 -54
- data/lib/ratatui_ruby/dsl.rb +0 -64
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com> -->
|
|
2
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
3
|
+
|
|
4
|
+
# DWIM / DX Improvements for Application Developers
|
|
5
|
+
|
|
6
|
+
## Problem Statement
|
|
7
|
+
|
|
8
|
+
Ruby's philosophy of "Do What I Mean" (DWIM) and human-centric design should extend to ratatui_ruby's API. Currently, app developers encounter friction points that force them to remember non-obvious conventions, use overly verbose code, or pattern-match when simple predicates would suffice.
|
|
9
|
+
|
|
10
|
+
This proposal identifies DX issues across the widget API and suggests improvements that maintain backward compatibility while providing ergonomic alternatives.
|
|
11
|
+
|
|
12
|
+
## DX Issues Identified
|
|
13
|
+
|
|
14
|
+
### 1. Confusing Event Method Names
|
|
15
|
+
|
|
16
|
+
**Current problem**: `event.char` doesn't exist, but `event.code` returns things like `"enter"`, `"ctrl"`, not just characters.
|
|
17
|
+
|
|
18
|
+
**What users expect**:
|
|
19
|
+
- `event.char` should return the printable character (matching the name)
|
|
20
|
+
- `event.ctrl_c?`, `event.enter?`, etc. should work for all key combinations
|
|
21
|
+
- `event.key?`, `event.mouse?` predicates exist but only for broad categories
|
|
22
|
+
|
|
23
|
+
**Solution implemented**: Added `char` method and dynamic predicates via `method_missing`. See `lib/ratatui_ruby/event/key.rb`.
|
|
24
|
+
|
|
25
|
+
### 2. Dual Parameter APIs Without Predicates
|
|
26
|
+
|
|
27
|
+
**Current problem**: Widgets accept both forms but no convenience methods to query the state:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
# Both work, but which one does the widget store?
|
|
31
|
+
gauge1 = Gauge.new(ratio: 0.75)
|
|
32
|
+
gauge2 = Gauge.new(percent: 75)
|
|
33
|
+
gauge1.ratio # Works
|
|
34
|
+
gauge1.percent # Does NOT exist
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Similarly with List and Table:
|
|
38
|
+
```ruby
|
|
39
|
+
list.selected_index = 2 # Works
|
|
40
|
+
list.selected? # Does NOT exist
|
|
41
|
+
list.is_selected? # Does NOT exist
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Affected widgets**:
|
|
45
|
+
- `Gauge` (ratio vs percent)
|
|
46
|
+
- `LineGauge` (ratio vs percent)
|
|
47
|
+
- `List` (selected_index with no query methods)
|
|
48
|
+
- `Table` (selected_row and selected_column with no query methods)
|
|
49
|
+
|
|
50
|
+
**Suggested solutions**:
|
|
51
|
+
|
|
52
|
+
For `Gauge` and `LineGauge`:
|
|
53
|
+
```ruby
|
|
54
|
+
# Add convenience predicates
|
|
55
|
+
gauge.percent # => 75 (coerced from ratio internally)
|
|
56
|
+
gauge.percent = 50 # => Updates ratio to 0.5
|
|
57
|
+
|
|
58
|
+
# Or provide explicit accessors
|
|
59
|
+
gauge.as_percent # => 75
|
|
60
|
+
gauge.as_ratio # => 0.75
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For `List` and `Table`:
|
|
64
|
+
```ruby
|
|
65
|
+
list.selected? # => true if selected_index is not nil
|
|
66
|
+
list.selection # => 2 (alias for selected_index)
|
|
67
|
+
list.selected_item # => "Item 3"
|
|
68
|
+
|
|
69
|
+
table.selected_row? # => true if selected_row is not nil
|
|
70
|
+
table.selected_cell? # => true if both row and column selected
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 3. Symbol Constants for Enum Values
|
|
74
|
+
|
|
75
|
+
**Current problem**: Magic symbol values scattered across code:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
list = List.new(
|
|
79
|
+
highlight_spacing: :when_selected, # What are the other options?
|
|
80
|
+
direction: :top_to_bottom, # Is :bottom_to_top valid?
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
layout = Layout.new(
|
|
84
|
+
flex: :legacy # What does "legacy" mean?
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
gauge = Gauge.new(
|
|
88
|
+
use_unicode: true # Unclear what ASCII fallback looks like
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Users must consult docs or source code to discover valid options.
|
|
93
|
+
|
|
94
|
+
**Suggested solution**: Add constants to widget classes:
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
class List < Data
|
|
98
|
+
# Highlight spacing modes
|
|
99
|
+
HIGHLIGHT_ALWAYS = :always
|
|
100
|
+
HIGHLIGHT_WHEN_SELECTED = :when_selected
|
|
101
|
+
HIGHLIGHT_NEVER = :never
|
|
102
|
+
|
|
103
|
+
# Direction modes
|
|
104
|
+
DIRECTION_TOP_TO_BOTTOM = :top_to_bottom
|
|
105
|
+
DIRECTION_BOTTOM_TO_TOP = :bottom_to_top
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
list = List.new(
|
|
109
|
+
highlight_spacing: List::HIGHLIGHT_WHEN_SELECTED,
|
|
110
|
+
direction: List::DIRECTION_TOP_TO_BOTTOM,
|
|
111
|
+
)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Benefits:
|
|
115
|
+
- IDE autocomplete shows valid options
|
|
116
|
+
- Self-documenting code
|
|
117
|
+
- Typos caught at runtime (symbol vs constant)
|
|
118
|
+
- Easy to grep for where these modes are used
|
|
119
|
+
|
|
120
|
+
Affected widgets and their enum values:
|
|
121
|
+
- `List`: `highlight_spacing` (:always, :when_selected, :never), `direction` (:top_to_bottom, :bottom_to_top)
|
|
122
|
+
- `Table`: `highlight_spacing` (same as List), `flex` (:legacy, :default, :fill)
|
|
123
|
+
- `Layout`: `direction` (:vertical, :horizontal), `flex` (:legacy, :default, :fill)
|
|
124
|
+
- `Gauge`/`LineGauge`: `use_unicode` (boolean, but could have MODE_UNICODE, MODE_ASCII)
|
|
125
|
+
- `Paragraph`: `alignment` (:left, :center, :right)
|
|
126
|
+
- `Block`: `border_type` (:plain, :rounded, :double, :thick)
|
|
127
|
+
- `Canvas`: `marker` (:braille, :dots, :half_block, :sextant, :octant)
|
|
128
|
+
|
|
129
|
+
### 4. Inconsistent Style APIs
|
|
130
|
+
|
|
131
|
+
**Current problem**: Different widgets accept styles differently:
|
|
132
|
+
|
|
133
|
+
```ruby
|
|
134
|
+
# Table accepts both
|
|
135
|
+
table = Table.new(style: Style.new(fg: :blue))
|
|
136
|
+
table = Table.new(style: { fg: :blue }) # Hash shorthand
|
|
137
|
+
|
|
138
|
+
# But Paragraph doesn't
|
|
139
|
+
paragraph = Paragraph.new(text: "hi", style: Style.new(fg: :blue))
|
|
140
|
+
paragraph = Paragraph.new(text: "hi", style: { fg: :blue }) # Works but undocumented
|
|
141
|
+
|
|
142
|
+
# And Gauge has separate properties
|
|
143
|
+
gauge = Gauge.new(style: Style.new(fg: :blue), gauge_style: Style.new(fg: :green))
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Suggested solution**: Standardize style handling across all widgets:
|
|
147
|
+
|
|
148
|
+
1. All widgets should accept `Style` objects and `Hash` shorthand
|
|
149
|
+
2. Document this clearly in each widget
|
|
150
|
+
3. Add a convenience constructor:
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
class Style
|
|
154
|
+
def self.with(fg: nil, bg: nil, modifiers: [])
|
|
155
|
+
Style.new(fg: fg, bg: bg, modifiers: modifiers)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Cleaner than always spelling out keyword args
|
|
160
|
+
paragraph = Paragraph.new(text: "hi", style: Style.with(fg: :blue))
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 5. Missing State Query Predicates
|
|
164
|
+
|
|
165
|
+
**Current problem**: Widgets store state but provide no query methods:
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
list.selected_index = 0
|
|
169
|
+
|
|
170
|
+
# To check if something is selected, must do:
|
|
171
|
+
if list.selected_index&.nonzero? # Awkward
|
|
172
|
+
if list.selected_index.nil? == false # Confusing
|
|
173
|
+
|
|
174
|
+
# Should be:
|
|
175
|
+
list.selected? # => true
|
|
176
|
+
list.empty? # => false (for items array)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Suggested solution**: Add predicates to state-holding widgets:
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
# List
|
|
183
|
+
list.selected? # => !selected_index.nil?
|
|
184
|
+
list.empty? # => items.empty?
|
|
185
|
+
list.selection # => selected_index (alias)
|
|
186
|
+
list.selected_item # => items[selected_index] (convenience)
|
|
187
|
+
|
|
188
|
+
# Table
|
|
189
|
+
table.selected_row? # => !selected_row.nil?
|
|
190
|
+
table.selected_cell? # => !selected_row.nil? && !selected_column.nil?
|
|
191
|
+
table.empty? # => rows.empty?
|
|
192
|
+
|
|
193
|
+
# Gauge
|
|
194
|
+
gauge.filled? # => ratio > 0
|
|
195
|
+
gauge.complete? # => ratio >= 1.0
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### 6. Magic Numeric Coercions
|
|
199
|
+
|
|
200
|
+
**Current problem**: Widgets accept `Numeric` but silently coerce:
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
# These all work, but behavior is undocumented
|
|
204
|
+
list = List.new(selected_index: "2") # Coerced to 2
|
|
205
|
+
list = List.new(selected_index: 2.7) # Coerced to 2
|
|
206
|
+
list = List.new(selected_index: 2.0) # Coerced to 2
|
|
207
|
+
|
|
208
|
+
gauge = Gauge.new(percent: 150) # Should clamp?
|
|
209
|
+
gauge = Gauge.new(ratio: 1.5) # Should clamp?
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Suggested solution**:
|
|
213
|
+
|
|
214
|
+
1. Document coercion rules explicitly in RDoc
|
|
215
|
+
2. Add validation and raise on invalid inputs:
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
def initialize(percent: nil, ...)
|
|
219
|
+
if percent
|
|
220
|
+
raise ArgumentError, "percent must be 0..100, got #{percent}" unless percent.between?(0, 100)
|
|
221
|
+
ratio = Float(percent) / 100.0
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
3. Provide clear error messages:
|
|
227
|
+
```ruby
|
|
228
|
+
gauge = Gauge.new(percent: 150)
|
|
229
|
+
# => ArgumentError: percent must be between 0 and 100 (got 150)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Implementation Strategy
|
|
233
|
+
|
|
234
|
+
### Phase 1: Event Improvements (DONE)
|
|
235
|
+
- [x] Add `char` method to Key event
|
|
236
|
+
- [x] Implement dynamic predicates via `method_missing`
|
|
237
|
+
- [x] Update examples to use new API
|
|
238
|
+
|
|
239
|
+
### Phase 2: State Query Predicates
|
|
240
|
+
- [ ] Add predicates to `List` (selected?, empty?, selected_item)
|
|
241
|
+
- [ ] Add predicates to `Table` (selected_row?, selected_cell?, empty?)
|
|
242
|
+
- [ ] Add predicates to `Gauge` (filled?, complete?)
|
|
243
|
+
- [ ] Tests for all new predicates
|
|
244
|
+
|
|
245
|
+
### Phase 3: Symbol Constants
|
|
246
|
+
- [ ] Add enum constants to `List`, `Table`, `Layout`
|
|
247
|
+
- [ ] Add enum constants to `Gauge`, `LineGauge`, `Paragraph`, `Block`
|
|
248
|
+
- [ ] Update all examples to use constants
|
|
249
|
+
- [ ] Document constants in RDoc
|
|
250
|
+
|
|
251
|
+
### Phase 4: Style Consistency
|
|
252
|
+
- [ ] Standardize `Hash` shorthand support across all widgets
|
|
253
|
+
- [ ] Add `Style.with(fg:, bg:, modifiers:)` convenience constructor
|
|
254
|
+
- [ ] Update `.rbs` files to reflect HashStyle support
|
|
255
|
+
- [ ] Document in style guide
|
|
256
|
+
|
|
257
|
+
### Phase 5: Numeric Coercion Validation
|
|
258
|
+
- [ ] Add validation to `Gauge`, `LineGauge`, `List`, `Table`
|
|
259
|
+
- [ ] Raise `ArgumentError` on out-of-range values
|
|
260
|
+
- [ ] Provide clear error messages
|
|
261
|
+
- [ ] Update tests
|
|
262
|
+
|
|
263
|
+
### Phase 6: Convenience Accessors
|
|
264
|
+
- [ ] Add `percent` to `Gauge` and `LineGauge`
|
|
265
|
+
- [ ] Add `selection` alias to `List` and `Table`
|
|
266
|
+
- [ ] Add `selected_item` to `List`
|
|
267
|
+
- [ ] Tests and documentation
|
|
268
|
+
|
|
269
|
+
## Example: Before and After
|
|
270
|
+
|
|
271
|
+
### Before (Confusing)
|
|
272
|
+
```ruby
|
|
273
|
+
class GameApp
|
|
274
|
+
def initialize
|
|
275
|
+
@menu = List.new(
|
|
276
|
+
items: ["Start Game", "Load Game", "Options", "Quit"],
|
|
277
|
+
selected_index: 0,
|
|
278
|
+
highlight_spacing: :when_selected, # What's valid here?
|
|
279
|
+
direction: :top_to_bottom
|
|
280
|
+
)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def handle_input(event)
|
|
284
|
+
case event
|
|
285
|
+
when :ctrl_c
|
|
286
|
+
exit
|
|
287
|
+
when :up
|
|
288
|
+
if @menu.selected_index && @menu.selected_index > 0
|
|
289
|
+
@menu = @menu.with(selected_index: @menu.selected_index - 1)
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def render(tui)
|
|
295
|
+
tui.draw(@menu)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### After (DWIM)
|
|
301
|
+
```ruby
|
|
302
|
+
class GameApp
|
|
303
|
+
def initialize
|
|
304
|
+
@menu = List.new(
|
|
305
|
+
items: ["Start Game", "Load Game", "Options", "Quit"],
|
|
306
|
+
selected_index: 0,
|
|
307
|
+
highlight_spacing: List::HIGHLIGHT_WHEN_SELECTED, # IDE autocomplete!
|
|
308
|
+
direction: List::DIRECTION_TOP_TO_BOTTOM
|
|
309
|
+
)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def handle_input(event)
|
|
313
|
+
return if event.ctrl_c? # Dynamic predicate!
|
|
314
|
+
|
|
315
|
+
if event.up?
|
|
316
|
+
move_menu_up if @menu.selected? # State predicate!
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def move_menu_up
|
|
321
|
+
index = @menu.selected_index
|
|
322
|
+
return if index == 0
|
|
323
|
+
@menu = @menu.with(selected_index: index - 1)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def render(tui)
|
|
327
|
+
tui.draw(@menu)
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Migration Path
|
|
333
|
+
|
|
334
|
+
All changes are backward compatible (additive):
|
|
335
|
+
- Existing code using symbols continues to work
|
|
336
|
+
- New constants coexist with symbols
|
|
337
|
+
- New predicates don't change existing behavior
|
|
338
|
+
- New methods are additions, not replacements
|
|
339
|
+
|
|
340
|
+
Apps can migrate at their own pace:
|
|
341
|
+
```ruby
|
|
342
|
+
# Old style still works
|
|
343
|
+
list = List.new(highlight_spacing: :when_selected)
|
|
344
|
+
|
|
345
|
+
# New style also works
|
|
346
|
+
list = List.new(highlight_spacing: List::HIGHLIGHT_WHEN_SELECTED)
|
|
347
|
+
|
|
348
|
+
# Mix and match
|
|
349
|
+
if list.selected? # New predicate
|
|
350
|
+
puts list.selected_index # Old accessor
|
|
351
|
+
end
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Metrics for Success
|
|
355
|
+
|
|
356
|
+
1. **Discoverability**: New developers can find valid options via IDE autocomplete
|
|
357
|
+
2. **Clarity**: Code self-documents valid states and modes
|
|
358
|
+
3. **Type safety**: Constants and predicates provide type checking
|
|
359
|
+
4. **Error feedback**: Invalid inputs raise with helpful messages
|
|
360
|
+
5. **Backward compatibility**: Zero breaking changes, all existing code works
|
|
361
|
+
|
|
362
|
+
## Related Issues
|
|
363
|
+
|
|
364
|
+
- AGENTS.md requirement: All examples must have tests verifying behavior
|
|
365
|
+
- Example improvements: Apply constants and predicates to all example code
|
|
366
|
+
- Documentation: Update style guide with DWIM principles
|
data/doc/contributors/index.md
CHANGED
data/doc/custom.css
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
img {
|
|
2
7
|
max-width: 100%;
|
|
3
8
|
height: auto;
|
|
@@ -5,4 +10,13 @@ img {
|
|
|
5
10
|
|
|
6
11
|
.theme-toggle {
|
|
7
12
|
margin-left: 0 !important;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Terminal Previews (Native PNGs)
|
|
16
|
+
* The images already contain the window chrome and shadows.
|
|
17
|
+
* We just need to center them and ensure they scale down on mobile.
|
|
18
|
+
*/
|
|
19
|
+
img[src*="images/"] {
|
|
20
|
+
display: block;
|
|
21
|
+
margin: 2em auto;
|
|
8
22
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# Event Handling in RatatuiRuby
|
|
8
|
+
|
|
9
|
+
`ratatui_ruby` provides a rich, object-oriented event system that supports multiple coding styles, from simple boolean predicates to modern Ruby pattern matching.
|
|
10
|
+
|
|
11
|
+
Events are retrieved using `RatatuiRuby.poll_event`. This method returns an instance of a subclass of `RatatuiRuby::Event` (e.g., `RatatuiRuby::Event::Key`, `RatatuiRuby::Event::Mouse`). When no event is available, it returns `RatatuiRuby::Event::None`—a [null object](https://martinfowler.com/eaaCatalog/specialCase.html) that safely responds to all event predicates with `false`.
|
|
12
|
+
|
|
13
|
+
## 1. Symbol and String Comparison (Simplest)
|
|
14
|
+
|
|
15
|
+
For simple key events, `RatatuiRuby::Event::Key` objects can be compared directly to Symbols or Strings. This is often the quickest way to get started.
|
|
16
|
+
|
|
17
|
+
* **String**: Matches the key character (e.g., "a", "q").
|
|
18
|
+
* **Symbol**: Matches special keys (e.g., `:enter`, `:esc`) or modifier combinations (e.g., `:ctrl_c`).
|
|
19
|
+
|
|
20
|
+
> [!NOTE]
|
|
21
|
+
> On macOS, the **Option** key is mapped to `alt`. The **Command** key is typically intercepted by the terminal emulator and may not be sent to the application, or it may be mapped to Meta/Alt depending on your terminal settings.
|
|
22
|
+
|
|
23
|
+
For a complete list of supported keys, modifiers, and event types, please refer to the [API Documentation for RatatuiRuby::Event](file:///Users/kerrick/Developer/ratatui_ruby/lib/ratatui_ruby/event.rb).
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
event = RatatuiRuby.poll_event
|
|
27
|
+
|
|
28
|
+
# 1. Check for quit keys
|
|
29
|
+
if event == "q" || event == :ctrl_c
|
|
30
|
+
break
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# 2. Check for special key
|
|
34
|
+
if event == :enter
|
|
35
|
+
submit_form
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 2. Predicate Methods (Intermediate)
|
|
40
|
+
|
|
41
|
+
If you need more control or logic (e.g. `if/elsif`), or need to handle non-key events like Resize or Mouse, use the predicate methods.
|
|
42
|
+
|
|
43
|
+
### Polymorphic Predicates
|
|
44
|
+
|
|
45
|
+
Safe to call on *any* event object. They return `true` only for the matching event type.
|
|
46
|
+
|
|
47
|
+
Available: `key?`, `mouse?`, `resize?`, `paste?`, `focus_gained?`, `focus_lost?`.
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
event = RatatuiRuby.poll_event
|
|
51
|
+
|
|
52
|
+
if event.key?
|
|
53
|
+
handle_keypress(event)
|
|
54
|
+
elsif event.mouse?
|
|
55
|
+
handle_click(event)
|
|
56
|
+
elsif event.resize?
|
|
57
|
+
resize_layout(event.width, event.height)
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Helper Predicates
|
|
62
|
+
|
|
63
|
+
Specific to certain event classes to simplify checks.
|
|
64
|
+
|
|
65
|
+
#### `RatatuiRuby::Event::Key`
|
|
66
|
+
* `ctrl?`, `alt?`, `shift?`: Check if modifier is held.
|
|
67
|
+
* `text?`: Returns `true` if the event is a printable character (length == 1).
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
if event.key? && event.ctrl? && event.code == "s"
|
|
71
|
+
save_file
|
|
72
|
+
end
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### `RatatuiRuby::Event::Mouse`
|
|
76
|
+
* `down?`, `up?`, `drag?`: Check mouse action.
|
|
77
|
+
* `scroll_up?`, `scroll_down?`: Check scroll direction.
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
if event.mouse? && event.scroll_up?
|
|
81
|
+
scroll_view(-1)
|
|
82
|
+
end
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 3. Pattern Matching (Powerful)
|
|
86
|
+
|
|
87
|
+
For complex applications, Ruby 3.0+ Pattern Matching with the `type:` discriminator is the most idiomatic and concise approach.
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
loop do
|
|
91
|
+
case RatatuiRuby.poll_event
|
|
92
|
+
|
|
93
|
+
# Match specific key code
|
|
94
|
+
in type: :key, code: "q"
|
|
95
|
+
break
|
|
96
|
+
|
|
97
|
+
# Match complex combo
|
|
98
|
+
in type: :key, code: "c", modifiers: ["ctrl"]
|
|
99
|
+
break
|
|
100
|
+
|
|
101
|
+
# Capture variables
|
|
102
|
+
in type: :key, code: "up" | "down" => direction
|
|
103
|
+
move_cursor(direction)
|
|
104
|
+
|
|
105
|
+
# Match mouse events
|
|
106
|
+
in type: :mouse, kind: "down", x:, y:
|
|
107
|
+
handle_click(x, y)
|
|
108
|
+
|
|
109
|
+
in type: :none
|
|
110
|
+
# No event available, continue loop
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Summary of Event Classes
|
|
116
|
+
|
|
117
|
+
| Event Class | Discriminator (`type:`) | Attributes | Predicate |
|
|
118
|
+
| :--- | :--- | :--- | :--- |
|
|
119
|
+
| `RatatuiRuby::Event::Key` | `:key` | `code`, `modifiers` | `key?` |
|
|
120
|
+
| `RatatuiRuby::Event::Mouse` | `:mouse` | `kind`, `x`, `y`, `button`, `modifiers` | `mouse?` |
|
|
121
|
+
| `RatatuiRuby::Event::Resize` | `:resize` | `width`, `height` | `resize?` |
|
|
122
|
+
| `RatatuiRuby::Event::Paste` | `:paste` | `content` | `paste?` |
|
|
123
|
+
| `RatatuiRuby::Event::FocusGained` | `:focus_gained` | (none) | `focus_gained?` |
|
|
124
|
+
| `RatatuiRuby::Event::FocusLost` | `:focus_lost` | (none) | `focus_lost?` |
|
|
125
|
+
| `RatatuiRuby::Event::None` | `:none` | (none) | `none?` |
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|