ratatui_ruby 0.6.0 → 0.7.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 +1 -1
- data/.builds/ruby-3.3.yml +1 -1
- data/.builds/ruby-3.4.yml +1 -1
- data/.builds/ruby-4.0.0.yml +1 -1
- data/AGENTS.md +4 -4
- data/CHANGELOG.md +35 -0
- data/README.md +26 -1
- data/doc/application_architecture.md +16 -16
- data/doc/application_testing.md +1 -1
- data/doc/contributors/architectural_overhaul/chat_conversations.md +4952 -0
- data/doc/contributors/architectural_overhaul/implementation_plan.md +60 -0
- data/doc/contributors/architectural_overhaul/task.md +37 -0
- data/doc/contributors/design/ruby_frontend.md +277 -81
- data/doc/contributors/design/rust_backend.md +349 -55
- data/doc/contributors/developing_examples.md +5 -5
- data/doc/contributors/index.md +7 -5
- data/doc/contributors/v1.0.0_blockers.md +1729 -0
- data/doc/index.md +11 -6
- data/doc/interactive_design.md +2 -2
- data/doc/quickstart.md +66 -97
- data/doc/v0.7.0_migration.md +236 -0
- data/doc/why.md +93 -0
- data/examples/app_all_events/README.md +6 -4
- 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/msg.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_color_picker/README.md +7 -5
- data/examples/app_color_picker/app.rb +1 -1
- data/examples/app_login_form/README.md +2 -0
- data/examples/app_stateful_interaction/README.md +2 -0
- data/examples/app_stateful_interaction/app.rb +1 -1
- data/examples/verify_quickstart_dsl/README.md +4 -3
- data/examples/verify_quickstart_dsl/app.rb +1 -1
- data/examples/verify_quickstart_layout/README.md +1 -1
- data/examples/verify_quickstart_lifecycle/README.md +3 -3
- data/examples/verify_quickstart_lifecycle/app.rb +2 -2
- data/examples/verify_readme_usage/README.md +1 -1
- data/examples/widget_barchart_demo/README.md +2 -1
- data/examples/widget_block_demo/README.md +2 -0
- data/examples/widget_box_demo/README.md +3 -3
- data/examples/widget_calendar_demo/README.md +3 -3
- data/examples/widget_calendar_demo/app.rb +5 -1
- data/examples/widget_canvas_demo/README.md +3 -3
- data/examples/widget_cell_demo/README.md +3 -3
- data/examples/widget_center_demo/README.md +3 -3
- data/examples/widget_chart_demo/README.md +3 -3
- data/examples/widget_gauge_demo/README.md +3 -3
- data/examples/widget_layout_split/README.md +3 -3
- data/examples/widget_line_gauge_demo/README.md +3 -3
- data/examples/widget_list_demo/README.md +3 -3
- data/examples/widget_map_demo/README.md +3 -3
- data/examples/widget_map_demo/app.rb +2 -2
- data/examples/widget_overlay_demo/README.md +36 -0
- data/examples/widget_popup_demo/README.md +3 -3
- data/examples/widget_ratatui_logo_demo/README.md +3 -3
- data/examples/widget_ratatui_logo_demo/app.rb +1 -1
- data/examples/widget_ratatui_mascot_demo/README.md +3 -3
- data/examples/widget_rect/README.md +3 -3
- data/examples/widget_render/README.md +3 -3
- data/examples/widget_render/app.rb +3 -3
- data/examples/widget_rich_text/README.md +3 -3
- data/examples/widget_scroll_text/README.md +3 -3
- data/examples/widget_scrollbar_demo/README.md +3 -3
- data/examples/widget_sparkline_demo/README.md +3 -3
- data/examples/widget_style_colors/README.md +3 -3
- data/examples/widget_table_demo/README.md +3 -3
- data/examples/widget_table_demo/app.rb +19 -4
- data/examples/widget_tabs_demo/README.md +3 -3
- data/examples/widget_text_width/README.md +3 -3
- data/examples/widget_text_width/app.rb +8 -1
- data/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/ext/ratatui_ruby/src/frame.rs +6 -5
- data/ext/ratatui_ruby/src/lib.rs +3 -2
- data/ext/ratatui_ruby/src/rendering.rs +22 -21
- data/ext/ratatui_ruby/src/text.rs +12 -3
- data/ext/ratatui_ruby/src/widgets/canvas.rs +5 -5
- data/ext/ratatui_ruby/src/widgets/table.rs +81 -36
- data/lib/ratatui_ruby/buffer/cell.rb +168 -0
- data/lib/ratatui_ruby/buffer.rb +15 -0
- data/lib/ratatui_ruby/frame.rb +8 -8
- data/lib/ratatui_ruby/layout/constraint.rb +95 -0
- data/lib/ratatui_ruby/layout/layout.rb +106 -0
- data/lib/ratatui_ruby/layout/rect.rb +118 -0
- data/lib/ratatui_ruby/layout.rb +19 -0
- data/lib/ratatui_ruby/list_state.rb +2 -2
- data/lib/ratatui_ruby/schema/layout.rb +1 -1
- data/lib/ratatui_ruby/schema/row.rb +66 -0
- data/lib/ratatui_ruby/schema/table.rb +10 -10
- data/lib/ratatui_ruby/schema/text.rb +27 -2
- data/lib/ratatui_ruby/style/style.rb +81 -0
- data/lib/ratatui_ruby/style.rb +15 -0
- data/lib/ratatui_ruby/table_state.rb +1 -1
- data/lib/ratatui_ruby/test_helper/snapshot.rb +24 -0
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +1 -1
- data/lib/ratatui_ruby/tui/buffer_factories.rb +20 -0
- data/lib/ratatui_ruby/tui/canvas_factories.rb +44 -0
- data/lib/ratatui_ruby/tui/core.rb +38 -0
- data/lib/ratatui_ruby/tui/layout_factories.rb +74 -0
- data/lib/ratatui_ruby/tui/state_factories.rb +33 -0
- data/lib/ratatui_ruby/tui/style_factories.rb +20 -0
- data/lib/ratatui_ruby/tui/text_factories.rb +44 -0
- data/lib/ratatui_ruby/tui/widget_factories.rb +195 -0
- data/lib/ratatui_ruby/tui.rb +75 -0
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +47 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +25 -0
- data/lib/ratatui_ruby/widgets/bar_chart.rb +239 -0
- data/lib/ratatui_ruby/widgets/block.rb +192 -0
- data/lib/ratatui_ruby/widgets/calendar.rb +84 -0
- data/lib/ratatui_ruby/widgets/canvas.rb +231 -0
- data/lib/ratatui_ruby/widgets/cell.rb +47 -0
- data/lib/ratatui_ruby/widgets/center.rb +59 -0
- data/lib/ratatui_ruby/widgets/chart.rb +185 -0
- data/lib/ratatui_ruby/widgets/clear.rb +54 -0
- data/lib/ratatui_ruby/widgets/cursor.rb +42 -0
- data/lib/ratatui_ruby/widgets/gauge.rb +72 -0
- data/lib/ratatui_ruby/widgets/line_gauge.rb +80 -0
- data/lib/ratatui_ruby/widgets/list.rb +127 -0
- data/lib/ratatui_ruby/widgets/list_item.rb +43 -0
- data/lib/ratatui_ruby/widgets/overlay.rb +43 -0
- data/lib/ratatui_ruby/widgets/paragraph.rb +99 -0
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +31 -0
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +36 -0
- data/lib/ratatui_ruby/widgets/row.rb +68 -0
- data/lib/ratatui_ruby/widgets/scrollbar.rb +143 -0
- data/lib/ratatui_ruby/widgets/shape/label.rb +68 -0
- data/lib/ratatui_ruby/widgets/sparkline.rb +134 -0
- data/lib/ratatui_ruby/widgets/table.rb +141 -0
- data/lib/ratatui_ruby/widgets/tabs.rb +85 -0
- data/lib/ratatui_ruby/widgets.rb +40 -0
- data/lib/ratatui_ruby.rb +23 -39
- data/sig/examples/app_all_events/view.rbs +1 -1
- data/sig/examples/app_all_events/view_state.rbs +1 -1
- data/sig/ratatui_ruby/schema/row.rbs +22 -0
- data/sig/ratatui_ruby/schema/table.rbs +1 -1
- data/sig/ratatui_ruby/schema/text.rbs +1 -0
- data/sig/ratatui_ruby/session.rbs +29 -49
- data/sig/ratatui_ruby/tui/buffer_factories.rbs +10 -0
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +14 -0
- data/sig/ratatui_ruby/tui/core.rbs +14 -0
- data/sig/ratatui_ruby/tui/layout_factories.rbs +19 -0
- data/sig/ratatui_ruby/tui/state_factories.rbs +12 -0
- data/sig/ratatui_ruby/tui/style_factories.rbs +10 -0
- data/sig/ratatui_ruby/tui/text_factories.rbs +14 -0
- data/sig/ratatui_ruby/tui/widget_factories.rbs +39 -0
- data/sig/ratatui_ruby/tui.rbs +19 -0
- data/tasks/autodoc.rake +1 -35
- data/tasks/sourcehut.rake +4 -1
- metadata +62 -15
- data/doc/contributors/dwim_dx.md +0 -366
- data/doc/contributors/examples_audit/p1_high.md +0 -21
- data/doc/contributors/examples_audit/p2_moderate.md +0 -81
- data/doc/contributors/examples_audit.md +0 -41
- data/doc/images/app_analytics.png +0 -0
- data/doc/images/app_custom_widget.png +0 -0
- data/doc/images/app_mouse_events.png +0 -0
- data/doc/images/widget_table_flex.png +0 -0
- data/lib/ratatui_ruby/session/autodoc.rb +0 -482
- data/lib/ratatui_ruby/session.rb +0 -178
- data/tasks/autodoc/inventory.rb +0 -63
- data/tasks/autodoc/notice.rb +0 -26
- data/tasks/autodoc/rbs.rb +0 -38
- data/tasks/autodoc/rdoc.rb +0 -45
data/doc/index.md
CHANGED
|
@@ -7,13 +7,18 @@
|
|
|
7
7
|
|
|
8
8
|
## Documentation for Users
|
|
9
9
|
|
|
10
|
-
- [README](../README.md)
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
10
|
+
- [README](../README.md): Project overview and installation
|
|
11
|
+
- [Why RatatuiRuby?](./why.md): Philosophy, comparisons, and what makes us different
|
|
12
|
+
- [Quickstart](./quickstart.md): Build your first TUI app
|
|
13
|
+
- [Application Architecture](./application_architecture.md): Lifecycle patterns and API choices
|
|
14
|
+
- [Event Handling](./event_handling.md): Keyboard, mouse, and terminal events
|
|
15
|
+
- [Interactive Design](./interactive_design.md): Cached layout pattern for hit testing
|
|
16
|
+
- [Terminal Limitations](./terminal_limitations.md): Platform quirks and workarounds
|
|
17
|
+
- [Testing Your Application](./application_testing.md): Snapshot testing and style assertions
|
|
18
|
+
- [Migrating to v0.7.0](./v0.7.0_migration.md): Namespace changes and upgrade guide
|
|
14
19
|
|
|
15
20
|
|
|
16
21
|
## Documentation for Contributors
|
|
17
22
|
|
|
18
|
-
- [Contributing Guidelines](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md)
|
|
19
|
-
- [More Documentation for Contributors](./contributors/index.md)
|
|
23
|
+
- [Contributing Guidelines](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md): How to contribute patches and features
|
|
24
|
+
- [More Documentation for Contributors](./contributors/index.md): Internal design docs and style guides
|
data/doc/interactive_design.md
CHANGED
|
@@ -103,10 +103,10 @@ end
|
|
|
103
103
|
|
|
104
104
|
## Layout.split
|
|
105
105
|
|
|
106
|
-
`Layout.split` computes layout geometry without rendering. It returns an array of `Rect` objects. While you can call `RatatuiRuby::Layout.split` directly, we recommend using the `
|
|
106
|
+
`Layout.split` computes layout geometry without rendering. It returns an array of `Rect` objects. While you can call `RatatuiRuby::Layout.split` directly, we recommend using the `TUI` helper (`tui.layout_split`) for cleaner application code.
|
|
107
107
|
|
|
108
108
|
```ruby
|
|
109
|
-
# Preferred (
|
|
109
|
+
# Preferred (TUI API)
|
|
110
110
|
left, right = tui.layout_split(area, constraints: [...])
|
|
111
111
|
|
|
112
112
|
# Manual (Core API)
|
data/doc/quickstart.md
CHANGED
|
@@ -8,25 +8,7 @@ Welcome to **ratatui_ruby**! This guide will help you get up and running with yo
|
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```ruby
|
|
14
|
-
gem "ratatui_ruby"
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
And then execute:
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
bundle install
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Or install it yourself as:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
gem install ratatui_ruby
|
|
29
|
-
```
|
|
11
|
+
See [Installation in the README](../README.md#installation) for setup instructions.
|
|
30
12
|
|
|
31
13
|
|
|
32
14
|
## Tutorials
|
|
@@ -45,10 +27,10 @@ begin
|
|
|
45
27
|
loop do
|
|
46
28
|
# 2. Create your UI (Immediate Mode)
|
|
47
29
|
# We define a Paragraph widget inside a Block with a title and borders.
|
|
48
|
-
view = RatatuiRuby::Paragraph.new(
|
|
30
|
+
view = RatatuiRuby::Widgets::Paragraph.new(
|
|
49
31
|
text: "Hello, Ratatui! Press 'q' to quit.",
|
|
50
32
|
alignment: :center,
|
|
51
|
-
block: RatatuiRuby::Block.new(
|
|
33
|
+
block: RatatuiRuby::Widgets::Block.new(
|
|
52
34
|
title: "My Ruby TUI App",
|
|
53
35
|
title_alignment: :center,
|
|
54
36
|
borders: [:all],
|
|
@@ -77,7 +59,7 @@ end
|
|
|
77
59
|
```
|
|
78
60
|
<!-- SYNC:END -->
|
|
79
61
|
|
|
80
|
-

|
|
62
|
+
[](../examples/verify_quickstart_lifecycle/README.md)
|
|
81
63
|
|
|
82
64
|
#### How it works
|
|
83
65
|
|
|
@@ -87,12 +69,13 @@ end
|
|
|
87
69
|
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.
|
|
88
70
|
5. **`RatatuiRuby.restore_terminal`**: Essential for leaving raw mode and returning to the shell. Always wrap your loop in `begin...ensure` to guarantee this runs.
|
|
89
71
|
|
|
90
|
-
###
|
|
72
|
+
### Simplified API
|
|
91
73
|
|
|
92
|
-
You can simplify your code by using `RatatuiRuby.run`. This method handles the terminal lifecycle for you, yielding a `
|
|
74
|
+
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.
|
|
93
75
|
|
|
94
76
|
<!-- SYNC:START:../examples/verify_quickstart_dsl/app.rb:main -->
|
|
95
77
|
```ruby
|
|
78
|
+
# 1. Initialize the terminal, start the run loop, and ensure the terminal is restored.
|
|
96
79
|
RatatuiRuby.run do |tui|
|
|
97
80
|
loop do
|
|
98
81
|
# 2. Create your UI with methods instead of classes.
|
|
@@ -128,8 +111,8 @@ end
|
|
|
128
111
|
#### How it works
|
|
129
112
|
|
|
130
113
|
1. **`RatatuiRuby.run`**: This context manager initializes the terminal before the block starts and ensures `restore_terminal` is called when the block exits (even if an error occurs).
|
|
131
|
-
2. **Widget Shorthand**: The block yields a `
|
|
132
|
-
3. **Method Shorthand**: The
|
|
114
|
+
2. **Widget Shorthand**: The block yields a `TUI` object (here named `tui`). This object provides factory methods for every widget, allowing you to write `tui.paragraph(...)` instead of the more verbose `RatatuiRuby::Widgets::Paragraph.new(...)`.
|
|
115
|
+
3. **Method Shorthand**: The `TUI` object also provides aliases for module functions of `RatatuiRuby`, allowing you to write `tui.draw(...)` instead of the more verbose `RatatuiRuby.draw(...)`.
|
|
133
116
|
4. **Pattern Matching for Events**: Use `case...in` with pattern matching for elegant event dispatch. Always include an `else` clause at the end to catch unmatched event types (mouse, resize, paste, focus, etc.), otherwise Ruby raises `NoMatchingPatternError`.
|
|
134
117
|
|
|
135
118
|
For a deeper dive into the available application architectures (Manual vs Managed), see [Application Architecture](./application_architecture.md).
|
|
@@ -197,95 +180,81 @@ end
|
|
|
197
180
|
|
|
198
181
|
#### How it works
|
|
199
182
|
|
|
200
|
-
1. **`tui.layout_split` (`RatatuiRuby::Layout.split`)**: Takes an area (like `frame.area`) and splits it into multiple sub-areas based on constraints.
|
|
201
|
-
2. **`tui.constraint_*` (`RatatuiRuby::Constraint`)**: Defines how space is distributed (e.g., `percentage`, `length`, `min`, `max`).
|
|
183
|
+
1. **`tui.layout_split` (`RatatuiRuby::Layout::Layout.split`)**: Takes an area (like `frame.area`) and splits it into multiple sub-areas based on constraints.
|
|
184
|
+
2. **`tui.constraint_*` (`RatatuiRuby::Layout::Constraint`)**: Defines how space is distributed (e.g., `percentage`, `length`, `min`, `max`).
|
|
202
185
|
3. **`Frame#render_widget(widget, rect)`**: You pass the specific area (like `top` or `bottom`) to render the widget into that exact region.
|
|
203
186
|
4. **`tui.text_span` (`RatatuiRuby::Text::Span`)**: Allows for rich styling within a single line of text.
|
|
204
187
|
|
|
188
|
+
[](../examples/verify_quickstart_layout/README.md)
|
|
189
|
+
|
|
205
190
|
## Examples
|
|
206
191
|
|
|
207
192
|
These examples showcase the full power of **ratatui_ruby**. You can find their source code in the [examples directory](../examples).
|
|
208
193
|
|
|
209
|
-
###
|
|
210
|
-
|
|
211
|
-
Full-featured examples demonstrating complex layouts and real-world TUI patterns.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
#### [All Events](../examples/app_all_events/app.rb)
|
|
216
|
-
|
|
217
|
-
Handling terminal events is unpredictable. Developers need to know exactly what the terminal sends for `Ctrl+C` or a mouse drag.
|
|
218
|
-
|
|
219
|
-
This app captures and visualizes every event—keys, mouse, resize, paste, and focus.
|
|
220
|
-
|
|
221
|
-
Use it to debug your input handling or verify terminal behavior.
|
|
222
|
-
|
|
223
|
-
**What you'll learn:**
|
|
224
|
-
|
|
225
|
-
* **Proto-TEA Architecture**: Implements unidirectional data flow (Model-View-Update) with immutable state and pure functions.
|
|
226
|
-
* **Event Handling**: Captures and distinguishes all input types, including modifiers (`Ctrl+C`) and focus changes.
|
|
227
|
-
* **Scalable Structure**: Organizes a non-trivial application into small, focused classes instead of a monolithic script.
|
|
228
|
-
|
|
229
|
-

|
|
230
|
-
|
|
231
|
-
#### [Color Picker](https://git.sr.ht/~kerrick/ratatui_ruby/tree/main/item/examples/app_color_picker/app.rb)
|
|
232
|
-
|
|
233
|
-
Interactive tools require complex state. Mapping mouse clicks to widgets and handling modal dialogs creates messy code if handled in the main loop.
|
|
234
|
-
|
|
235
|
-
This app implements a full Color Picker using a "Proto-Kit (Component-Based)" pattern. Each component encapsulates its own rendering, state, and event handling.
|
|
236
|
-
|
|
237
|
-
Use it to build forms, editors, and mouse-driven tools.
|
|
238
|
-
|
|
239
|
-
**What you'll learn:**
|
|
240
|
-
|
|
241
|
-
* **Proto-Kit Architecture**: Self-contained components with `render(tui, frame, area)` and `handle_event(event)`.
|
|
242
|
-
* **Encapsulated Hit Testing**: Components cache their render area and check `contains?` internally.
|
|
243
|
-
* **Modal Dialogs**: Implements overlay patterns that intercept input via Chain of Responsibility.
|
|
244
|
-
|
|
245
|
-
#### [Custom Widget (Escape Hatch)](https://git.sr.ht/~kerrick/ratatui_ruby/tree/main/item/examples/app_custom_widget/app.rb)
|
|
246
|
-
|
|
247
|
-
Demonstrates how to define a custom widget in pure Ruby using the `render(area, buffer)` escape hatch for low-level drawing.
|
|
194
|
+
### Widget Demos
|
|
248
195
|
|
|
249
|
-
|
|
196
|
+
Focused examples for individual widgets. Each demonstrates a single widget and its configuration options.
|
|
197
|
+
|
|
198
|
+
| Widget | What it demonstrates |
|
|
199
|
+
|--------|---------------------|
|
|
200
|
+
| [Bar Chart](../examples/widget_barchart_demo/app.rb) | Grouped bars, data visualization, custom bar styling |
|
|
201
|
+
| [Block](../examples/widget_block_demo/app.rb) | Borders, titles, padding, nested widgets |
|
|
202
|
+
| [Box](../examples/widget_box_demo/app.rb) | Block + Paragraph composition, text wrapping |
|
|
203
|
+
| [Calendar](../examples/widget_calendar_demo/app.rb) | Date highlighting, month display, event markers |
|
|
204
|
+
| [Chart](../examples/widget_chart_demo/app.rb) | Line/scatter plots, axes, legends, datasets |
|
|
205
|
+
| [Gauge](../examples/widget_gauge_demo/app.rb) | Progress bars, percentage display, unicode blocks |
|
|
206
|
+
| [Layout Split](../examples/widget_layout_split/app.rb) | Constraint types, flex modes, responsive layouts |
|
|
207
|
+
| [Line Gauge](../examples/widget_line_gauge_demo/app.rb) | Horizontal progress, labels, thin-style gauges |
|
|
208
|
+
| [List](../examples/widget_list_demo/app.rb) | Selection, scrolling, highlight styles, rich text items |
|
|
209
|
+
| [Map](../examples/widget_map_demo/app.rb) | Canvas widget, world map rendering, coordinates |
|
|
210
|
+
| [Popup](../examples/widget_popup_demo/app.rb) | Clear widget, modal dialogs, overlay composition |
|
|
211
|
+
| [Ratatui Logo](../examples/widget_ratatui_logo_demo/app.rb) | Decorative branding widget |
|
|
212
|
+
| [Ratatui Mascot](../examples/widget_ratatui_mascot_demo/app.rb) | ASCII art Ferris mascot |
|
|
213
|
+
| [Rect](../examples/widget_rect/app.rb) | Geometry helpers, area calculations, contains/intersection |
|
|
214
|
+
| [Rich Text](../examples/widget_rich_text/app.rb) | Spans, lines, inline styling, mixed colors |
|
|
215
|
+
| [Scrollbar](../examples/widget_scrollbar_demo/app.rb) | Orientations, thumb/track styling, scroll state |
|
|
216
|
+
| [Scroll Text](../examples/widget_scroll_text/app.rb) | Paragraph scrolling, viewport control, long content |
|
|
217
|
+
| [Sparkline](../examples/widget_sparkline_demo/app.rb) | Mini charts, time series, bar sets |
|
|
218
|
+
| [Style Colors](../examples/widget_style_colors/app.rb) | Named colors, RGB, indexed 256-color palette |
|
|
219
|
+
| [Table](../examples/widget_table_demo/app.rb) | Row selection, column widths, per-cell styling |
|
|
220
|
+
| [Tabs](../examples/widget_tabs_demo/app.rb) | Tab navigation, highlighting, dividers |
|
|
221
|
+
| [Text Width](../examples/widget_text_width/app.rb) | Unicode-aware width measurement, CJK support |
|
|
222
|
+
| [Canvas](../examples/widget_canvas_demo/app.rb) | Drawing shapes, markers, custom graphics |
|
|
223
|
+
| [Cell](../examples/widget_cell_demo/app.rb) | Buffer cell inspection, styling attributes |
|
|
224
|
+
| [Center](../examples/widget_center_demo/app.rb) | Centering content, horizontal/vertical alignment |
|
|
225
|
+
| [Overlay](../examples/widget_overlay_demo/app.rb) | Layering widgets, modal backgrounds |
|
|
226
|
+
| [Custom Render](../examples/widget_render/app.rb) | Low-level Draw API, escape hatch for custom widgets |
|
|
250
227
|
|
|
251
|
-
|
|
228
|
+
### Sample Applications
|
|
252
229
|
|
|
253
|
-
|
|
230
|
+
These larger examples combine widgets into complete applications, demonstrating real-world TUI patterns and architectures.
|
|
254
231
|
|
|
255
|
-
|
|
232
|
+
| Application | Architecture | What you'll learn |
|
|
233
|
+
|-------------|--------------|-------------------|
|
|
234
|
+
| [All Events](../examples/app_all_events/app.rb) | Model-View-Update | Event handling, unidirectional data flow, scalable structure |
|
|
235
|
+
| [Color Picker](../examples/app_color_picker/app.rb) | Component-Based | Hit testing, modal dialogs, encapsulated state |
|
|
236
|
+
| [Login Form](../examples/app_login_form/app.rb) | Overlay + Center | Modal forms, cursor positioning, text input |
|
|
237
|
+
| [Stateful Interaction](../examples/app_stateful_interaction/app.rb) | State Objects | ListState/TableState, offset read-back, mouse click-to-row |
|
|
256
238
|
|
|
257
|
-
####
|
|
239
|
+
#### All Events
|
|
258
240
|
|
|
259
|
-
|
|
241
|
+
[](../examples/app_all_events/README.md)
|
|
260
242
|
|
|
261
|
-
|
|
243
|
+
#### Color Picker
|
|
262
244
|
|
|
245
|
+
[](../examples/app_color_picker/README.md)
|
|
263
246
|
|
|
247
|
+
#### Login Form
|
|
264
248
|
|
|
249
|
+
[](../examples/app_login_form/README.md)
|
|
265
250
|
|
|
266
251
|
|
|
252
|
+
## Next Steps
|
|
267
253
|
|
|
268
|
-
|
|
254
|
+
Now that you've seen what **ratatui_ruby** can do:
|
|
269
255
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
* [Calendar](../examples/widget_calendar_demo/app.rb)
|
|
276
|
-
* [Chart](../examples/widget_chart_demo/app.rb)
|
|
277
|
-
* [Gauge](../examples/widget_gauge_demo/app.rb)
|
|
278
|
-
* [Line Gauge](../examples/widget_line_gauge_demo/app.rb)
|
|
279
|
-
* [List](../examples/widget_list_demo/app.rb)
|
|
280
|
-
* [Map (Canvas)](../examples/widget_map_demo/app.rb)
|
|
281
|
-
* [Popup (Clear)](../examples/widget_popup_demo/app.rb)
|
|
282
|
-
* [Rect](../examples/widget_rect/app.rb)
|
|
283
|
-
* [Ratatui Logo](../examples/widget_ratatui_logo_demo/app.rb)
|
|
284
|
-
* [Ratatui Mascot](../examples/widget_ratatui_mascot_demo/app.rb)
|
|
285
|
-
* [Rich Text](../examples/widget_rich_text/app.rb)
|
|
286
|
-
* [Scrollbar](../examples/widget_scrollbar_demo/app.rb)
|
|
287
|
-
* [Scroll Text](../examples/widget_scroll_text/app.rb)
|
|
288
|
-
* [Sparkline](../examples/widget_sparkline_demo/app.rb)
|
|
289
|
-
* [Table (Selection)](../examples/widget_table_demo/app.rb)
|
|
290
|
-
* [Tabs](../examples/widget_tabs_demo/app.rb)
|
|
291
|
-
* [Widget Style Colors](../examples/widget_style_colors/app.rb)
|
|
256
|
+
- **Deep dive**: Read the [Application Architecture](./application_architecture.md) guide for scaling patterns
|
|
257
|
+
- **Test your TUI**: See the [Testing Guide](./application_testing.md) for snapshot and style assertions
|
|
258
|
+
- **Explore the API**: Browse the [full RDoc documentation](./index.md)
|
|
259
|
+
- **Learn the philosophy**: Read [Why RatatuiRuby?](./why.md) for comparisons and design decisions
|
|
260
|
+
- **Get help**: Join the [discussion mailing list](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss)
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Migrating to v0.7.0
|
|
7
|
+
|
|
8
|
+
v0.7.0 restructures the library to align with upstream Ratatui. For most users, this is a non-breaking change. For some, it is breaking.
|
|
9
|
+
|
|
10
|
+
## Are You Affected?
|
|
11
|
+
|
|
12
|
+
**If your code looks like this, you're fine:**
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
RatatuiRuby.run do |tui|
|
|
16
|
+
tui.draw tui.paragraph(text: "Hello", block: tui.block(title: "Title"))
|
|
17
|
+
event = tui.poll_event
|
|
18
|
+
end
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The TUI API method names are unchanged. Your application works without modification.
|
|
22
|
+
|
|
23
|
+
**If your code uses `highlight_style:` on Tables, rename it:**
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
# Before (v0.6.0)
|
|
27
|
+
tui.table(rows: [...], highlight_style: tui.style(fg: :yellow))
|
|
28
|
+
|
|
29
|
+
# After (v0.7.0)
|
|
30
|
+
tui.table(rows: [...], row_highlight_style: tui.style(fg: :yellow))
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
This change aligns with Ratatui's API naming convention.
|
|
34
|
+
|
|
35
|
+
**If your code instantiates classes directly, you have work to do:**
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
# These lines break in v0.7.0
|
|
39
|
+
paragraph = RatatuiRuby::Paragraph.new(text: "Hello")
|
|
40
|
+
style = RatatuiRuby::Style.new(fg: :red)
|
|
41
|
+
rect = RatatuiRuby::Rect.new(x: 0, y: 0, width: 10, height: 5)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The old flat namespace no longer exists. Classes moved into modules.
|
|
45
|
+
|
|
46
|
+
## Option 1: Use the TUI API (Recommended)
|
|
47
|
+
|
|
48
|
+
Switch to the TUI API. It hides namespace verbosity and provides IDE autocomplete.
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
RatatuiRuby.run do |tui|
|
|
52
|
+
# All these work exactly as before
|
|
53
|
+
paragraph = tui.paragraph(text: "Hello")
|
|
54
|
+
style = tui.style(fg: :red)
|
|
55
|
+
rect = tui.rect(x: 0, y: 0, width: 10, height: 5)
|
|
56
|
+
constraint = tui.constraint_length(20)
|
|
57
|
+
|
|
58
|
+
# New in v0.7.0
|
|
59
|
+
cell = tui.table_cell(content: "Error", style: tui.style(bg: :red))
|
|
60
|
+
row = tui.table_row(cells: ["A", "B", "C"], style: tui.style(bg: :dark_gray))
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Option 2: Update to New Namespaces
|
|
65
|
+
|
|
66
|
+
If you prefer direct class instantiation, update to the new paths:
|
|
67
|
+
|
|
68
|
+
| Before | After |
|
|
69
|
+
|--------|-------|
|
|
70
|
+
| `RatatuiRuby::Rect` | `RatatuiRuby::Layout::Rect` |
|
|
71
|
+
| `RatatuiRuby::Constraint` | `RatatuiRuby::Layout::Constraint` |
|
|
72
|
+
| `RatatuiRuby::Layout` | `RatatuiRuby::Layout::Layout` |
|
|
73
|
+
| `RatatuiRuby::Style` | `RatatuiRuby::Style::Style` |
|
|
74
|
+
| `RatatuiRuby::Paragraph` | `RatatuiRuby::Widgets::Paragraph` |
|
|
75
|
+
| `RatatuiRuby::Block` | `RatatuiRuby::Widgets::Block` |
|
|
76
|
+
| `RatatuiRuby::Table` | `RatatuiRuby::Widgets::Table` |
|
|
77
|
+
| `RatatuiRuby::List` | `RatatuiRuby::Widgets::List` |
|
|
78
|
+
| `RatatuiRuby::Cell` | `RatatuiRuby::Buffer::Cell` |
|
|
79
|
+
| *(all other widgets)* | `RatatuiRuby::Widgets::*` |
|
|
80
|
+
|
|
81
|
+
### Bulk Migration
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
find . -name "*.rb" -exec sed -i '' \
|
|
85
|
+
's/RatatuiRuby::Rect/RatatuiRuby::Layout::Rect/g; \
|
|
86
|
+
s/RatatuiRuby::Constraint\./RatatuiRuby::Layout::Constraint./g; \
|
|
87
|
+
s/RatatuiRuby::Paragraph\.new/RatatuiRuby::Widgets::Paragraph.new/g; \
|
|
88
|
+
s/RatatuiRuby::Block\.new/RatatuiRuby::Widgets::Block.new/g; \
|
|
89
|
+
s/RatatuiRuby::List\.new/RatatuiRuby::Widgets::List.new/g; \
|
|
90
|
+
s/RatatuiRuby::Table\.new/RatatuiRuby::Widgets::Table.new/g; \
|
|
91
|
+
s/RatatuiRuby::Style\.new/RatatuiRuby::Style::Style.new/g; \
|
|
92
|
+
s/RatatuiRuby::Session/RatatuiRuby::TUI/g; \
|
|
93
|
+
s/highlight_style:/row_highlight_style:/g' {} \;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Session → TUI Rename
|
|
97
|
+
|
|
98
|
+
The `Session` class is now `TUI`. If you reference it directly:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
# Before
|
|
102
|
+
tui = RatatuiRuby::Session.new
|
|
103
|
+
|
|
104
|
+
# After
|
|
105
|
+
tui = RatatuiRuby::TUI.new
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Most users never reference the class directly. The `|tui|` block parameter works unchanged.
|
|
109
|
+
|
|
110
|
+
## Table: highlight_style → row_highlight_style
|
|
111
|
+
|
|
112
|
+
The `highlight_style:` parameter on Table is now `row_highlight_style:`. This aligns with Ratatui's naming convention where `row_highlight_style`, `column_highlight_style`, and `cell_highlight_style` form a consistent trio.
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
# Before (v0.6.0)
|
|
116
|
+
tui.table(
|
|
117
|
+
rows: data,
|
|
118
|
+
highlight_style: tui.style(fg: :yellow)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# After (v0.7.0)
|
|
122
|
+
tui.table(
|
|
123
|
+
rows: data,
|
|
124
|
+
row_highlight_style: tui.style(fg: :yellow)
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Text::Line style Field
|
|
129
|
+
|
|
130
|
+
`Text::Line` now accepts a `style:` parameter for line-level styling. This matches Ratatui's `Line` struct.
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
# New in v0.7.0: Line-level styling
|
|
134
|
+
line = tui.text_line(
|
|
135
|
+
spans: [tui.text_span(content: "Hello")],
|
|
136
|
+
style: tui.style(bg: :dark_gray) # Applied to entire line
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Existing code without `style:` continues to work unchanged.
|
|
141
|
+
|
|
142
|
+
## New Table Cell and Row Classes
|
|
143
|
+
|
|
144
|
+
v0.7.0 adds `Widgets::Cell` and `Widgets::Row` for table construction with per-cell styling:
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
table = tui.table(
|
|
148
|
+
rows: [
|
|
149
|
+
tui.table_row(
|
|
150
|
+
cells: [
|
|
151
|
+
tui.table_cell(content: "Name", style: tui.style(fg: :blue)),
|
|
152
|
+
"Value"
|
|
153
|
+
],
|
|
154
|
+
style: tui.style(bg: :dark_gray)
|
|
155
|
+
)
|
|
156
|
+
],
|
|
157
|
+
widths: [tui.constraint_length(20), tui.constraint_fill]
|
|
158
|
+
)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Buffer::Cell vs Widgets::Cell
|
|
162
|
+
|
|
163
|
+
Two `Cell` classes now exist:
|
|
164
|
+
|
|
165
|
+
- **`Buffer::Cell`** — Terminal cell for inspection (returned by `get_cell_at`)
|
|
166
|
+
- **`Widgets::Cell`** — Table cell for construction (content + style wrapper)
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
# Buffer inspection (unchanged)
|
|
170
|
+
cell = RatatuiRuby.get_cell_at(0, 0) # Returns Buffer::Cell
|
|
171
|
+
cell.char # => "X"
|
|
172
|
+
cell.fg # => :red
|
|
173
|
+
|
|
174
|
+
# Table cell construction (new)
|
|
175
|
+
cell = tui.table_cell(content: "Error", style: tui.style(bg: :red))
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Why This Change?
|
|
179
|
+
|
|
180
|
+
The old flat namespace caused name collisions (`Cell` for buffers vs. tables) and diverged from Ratatui's module structure. The new hierarchy:
|
|
181
|
+
|
|
182
|
+
- Maps 1:1 to Ratatui documentation
|
|
183
|
+
- Prevents future collisions
|
|
184
|
+
- Enables IDE autocomplete via explicit TUI methods
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## For LLMs
|
|
189
|
+
|
|
190
|
+
Copy the following prompt to your AI assistant to help migrate your `ratatui_ruby` application from v0.6.0 to v0.7.0.
|
|
191
|
+
|
|
192
|
+
````markdown
|
|
193
|
+
I'm migrating a Ruby TUI application from `ratatui_ruby` v0.6.0 to v0.7.0. The library restructured its namespaces. Apply these transformations:
|
|
194
|
+
|
|
195
|
+
**Namespace Changes:**
|
|
196
|
+
- `RatatuiRuby::Rect` → `RatatuiRuby::Layout::Rect`
|
|
197
|
+
- `RatatuiRuby::Constraint` → `RatatuiRuby::Layout::Constraint`
|
|
198
|
+
- `RatatuiRuby::Layout` → `RatatuiRuby::Layout::Layout`
|
|
199
|
+
- `RatatuiRuby::Style` → `RatatuiRuby::Style::Style`
|
|
200
|
+
- `RatatuiRuby::Paragraph` → `RatatuiRuby::Widgets::Paragraph`
|
|
201
|
+
- `RatatuiRuby::Block` → `RatatuiRuby::Widgets::Block`
|
|
202
|
+
- `RatatuiRuby::Table` → `RatatuiRuby::Widgets::Table`
|
|
203
|
+
- `RatatuiRuby::List` → `RatatuiRuby::Widgets::List`
|
|
204
|
+
- `RatatuiRuby::Cell` → `RatatuiRuby::Buffer::Cell`
|
|
205
|
+
- All other widgets: `RatatuiRuby::X` → `RatatuiRuby::Widgets::X`
|
|
206
|
+
|
|
207
|
+
**Class Rename:**
|
|
208
|
+
- `RatatuiRuby::Session` → `RatatuiRuby::TUI`
|
|
209
|
+
|
|
210
|
+
**Parameter Rename:**
|
|
211
|
+
- `Table` `highlight_style:` → `row_highlight_style:`
|
|
212
|
+
|
|
213
|
+
**Preferred Approach:** Convert direct class instantiation to TUI API:
|
|
214
|
+
```ruby
|
|
215
|
+
# Instead of:
|
|
216
|
+
RatatuiRuby::Widgets::Paragraph.new(text: "Hello")
|
|
217
|
+
|
|
218
|
+
# Use:
|
|
219
|
+
tui.paragraph(text: "Hello")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**TUI API method names are unchanged.** Code using `tui.paragraph(...)`, `tui.block(...)`, `tui.style(...)` etc. works without modification.
|
|
223
|
+
|
|
224
|
+
**Cell Disambiguation:**
|
|
225
|
+
- `Buffer::Cell` — Terminal cell for inspection (returned by `get_cell_at`)
|
|
226
|
+
- `Widgets::Cell` — Table cell for construction (use `tui.table_cell`)
|
|
227
|
+
- The old `RatatuiRuby::Cell` is now `RatatuiRuby::Buffer::Cell`
|
|
228
|
+
|
|
229
|
+
**New in v0.7.0:**
|
|
230
|
+
- `tui.table_cell(content:, style:)` — styled table cells
|
|
231
|
+
- `tui.table_row(cells:, style:, height:)` — styled table rows
|
|
232
|
+
- `Text::Line` now accepts `style:` parameter
|
|
233
|
+
|
|
234
|
+
Please update my code following these rules.
|
|
235
|
+
````
|
|
236
|
+
|
data/doc/why.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
# Why RatatuiRuby?
|
|
6
|
+
|
|
7
|
+
The terminal is having a renaissance. Ruby deserves to be at the forefront.
|
|
8
|
+
|
|
9
|
+
**RatatuiRuby** is a high-performance, immediate-mode TUI engine that brings the power of Rust's [Ratatui](https://ratatui.rs) library directly into Ruby. No ports. No emulations. A native bridge to the industry-standard Rust crate.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## The Pitch
|
|
13
|
+
|
|
14
|
+
You want to build a terminal UI. You love Ruby. Your options were:
|
|
15
|
+
|
|
16
|
+
1. **Learn Go** for Bubble Tea
|
|
17
|
+
2. **Learn Rust** for Ratatui
|
|
18
|
+
3. **Use a pure-Ruby library** with limited performance
|
|
19
|
+
|
|
20
|
+
We built a fourth option: **Write Ruby. Run Rust.**
|
|
21
|
+
|
|
22
|
+
RatatuiRuby gives you Rust's layout engine, rendering speed, and battle-tested widgets — with Ruby's expressiveness, ecosystem, and joy.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## RatatuiRuby vs. CharmRuby
|
|
26
|
+
|
|
27
|
+
[CharmRuby](https://github.com/marcoroth/charm_ruby) is an excellent project by Marco Roth. It provides Ruby bindings to Charm's Go libraries (Bubble Tea, Lipgloss). The Ruby ecosystem is better because both projects exist.
|
|
28
|
+
|
|
29
|
+
So which one should you choose?
|
|
30
|
+
|
|
31
|
+
| | CharmRuby | RatatuiRuby |
|
|
32
|
+
|---|-----------|-------------|
|
|
33
|
+
| **Backend** | Go runtime | Rust (no runtime) |
|
|
34
|
+
| **Architecture** | Elm Architecture (MVU) | Immediate-mode + your choice |
|
|
35
|
+
| **GC Behavior** | Two GCs (Ruby + Go) | One GC (Ruby only) |
|
|
36
|
+
| **Rendering** | String manipulation | Constraint-based layout tree |
|
|
37
|
+
| **Best for** | Fans of Bubble Tea, MVU | Native performance, heavy-duty apps |
|
|
38
|
+
|
|
39
|
+
**What's a runtime?** A runtime is background machinery that a language needs to run. Go has one (for goroutines and garbage collection). Rust doesn't — it compiles to plain machine code. When you use Go bindings, you're running *two* runtimes in the same process (Ruby's and Go's), which adds complexity and memory overhead. With Rust bindings, there's only Ruby.
|
|
40
|
+
|
|
41
|
+
**Choose CharmRuby** if you prefer Charm's aesthetics or are migrating existing Bubble Tea code.
|
|
42
|
+
|
|
43
|
+
**Choose RatatuiRuby** if you want zero-overhead native performance and architectural freedom. RatatuiRuby doesn't force a framework — you can build MVU, component-based, or any pattern you prefer.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Why Not Just Write Rust?
|
|
47
|
+
|
|
48
|
+
Rust is amazing. It's also strict.
|
|
49
|
+
|
|
50
|
+
The borrow checker enforces memory safety. That's great for systems programming. It's painful for UI iteration. Moving a sidebar, changing a color, or swapping a widget often requires refactoring ownership chains.
|
|
51
|
+
|
|
52
|
+
With RatatuiRuby, you just change the object. You get Rust's performance where it matters — rendering — and Ruby's flexibility where it counts — designing.
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## Why Not Just Write Go?
|
|
56
|
+
|
|
57
|
+
Go is pragmatic. But using Go bindings means running *two* runtimes in the same process: Ruby's and Go's. That adds complexity and memory overhead.
|
|
58
|
+
|
|
59
|
+
With RatatuiRuby, there's only Ruby. Rust compiles to plain machine code with no runtime — it integrates seamlessly.
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
## Why Ruby?
|
|
63
|
+
|
|
64
|
+
[Ruby isn't just another language](https://www.ruby-lang.org/en/). It's an ecosystem:
|
|
65
|
+
|
|
66
|
+
- **[ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html)** — Query your database with elegant, chainable methods
|
|
67
|
+
- **[RSpec](https://rspec.info/)** — Write expressive, readable tests with `describe`, `it`, and `expect`
|
|
68
|
+
- **[Blocks](https://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/blocks.html)** — Pass behavior to methods with `do...end`, the heart of Ruby's expressiveness
|
|
69
|
+
- **[Metaprogramming](https://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/objinitialization.html)** — Define methods dynamically, build DSLs, and write code that writes code
|
|
70
|
+
- **[Bundler](https://bundler.io/)** — Access 180,000+ gems with a single `bundle add`
|
|
71
|
+
|
|
72
|
+
Build a dashboard for your Rails app. Monitor your Sidekiq jobs. Create developer tools in the same language as the code they inspect.
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
## The Philosophy: A Solid Foundation
|
|
76
|
+
|
|
77
|
+
RatatuiRuby is a **low-level engine**. It provides raw primitives — Layouts, Blocks, Text, Tables, Charts — to build anything.
|
|
78
|
+
|
|
79
|
+
It doesn't force a framework on you. You can use:
|
|
80
|
+
- **Model-View-Update** for dashboards and data displays
|
|
81
|
+
- **Component-based** patterns for interactive tools
|
|
82
|
+
- **Your own architecture** for everything else
|
|
83
|
+
|
|
84
|
+
This is the foundation for Ruby's next generation of TUI tools, dashboards, and interactive scripts.
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
## Get Started
|
|
88
|
+
|
|
89
|
+
Ready to build?
|
|
90
|
+
|
|
91
|
+
- [Quickstart Guide](./quickstart.md) — Your first app in 5 minutes
|
|
92
|
+
- [Widget Gallery](./quickstart.md#widget-demos) — See what's possible
|
|
93
|
+
- [Application Architecture](./application_architecture.md) — Patterns for scaling
|
|
@@ -5,9 +5,11 @@ SPDX-License-Identifier: CC-BY-SA-4.0
|
|
|
5
5
|
|
|
6
6
|
# App All Events Example
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
[](app.rb)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
This example application captures and visualizes every event supported by `ratatui_ruby`. It serves as a comprehensive reference for event handling and a demonstration of the Model-View-Update architectural pattern.
|
|
11
|
+
|
|
12
|
+
## Architecture: Model-View-Update
|
|
11
13
|
|
|
12
14
|
This application demonstrates **unidirectional data flow** inspired by The Elm Architecture. This separation ensures that state management is predictable and easy to test.
|
|
13
15
|
|
|
@@ -85,7 +87,7 @@ Complex applications require structured state habits. `AppAllEvents` and the [Co
|
|
|
85
87
|
|
|
86
88
|
### The Dashboard Approach (AppAllEvents)
|
|
87
89
|
|
|
88
|
-
Dashboards display data. They rarely require complex mouse interaction.
|
|
90
|
+
Dashboards display data. They rarely require complex mouse interaction. Model-View-Update works best here. State is immutable. Logic is pure. Updates are predictable. This simplifies testing.
|
|
89
91
|
|
|
90
92
|
Use this pattern for logs, monitors, and data viewers.
|
|
91
93
|
|
|
@@ -93,7 +95,7 @@ Use this pattern for logs, monitors, and data viewers.
|
|
|
93
95
|
|
|
94
96
|
Tools require interaction. Users click buttons and drag sliders. Each UI component needs to know where it exists on screen for hit testing.
|
|
95
97
|
|
|
96
|
-
The Color Picker uses a
|
|
98
|
+
The Color Picker uses a Component-Based pattern. Each component encapsulates its own rendering, state, and event handling. The Container routes events and coordinates cross-component effects.
|
|
97
99
|
|
|
98
100
|
Use this pattern for forms, editors, and mouse-driven tools.
|
|
99
101
|
|
|
@@ -23,7 +23,7 @@ require_relative "view/app_view"
|
|
|
23
23
|
#
|
|
24
24
|
# === Architecture
|
|
25
25
|
#
|
|
26
|
-
# This example uses the
|
|
26
|
+
# This example uses the Model-View-Update pattern:
|
|
27
27
|
# - **Model**: Immutable AppModel holds all state
|
|
28
28
|
# - **Msg**: Semantic message types decouple events from logic
|
|
29
29
|
# - **Update**: Pure function computes next state
|
|
@@ -7,7 +7,7 @@ require_relative "timestamp"
|
|
|
7
7
|
require_relative "event_entry"
|
|
8
8
|
require_relative "event_color_cycle"
|
|
9
9
|
|
|
10
|
-
# Immutable application state for the
|
|
10
|
+
# Immutable application state for the Model-View-Update architecture.
|
|
11
11
|
#
|
|
12
12
|
# The Elm Architecture requires a single immutable Model. State changes return
|
|
13
13
|
# a new Model instance. This consolidates all app state into one place.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
4
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
5
|
|
|
6
|
-
# Semantic message types for the
|
|
6
|
+
# Semantic message types for the Model-View-Update architecture.
|
|
7
7
|
#
|
|
8
8
|
# Raw events from the terminal are converted to semantic Msg types. This
|
|
9
9
|
# decouples the Update function from the event system, making it easier
|