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
|
@@ -9,7 +9,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|
|
9
9
|
|
|
10
10
|
Writing to stdout or stderr during a TUI session **corrupts the display**.
|
|
11
11
|
|
|
12
|
-
When your application is running inside `RatatuiRuby.run`, the terminal is in "raw mode" and RatatuiRuby has taken control of the display buffer. Any output via `puts`, `warn`, `p`, `print`, or direct writes to `
|
|
12
|
+
When your application is running inside `RatatuiRuby.run`, the terminal is in "raw mode" and RatatuiRuby has taken control of the display buffer. Any output via `puts`, `warn`, `p`, `print`, or direct writes to `$stdout`/`$stderr` will:
|
|
13
13
|
|
|
14
14
|
1. **Corrupt the screen layout** - Characters appear in random positions
|
|
15
15
|
2. **Mix with TUI output** - Text interleaves with your widgets unpredictably
|
|
@@ -24,8 +24,34 @@ In raw mode:
|
|
|
24
24
|
|
|
25
25
|
## Safe Patterns
|
|
26
26
|
|
|
27
|
+
### Use `guard_io` to swallow output from gems
|
|
28
|
+
|
|
29
|
+
If you're using a gem that might write to stdout/stderr, wrap its calls:
|
|
30
|
+
|
|
31
|
+
<!-- SPDX-SnippetBegin -->
|
|
32
|
+
<!--
|
|
33
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
34
|
+
SPDX-License-Identifier: MIT-0
|
|
35
|
+
-->
|
|
36
|
+
```ruby
|
|
37
|
+
RatatuiRuby.run do |tui|
|
|
38
|
+
RatatuiRuby.guard_io do
|
|
39
|
+
SomeChattyGem.do_something # Any puts/warn calls are swallowed
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Outside guard_io, you can still debug intentionally:
|
|
43
|
+
# Object::STDERR.puts "debug: something" # Escape hatch (corrupts display!)
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
<!-- SPDX-SnippetEnd -->
|
|
47
|
+
|
|
27
48
|
### Defer output until after the TUI exits
|
|
28
49
|
|
|
50
|
+
<!-- SPDX-SnippetBegin -->
|
|
51
|
+
<!--
|
|
52
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
53
|
+
SPDX-License-Identifier: MIT-0
|
|
54
|
+
-->
|
|
29
55
|
```ruby
|
|
30
56
|
messages = []
|
|
31
57
|
|
|
@@ -39,22 +65,40 @@ end
|
|
|
39
65
|
# Now safe to print
|
|
40
66
|
messages.each { |msg| puts msg }
|
|
41
67
|
```
|
|
68
|
+
<!-- SPDX-SnippetEnd -->
|
|
69
|
+
|
|
70
|
+
### Use Logger to write to a file
|
|
42
71
|
|
|
43
|
-
|
|
72
|
+
The `Logger` class from Ruby's standard library is the idiomatic solution:
|
|
44
73
|
|
|
74
|
+
<!-- SPDX-SnippetBegin -->
|
|
75
|
+
<!--
|
|
76
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
77
|
+
SPDX-License-Identifier: MIT-0
|
|
78
|
+
-->
|
|
45
79
|
```ruby
|
|
46
|
-
|
|
80
|
+
require "logger"
|
|
81
|
+
require "tmpdir"
|
|
82
|
+
|
|
83
|
+
LOG = Logger.new(File.join(Dir.tmpdir, "my_app.log"))
|
|
84
|
+
LOG.level = Logger::DEBUG
|
|
47
85
|
|
|
48
86
|
RatatuiRuby.run do |tui|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
87
|
+
LOG.info "Application started"
|
|
88
|
+
LOG.debug "Processing event: #{event.inspect}"
|
|
89
|
+
|
|
52
90
|
# ... TUI logic ...
|
|
53
91
|
end
|
|
54
92
|
```
|
|
93
|
+
<!-- SPDX-SnippetEnd -->
|
|
55
94
|
|
|
56
95
|
### Display messages in the TUI itself
|
|
57
96
|
|
|
97
|
+
<!-- SPDX-SnippetBegin -->
|
|
98
|
+
<!--
|
|
99
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
100
|
+
SPDX-License-Identifier: MIT-0
|
|
101
|
+
-->
|
|
58
102
|
```ruby
|
|
59
103
|
RatatuiRuby.run do |tui|
|
|
60
104
|
@status_message = "Something happened"
|
|
@@ -68,9 +112,86 @@ RatatuiRuby.run do |tui|
|
|
|
68
112
|
end
|
|
69
113
|
end
|
|
70
114
|
```
|
|
115
|
+
<!-- SPDX-SnippetEnd -->
|
|
71
116
|
|
|
72
117
|
## Library Behavior
|
|
73
118
|
|
|
74
119
|
RatatuiRuby automatically defers its own warnings (like experimental feature notices) during TUI sessions. They are queued and printed after `restore_terminal` is called.
|
|
75
120
|
|
|
76
121
|
You don't need to do anything special for library warnings—they're handled automatically.
|
|
122
|
+
|
|
123
|
+
## Bypassing guard_io
|
|
124
|
+
|
|
125
|
+
If you need to write to stdout/stderr even when `guard_io` is active (e.g., for [pipeline integration](#headless-mode-batchpipelinecli) or IPC), use the original IO constants:
|
|
126
|
+
|
|
127
|
+
<!-- SPDX-SnippetBegin -->
|
|
128
|
+
<!--
|
|
129
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
130
|
+
SPDX-License-Identifier: MIT-0
|
|
131
|
+
-->
|
|
132
|
+
```ruby
|
|
133
|
+
RatatuiRuby.guard_io do
|
|
134
|
+
SomeChattyGem.do_something # This is swallowed
|
|
135
|
+
|
|
136
|
+
# But this gets through:
|
|
137
|
+
Object::STDOUT.puts "structured output for downstream tools"
|
|
138
|
+
end
|
|
139
|
+
```
|
|
140
|
+
<!-- SPDX-SnippetEnd -->
|
|
141
|
+
|
|
142
|
+
This works regardless of whether `guard_io` is active. During a TUI session, the display will be corrupted—but the output will reach its destination.
|
|
143
|
+
|
|
144
|
+
## Headless Mode (Batch/Pipeline/CLI)
|
|
145
|
+
|
|
146
|
+
If your app supports both TUI and non-TUI modes (e.g., `my_app --no-tui`), call `headless!` at startup to silence `guard_io` warnings:
|
|
147
|
+
|
|
148
|
+
<!-- SPDX-SnippetBegin -->
|
|
149
|
+
<!--
|
|
150
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
151
|
+
SPDX-License-Identifier: MIT-0
|
|
152
|
+
-->
|
|
153
|
+
```ruby
|
|
154
|
+
if ARGV.include?("--no-tui")
|
|
155
|
+
RatatuiRuby.headless!
|
|
156
|
+
# guard_io calls are now silent no-ops
|
|
157
|
+
process_batch_work
|
|
158
|
+
else
|
|
159
|
+
RatatuiRuby.run do |tui|
|
|
160
|
+
# TUI mode - guard_io works normally
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
```
|
|
164
|
+
<!-- SPDX-SnippetEnd -->
|
|
165
|
+
|
|
166
|
+
When headless, `guard_io` becomes a no-op (output flows normally), and calling `run` or `init_terminal` raises an error.
|
|
167
|
+
|
|
168
|
+
## Temporarily Exiting TUI Mode
|
|
169
|
+
|
|
170
|
+
Some apps need to temporarily leave TUI mode for user interaction—like lazygit does when opening an external editor for commit messages. Use `restore_terminal` and `init_terminal`:
|
|
171
|
+
|
|
172
|
+
<!-- SPDX-SnippetBegin -->
|
|
173
|
+
<!--
|
|
174
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
175
|
+
SPDX-License-Identifier: MIT-0
|
|
176
|
+
-->
|
|
177
|
+
```ruby
|
|
178
|
+
RatatuiRuby.run do |tui|
|
|
179
|
+
# ... TUI is active ...
|
|
180
|
+
|
|
181
|
+
if user_wants_external_editor
|
|
182
|
+
RatatuiRuby.restore_terminal
|
|
183
|
+
|
|
184
|
+
# Now in normal terminal mode
|
|
185
|
+
system("$EDITOR", filename)
|
|
186
|
+
puts "Press Enter to return to the TUI..."
|
|
187
|
+
gets
|
|
188
|
+
|
|
189
|
+
RatatuiRuby.init_terminal
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# ... TUI is active again ...
|
|
193
|
+
end
|
|
194
|
+
```
|
|
195
|
+
<!-- SPDX-SnippetEnd -->
|
|
196
|
+
|
|
197
|
+
This pattern lets you hand control back to the user or spawn external processes that need normal terminal access.
|
|
@@ -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
|
# App All Events Example
|
|
@@ -33,9 +33,15 @@ Semantic value objects that decouple raw terminal events from business logic:
|
|
|
33
33
|
### 3. Update (`update.rb`)
|
|
34
34
|
A **pure function** that computes the next state:
|
|
35
35
|
|
|
36
|
+
<!-- SPDX-SnippetBegin -->
|
|
37
|
+
<!--
|
|
38
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
39
|
+
SPDX-License-Identifier: MIT-0
|
|
40
|
+
-->
|
|
36
41
|
```ruby
|
|
37
42
|
Update.call(msg, model) -> Model
|
|
38
43
|
```
|
|
44
|
+
<!-- SPDX-SnippetEnd -->
|
|
39
45
|
|
|
40
46
|
All logic previously in `Events.record` now lives here. The function never mutates, never draws, never performs IO.
|
|
41
47
|
|
|
@@ -47,6 +53,11 @@ Pure rendering logic. Views accept the immutable `AppModel` and draw to the scre
|
|
|
47
53
|
### 5. Runtime (`app.rb`)
|
|
48
54
|
The MVU loop:
|
|
49
55
|
|
|
56
|
+
<!-- SPDX-SnippetBegin -->
|
|
57
|
+
<!--
|
|
58
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
59
|
+
SPDX-License-Identifier: MIT-0
|
|
60
|
+
-->
|
|
50
61
|
```ruby
|
|
51
62
|
loop do
|
|
52
63
|
tui.draw { |f| view.call(model, tui, f, f.area) }
|
|
@@ -55,6 +66,7 @@ loop do
|
|
|
55
66
|
model = Update.call(msg, model)
|
|
56
67
|
end
|
|
57
68
|
```
|
|
69
|
+
<!-- SPDX-SnippetEnd -->
|
|
58
70
|
|
|
59
71
|
## Library Features Showcased
|
|
60
72
|
|
|
@@ -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
|
# Color Picker Example
|
|
@@ -23,6 +23,11 @@ This app uses a **Strict Component-Based Architecture** where every UI element e
|
|
|
23
23
|
|
|
24
24
|
Every component implements this duck-type interface:
|
|
25
25
|
|
|
26
|
+
<!-- SPDX-SnippetBegin -->
|
|
27
|
+
<!--
|
|
28
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
29
|
+
SPDX-License-Identifier: MIT-0
|
|
30
|
+
-->
|
|
26
31
|
```ruby
|
|
27
32
|
# Renders the component into the given area
|
|
28
33
|
# Caches `area` for hit testing
|
|
@@ -40,6 +45,7 @@ end
|
|
|
40
45
|
def tick
|
|
41
46
|
end
|
|
42
47
|
```
|
|
48
|
+
<!-- SPDX-SnippetEnd -->
|
|
43
49
|
|
|
44
50
|
### 1. The MainContainer (Orchestrator)
|
|
45
51
|
|
|
@@ -85,6 +91,11 @@ Components return semantic symbols instead of just `:consumed`:
|
|
|
85
91
|
|
|
86
92
|
The `MainContainer` interprets these signals to coordinate cross-component communication:
|
|
87
93
|
|
|
94
|
+
<!-- SPDX-SnippetBegin -->
|
|
95
|
+
<!--
|
|
96
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
97
|
+
SPDX-License-Identifier: MIT-0
|
|
98
|
+
-->
|
|
88
99
|
```ruby
|
|
89
100
|
result = @input.handle_event(event)
|
|
90
101
|
case result
|
|
@@ -93,6 +104,7 @@ when :submitted
|
|
|
93
104
|
return :consumed
|
|
94
105
|
end
|
|
95
106
|
```
|
|
107
|
+
<!-- SPDX-SnippetEnd -->
|
|
96
108
|
|
|
97
109
|
### ⏱️ Lifecycle Hooks (`tick`)
|
|
98
110
|
|
|
@@ -109,9 +121,15 @@ Read this example if you are trying to solve:
|
|
|
109
121
|
|
|
110
122
|
## Usage
|
|
111
123
|
|
|
124
|
+
<!-- SPDX-SnippetBegin -->
|
|
125
|
+
<!--
|
|
126
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
127
|
+
SPDX-License-Identifier: MIT-0
|
|
128
|
+
-->
|
|
112
129
|
```bash
|
|
113
130
|
ruby examples/app_color_picker/app.rb
|
|
114
131
|
```
|
|
132
|
+
<!-- SPDX-SnippetEnd -->
|
|
115
133
|
|
|
116
134
|
- Type a hex code (e.g., `#FF0055`) or color name (`cyan`).
|
|
117
135
|
- Press `Enter` to generate the palette.
|
|
@@ -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
|
# Login Form Example
|
|
@@ -36,9 +36,15 @@ This example solves this by using the `Overlay` widget to stack a centered popup
|
|
|
36
36
|
|
|
37
37
|
## Usage
|
|
38
38
|
|
|
39
|
+
<!-- SPDX-SnippetBegin -->
|
|
40
|
+
<!--
|
|
41
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
42
|
+
SPDX-License-Identifier: MIT-0
|
|
43
|
+
-->
|
|
39
44
|
```bash
|
|
40
45
|
ruby examples/app_login_form/app.rb
|
|
41
46
|
```
|
|
47
|
+
<!-- SPDX-SnippetEnd -->
|
|
42
48
|
|
|
43
49
|
## Learning Outcomes
|
|
44
50
|
|