ratatui_ruby 1.0.0 → 1.1.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 +3 -2
- data/CHANGELOG.md +33 -7
- data/Steepfile +1 -0
- data/doc/concepts/application_testing.md +5 -5
- data/doc/concepts/event_handling.md +1 -1
- data/doc/contributors/design/ruby_frontend.md +40 -12
- data/doc/contributors/design/rust_backend.md +13 -1
- data/doc/contributors/releasing.md +215 -0
- data/doc/contributors/todo/align/api_completeness_audit-finished.md +6 -0
- data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +1 -7
- data/doc/contributors/todo/align/term.md +351 -0
- data/doc/contributors/upstream_requests/paragraph_span_rects.md +259 -0
- data/doc/getting_started/quickstart.md +1 -1
- data/doc/getting_started/why.md +3 -3
- data/doc/images/app_external_editor.gif +0 -0
- data/doc/index.md +1 -6
- data/examples/app_external_editor/README.md +62 -0
- data/examples/app_external_editor/app.rb +344 -0
- data/examples/widget_list/app.rb +2 -4
- data/examples/widget_table/app.rb +8 -2
- data/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/ext/ratatui_ruby/src/events.rs +171 -203
- data/ext/ratatui_ruby/src/lib.rs +36 -0
- data/ext/ratatui_ruby/src/lib_header.rs +11 -0
- data/ext/ratatui_ruby/src/terminal/capabilities.rs +46 -0
- data/ext/ratatui_ruby/src/terminal/init.rs +92 -0
- data/ext/ratatui_ruby/src/terminal/mod.rs +12 -3
- data/ext/ratatui_ruby/src/terminal/queries.rs +15 -0
- data/ext/ratatui_ruby/src/terminal/query.rs +64 -2
- data/lib/ratatui_ruby/backend/window_size.rb +50 -0
- data/lib/ratatui_ruby/backend.rb +59 -0
- data/lib/ratatui_ruby/event/key/navigation.rb +10 -1
- data/lib/ratatui_ruby/event/key.rb +84 -0
- data/lib/ratatui_ruby/event/mouse.rb +95 -3
- data/lib/ratatui_ruby/event/resize.rb +45 -3
- data/lib/ratatui_ruby/layout/alignment.rb +91 -0
- data/lib/ratatui_ruby/layout/layout.rb +1 -2
- data/lib/ratatui_ruby/layout/size.rb +10 -3
- data/lib/ratatui_ruby/layout.rb +4 -0
- data/lib/ratatui_ruby/terminal/capabilities.rb +316 -0
- data/lib/ratatui_ruby/terminal/viewport.rb +1 -1
- data/lib/ratatui_ruby/terminal.rb +66 -0
- data/lib/ratatui_ruby/test_helper/global_state.rb +111 -0
- data/lib/ratatui_ruby/test_helper.rb +3 -0
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby/widgets/table.rb +2 -2
- data/lib/ratatui_ruby.rb +25 -4
- data/sig/examples/app_external_editor/app.rbs +12 -0
- data/sig/generated/event_key_predicates.rbs +1348 -0
- data/sig/ratatui_ruby/backend/window_size.rbs +17 -0
- data/sig/ratatui_ruby/backend.rbs +12 -0
- data/sig/ratatui_ruby/event.rbs +7 -0
- data/sig/ratatui_ruby/layout/alignment.rbs +26 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +2 -0
- data/sig/ratatui_ruby/terminal/capabilities.rbs +38 -0
- data/sig/ratatui_ruby/terminal/viewport.rbs +15 -1
- data/tasks/bump/bump_workflow.rb +49 -0
- data/tasks/bump/changelog.rb +57 -0
- data/tasks/bump/patch_release.rb +19 -0
- data/tasks/bump/release_branch.rb +17 -0
- data/tasks/bump/release_from_trunk.rb +49 -0
- data/tasks/bump/repository.rb +54 -0
- data/tasks/bump/ruby_gem.rb +6 -26
- data/tasks/bump/sem_ver.rb +4 -0
- data/tasks/bump/unreleased_section.rb +17 -0
- data/tasks/bump.rake +21 -11
- data/tasks/doc/documentation.rb +59 -0
- data/tasks/doc/link/file_url.rb +30 -0
- data/tasks/doc/link/relative_path.rb +61 -0
- data/tasks/doc/link/web_url.rb +55 -0
- data/tasks/doc/link.rb +52 -0
- data/tasks/doc/link_audit.rb +116 -0
- data/tasks/doc/problem.rb +40 -0
- data/tasks/doc/source_file.rb +93 -0
- data/tasks/doc.rake +18 -0
- data/tasks/rbs_predicates/predicate_catalog.rb +52 -0
- data/tasks/rbs_predicates/predicate_tests.rb +124 -0
- data/tasks/rbs_predicates/rbs_signature.rb +63 -0
- data/tasks/rbs_predicates.rake +31 -0
- data/tasks/test.rake +3 -0
- data/tasks/website/version.rb +23 -28
- metadata +38 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4af7cd6e9b1850a0abe3099f29c1dbf4d9e4f01cd1782196b0948c8591d9ba3
|
|
4
|
+
data.tar.gz: 7e68a66603d410baaad20d9267b3da083bff66a1a9c7d3dd9d0142a4b89fca9f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b3790091fe5de4276ff383caffc753012efc7d8646eb7d2d5a2467e73518dbd8584c692ffec368a374d6cf9a11981be6af0d3d51a1421e48f4afe1e528547618
|
|
7
|
+
data.tar.gz: f63f2bbb7abf4462be09d17aabc8bdf7737853b79e4ff5d55425a2246687a23c47e5a04c19bd41405171f0e14f94749ba70e5fe07578ffcb5ffec1e248f43246
|
data/.builds/ruby-3.2.yml
CHANGED
data/.builds/ruby-3.3.yml
CHANGED
data/.builds/ruby-3.4.yml
CHANGED
data/.builds/ruby-4.0.0.yml
CHANGED
data/AGENTS.md
CHANGED
|
@@ -27,6 +27,7 @@ Architecture:
|
|
|
27
27
|
|
|
28
28
|
### STRICT REQUIREMENTS
|
|
29
29
|
|
|
30
|
+
- **Check Before Implementing:** FIRST check tests for existing coverage. If it works, say so and point to the test.
|
|
30
31
|
- Every file MUST begin with an SPDX-compliant header. Use `AGPL-3.0-or-later` for code; `CC-BY-SA-4.0` for documentation. `reuse annotate` can help you generate the header. **For Ruby files**, wrap SPDX comments in `#--` / `#++` to hide them from RDoc output.
|
|
31
32
|
- Every line of Ruby MUST be covered by tests that would stand up to mutation testing.
|
|
32
33
|
- Tests must be meaningful and verify specific behavior or rendering output; simply verifying that code "doesn't crash" is insufficient and unacceptable.
|
|
@@ -62,14 +63,14 @@ Architecture:
|
|
|
62
63
|
- Every public Ruby class/method must be documented for humans in RDoc (preferred)--**not** YARD--or markdown files (fallback), and must have `*.rbs` types defined.
|
|
63
64
|
- Every significant architectural and design decision must be documented for contributors in markdown files. Mermaid is allowed.
|
|
64
65
|
- **Rust-backed methods:** For methods implemented in Rust (magnus bindings), use RDoc directives instead of empty method bodies. Use `##` followed by `:method:`, `:call-seq:`, and prose. End with `(Native method implemented in Rust)`. See `lib/ratatui_ruby.rb` for examples.
|
|
65
|
-
- Refer to [
|
|
66
|
+
- Refer to [doc/contributors/design/ruby_frontend.md](doc/contributors/design/ruby_frontend.md) for detailed design philosophy regarding the Immediate Mode paradigm including Data-Driven UI and Frames.
|
|
66
67
|
|
|
67
68
|
### Rust Standards
|
|
68
69
|
|
|
69
70
|
- **Crate Type:** `cdylib`.
|
|
70
71
|
- **Bindings:** Use [magnus](https://github.com/matsadler/magnus).
|
|
71
72
|
- **Platform:** Support macOS (Apple Silicon), Linux, and Windows.
|
|
72
|
-
- Refer to [
|
|
73
|
+
- Refer to [doc/contributors/design/rust_backend.md](doc/contributors/design/rust_backend.md) for detailed implementation guidelines, module structure, and rendering logic.
|
|
73
74
|
|
|
74
75
|
## 2. Directory Structure Convention
|
|
75
76
|
|
data/CHANGELOG.md
CHANGED
|
@@ -18,15 +18,41 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
18
18
|
|
|
19
19
|
### Removed
|
|
20
20
|
|
|
21
|
+
## [1.1.0] - 2026-01-25
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **Terminal Capability Detection**: New class methods on `RatatuiRuby::Terminal` for environment-based capability detection before initializing TUI mode:
|
|
26
|
+
- `Terminal.tty?` — checks if stdout is connected to a terminal
|
|
27
|
+
- `Terminal.dumb?` — checks if TERM is explicitly set to "dumb"
|
|
28
|
+
- `Terminal.no_color?` — checks if NO_COLOR environment variable is set (respects the [NO_COLOR standard](https://no-color.org/))
|
|
29
|
+
- `Terminal.force_color?` — checks if FORCE_COLOR environment variable is set
|
|
30
|
+
- `Terminal.interactive?` — returns true only when tty? and not dumb?
|
|
31
|
+
- `Terminal.available_color_count` — returns color support level (8, 256, or 65535) via crossterm detection
|
|
32
|
+
- `Terminal.color_support` — convenience method returning `:none`, `:basic`, `:ansi256`, or `:truecolor`
|
|
33
|
+
- `Terminal.supports_keyboard_enhancement?` — checks for Kitty keyboard protocol support
|
|
34
|
+
- `Backend.window_size` — returns terminal dimensions as `Backend::WindowSize` with both character grid (`columns_rows`) and pixel (`pixels`) sizes as `Layout::Size` instances; mirrors upstream Ratatui's `backend::WindowSize` struct
|
|
35
|
+
- `Terminal.force_color_output(enable)` — globally overrides NO_COLOR detection for `--color=always` flags
|
|
36
|
+
- **Alignment Constants**: New `RatatuiRuby::Layout::HorizontalAlignment` and `RatatuiRuby::Layout::VerticalAlignment` modules with discoverable constants (`LEFT`, `CENTER`, `RIGHT`, `TOP`, `BOTTOM`). `Layout::Alignment` is an alias for `HorizontalAlignment`. Use the constants for IDE discoverability, or continue passing symbols (`:left`, `:center`, etc.) directly—both work.
|
|
37
|
+
- **Frame Count Query**: `RatatuiRuby.frame_count` returns the number of frames drawn since terminal initialization. The count starts at 0 when the terminal is created, increments by 1 after each draw, and resets when the terminal is restored and re-initialized.
|
|
38
|
+
- **Mouse and Resize Symbol Comparison**: `Event::Mouse` and `Event::Resize` now support symbol comparison via `to_sym` and `==`, matching `Event::Key`. Use `event == :mouse_left_down`, `event == :scroll_up`, or `event == :resize` for cleaner event handling.
|
|
39
|
+
- **Key Event DWIM Predicates**: `Event::Key` now supports alternate predicate forms for disambiguation and case handling. Arrow key aliases (`arrow_up?`, `up_arrow?`) distinguish keyboard input from `Mouse#up?`/`Mouse#down?`. The `key_` prefix and `_key` suffix (`key_up?`, `q_key?`) provide explicit key event matching in mixed event contexts. Capital letters match their shifted form naturally (`G?` matches `code="G"` with shift), and uppercase in predicates implies shift (`alt_B?` matches `alt_shift_B`).
|
|
40
|
+
- **Generated RBS Predicate Declarations**: New `rake rbs:predicates` task generates RBS type declarations for all 1,328 `Event::Key` predicate methods (base keys, modifiers, characters, function keys, and all modifier combinations). Predicates are derived from a single source of truth in Rust FFI.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
### Removed
|
|
47
|
+
|
|
21
48
|
## [1.0.0] - 2026-01-25
|
|
22
|
-
This release is functionally equivalent to v0.10.3, with additional bug fixes.
|
|
23
|
-
The version bump signals the beginning of the 1.0 release series.
|
|
24
49
|
|
|
25
50
|
### Added
|
|
26
51
|
|
|
27
52
|
### Changed
|
|
28
53
|
|
|
29
54
|
### Fixed
|
|
55
|
+
|
|
30
56
|
- **back_tab? DWIM**: `back_tab?` and `backtab?` predicates now match events with code "back_tab" regardless of whether the shift modifier is explicitly present, since back_tab semantically implies shift.
|
|
31
57
|
- **Terminal Queries During Draw (Deadlock)**: Calling `viewport_area`, `terminal_size`, `get_cell_at`, `poll_event`, `get_cursor_position`, or `get_viewport_type` from inside a `draw()` block previously caused the application to freeze forever. The thread blocked on a Mutex. Ruby's `Timeout` could not interrupt it. The only recovery was `kill -9`. These reads now work via a snapshot captured before rendering.
|
|
32
58
|
- **Terminal Mutations During Draw (Deadlock)**: Calling `insert_before`, `set_cursor_position`, or `resize_terminal` from inside a `draw()` block previously caused the same silent freeze. These writes now raise `Error::Invariant` with a clear message.
|
|
@@ -34,6 +60,8 @@ The version bump signals the beginning of the 1.0 release series.
|
|
|
34
60
|
- **Event Injection During Draw (Deadlock)**: Calling `inject_test_event` from inside a `draw()` block previously froze the application. Event injection now works correctly during draw.
|
|
35
61
|
- **TableState Row Navigation Methods**: Added missing row navigation methods (`select_next`, `select_previous`, `select_first`, `select_last`) that should have been included alongside the column navigation methods added in v0.10.0. These methods match `ListState`'s navigation API and are used in the `app_stateful_interaction` example.
|
|
36
62
|
|
|
63
|
+
### Removed
|
|
64
|
+
|
|
37
65
|
## [0.10.3] - 2026-01-16
|
|
38
66
|
|
|
39
67
|
### Added
|
|
@@ -348,7 +376,7 @@ The version bump signals the beginning of the 1.0 release series.
|
|
|
348
376
|
## [0.7.0] - 2026-01-03
|
|
349
377
|
|
|
350
378
|
> [!WARNING]
|
|
351
|
-
> v0.7.0 contains significant breaking changes. See the [Migration Guide](
|
|
379
|
+
> v0.7.0 contains significant breaking changes. See the [Migration Guide](https://man.sr.ht/~kerrick/ratatui_ruby/history/migrations/v0_7_0.md) for upgrade instructions.
|
|
352
380
|
|
|
353
381
|
### Added
|
|
354
382
|
|
|
@@ -360,7 +388,7 @@ The version bump signals the beginning of the 1.0 release series.
|
|
|
360
388
|
|
|
361
389
|
### Changed
|
|
362
390
|
|
|
363
|
-
- **Namespace Restructure (Breaking)**: Classes reorganized to match Ratatui's module hierarchy. See [Migration Guide](
|
|
391
|
+
- **Namespace Restructure (Breaking)**: Classes reorganized to match Ratatui's module hierarchy. See [Migration Guide](https://man.sr.ht/~kerrick/ratatui_ruby/history/migrations/v0_7_0.md) for details:
|
|
364
392
|
- `RatatuiRuby::Rect` → `RatatuiRuby::Layout::Rect`
|
|
365
393
|
- `RatatuiRuby::Constraint` → `RatatuiRuby::Layout::Constraint`
|
|
366
394
|
- `RatatuiRuby::Layout` → `RatatuiRuby::Layout::Layout`
|
|
@@ -683,10 +711,8 @@ The version bump signals the beginning of the 1.0 release series.
|
|
|
683
711
|
- **Testing Support**: Included `RatatuiRuby::TestHelper` and RSpec integration to make testing your TUI applications possible.
|
|
684
712
|
|
|
685
713
|
[Unreleased]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/HEAD
|
|
714
|
+
[1.1.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.1.0
|
|
686
715
|
[1.0.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.0.0
|
|
687
|
-
[1.0.0-beta.3]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.0.0-beta.3
|
|
688
|
-
[1.0.0-beta.2]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.0.0-beta.2
|
|
689
|
-
[1.0.0-beta.1]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.0.0-beta.1
|
|
690
716
|
[0.10.3]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.10.3
|
|
691
717
|
[0.10.2]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.10.2
|
|
692
718
|
[0.10.1]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.10.1
|
data/Steepfile
CHANGED
|
@@ -76,7 +76,7 @@ end
|
|
|
76
76
|
```
|
|
77
77
|
<!-- SPDX-SnippetEnd -->
|
|
78
78
|
|
|
79
|
-
For the full API list, including `buffer_content` and `cursor_position`, see [RatatuiRuby::TestHelper::Terminal](
|
|
79
|
+
For the full API list, including `buffer_content` and `cursor_position`, see [RatatuiRuby::TestHelper::Terminal](../../lib/ratatui_ruby/test_helper/terminal.rb).
|
|
80
80
|
|
|
81
81
|
## Verifying Styles
|
|
82
82
|
|
|
@@ -99,7 +99,7 @@ assert_area_style({ x: 0, y: 0, w: 10, h: 1 }, bg: :blue)
|
|
|
99
99
|
```
|
|
100
100
|
<!-- SPDX-SnippetEnd -->
|
|
101
101
|
|
|
102
|
-
See [RatatuiRuby::TestHelper::StyleAssertions](
|
|
102
|
+
See [RatatuiRuby::TestHelper::StyleAssertions](../../lib/ratatui_ruby/test_helper/style_assertions.rb) for the comprehensive list of style helpers.
|
|
103
103
|
|
|
104
104
|
## Simulating Input
|
|
105
105
|
|
|
@@ -127,7 +127,7 @@ end
|
|
|
127
127
|
```
|
|
128
128
|
<!-- SPDX-SnippetEnd -->
|
|
129
129
|
|
|
130
|
-
See [RatatuiRuby::TestHelper::EventInjection](
|
|
130
|
+
See [RatatuiRuby::TestHelper::EventInjection](../../lib/ratatui_ruby/test_helper/event_injection.rb) for helper methods like `inject_keys` and `inject_click`.
|
|
131
131
|
|
|
132
132
|
## Snapshot Testing
|
|
133
133
|
|
|
@@ -158,7 +158,7 @@ To prevent this:
|
|
|
158
158
|
1. **Seed Randomness:** Use a fixed seed for any RNG.
|
|
159
159
|
2. **Stub Time:** Force the application to use a static time.
|
|
160
160
|
|
|
161
|
-
For detailed strategies and code examples, see [RatatuiRuby::TestHelper::Snapshot](
|
|
161
|
+
For detailed strategies and code examples, see [RatatuiRuby::TestHelper::Snapshot](../../lib/ratatui_ruby/test_helper/snapshot.rb).
|
|
162
162
|
|
|
163
163
|
## Isolated View Testing
|
|
164
164
|
|
|
@@ -186,7 +186,7 @@ end
|
|
|
186
186
|
```
|
|
187
187
|
<!-- SPDX-SnippetEnd -->
|
|
188
188
|
|
|
189
|
-
See [RatatuiRuby::TestHelper::TestDoubles](
|
|
189
|
+
See [RatatuiRuby::TestHelper::TestDoubles](../../lib/ratatui_ruby/test_helper/test_doubles.rb).
|
|
190
190
|
|
|
191
191
|
## Example
|
|
192
192
|
|
|
@@ -27,7 +27,7 @@ For simple key events, `RatatuiRuby::Event::Key` objects can be compared directl
|
|
|
27
27
|
> [!NOTE]
|
|
28
28
|
> On macOS, the **Option** key is mapped to `alt`. The **Command** key is typically intercepted by the terminal emulator and may not be sent to the application, or it may be mapped to Meta/Alt depending on your terminal settings.
|
|
29
29
|
|
|
30
|
-
For a complete list of supported keys, modifiers, and event types, please refer to the [API Documentation for RatatuiRuby::Event](
|
|
30
|
+
For a complete list of supported keys, modifiers, and event types, please refer to the [API Documentation for RatatuiRuby::Event](../../lib/ratatui_ruby/event.rb).
|
|
31
31
|
|
|
32
32
|
<!-- SPDX-SnippetBegin -->
|
|
33
33
|
<!--
|
|
@@ -9,25 +9,53 @@ This document describes the architectural design and guiding principles of the R
|
|
|
9
9
|
|
|
10
10
|
## Guiding Design Principles
|
|
11
11
|
|
|
12
|
-
### 1.
|
|
12
|
+
### 1. Three-Tier Namespace Architecture
|
|
13
13
|
|
|
14
|
-
The
|
|
14
|
+
The gem provides three distinct namespaces, each with a specific purpose:
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
- **Predictability**: No mental translation required between Rust and Ruby codebases.
|
|
18
|
-
- **Scalability**: As Ratatui adds new types, the Ruby placement is deterministic.
|
|
16
|
+
**Tier 1: `Ratatui::` — Upstream Alignment**
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
Pure upstream Ratatui types with 1:1 API correspondence. If it exists in Rust Ratatui, it has the same name and location here.
|
|
21
19
|
|
|
22
20
|
| Rust Module | Ruby Module | Purpose |
|
|
23
21
|
|-------------|-------------|---------|
|
|
24
|
-
| `ratatui::layout` | `
|
|
25
|
-
| `ratatui::widgets` | `
|
|
26
|
-
| `ratatui::style` | `
|
|
27
|
-
| `ratatui::text` | `
|
|
28
|
-
| `ratatui::buffer` | `
|
|
22
|
+
| `ratatui::layout` | `Ratatui::Layout` | Rect, Constraint, Layout, Position, Size |
|
|
23
|
+
| `ratatui::widgets` | `Ratatui::Widgets` | All widgets (Table, List, Paragraph, Block, etc.) |
|
|
24
|
+
| `ratatui::style` | `Ratatui::Style` | Style, Color |
|
|
25
|
+
| `ratatui::text` | `Ratatui::Text` | Span, Line |
|
|
26
|
+
| `ratatui::buffer` | `Ratatui::Buffer` | Cell (for buffer inspection) |
|
|
27
|
+
| `ratatui::backend` | `Ratatui::Backend` | WindowSize |
|
|
28
|
+
| `ratatui::Terminal` | `Ratatui::Terminal` | Terminal lifecycle (draw, size, cursor) |
|
|
29
|
+
| `ratatui::Frame` | `Ratatui::Frame` | Frame object for render callbacks |
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
**Tier 2: `Crossterm::` — Backend Alignment**
|
|
32
|
+
|
|
33
|
+
Direct exposure of crossterm functionality. These are terminal I/O primitives that Ratatui builds upon.
|
|
34
|
+
|
|
35
|
+
| Rust Module | Ruby Module | Purpose |
|
|
36
|
+
|-------------|-------------|---------|
|
|
37
|
+
| `crossterm::terminal` | `Crossterm::Terminal` | `supports_keyboard_enhancement?`, `window_size` |
|
|
38
|
+
| `crossterm::style` | `Crossterm::Style` | `available_color_count`, `force_color_output` |
|
|
39
|
+
|
|
40
|
+
**Tier 3: `RatatuiRuby::` — Ruby Convenience Layer**
|
|
41
|
+
|
|
42
|
+
Ruby-specific conveniences, the main entry point, and the TUI DSL facade. This is where Ruby idioms live.
|
|
43
|
+
|
|
44
|
+
- `RatatuiRuby.run { |tui| ... }` — Main entry point with setup/teardown
|
|
45
|
+
- `RatatuiRuby.tty?`, `RatatuiRuby.dumb?`, `RatatuiRuby.interactive?` — Environment detection (Ruby-specific)
|
|
46
|
+
- `RatatuiRuby::TUI` — DSL facade with shorthand factory methods
|
|
47
|
+
- `RatatuiRuby::TestHelper` — Testing utilities
|
|
48
|
+
- `RatatuiRuby::Error` — Exception hierarchy
|
|
49
|
+
|
|
50
|
+
**Why Three Tiers?**
|
|
51
|
+
|
|
52
|
+
1. **Upstream Purity**: Users who want exact Ratatui API parity use `Ratatui::` and `Crossterm::` namespaces.
|
|
53
|
+
2. **Ruby Idioms**: Users who want convenience use `RatatuiRuby.run`, the TUI facade, and helper methods.
|
|
54
|
+
3. **Documentation Mapping**: A contributor reading Ratatui's Rust docs immediately knows where to find the Ruby equivalent.
|
|
55
|
+
4. **Predictability**: As upstream adds types, their Ruby placement is deterministic.
|
|
56
|
+
|
|
57
|
+
> [!NOTE]
|
|
58
|
+
> This three-tier architecture will be rolled out incrementally as 1.x releases. The `Ratatui::` and `Crossterm::` namespaces are additive—`RatatuiRuby::` will continue to work by delegating to them. No breaking changes required.
|
|
31
59
|
|
|
32
60
|
### 2. Two-Layer Architecture
|
|
33
61
|
|
|
@@ -166,11 +166,20 @@ Defines the Ruby module hierarchy using `magnus` and exports public functions (`
|
|
|
166
166
|
|
|
167
167
|
Manages the global `TERMINAL` singleton (mutex-wrapped `CrosstermBackend<Stdout>`).
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
**Lifecycle Functions:**
|
|
170
170
|
- `init()` — Enter raw mode, enable mouse capture, switch to alternate screen
|
|
171
171
|
- `restore()` — Disable raw mode, restore main screen
|
|
172
172
|
- `get_cell_at(x, y)` — Return buffer cell as Ruby `Buffer::Cell` object
|
|
173
173
|
|
|
174
|
+
**Crossterm Capability Queries:**
|
|
175
|
+
|
|
176
|
+
These functions expose crossterm's terminal capability detection to Ruby. In the three-tier architecture, they'll be surfaced via the `Crossterm::` namespace:
|
|
177
|
+
|
|
178
|
+
- `terminal_window_size()` — Returns `(columns, rows, pixel_width, pixel_height)` via `crossterm::terminal::window_size()`
|
|
179
|
+
- `available_color_count()` — Returns color depth (8/256/65535) via crossterm's `COLORTERM`/`TERM` detection
|
|
180
|
+
- `supports_keyboard_enhancement()` — Queries Kitty keyboard protocol support
|
|
181
|
+
- `force_color_output(enable)` — Overrides `NO_COLOR` detection via `crossterm::style::force_color_output()`
|
|
182
|
+
|
|
174
183
|
**Safety Note:** The terminal is a global mutable resource. All access goes through a mutex. Holding the lock across Ruby calls risks deadlock—release the lock before calling back into Ruby.
|
|
175
184
|
|
|
176
185
|
### `frame.rs` — Frame Wrapper
|
|
@@ -230,6 +239,9 @@ pub fn render_widget(frame: &mut Frame, area: Rect, node: Value) -> Result<(), E
|
|
|
230
239
|
|
|
231
240
|
**Namespace Pattern:** All built-in widgets use the `RatatuiRuby::Widgets::*` namespace. The dispatcher matches on full class names, not prefixes.
|
|
232
241
|
|
|
242
|
+
> [!NOTE]
|
|
243
|
+
> The dispatcher will be updated to also match `Ratatui::Widgets::*` class names when the three-tier namespace architecture rolls out. This is additive—existing `RatatuiRuby::` names will continue to work. See [Ruby Frontend Design](./ruby_frontend.md) for details.
|
|
244
|
+
|
|
233
245
|
### `widgets/*.rs` — Widget Renderers
|
|
234
246
|
|
|
235
247
|
Each widget has its own module with a standard interface:
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
+
-->
|
|
5
|
+
|
|
6
|
+
# Releasing
|
|
7
|
+
|
|
8
|
+
This guide documents RatatuiRuby's release workflow. We use
|
|
9
|
+
[trunk-based development](https://trunkbaseddevelopment.com/committing-straight-to-the-trunk/)
|
|
10
|
+
with [release branches](https://trunkbaseddevelopment.com/branch-for-release/).
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
- **`trunk`** — Active development. Features land here first.
|
|
15
|
+
- **`release/X.Y`** — Release series branches (e.g., `release/1.0`).
|
|
16
|
+
- **`stable`** — Always points to the latest stable release.
|
|
17
|
+
|
|
18
|
+
<!-- SPDX-SnippetBegin -->
|
|
19
|
+
<!--
|
|
20
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
21
|
+
SPDX-License-Identifier: MIT-0
|
|
22
|
+
-->
|
|
23
|
+
```
|
|
24
|
+
trunk ──●──●──●──●──●──●──●──●──●── (future work)
|
|
25
|
+
\ \
|
|
26
|
+
release/1.0 ───●──●──● \ (1.0.0, 1.0.1, ...)
|
|
27
|
+
\
|
|
28
|
+
release/1.1 ●──●──●── (1.1.0, 1.1.1, ...)
|
|
29
|
+
```
|
|
30
|
+
<!-- SPDX-SnippetEnd -->
|
|
31
|
+
|
|
32
|
+
## Versioning Philosophy
|
|
33
|
+
|
|
34
|
+
We follow strict SemVer without ceremony:
|
|
35
|
+
|
|
36
|
+
- **Breaking change?** → Bump major
|
|
37
|
+
- **New feature?** → Bump minor
|
|
38
|
+
- **Bug fix?** → Bump patch
|
|
39
|
+
|
|
40
|
+
Version numbers are technical artifacts, not marketing. If we end up at v50 by
|
|
41
|
+
year's end, so be it.
|
|
42
|
+
|
|
43
|
+
## Changelog Management
|
|
44
|
+
|
|
45
|
+
Trunk maintains the canonical project history. Each release branch maintains
|
|
46
|
+
its own changelog during development, then syncs back to trunk.
|
|
47
|
+
|
|
48
|
+
### During Beta/RC Cycles
|
|
49
|
+
|
|
50
|
+
The release branch (`release/1.0`) tracks granular changes:
|
|
51
|
+
|
|
52
|
+
<!-- SPDX-SnippetBegin -->
|
|
53
|
+
<!--
|
|
54
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
55
|
+
SPDX-License-Identifier: MIT-0
|
|
56
|
+
-->
|
|
57
|
+
```markdown
|
|
58
|
+
## [Unreleased]
|
|
59
|
+
|
|
60
|
+
## [1.0.0-beta.2] - 2026-01-20
|
|
61
|
+
### Fixed
|
|
62
|
+
- TableState row navigation methods
|
|
63
|
+
|
|
64
|
+
## [1.0.0-beta.1] - 2026-01-20
|
|
65
|
+
- Initial 1.0 beta release
|
|
66
|
+
```
|
|
67
|
+
<!-- SPDX-SnippetEnd -->
|
|
68
|
+
|
|
69
|
+
Trunk's `[Unreleased]` section accumulates features for the next minor:
|
|
70
|
+
|
|
71
|
+
<!-- SPDX-SnippetBegin -->
|
|
72
|
+
<!--
|
|
73
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
74
|
+
SPDX-License-Identifier: MIT-0
|
|
75
|
+
-->
|
|
76
|
+
```markdown
|
|
77
|
+
## [Unreleased]
|
|
78
|
+
### Added
|
|
79
|
+
- Terminal Capability Detection
|
|
80
|
+
|
|
81
|
+
### Fixed
|
|
82
|
+
- TableState row navigation methods
|
|
83
|
+
```
|
|
84
|
+
<!-- SPDX-SnippetEnd -->
|
|
85
|
+
|
|
86
|
+
The fix appears in both places. This is correct — both branches contain it.
|
|
87
|
+
|
|
88
|
+
### When Final Ships
|
|
89
|
+
|
|
90
|
+
When `1.0.0` final releases, **consolidate** all beta entries into one section
|
|
91
|
+
on both branches:
|
|
92
|
+
|
|
93
|
+
**release/1.0:**
|
|
94
|
+
<!-- SPDX-SnippetBegin -->
|
|
95
|
+
<!--
|
|
96
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
97
|
+
SPDX-License-Identifier: MIT-0
|
|
98
|
+
-->
|
|
99
|
+
```markdown
|
|
100
|
+
## [1.0.0] - 2026-xx-xx
|
|
101
|
+
### Fixed
|
|
102
|
+
- TableState row navigation methods
|
|
103
|
+
|
|
104
|
+
## [0.10.3] - 2026-01-16
|
|
105
|
+
...
|
|
106
|
+
```
|
|
107
|
+
<!-- SPDX-SnippetEnd -->
|
|
108
|
+
|
|
109
|
+
**trunk (synced):**
|
|
110
|
+
<!-- SPDX-SnippetBegin -->
|
|
111
|
+
<!--
|
|
112
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
113
|
+
SPDX-License-Identifier: MIT-0
|
|
114
|
+
-->
|
|
115
|
+
```markdown
|
|
116
|
+
## [Unreleased]
|
|
117
|
+
### Added
|
|
118
|
+
- Terminal Capability Detection
|
|
119
|
+
|
|
120
|
+
## [1.0.0] - 2026-xx-xx
|
|
121
|
+
### Fixed
|
|
122
|
+
- TableState row navigation methods
|
|
123
|
+
|
|
124
|
+
## [0.10.3] - 2026-01-16
|
|
125
|
+
...
|
|
126
|
+
```
|
|
127
|
+
<!-- SPDX-SnippetEnd -->
|
|
128
|
+
|
|
129
|
+
The beta granularity served its purpose during testing. Git tags preserve the
|
|
130
|
+
detailed history.
|
|
131
|
+
|
|
132
|
+
## Release Workflows
|
|
133
|
+
|
|
134
|
+
### Bugfix (Patch) Release
|
|
135
|
+
|
|
136
|
+
For bugs affecting a released version:
|
|
137
|
+
|
|
138
|
+
1. **Fix on trunk first** — All bugs get fixed on trunk.
|
|
139
|
+
2. **Cherry-pick to release branch** with provenance:
|
|
140
|
+
```bash
|
|
141
|
+
git checkout release/1.0
|
|
142
|
+
git cherry-pick -x <commit> # -x adds "cherry picked from" trailer
|
|
143
|
+
```
|
|
144
|
+
3. **Update the changelog** on the release branch.
|
|
145
|
+
4. **Bump and release:**
|
|
146
|
+
```bash
|
|
147
|
+
bundle exec rake bump:patch
|
|
148
|
+
bundle exec rake release
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### New Version (Major/Minor)
|
|
152
|
+
|
|
153
|
+
When trunk is ready for a new release series:
|
|
154
|
+
|
|
155
|
+
1. **Decide version** based on changes:
|
|
156
|
+
- Breaking changes → Major (2.0.0)
|
|
157
|
+
- New features only → Minor (1.1.0)
|
|
158
|
+
|
|
159
|
+
2. **Create release branch:**
|
|
160
|
+
```bash
|
|
161
|
+
git checkout trunk
|
|
162
|
+
git checkout -b release/1.1 # or release/2.0
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
3. **Release from the branch:**
|
|
166
|
+
```bash
|
|
167
|
+
bundle exec rake bump:exact[1.1.0-beta.1]
|
|
168
|
+
bundle exec rake release
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
4. **Bump trunk** to the next dev version if desired.
|
|
172
|
+
|
|
173
|
+
5. **Iterate** through betas/RCs as needed, then ship final.
|
|
174
|
+
|
|
175
|
+
6. **Sync changelog** — When final ships, add the consolidated section to trunk.
|
|
176
|
+
|
|
177
|
+
### Prerelease Notes
|
|
178
|
+
|
|
179
|
+
RubyGems normalizes prerelease versions. Our `rake release` task automatically:
|
|
180
|
+
|
|
181
|
+
1. Lets Bundler create the normalized tag (e.g., `v1.0.0.pre.beta.1`)
|
|
182
|
+
2. Deletes it locally and remotely
|
|
183
|
+
3. Creates the SemVer tag (e.g., `v1.0.0-beta.1`) and pushes it
|
|
184
|
+
|
|
185
|
+
This keeps our Git tags strictly SemVer-compliant.
|
|
186
|
+
|
|
187
|
+
## Commands Reference
|
|
188
|
+
|
|
189
|
+
<!-- SPDX-SnippetBegin -->
|
|
190
|
+
<!--
|
|
191
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
192
|
+
SPDX-License-Identifier: MIT-0
|
|
193
|
+
-->
|
|
194
|
+
```bash
|
|
195
|
+
# Bump version
|
|
196
|
+
bundle exec rake bump:patch # 1.0.0 → 1.0.1
|
|
197
|
+
bundle exec rake bump:minor # 1.0.0 → 1.1.0
|
|
198
|
+
bundle exec rake bump:major # 1.0.0 → 2.0.0
|
|
199
|
+
bundle exec rake bump:exact[1.0.0-beta.1]
|
|
200
|
+
|
|
201
|
+
# Release (builds, tags, pushes gem, updates stable branch)
|
|
202
|
+
bundle exec rake release
|
|
203
|
+
|
|
204
|
+
# Watch builds
|
|
205
|
+
bin/hbs # Wait for SourceHut builds
|
|
206
|
+
bin/hbs && bundle exec rake release # Release only if builds pass
|
|
207
|
+
```
|
|
208
|
+
<!-- SPDX-SnippetEnd -->
|
|
209
|
+
|
|
210
|
+
## Further Reading
|
|
211
|
+
|
|
212
|
+
- [Trunk-Based Development](https://trunkbaseddevelopment.com/)
|
|
213
|
+
- [Branch for Release](https://trunkbaseddevelopment.com/branch-for-release/)
|
|
214
|
+
- [SemVer Specification](https://semver.org/)
|
|
215
|
+
- [Keep a Changelog](https://keepachangelog.com/)
|
|
@@ -62,6 +62,12 @@ These documents catalog EVERY public feature, method, function, enum variant, an
|
|
|
62
62
|
| Direction::Vertical | ratatui-core/src/layout/direction.rs:20 | ✅ |
|
|
63
63
|
| Position struct | ratatui-core/src/layout/position.rs:57 | ✅ |
|
|
64
64
|
| Size struct | ratatui-core/src/layout/size.rs:46 | ✅ |
|
|
65
|
+
| HorizontalAlignment::Left | ratatui-core/src/layout/alignment.rs:25 | ✅ |
|
|
66
|
+
| HorizontalAlignment::Center | ratatui-core/src/layout/alignment.rs:26 | ✅ |
|
|
67
|
+
| HorizontalAlignment::Right | ratatui-core/src/layout/alignment.rs:27 | ✅ |
|
|
68
|
+
| VerticalAlignment::Top | ratatui-core/src/layout/alignment.rs:40 | ✅ |
|
|
69
|
+
| VerticalAlignment::Center | ratatui-core/src/layout/alignment.rs:41 | ✅ |
|
|
70
|
+
| VerticalAlignment::Bottom | ratatui-core/src/layout/alignment.rs:42 | ✅ |
|
|
65
71
|
| Rect struct | ratatui-core/src/layout/rect.rs:134 | ✅ |
|
|
66
72
|
| Rect::new | ratatui-core/src/layout/rect.rs:166 | ✅ |
|
|
67
73
|
| Rect::area | ratatui-core/src/layout/rect.rs:190 | ✅ |
|
|
@@ -29,19 +29,13 @@ These documents catalog EVERY public feature, method, function, enum variant, an
|
|
|
29
29
|
|
|
30
30
|
**Notes:**
|
|
31
31
|
- **Terminal struct**: No direct Terminal object; abstracted behind `RatatuiRuby` module methods
|
|
32
|
-
- **Terminal::get_cursor_position/set_cursor_position**: Only available via [Frame](
|
|
32
|
+
- **Terminal::get_cursor_position/set_cursor_position**: Only available via [Frame](../../../../lib/ratatui_ruby/frame.rb#72-257) during draw, not on Terminal
|
|
33
33
|
|
|
34
34
|
## Layout Features
|
|
35
35
|
|
|
36
36
|
| Feature Name | File/Line | Status |
|
|
37
37
|
|--------------|-----------|--------|
|
|
38
38
|
| Spacing enum | ratatui-core/src/layout/layout.rs:80 | ❌ |
|
|
39
|
-
| HorizontalAlignment::Left | ratatui-core/src/layout/alignment.rs:25 | ❌ |
|
|
40
|
-
| HorizontalAlignment::Center | ratatui-core/src/layout/alignment.rs:26 | ❌ |
|
|
41
|
-
| HorizontalAlignment::Right | ratatui-core/src/layout/alignment.rs:27 | ❌ |
|
|
42
|
-
| VerticalAlignment::Top | ratatui-core/src/layout/alignment.rs:40 | ❌ |
|
|
43
|
-
| VerticalAlignment::Center | ratatui-core/src/layout/alignment.rs:41 | ❌ |
|
|
44
|
-
| VerticalAlignment::Bottom | ratatui-core/src/layout/alignment.rs:42 | ❌ |
|
|
45
39
|
| Offset struct | ratatui-core/src/layout/offset.rs:10 | ❌ |
|
|
46
40
|
| Margin struct | ratatui-core/src/layout/margin.rs:38 | ❌ |
|
|
47
41
|
|