ratatui_ruby 0.7.4 → 0.9.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 +2 -2
- data/.builds/ruby-3.3.yml +2 -2
- data/.builds/ruby-3.4.yml +2 -2
- data/.builds/ruby-4.0.0.yml +2 -2
- data/.pre-commit-config.yaml +1 -1
- data/AGENTS.md +3 -3
- data/CHANGELOG.md +70 -1
- data/LICENSES/LGPL-3.0-or-later.txt +304 -0
- data/LICENSES/MIT-0.txt +16 -0
- data/README.md +33 -5
- data/Rakefile +1 -1
- data/doc/concepts/application_architecture.md +44 -3
- data/doc/concepts/application_testing.md +43 -1
- data/doc/concepts/async.md +32 -2
- data/doc/concepts/custom_widgets.md +247 -0
- data/doc/concepts/event_handling.md +32 -3
- data/doc/concepts/interactive_design.md +32 -2
- data/doc/contributors/auditing/parity.md +7 -1
- data/doc/contributors/design/ruby_frontend.md +85 -1
- data/doc/contributors/design/rust_backend.md +67 -1
- data/doc/contributors/developing_examples.md +56 -2
- data/doc/contributors/documentation_style.md +20 -3
- data/doc/contributors/future_work.md +169 -0
- data/doc/contributors/index.md +1 -1
- data/doc/contributors/v1.0.0_blockers.md +15 -175
- data/doc/getting_started/quickstart.md +35 -9
- data/doc/getting_started/why.md +1 -1
- data/doc/index.md +2 -1
- data/doc/troubleshooting/debugging.md +32 -2
- data/doc/troubleshooting/terminal_limitations.md +8 -2
- data/doc/troubleshooting/tui_output.md +127 -6
- data/examples/app_all_events/README.md +14 -2
- data/examples/app_all_events/app.rb +1 -1
- data/examples/app_all_events/model/app_model.rb +1 -1
- data/examples/app_all_events/model/event_color_cycle.rb +1 -1
- data/examples/app_all_events/model/event_entry.rb +1 -1
- data/examples/app_all_events/model/msg.rb +1 -1
- data/examples/app_all_events/model/timestamp.rb +1 -1
- data/examples/app_all_events/update.rb +1 -1
- data/examples/app_all_events/view/app_view.rb +1 -1
- data/examples/app_all_events/view/controls_view.rb +1 -1
- data/examples/app_all_events/view/counts_view.rb +1 -1
- data/examples/app_all_events/view/live_view.rb +1 -1
- data/examples/app_all_events/view/log_view.rb +1 -1
- data/examples/app_all_events/view.rb +1 -1
- data/examples/app_color_picker/README.md +20 -2
- data/examples/app_color_picker/app.rb +1 -1
- data/examples/app_color_picker/clipboard.rb +1 -1
- data/examples/app_color_picker/color.rb +1 -1
- data/examples/app_color_picker/controls.rb +1 -1
- data/examples/app_color_picker/copy_dialog.rb +1 -1
- data/examples/app_color_picker/export_pane.rb +1 -1
- data/examples/app_color_picker/harmony.rb +1 -1
- data/examples/app_color_picker/input.rb +1 -1
- data/examples/app_color_picker/main_container.rb +1 -1
- data/examples/app_color_picker/palette.rb +1 -1
- data/examples/app_login_form/README.md +8 -2
- data/examples/app_login_form/app.rb +1 -1
- data/examples/app_stateful_interaction/README.md +2 -2
- data/examples/app_stateful_interaction/app.rb +71 -17
- data/examples/timeout_demo.rb +1 -1
- data/examples/verify_quickstart_dsl/README.md +6 -0
- data/examples/verify_quickstart_dsl/app.rb +3 -3
- data/examples/verify_quickstart_layout/README.md +6 -0
- data/examples/verify_quickstart_layout/app.rb +3 -3
- data/examples/verify_quickstart_lifecycle/README.md +13 -1
- data/examples/verify_quickstart_lifecycle/app.rb +10 -4
- data/examples/verify_readme_usage/README.md +6 -0
- data/examples/verify_readme_usage/app.rb +3 -3
- data/examples/widget_barchart/README.md +6 -0
- data/examples/widget_barchart/app.rb +2 -2
- data/examples/widget_block/README.md +7 -1
- data/examples/widget_block/app.rb +2 -2
- data/examples/widget_box/README.md +6 -0
- data/examples/widget_box/app.rb +9 -6
- data/examples/widget_calendar/README.md +6 -0
- data/examples/widget_calendar/app.rb +2 -2
- data/examples/widget_canvas/README.md +4 -0
- data/examples/widget_canvas/app.rb +2 -2
- data/examples/widget_cell/README.md +6 -0
- data/examples/widget_cell/app.rb +2 -3
- data/examples/widget_center/README.md +4 -0
- data/examples/widget_center/app.rb +2 -2
- data/examples/widget_chart/README.md +6 -0
- data/examples/widget_chart/app.rb +2 -2
- data/examples/widget_gauge/README.md +6 -0
- data/examples/widget_gauge/app.rb +2 -2
- data/examples/widget_layout_split/README.md +6 -0
- data/examples/widget_layout_split/app.rb +3 -3
- data/examples/widget_line_gauge/README.md +6 -0
- data/examples/widget_line_gauge/app.rb +2 -2
- data/examples/widget_list/README.md +6 -0
- data/examples/widget_list/app.rb +2 -2
- data/examples/widget_map/README.md +8 -2
- data/examples/widget_map/app.rb +2 -2
- data/examples/widget_overlay/README.md +7 -1
- data/examples/widget_overlay/app.rb +2 -2
- data/examples/widget_popup/README.md +6 -0
- data/examples/widget_popup/app.rb +2 -2
- data/examples/widget_ratatui_logo/README.md +6 -0
- data/examples/widget_ratatui_logo/app.rb +2 -3
- data/examples/widget_ratatui_mascot/README.md +6 -0
- data/examples/widget_ratatui_mascot/app.rb +2 -2
- data/examples/widget_rect/README.md +12 -0
- data/examples/widget_rect/app.rb +40 -26
- data/examples/widget_render/README.md +6 -0
- data/examples/widget_render/app.rb +2 -2
- data/examples/widget_render/app.rbs +41 -0
- data/examples/widget_rich_text/README.md +6 -0
- data/examples/widget_rich_text/app.rb +2 -2
- data/examples/widget_scroll_text/README.md +6 -0
- data/examples/widget_scroll_text/app.rb +2 -2
- data/examples/widget_scrollbar/README.md +6 -0
- data/examples/widget_scrollbar/app.rb +2 -2
- data/examples/widget_sparkline/README.md +6 -0
- data/examples/widget_sparkline/app.rb +2 -2
- data/examples/widget_style_colors/README.md +6 -0
- data/examples/widget_style_colors/app.rb +2 -2
- data/examples/widget_table/README.md +8 -2
- data/examples/widget_table/app.rb +2 -2
- data/examples/widget_tabs/README.md +6 -0
- data/examples/widget_tabs/app.rb +2 -2
- data/examples/widget_text_width/README.md +6 -0
- data/examples/widget_text_width/app.rb +4 -4
- data/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/ext/ratatui_ruby/extconf.rb +2 -2
- data/ext/ratatui_ruby/src/rendering.rs +1 -1
- data/ext/ratatui_ruby/src/style.rs +0 -8
- data/ext/ratatui_ruby/src/widgets/chart.rs +0 -118
- data/ext/ratatui_ruby/src/widgets/list_state.rs +36 -0
- data/lib/ratatui_ruby/buffer/cell.rb +34 -2
- data/lib/ratatui_ruby/buffer.rb +2 -2
- data/lib/ratatui_ruby/cell.rb +34 -2
- data/lib/ratatui_ruby/event/focus_gained.rb +26 -2
- data/lib/ratatui_ruby/event/focus_lost.rb +26 -2
- data/lib/ratatui_ruby/event/key/character.rb +18 -2
- data/lib/ratatui_ruby/event/key/media.rb +2 -2
- data/lib/ratatui_ruby/event/key/modifier.rb +10 -2
- data/lib/ratatui_ruby/event/key/navigation.rb +2 -2
- data/lib/ratatui_ruby/event/key/system.rb +2 -2
- data/lib/ratatui_ruby/event/key.rb +114 -2
- data/lib/ratatui_ruby/event/mouse.rb +42 -2
- data/lib/ratatui_ruby/event/none.rb +10 -2
- data/lib/ratatui_ruby/event/paste.rb +34 -2
- data/lib/ratatui_ruby/event/resize.rb +34 -2
- data/lib/ratatui_ruby/event.rb +26 -2
- data/lib/ratatui_ruby/frame.rb +74 -2
- data/lib/ratatui_ruby/layout/constraint.rb +58 -2
- data/lib/ratatui_ruby/layout/layout.rb +47 -2
- data/lib/ratatui_ruby/layout/rect.rb +403 -2
- data/lib/ratatui_ruby/layout.rb +2 -2
- data/lib/ratatui_ruby/list_state.rb +113 -2
- data/lib/ratatui_ruby/output_guard.rb +171 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +2 -2
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +2 -2
- data/lib/ratatui_ruby/schema/bar_chart.rb +50 -2
- data/lib/ratatui_ruby/schema/block.rb +21 -15
- data/lib/ratatui_ruby/schema/calendar.rb +2 -2
- data/lib/ratatui_ruby/schema/canvas.rb +10 -2
- data/lib/ratatui_ruby/schema/center.rb +10 -2
- data/lib/ratatui_ruby/schema/chart.rb +2 -28
- data/lib/ratatui_ruby/schema/clear.rb +10 -2
- data/lib/ratatui_ruby/schema/constraint.rb +58 -2
- data/lib/ratatui_ruby/schema/cursor.rb +10 -2
- data/lib/ratatui_ruby/schema/draw.rb +10 -2
- data/lib/ratatui_ruby/schema/gauge.rb +2 -2
- data/lib/ratatui_ruby/schema/layout.rb +18 -2
- data/lib/ratatui_ruby/schema/line_gauge.rb +2 -2
- data/lib/ratatui_ruby/schema/list.rb +10 -2
- data/lib/ratatui_ruby/schema/list_item.rb +10 -2
- data/lib/ratatui_ruby/schema/overlay.rb +10 -2
- data/lib/ratatui_ruby/schema/paragraph.rb +10 -2
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +2 -2
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +2 -2
- data/lib/ratatui_ruby/schema/rect.rb +58 -2
- data/lib/ratatui_ruby/schema/row.rb +10 -2
- data/lib/ratatui_ruby/schema/scrollbar.rb +2 -2
- data/lib/ratatui_ruby/schema/shape/label.rb +10 -2
- data/lib/ratatui_ruby/schema/sparkline.rb +10 -2
- data/lib/ratatui_ruby/schema/style.rb +18 -2
- data/lib/ratatui_ruby/schema/table.rb +2 -2
- data/lib/ratatui_ruby/schema/tabs.rb +2 -2
- data/lib/ratatui_ruby/schema/text.rb +34 -2
- data/lib/ratatui_ruby/scrollbar_state.rb +10 -2
- data/lib/ratatui_ruby/style/style.rb +18 -2
- data/lib/ratatui_ruby/style.rb +2 -2
- data/lib/ratatui_ruby/table_state.rb +10 -2
- data/lib/ratatui_ruby/terminal_lifecycle.rb +144 -0
- data/lib/ratatui_ruby/test_helper/event_injection.rb +34 -2
- data/lib/ratatui_ruby/test_helper/snapshot.rb +74 -9
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +98 -2
- data/lib/ratatui_ruby/test_helper/terminal.rb +50 -2
- data/lib/ratatui_ruby/test_helper/test_doubles.rb +18 -2
- data/lib/ratatui_ruby/test_helper.rb +10 -2
- data/lib/ratatui_ruby/tui/buffer_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/canvas_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/core.rb +2 -2
- data/lib/ratatui_ruby/tui/layout_factories.rb +32 -2
- data/lib/ratatui_ruby/tui/state_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/style_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/text_factories.rb +2 -2
- data/lib/ratatui_ruby/tui/widget_factories.rb +2 -2
- data/lib/ratatui_ruby/tui.rb +11 -3
- data/lib/ratatui_ruby/version.rb +3 -3
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -2
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -2
- data/lib/ratatui_ruby/widgets/bar_chart.rb +58 -2
- data/lib/ratatui_ruby/widgets/block.rb +37 -15
- data/lib/ratatui_ruby/widgets/calendar.rb +2 -2
- data/lib/ratatui_ruby/widgets/canvas.rb +10 -2
- data/lib/ratatui_ruby/widgets/cell.rb +10 -2
- data/lib/ratatui_ruby/widgets/center.rb +10 -2
- data/lib/ratatui_ruby/widgets/chart.rb +2 -28
- data/lib/ratatui_ruby/widgets/clear.rb +10 -2
- data/lib/ratatui_ruby/widgets/cursor.rb +10 -2
- data/lib/ratatui_ruby/widgets/gauge.rb +16 -2
- data/lib/ratatui_ruby/widgets/line_gauge.rb +16 -2
- data/lib/ratatui_ruby/widgets/list.rb +41 -2
- data/lib/ratatui_ruby/widgets/list_item.rb +10 -2
- data/lib/ratatui_ruby/widgets/overlay.rb +10 -2
- data/lib/ratatui_ruby/widgets/paragraph.rb +10 -2
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +2 -2
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +2 -2
- data/lib/ratatui_ruby/widgets/row.rb +10 -2
- data/lib/ratatui_ruby/widgets/scrollbar.rb +2 -2
- data/lib/ratatui_ruby/widgets/shape/label.rb +10 -2
- data/lib/ratatui_ruby/widgets/sparkline.rb +10 -2
- data/lib/ratatui_ruby/widgets/table.rb +62 -2
- data/lib/ratatui_ruby/widgets/tabs.rb +2 -2
- data/lib/ratatui_ruby/widgets.rb +2 -2
- data/lib/ratatui_ruby.rb +116 -81
- data/sig/examples/app_all_events/view.rbs +7 -1
- data/sig/examples/app_all_events/view_state.rbs +7 -1
- data/sig/examples/app_color_picker/app.rbs +5 -0
- data/sig/examples/app_stateful_interaction/app.rbs +7 -1
- data/sig/examples/verify_quickstart_dsl/app.rbs +7 -1
- data/sig/examples/verify_quickstart_lifecycle/app.rbs +7 -1
- data/sig/examples/verify_readme_usage/app.rbs +7 -1
- data/sig/examples/widget_block_demo/app.rbs +6 -0
- data/sig/examples/widget_box_demo/app.rbs +7 -1
- data/sig/examples/widget_calendar_demo/app.rbs +7 -1
- data/sig/examples/widget_cell_demo/app.rbs +7 -1
- data/sig/examples/widget_chart_demo/app.rbs +7 -1
- data/sig/examples/widget_gauge_demo/app.rbs +7 -1
- data/sig/examples/widget_layout_split/app.rbs +7 -1
- data/sig/examples/widget_line_gauge_demo/app.rbs +7 -1
- data/sig/examples/widget_list_demo/app.rbs +5 -0
- data/sig/examples/widget_map_demo/app.rbs +7 -1
- data/sig/examples/widget_popup_demo/app.rbs +7 -1
- data/sig/examples/widget_ratatui_logo_demo/app.rbs +7 -1
- data/sig/examples/widget_ratatui_mascot_demo/app.rbs +7 -1
- data/sig/examples/widget_rect/app.rbs +7 -1
- data/sig/examples/widget_render/app.rbs +7 -1
- data/sig/examples/widget_rich_text/app.rbs +7 -1
- data/sig/examples/widget_scroll_text/app.rbs +7 -1
- data/sig/examples/widget_scrollbar_demo/app.rbs +7 -1
- data/sig/examples/widget_sparkline_demo/app.rbs +7 -1
- data/sig/examples/widget_style_colors/app.rbs +7 -1
- data/sig/examples/widget_table_demo/app.rbs +7 -1
- data/sig/examples/widget_text_width/app.rbs +7 -1
- data/sig/ratatui_ruby/event.rbs +7 -1
- data/sig/ratatui_ruby/frame.rbs +15 -3
- data/sig/ratatui_ruby/list_state.rbs +11 -1
- data/sig/ratatui_ruby/ratatui_ruby.rbs +8 -2
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +7 -1
- data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +6 -0
- data/sig/ratatui_ruby/schema/bar_chart.rbs +6 -0
- data/sig/ratatui_ruby/schema/block.rbs +7 -1
- data/sig/ratatui_ruby/schema/calendar.rbs +6 -0
- data/sig/ratatui_ruby/schema/canvas.rbs +6 -0
- data/sig/ratatui_ruby/schema/center.rbs +6 -0
- data/sig/ratatui_ruby/schema/chart.rbs +6 -9
- data/sig/ratatui_ruby/schema/constraint.rbs +6 -0
- data/sig/ratatui_ruby/schema/cursor.rbs +6 -0
- data/sig/ratatui_ruby/schema/draw.rbs +6 -0
- data/sig/ratatui_ruby/schema/gauge.rbs +9 -1
- data/sig/ratatui_ruby/schema/layout.rbs +6 -0
- data/sig/ratatui_ruby/schema/line_gauge.rbs +9 -1
- data/sig/ratatui_ruby/schema/list.rbs +9 -1
- data/sig/ratatui_ruby/schema/list_item.rbs +7 -1
- data/sig/ratatui_ruby/schema/overlay.rbs +6 -0
- data/sig/ratatui_ruby/schema/paragraph.rbs +6 -0
- data/sig/ratatui_ruby/schema/ratatui_logo.rbs +6 -0
- data/sig/ratatui_ruby/schema/ratatui_mascot.rbs +5 -0
- data/sig/ratatui_ruby/schema/rect.rbs +30 -0
- data/sig/ratatui_ruby/schema/row.rbs +7 -1
- data/sig/ratatui_ruby/schema/scrollbar.rbs +6 -0
- data/sig/ratatui_ruby/schema/sparkline.rbs +6 -0
- data/sig/ratatui_ruby/schema/style.rbs +7 -1
- data/sig/ratatui_ruby/schema/table.rbs +11 -1
- data/sig/ratatui_ruby/schema/tabs.rbs +6 -0
- data/sig/ratatui_ruby/schema/text.rbs +7 -1
- data/sig/ratatui_ruby/scrollbar_state.rbs +7 -1
- data/sig/ratatui_ruby/session.rbs +7 -1
- data/sig/ratatui_ruby/table_state.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/event_injection.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/snapshot.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/style_assertions.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/terminal.rbs +7 -1
- data/sig/ratatui_ruby/test_helper/test_doubles.rbs +7 -1
- data/sig/ratatui_ruby/test_helper.rbs +7 -1
- data/sig/ratatui_ruby/tui/buffer_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/core.rbs +7 -1
- data/sig/ratatui_ruby/tui/layout_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/state_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/style_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/text_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui/widget_factories.rbs +7 -1
- data/sig/ratatui_ruby/tui.rbs +7 -1
- data/sig/ratatui_ruby/version.rbs +6 -0
- data/tasks/autodoc/examples.rb +9 -3
- data/tasks/autodoc/member.rb +1 -1
- data/tasks/autodoc/name.rb +1 -1
- data/tasks/bump/cargo_lockfile.rb +1 -1
- data/tasks/bump/changelog.rb +1 -1
- data/tasks/bump/header.rb +1 -1
- data/tasks/bump/history.rb +1 -1
- data/tasks/bump/links.rb +1 -1
- data/tasks/bump/manifest.rb +1 -1
- data/tasks/bump/ruby_gem.rb +1 -1
- data/tasks/bump/sem_ver.rb +1 -1
- data/tasks/bump/unreleased_section.rb +1 -1
- data/tasks/license/headers_md.rb +223 -0
- data/tasks/license/headers_rb.rb +210 -0
- data/tasks/license/license_utils.rb +130 -0
- data/tasks/license/snippets_md.rb +315 -0
- data/tasks/license/snippets_rdoc.rb +150 -0
- data/tasks/license.rake +91 -0
- data/tasks/rdoc_config.rb +1 -1
- data/tasks/resources/build.yml.erb +13 -7
- data/tasks/sourcehut.rake +3 -1
- data/tasks/terminal_preview/app_screenshot.rb +1 -1
- data/tasks/terminal_preview/crash_report.rb +1 -1
- data/tasks/terminal_preview/example_app.rb +1 -1
- data/tasks/terminal_preview/launcher_script.rb +1 -1
- data/tasks/terminal_preview/preview_collection.rb +1 -1
- data/tasks/terminal_preview/preview_timing.rb +1 -1
- data/tasks/terminal_preview/safety_confirmation.rb +1 -1
- data/tasks/terminal_preview/saved_screenshot.rb +1 -1
- data/tasks/terminal_preview/system_appearance.rb +1 -1
- data/tasks/terminal_preview/terminal_window.rb +1 -1
- data/tasks/terminal_preview/window_id.rb +1 -1
- data/tasks/website/index_page.rb +1 -1
- data/tasks/website/version.rb +1 -1
- data/tasks/website/version_menu.rb +1 -1
- data/tasks/website/versioned_documentation.rb +1 -1
- data/tasks/website/website.rb +1 -1
- metadata +15 -3
- data/doc/migration/v0_7_0.md +0 -236
|
@@ -4,11 +4,16 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
# alignment_audit
|
|
7
|
+
## Legacy Migrations
|
|
8
|
+
|
|
9
|
+
### Outstanding
|
|
10
|
+
|
|
11
|
+
- Migrate away from `schema/` folder structure as mentioned in ruby_frontend.md
|
|
12
|
+
|
|
7
13
|
## alignment_audit
|
|
8
14
|
- Symbol Sets
|
|
9
15
|
- line::Set, block::Set, scrollbar::Set
|
|
10
16
|
- Layout
|
|
11
|
-
- Rect methods (~13)
|
|
12
17
|
- Constraint batch constructors (6)
|
|
13
18
|
- Layout margin, spacing (2)
|
|
14
19
|
- Style
|
|
@@ -17,49 +22,17 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|
|
17
22
|
- Span methods (4)
|
|
18
23
|
- Line methods (6)
|
|
19
24
|
|
|
20
|
-
###### MISALIGNED (non-additive, breaking)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
25
|
### alignment_audit_granular_level
|
|
31
26
|
##### v0.7.0 Alignment Audit (Parameter-Level)
|
|
32
27
|
|
|
33
28
|
This document audits alignment between RatatuiRuby v0.7.0 and the upstream Ratatui/Crossterm Rust libraries at the **parameter and enum value level**. Only gaps are listed.
|
|
34
29
|
|
|
35
|
-
> [!IMPORTANT]
|
|
36
|
-
> **MISSING** = Can be added as new features, backwards-compatible.
|
|
37
|
-
> **MISALIGNED** = Requires breaking changes before v1.0.0 release.
|
|
38
|
-
|
|
39
30
|
---
|
|
40
31
|
|
|
41
32
|
|
|
42
33
|
###### MISSING — Layout Module
|
|
43
34
|
|
|
44
|
-
###### `Layout::Rect` — Missing Methods
|
|
45
35
|
|
|
46
|
-
| Missing Method | Signature | Notes |
|
|
47
|
-
|----------------|-----------|-------|
|
|
48
|
-
| `area` | `rect.area` → `Integer` | Returns `width * height` |
|
|
49
|
-
| `left` | `rect.left` → `Integer` | Returns `x` (alias) |
|
|
50
|
-
| `right` | `rect.right` → `Integer` | Returns `x + width` |
|
|
51
|
-
| `top` | `rect.top` → `Integer` | Returns `y` (alias) |
|
|
52
|
-
| `bottom` | `rect.bottom` → `Integer` | Returns `y + height` |
|
|
53
|
-
| `union` | `rect.union(other)` → `Rect` | Bounding box of both rects |
|
|
54
|
-
| `inner` | `rect.inner(margin)` → `Rect` | Shrink by margin |
|
|
55
|
-
| `offset` | `rect.offset(dx, dy)` → `Rect` | Translate position |
|
|
56
|
-
| `clamp` | `rect.clamp(other)` → `Rect` | Clamp to bounds |
|
|
57
|
-
| `rows` | `rect.rows` → `Iterator` | Iterate row positions |
|
|
58
|
-
| `columns` | `rect.columns` → `Iterator` | Iterate column positions |
|
|
59
|
-
| `positions` | `rect.positions` → `Iterator` | Iterate all positions |
|
|
60
|
-
| `is_empty` | `rect.empty?` → `Boolean` | True if zero area |
|
|
61
|
-
|
|
62
|
-
---
|
|
63
36
|
|
|
64
37
|
###### `Layout::Constraint` — Missing Batch Constructors
|
|
65
38
|
|
|
@@ -144,15 +117,10 @@ These are public `&self` methods on upstream widgets that compute/query values w
|
|
|
144
117
|
|
|
145
118
|
###### State Navigation Methods — Missing
|
|
146
119
|
|
|
147
|
-
|
|
120
|
+
TableState has navigation helpers that are not exposed.
|
|
148
121
|
|
|
149
122
|
| State Class | Missing Method | Ratatui API | Notes |
|
|
150
123
|
|-------------|----------------|-------------|-------|
|
|
151
|
-
| `ListState` | `select_next` | `state.select_next()` | Move selection to next item |
|
|
152
|
-
| `ListState` | `select_previous` | `state.select_previous()` | Move selection to previous item |
|
|
153
|
-
| `ListState` | `select_first` | `state.select_first()` | Jump to first item |
|
|
154
|
-
| `ListState` | `select_last` | `state.select_last()` | Jump to last item |
|
|
155
|
-
|
|
156
124
|
| `TableState` | `selected_cell` | `state.selected_cell()` | Get (row, col) tuple |
|
|
157
125
|
| `TableState` | `with_selected_cell` | `state.with_selected_cell((r,c))` | Builder pattern |
|
|
158
126
|
| `TableState` | `select_next_column` | `state.select_next_column()` | Navigate columns |
|
|
@@ -168,6 +136,11 @@ ListState and TableState have navigation helpers that are not exposed.
|
|
|
168
136
|
|--------|---------|-------------|-------|
|
|
169
137
|
| `Rect` | `as_position` | `rect.as_position()` → `Position` | Convert to Position |
|
|
170
138
|
| `Rect` | `as_size` | `rect.as_size()` → `Size` | Convert to Size |
|
|
139
|
+
| `Rect` | `outer` | `rect.outer(margin)` → `Rect` | Expand by margin (inverse of `inner`) |
|
|
140
|
+
| `Rect` | `resize` | `rect.resize(size)` → `Rect` | Change dimensions, preserve position |
|
|
141
|
+
| `Rect` | `centered_horizontally` | `rect.centered_horizontally(constraint)` → `Rect` | Center horizontally via Layout |
|
|
142
|
+
| `Rect` | `centered_vertically` | `rect.centered_vertically(constraint)` → `Rect` | Center vertically via Layout |
|
|
143
|
+
| `Rect` | `centered` | `rect.centered(h, v)` → `Rect` | Center both axes |
|
|
171
144
|
| `Constraint` | `apply` | `constraint.apply(length)` → `u16` | Compute constrained size |
|
|
172
145
|
| `Layout` | `split_with_spacers` | `layout.split_with_spacers(area)` | Returns segments AND spacers |
|
|
173
146
|
|
|
@@ -229,8 +202,6 @@ These are gaps that can be filled in future minor releases without breaking exis
|
|
|
229
202
|
|
|
230
203
|
| Component | Missing Feature | Notes |
|
|
231
204
|
|-----------|-----------------|-------|
|
|
232
|
-
| `Rect` | `area()`, `left()`, `right()`, `top()`, `bottom()` | New instance methods |
|
|
233
|
-
| `Rect` | `union(other)`, `inner(margin)`, `offset(offset)` | New instance methods |
|
|
234
205
|
| `Constraint` | `from_lengths()`, `from_percentages()`, etc. | New class methods |
|
|
235
206
|
| `Layout` | `margin`, `spacing` | New optional constructor args |
|
|
236
207
|
| `Style` | `sub_modifier`, `underline_color` | New optional constructor args |
|
|
@@ -529,10 +500,8 @@ All current parameter names are well-chosen. No changes recommended.
|
|
|
529
500
|
|
|
530
501
|
###### High Priority (Immediate DX Wins)
|
|
531
502
|
|
|
532
|
-
1. **Add `
|
|
533
|
-
2. **Add `
|
|
534
|
-
3. **Add terse shape aliases**: `circle`, `point`, `rectangle`, `map`, `label`
|
|
535
|
-
4. **Add CSS-friendly constraint aliases**: `fixed`, `percent`, `fill`, `flex`, `fr`, `min`, `max`
|
|
503
|
+
1. **Add `item` alias** for `list_item`
|
|
504
|
+
2. **Add terse shape aliases**: `circle`, `point`, `rectangle`, `map`, `label`
|
|
536
505
|
|
|
537
506
|
###### Medium Priority (Pattern Completion)
|
|
538
507
|
|
|
@@ -549,10 +518,8 @@ All current parameter names are well-chosen. No changes recommended.
|
|
|
549
518
|
|
|
550
519
|
###### Implementation Checklist
|
|
551
520
|
|
|
552
|
-
- [ ] Add `split` alias to `LayoutFactories`
|
|
553
521
|
- [ ] Add `item` alias to `WidgetFactories`
|
|
554
522
|
- [ ] Add terse shape aliases to `CanvasFactories`
|
|
555
|
-
- [ ] Add CSS-friendly constraint aliases to `LayoutFactories`
|
|
556
523
|
- [ ] Add `shape(type, ...)` dispatcher
|
|
557
524
|
- [ ] Add `constraint(type, ...)` dispatcher
|
|
558
525
|
- [ ] Add bidirectional shape aliases (`*_shape`)
|
|
@@ -569,10 +536,8 @@ If all recommendations in this audit are adopted, **none constitute breaking cha
|
|
|
569
536
|
|
|
570
537
|
| Recommendation | Breaking? | Rationale |
|
|
571
538
|
|----------------|-----------|-----------|
|
|
572
|
-
| Add `split` alias | No | Additive; `layout_split` unchanged |
|
|
573
539
|
| Add `item` alias | No | Additive; `list_item` unchanged |
|
|
574
540
|
| Add terse shape aliases (`circle`, etc.) | No | Additive; `shape_*` methods unchanged |
|
|
575
|
-
| Add CSS-friendly constraint aliases | No | Additive; `constraint_*` methods unchanged |
|
|
576
541
|
| Add bidirectional aliases (`*_shape`) | No | Additive; does not remove existing forms |
|
|
577
542
|
| Add dispatcher methods | No | Additive; new methods only |
|
|
578
543
|
| Keep verbose forms (`table_row`, etc.) | No | No removal or rename |
|
|
@@ -656,62 +621,6 @@ table.selected_row? # => true if selected_row is not nil
|
|
|
656
621
|
table.selected_cell? # => true if both row and column selected
|
|
657
622
|
```
|
|
658
623
|
|
|
659
|
-
##### 3. Symbol Constants for Enum Values
|
|
660
|
-
|
|
661
|
-
**Current problem**: Magic symbol values scattered across code:
|
|
662
|
-
|
|
663
|
-
```ruby
|
|
664
|
-
list = List.new(
|
|
665
|
-
highlight_spacing: :when_selected, # What are the other options?
|
|
666
|
-
direction: :top_to_bottom, # Is :bottom_to_top valid?
|
|
667
|
-
)
|
|
668
|
-
|
|
669
|
-
layout = Layout.new(
|
|
670
|
-
flex: :legacy # What does "legacy" mean?
|
|
671
|
-
)
|
|
672
|
-
|
|
673
|
-
gauge = Gauge.new(
|
|
674
|
-
use_unicode: true # Unclear what ASCII fallback looks like
|
|
675
|
-
)
|
|
676
|
-
```
|
|
677
|
-
|
|
678
|
-
Users must consult docs or source code to discover valid options.
|
|
679
|
-
|
|
680
|
-
**Suggested solution**: Add constants to widget classes:
|
|
681
|
-
|
|
682
|
-
```ruby
|
|
683
|
-
class List < Data
|
|
684
|
-
# Highlight spacing modes
|
|
685
|
-
HIGHLIGHT_ALWAYS = :always
|
|
686
|
-
HIGHLIGHT_WHEN_SELECTED = :when_selected
|
|
687
|
-
HIGHLIGHT_NEVER = :never
|
|
688
|
-
|
|
689
|
-
# Direction modes
|
|
690
|
-
DIRECTION_TOP_TO_BOTTOM = :top_to_bottom
|
|
691
|
-
DIRECTION_BOTTOM_TO_TOP = :bottom_to_top
|
|
692
|
-
end
|
|
693
|
-
|
|
694
|
-
list = List.new(
|
|
695
|
-
highlight_spacing: List::HIGHLIGHT_WHEN_SELECTED,
|
|
696
|
-
direction: List::DIRECTION_TOP_TO_BOTTOM,
|
|
697
|
-
)
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
Benefits:
|
|
701
|
-
- IDE autocomplete shows valid options
|
|
702
|
-
- Self-documenting code
|
|
703
|
-
- Typos caught at runtime (symbol vs constant)
|
|
704
|
-
- Easy to grep for where these modes are used
|
|
705
|
-
|
|
706
|
-
Affected widgets and their enum values:
|
|
707
|
-
- `List`: `highlight_spacing` (:always, :when_selected, :never), `direction` (:top_to_bottom, :bottom_to_top)
|
|
708
|
-
- `Table`: `highlight_spacing` (same as List), `flex` (:legacy, :default, :fill)
|
|
709
|
-
- `Layout`: `direction` (:vertical, :horizontal), `flex` (:legacy, :default, :fill)
|
|
710
|
-
- `Gauge`/`LineGauge`: `use_unicode` (boolean, but could have MODE_UNICODE, MODE_ASCII)
|
|
711
|
-
- `Paragraph`: `alignment` (:left, :center, :right)
|
|
712
|
-
- `Block`: `border_type` (:plain, :rounded, :double, :thick)
|
|
713
|
-
- `Canvas`: `marker` (:braille, :dots, :half_block, :sextant, :octant)
|
|
714
|
-
|
|
715
624
|
##### 4. Inconsistent Style APIs
|
|
716
625
|
|
|
717
626
|
**Current problem**: Different widgets accept styles differently:
|
|
@@ -746,41 +655,6 @@ end
|
|
|
746
655
|
paragraph = Paragraph.new(text: "hi", style: Style.with(fg: :blue))
|
|
747
656
|
```
|
|
748
657
|
|
|
749
|
-
##### 5. Missing State Query Predicates
|
|
750
|
-
|
|
751
|
-
**Current problem**: Widgets store state but provide no query methods:
|
|
752
|
-
|
|
753
|
-
```ruby
|
|
754
|
-
list.selected_index = 0
|
|
755
|
-
|
|
756
|
-
### To check if something is selected, must do:
|
|
757
|
-
if list.selected_index&.nonzero? # Awkward
|
|
758
|
-
if list.selected_index.nil? == false # Confusing
|
|
759
|
-
|
|
760
|
-
### Should be:
|
|
761
|
-
list.selected? # => true
|
|
762
|
-
list.empty? # => false (for items array)
|
|
763
|
-
```
|
|
764
|
-
|
|
765
|
-
**Suggested solution**: Add predicates to state-holding widgets:
|
|
766
|
-
|
|
767
|
-
```ruby
|
|
768
|
-
### List
|
|
769
|
-
list.selected? # => !selected_index.nil?
|
|
770
|
-
list.empty? # => items.empty?
|
|
771
|
-
list.selection # => selected_index (alias)
|
|
772
|
-
list.selected_item # => items[selected_index] (convenience)
|
|
773
|
-
|
|
774
|
-
### Table
|
|
775
|
-
table.selected_row? # => !selected_row.nil?
|
|
776
|
-
table.selected_cell? # => !selected_row.nil? && !selected_column.nil?
|
|
777
|
-
table.empty? # => rows.empty?
|
|
778
|
-
|
|
779
|
-
### Gauge
|
|
780
|
-
gauge.filled? # => ratio > 0
|
|
781
|
-
gauge.complete? # => ratio >= 1.0
|
|
782
|
-
```
|
|
783
|
-
|
|
784
658
|
##### 6. Magic Numeric Coercions
|
|
785
659
|
|
|
786
660
|
**Current problem**: Widgets accept `Numeric` but silently coerce:
|
|
@@ -817,18 +691,6 @@ gauge = Gauge.new(percent: 150)
|
|
|
817
691
|
|
|
818
692
|
#### Implementation Strategy
|
|
819
693
|
|
|
820
|
-
##### Phase 1: State Query Predicates
|
|
821
|
-
- [ ] Add predicates to `List` (selected?, empty?, selected_item)
|
|
822
|
-
- [ ] Add predicates to `Table` (selected_row?, selected_cell?, empty?)
|
|
823
|
-
- [ ] Add predicates to `Gauge` (filled?, complete?)
|
|
824
|
-
- [ ] Tests for all new predicates
|
|
825
|
-
|
|
826
|
-
##### Phase 2: Symbol Constants
|
|
827
|
-
- [ ] Add enum constants to `List`, `Table`, `Layout`
|
|
828
|
-
- [ ] Add enum constants to `Gauge`, `LineGauge`, `Paragraph`, `Block`
|
|
829
|
-
- [ ] Update all examples to use constants
|
|
830
|
-
- [ ] Document constants in RDoc
|
|
831
|
-
|
|
832
694
|
##### Phase 3: Style Consistency
|
|
833
695
|
- [ ] Standardize `Hash` shorthand support across all widgets
|
|
834
696
|
- [ ] Add `Style.with(fg:, bg:, modifiers:)` convenience constructor
|
|
@@ -1011,26 +873,4 @@ end
|
|
|
1011
873
|
def constraint_length(length)
|
|
1012
874
|
constraint(:length, length)
|
|
1013
875
|
end
|
|
1014
|
-
```
|
|
1015
|
-
|
|
1016
|
-
---
|
|
1017
|
-
|
|
1018
|
-
##### 2. Enhance Widget Examples with Functional Context
|
|
1019
|
-
|
|
1020
|
-
**Status:** Recommended — Move beyond "parameter playgrounds" to "real-world patterns"
|
|
1021
|
-
|
|
1022
|
-
Current `widget_*` examples mostly focus on interactive parameter turning (changing colors, borders, etc.). While useful for API discovery, they don't show *how* to use the widget in a real application logic flow.
|
|
1023
|
-
|
|
1024
|
-
###### The Standard: widget_tabs
|
|
1025
|
-
|
|
1026
|
-
The `widget_tabs` was enhanced to show **conditional rendering** of content based on the selected tab in git commit `38ceed39a011d557cc66e11a4598d3341dc7a0cc`. It doesn't just highlight the tab; it changes the screen content. This connects the widget (the tabs) to the problem it solves (view segregation).
|
|
1027
|
-
|
|
1028
|
-
###### Action
|
|
1029
|
-
|
|
1030
|
-
Identify other widget examples that could benefit from this "functional context" treatment:
|
|
1031
|
-
|
|
1032
|
-
- **widget_popup:** Show a multi-step modal flow (e.g., Confirm -> Success) rather than just a static overlay.
|
|
1033
|
-
- **widget_list:** Show a master-detail view where selecting a list item updates a detail pane.
|
|
1034
|
-
- **widget_input:** (If created) Show specific validation logic (email vs number).
|
|
1035
|
-
|
|
1036
|
-
**Goal:** Every widget example should answer "How do I build a feature with this?" not just "What does this parameter do?"
|
|
876
|
+
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
SPDX-FileCopyrightText:
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
3
|
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
4
|
-->
|
|
5
5
|
# Quickstart
|
|
@@ -17,7 +17,12 @@ See [Installation in the README](../README.md#installation) for setup instructio
|
|
|
17
17
|
|
|
18
18
|
Here is a "Hello World" application that demonstrates the core lifecycle of a **ratatui_ruby** app.
|
|
19
19
|
|
|
20
|
-
<!--
|
|
20
|
+
<!-- SPDX-SnippetBegin -->
|
|
21
|
+
<!--
|
|
22
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
23
|
+
SPDX-License-Identifier: MIT-0
|
|
24
|
+
-->
|
|
25
|
+
<!-- SYNC:START:examples/verify_quickstart_lifecycle/app.rb:main -->
|
|
21
26
|
```ruby
|
|
22
27
|
# 1. Initialize the terminal
|
|
23
28
|
RatatuiRuby.init_terminal
|
|
@@ -34,7 +39,7 @@ begin
|
|
|
34
39
|
title: "My Ruby TUI App",
|
|
35
40
|
title_alignment: :center,
|
|
36
41
|
borders: [:all],
|
|
37
|
-
|
|
42
|
+
border_style: { fg: "cyan" },
|
|
38
43
|
style: { fg: "white" }
|
|
39
44
|
)
|
|
40
45
|
)
|
|
@@ -51,13 +56,20 @@ begin
|
|
|
51
56
|
else
|
|
52
57
|
nil
|
|
53
58
|
end
|
|
59
|
+
|
|
60
|
+
# 5. Guard against accidental output (optional but recommended)
|
|
61
|
+
# Wrap any code that might puts/warn to prevent screen corruption.
|
|
62
|
+
RatatuiRuby.guard_io do
|
|
63
|
+
# SomeChattyGem.do_something
|
|
64
|
+
end
|
|
54
65
|
end
|
|
55
66
|
ensure
|
|
56
|
-
#
|
|
67
|
+
# 6. Restore the terminal to its original state
|
|
57
68
|
RatatuiRuby.restore_terminal
|
|
58
69
|
end
|
|
59
70
|
```
|
|
60
71
|
<!-- SYNC:END -->
|
|
72
|
+
<!-- SPDX-SnippetEnd -->
|
|
61
73
|
|
|
62
74
|
[](../../examples/verify_quickstart_lifecycle/README.md)
|
|
63
75
|
|
|
@@ -67,13 +79,19 @@ end
|
|
|
67
79
|
2. **Immediate Mode UI**: On every iteration, describe your UI by creating `Data` objects (e.g., `Paragraph`, `Block`).
|
|
68
80
|
3. **`RatatuiRuby.draw { |frame| ... }`**: The block receives a `Frame` object as a canvas. Render widgets onto specific areas. Nothing is drawn until the block finishes, ensuring flicker-free updates.
|
|
69
81
|
4. **`RatatuiRuby.poll_event`**: Returns a typed `Event` object with predicates like `key?`, `mouse?`, `resize?`, etc. Returns `RatatuiRuby::Event::None` if no events are pending. Use predicates to check event type without pattern matching.
|
|
70
|
-
5. **`RatatuiRuby.
|
|
82
|
+
5. **`RatatuiRuby.guard_io { }`**: Wraps code that might write to stdout/stderr (e.g., chatty gems). Output is swallowed to prevent screen corruption. Optional but recommended for production apps.
|
|
83
|
+
6. **`RatatuiRuby.restore_terminal`**: Essential for leaving raw mode and returning to the shell. Always wrap your loop in `begin...ensure` to guarantee this runs.
|
|
71
84
|
|
|
72
85
|
### Simplified API
|
|
73
86
|
|
|
74
87
|
You can simplify your code by using `RatatuiRuby.run`. This method handles the terminal lifecycle for you, yielding a `TUI` object with factory methods for widgets.
|
|
75
88
|
|
|
76
|
-
<!--
|
|
89
|
+
<!-- SPDX-SnippetBegin -->
|
|
90
|
+
<!--
|
|
91
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
92
|
+
SPDX-License-Identifier: MIT-0
|
|
93
|
+
-->
|
|
94
|
+
<!-- SYNC:START:examples/verify_quickstart_dsl/app.rb:main -->
|
|
77
95
|
```ruby
|
|
78
96
|
# 1. Initialize the terminal, start the run loop, and ensure the terminal is restored.
|
|
79
97
|
RatatuiRuby.run do |tui|
|
|
@@ -86,7 +104,7 @@ RatatuiRuby.run do |tui|
|
|
|
86
104
|
title: "My Ruby TUI App",
|
|
87
105
|
title_alignment: :center,
|
|
88
106
|
borders: [:all],
|
|
89
|
-
|
|
107
|
+
border_style: { fg: "cyan" },
|
|
90
108
|
style: { fg: "white" }
|
|
91
109
|
)
|
|
92
110
|
)
|
|
@@ -107,6 +125,7 @@ RatatuiRuby.run do |tui|
|
|
|
107
125
|
end
|
|
108
126
|
```
|
|
109
127
|
<!-- SYNC:END -->
|
|
128
|
+
<!-- SPDX-SnippetEnd -->
|
|
110
129
|
|
|
111
130
|
#### How it works
|
|
112
131
|
|
|
@@ -121,7 +140,12 @@ For a deeper dive into the available application architectures (Manual vs Manage
|
|
|
121
140
|
|
|
122
141
|
Real-world applications often need to split the screen into multiple areas. `RatatuiRuby::Layout` lets you do this easily.
|
|
123
142
|
|
|
124
|
-
<!--
|
|
143
|
+
<!-- SPDX-SnippetBegin -->
|
|
144
|
+
<!--
|
|
145
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
146
|
+
SPDX-License-Identifier: MIT-0
|
|
147
|
+
-->
|
|
148
|
+
<!-- SYNC:START:examples/verify_quickstart_layout/app.rb:main -->
|
|
125
149
|
```ruby
|
|
126
150
|
loop do
|
|
127
151
|
tui.draw do |frame|
|
|
@@ -140,7 +164,7 @@ loop do
|
|
|
140
164
|
tui.paragraph(
|
|
141
165
|
text: "Hello, Ratatui!",
|
|
142
166
|
alignment: :center,
|
|
143
|
-
block: tui.block(title: "Content", borders: [:all],
|
|
167
|
+
block: tui.block(title: "Content", borders: [:all], border_style: { fg: "cyan" })
|
|
144
168
|
),
|
|
145
169
|
top
|
|
146
170
|
)
|
|
@@ -177,6 +201,7 @@ loop do
|
|
|
177
201
|
end
|
|
178
202
|
```
|
|
179
203
|
<!-- SYNC:END -->
|
|
204
|
+
<!-- SPDX-SnippetEnd -->
|
|
180
205
|
|
|
181
206
|
#### How it works
|
|
182
207
|
|
|
@@ -255,6 +280,7 @@ Now that you've seen what **ratatui_ruby** can do:
|
|
|
255
280
|
|
|
256
281
|
- **Deep dive**: Read the [Application Architecture](../concepts/application_architecture.md) guide for scaling patterns
|
|
257
282
|
- **Test your TUI**: See the [Testing Guide](../concepts/application_testing.md) for snapshot and style assertions
|
|
283
|
+
- **Avoid common mistakes**: See [Terminal Output During TUI Sessions](../troubleshooting/tui_output.md) to prevent screen corruption
|
|
258
284
|
- **Explore the API**: Browse the [full RDoc documentation](../index.md)
|
|
259
285
|
- **Learn the philosophy**: Read [Why RatatuiRuby?](./why.md) for comparisons and design decisions
|
|
260
286
|
- **Get help**: Join the [discussion mailing list](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss)
|
data/doc/getting_started/why.md
CHANGED
data/doc/index.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
SPDX-FileCopyrightText:
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
3
|
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
4
|
-->
|
|
5
5
|
# Start Here
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
- [Event Handling](./concepts/event_handling.md): Keyboard, mouse, and terminal events
|
|
21
21
|
- [Interactive Design](./concepts/interactive_design.md): Cached layout pattern for hit testing
|
|
22
22
|
- [Testing Your Application](./concepts/application_testing.md): Snapshot testing and style assertions
|
|
23
|
+
- [Custom Widgets](./concepts/custom_widgets.md): Build anything with the Draw API
|
|
23
24
|
- [Async Operations](./concepts/async.md): Background tasks and non-blocking I/O
|
|
24
25
|
|
|
25
26
|
### Troubleshooting
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
SPDX-FileCopyrightText:
|
|
3
|
-
SPDX-License-Identifier:
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
# Debugging TUI Applications
|
|
@@ -15,6 +15,11 @@ Write debug output to files. Tail them in a separate terminal.
|
|
|
15
15
|
|
|
16
16
|
Create timestamped log files to avoid overwrites:
|
|
17
17
|
|
|
18
|
+
<!-- SPDX-SnippetBegin -->
|
|
19
|
+
<!--
|
|
20
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
21
|
+
SPDX-License-Identifier: MIT-0
|
|
22
|
+
-->
|
|
18
23
|
```ruby
|
|
19
24
|
FileUtils.mkdir_p(File.join(Dir.tmpdir, "my_debug"))
|
|
20
25
|
timestamp = Time.now.strftime('%Y%m%d_%H%M%S_%N')
|
|
@@ -23,15 +28,27 @@ File.write(
|
|
|
23
28
|
"variable=#{value.inspect}\n"
|
|
24
29
|
)
|
|
25
30
|
```
|
|
31
|
+
<!-- SPDX-SnippetEnd -->
|
|
26
32
|
|
|
27
33
|
Or append to a single file:
|
|
28
34
|
|
|
35
|
+
<!-- SPDX-SnippetBegin -->
|
|
36
|
+
<!--
|
|
37
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
38
|
+
SPDX-License-Identifier: MIT-0
|
|
39
|
+
-->
|
|
29
40
|
```ruby
|
|
30
41
|
File.write("/tmp/debug.log", "#{Time.now}: #{message}\n", mode: "a")
|
|
31
42
|
```
|
|
43
|
+
<!-- SPDX-SnippetEnd -->
|
|
32
44
|
|
|
33
45
|
Tail the logs in a separate terminal:
|
|
34
46
|
|
|
47
|
+
<!-- SPDX-SnippetBegin -->
|
|
48
|
+
<!--
|
|
49
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
50
|
+
SPDX-License-Identifier: MIT-0
|
|
51
|
+
-->
|
|
35
52
|
```bash
|
|
36
53
|
# Single file
|
|
37
54
|
tail -f /tmp/debug.log
|
|
@@ -39,6 +56,7 @@ tail -f /tmp/debug.log
|
|
|
39
56
|
# Directory of timestamped files
|
|
40
57
|
watch -n 0.5 'ls -la /tmp/my_debug/ && cat /tmp/my_debug/*.log'
|
|
41
58
|
```
|
|
59
|
+
<!-- SPDX-SnippetEnd -->
|
|
42
60
|
|
|
43
61
|
## REPL Debugging with `__FILE__` Guards
|
|
44
62
|
|
|
@@ -46,17 +64,29 @@ Unit tests verify correctness. But during exploratory debugging, you want to pok
|
|
|
46
64
|
|
|
47
65
|
Wrap your main execution in a guard:
|
|
48
66
|
|
|
67
|
+
<!-- SPDX-SnippetBegin -->
|
|
68
|
+
<!--
|
|
69
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
70
|
+
SPDX-License-Identifier: MIT-0
|
|
71
|
+
-->
|
|
49
72
|
```ruby
|
|
50
73
|
if __FILE__ == $PROGRAM_NAME
|
|
51
74
|
MyApp.new.run
|
|
52
75
|
end
|
|
53
76
|
```
|
|
77
|
+
<!-- SPDX-SnippetEnd -->
|
|
54
78
|
|
|
55
79
|
Now load the file and interact with classes directly:
|
|
56
80
|
|
|
81
|
+
<!-- SPDX-SnippetBegin -->
|
|
82
|
+
<!--
|
|
83
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
84
|
+
SPDX-License-Identifier: MIT-0
|
|
85
|
+
-->
|
|
57
86
|
```bash
|
|
58
87
|
ruby -e 'load "./bin/my_tui"; obj = MyClass.new; sleep 1; puts obj.result'
|
|
59
88
|
```
|
|
89
|
+
<!-- SPDX-SnippetEnd -->
|
|
60
90
|
|
|
61
91
|
This exercises domain logic without entering raw terminal mode. Use it for exploratory debugging. Write tests using the [TestHelper](application_testing.md) for regression coverage.
|
|
62
92
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
SPDX-FileCopyrightText:
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
# Terminal Limitations
|
|
@@ -114,12 +114,18 @@ There's no way to catch SIGKILL. You can only mitigate the impact.
|
|
|
114
114
|
|
|
115
115
|
**Script graceful shutdowns.** If you write deployment or process management scripts, prefer graceful signals with a timeout before SIGKILL:
|
|
116
116
|
|
|
117
|
+
<!-- SPDX-SnippetBegin -->
|
|
118
|
+
<!--
|
|
119
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
120
|
+
SPDX-License-Identifier: MIT-0
|
|
121
|
+
-->
|
|
117
122
|
```bash
|
|
118
123
|
# Graceful first, force if needed
|
|
119
124
|
kill -15 $PID
|
|
120
125
|
sleep 2
|
|
121
126
|
kill -0 $PID 2>/dev/null && kill -9 $PID
|
|
122
127
|
```
|
|
128
|
+
<!-- SPDX-SnippetEnd -->
|
|
123
129
|
|
|
124
130
|
See [Application Architecture: Signal Handling](../concepts/application_architecture.md#signal-handling) for programmatic cleanup strategies.
|
|
125
131
|
|