ratatui_ruby 1.0.0 → 1.0.1
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/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/lib/ratatui_ruby/version.rb +1 -1
- metadata +1 -232
- data/.builds/ruby-3.2.yml +0 -54
- data/.builds/ruby-3.3.yml +0 -54
- data/.builds/ruby-3.4.yml +0 -54
- data/.builds/ruby-4.0.0.yml +0 -54
- data/.pre-commit-config.yaml +0 -16
- data/.rubocop.yml +0 -10
- data/AGENTS.md +0 -146
- data/CHANGELOG.md +0 -710
- data/README.md +0 -187
- data/README.rdoc +0 -302
- data/Rakefile +0 -11
- data/Steepfile +0 -49
- data/doc/concepts/application_architecture.md +0 -321
- data/doc/concepts/application_testing.md +0 -193
- data/doc/concepts/async.md +0 -190
- data/doc/concepts/custom_widgets.md +0 -247
- data/doc/concepts/debugging.md +0 -401
- data/doc/concepts/event_handling.md +0 -162
- data/doc/concepts/interactive_design.md +0 -146
- data/doc/contributors/auditing/parity.md +0 -239
- data/doc/contributors/design/ruby_frontend.md +0 -420
- data/doc/contributors/design/rust_backend.md +0 -422
- data/doc/contributors/design.md +0 -11
- data/doc/contributors/developing_examples.md +0 -400
- data/doc/contributors/documentation_style.md +0 -121
- data/doc/contributors/index.md +0 -21
- data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -375
- data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -206
- data/doc/contributors/todo/align/terminal.md +0 -647
- data/doc/contributors/todo/future_work.md +0 -169
- data/doc/contributors/upstream_requests/tab_rects.md +0 -173
- data/doc/contributors/upstream_requests/title_rects.md +0 -132
- data/doc/custom.css +0 -22
- data/doc/getting_started/quickstart.md +0 -291
- data/doc/getting_started/why.md +0 -93
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_cli_rich_moments.gif +0 -0
- data/doc/images/app_color_picker.png +0 -0
- data/doc/images/app_debugging_showcase.gif +0 -0
- data/doc/images/app_debugging_showcase.png +0 -0
- data/doc/images/app_login_form.png +0 -0
- data/doc/images/app_stateful_interaction.png +0 -0
- data/doc/images/verify_quickstart_dsl.png +0 -0
- data/doc/images/verify_quickstart_layout.png +0 -0
- data/doc/images/verify_quickstart_lifecycle.png +0 -0
- data/doc/images/verify_readme_usage.png +0 -0
- data/doc/images/widget_barchart.png +0 -0
- data/doc/images/widget_block.png +0 -0
- data/doc/images/widget_box.png +0 -0
- data/doc/images/widget_calendar.png +0 -0
- data/doc/images/widget_canvas.png +0 -0
- data/doc/images/widget_cell.png +0 -0
- data/doc/images/widget_center.png +0 -0
- data/doc/images/widget_chart.png +0 -0
- data/doc/images/widget_gauge.png +0 -0
- data/doc/images/widget_layout_split.png +0 -0
- data/doc/images/widget_line_gauge.png +0 -0
- data/doc/images/widget_list.png +0 -0
- data/doc/images/widget_map.png +0 -0
- data/doc/images/widget_overlay.png +0 -0
- data/doc/images/widget_popup.png +0 -0
- data/doc/images/widget_ratatui_logo.png +0 -0
- data/doc/images/widget_ratatui_mascot.png +0 -0
- data/doc/images/widget_rect.png +0 -0
- data/doc/images/widget_render.png +0 -0
- data/doc/images/widget_rich_text.png +0 -0
- data/doc/images/widget_scroll_text.png +0 -0
- data/doc/images/widget_scrollbar.png +0 -0
- data/doc/images/widget_sparkline.png +0 -0
- data/doc/images/widget_style_colors.png +0 -0
- data/doc/images/widget_table.png +0 -0
- data/doc/images/widget_tabs.png +0 -0
- data/doc/images/widget_text_width.png +0 -0
- data/doc/index.md +0 -39
- data/doc/troubleshooting/async.md +0 -4
- data/doc/troubleshooting/terminal_limitations.md +0 -131
- data/doc/troubleshooting/tui_output.md +0 -197
- data/examples/app_all_events/README.md +0 -114
- data/examples/app_all_events/app.rb +0 -98
- data/examples/app_all_events/model/app_model.rb +0 -159
- data/examples/app_all_events/model/event_color_cycle.rb +0 -43
- data/examples/app_all_events/model/event_entry.rb +0 -94
- data/examples/app_all_events/model/msg.rb +0 -39
- data/examples/app_all_events/model/timestamp.rb +0 -56
- data/examples/app_all_events/update.rb +0 -75
- data/examples/app_all_events/view/app_view.rb +0 -80
- data/examples/app_all_events/view/controls_view.rb +0 -54
- data/examples/app_all_events/view/counts_view.rb +0 -61
- data/examples/app_all_events/view/live_view.rb +0 -72
- data/examples/app_all_events/view/log_view.rb +0 -57
- data/examples/app_all_events/view.rb +0 -9
- data/examples/app_cli_rich_moments/README.md +0 -81
- data/examples/app_cli_rich_moments/app.rb +0 -189
- data/examples/app_color_picker/README.md +0 -156
- data/examples/app_color_picker/app.rb +0 -76
- data/examples/app_color_picker/clipboard.rb +0 -86
- data/examples/app_color_picker/color.rb +0 -193
- data/examples/app_color_picker/controls.rb +0 -92
- data/examples/app_color_picker/copy_dialog.rb +0 -168
- data/examples/app_color_picker/export_pane.rb +0 -128
- data/examples/app_color_picker/harmony.rb +0 -58
- data/examples/app_color_picker/input.rb +0 -176
- data/examples/app_color_picker/main_container.rb +0 -180
- data/examples/app_color_picker/palette.rb +0 -111
- data/examples/app_debugging_showcase/README.md +0 -119
- data/examples/app_debugging_showcase/app.rb +0 -318
- data/examples/app_login_form/README.md +0 -58
- data/examples/app_login_form/app.rb +0 -109
- data/examples/app_stateful_interaction/README.md +0 -35
- data/examples/app_stateful_interaction/app.rb +0 -328
- data/examples/timeout_demo.rb +0 -45
- data/examples/verify_quickstart_dsl/README.md +0 -55
- data/examples/verify_quickstart_dsl/app.rb +0 -49
- data/examples/verify_quickstart_layout/README.md +0 -77
- data/examples/verify_quickstart_layout/app.rb +0 -73
- data/examples/verify_quickstart_lifecycle/README.md +0 -68
- data/examples/verify_quickstart_lifecycle/app.rb +0 -62
- data/examples/verify_readme_usage/README.md +0 -49
- data/examples/verify_readme_usage/app.rb +0 -42
- data/examples/verify_website_managed/README.md +0 -48
- data/examples/verify_website_managed/app.rb +0 -36
- data/examples/verify_website_menu/README.md +0 -60
- data/examples/verify_website_menu/app.rb +0 -84
- data/examples/verify_website_spinner/README.md +0 -44
- data/examples/verify_website_spinner/app.rb +0 -34
- data/examples/widget_barchart/README.md +0 -58
- data/examples/widget_barchart/app.rb +0 -240
- data/examples/widget_block/README.md +0 -44
- data/examples/widget_block/app.rb +0 -258
- data/examples/widget_box/README.md +0 -54
- data/examples/widget_box/app.rb +0 -255
- data/examples/widget_calendar/README.md +0 -48
- data/examples/widget_calendar/app.rb +0 -115
- data/examples/widget_canvas/README.md +0 -31
- data/examples/widget_canvas/app.rb +0 -130
- data/examples/widget_cell/README.md +0 -45
- data/examples/widget_cell/app.rb +0 -112
- data/examples/widget_center/README.md +0 -33
- data/examples/widget_center/app.rb +0 -118
- data/examples/widget_chart/README.md +0 -50
- data/examples/widget_chart/app.rb +0 -220
- data/examples/widget_gauge/README.md +0 -50
- data/examples/widget_gauge/app.rb +0 -229
- data/examples/widget_layout_split/README.md +0 -53
- data/examples/widget_layout_split/app.rb +0 -260
- data/examples/widget_line_gauge/README.md +0 -50
- data/examples/widget_line_gauge/app.rb +0 -219
- data/examples/widget_list/README.md +0 -58
- data/examples/widget_list/app.rb +0 -384
- data/examples/widget_map/README.md +0 -48
- data/examples/widget_map/app.rb +0 -95
- data/examples/widget_overlay/README.md +0 -45
- data/examples/widget_overlay/app.rb +0 -250
- data/examples/widget_popup/README.md +0 -45
- data/examples/widget_popup/app.rb +0 -106
- data/examples/widget_ratatui_logo/README.md +0 -43
- data/examples/widget_ratatui_logo/app.rb +0 -104
- data/examples/widget_ratatui_mascot/README.md +0 -43
- data/examples/widget_ratatui_mascot/app.rb +0 -95
- data/examples/widget_rect/README.md +0 -53
- data/examples/widget_rect/app.rb +0 -222
- data/examples/widget_render/README.md +0 -46
- data/examples/widget_render/app.rb +0 -186
- data/examples/widget_render/app.rbs +0 -41
- data/examples/widget_rich_text/README.md +0 -44
- data/examples/widget_rich_text/app.rb +0 -193
- data/examples/widget_scroll_text/README.md +0 -46
- data/examples/widget_scroll_text/app.rb +0 -109
- data/examples/widget_scrollbar/README.md +0 -46
- data/examples/widget_scrollbar/app.rb +0 -155
- data/examples/widget_sparkline/README.md +0 -51
- data/examples/widget_sparkline/app.rb +0 -277
- data/examples/widget_style_colors/README.md +0 -43
- data/examples/widget_style_colors/app.rb +0 -83
- data/examples/widget_table/README.md +0 -57
- data/examples/widget_table/app.rb +0 -279
- data/examples/widget_tabs/README.md +0 -50
- data/examples/widget_tabs/app.rb +0 -183
- data/examples/widget_text_width/README.md +0 -44
- data/examples/widget_text_width/app.rb +0 -117
- data/migrate_to_buffer.rb +0 -145
- data/mise.toml +0 -8
- data/tasks/autodoc/examples.rb +0 -87
- data/tasks/autodoc/member.rb +0 -58
- data/tasks/autodoc/name.rb +0 -21
- data/tasks/autodoc.rake +0 -21
- data/tasks/bump/cargo_lockfile.rb +0 -21
- data/tasks/bump/changelog.rb +0 -47
- data/tasks/bump/header.rb +0 -32
- data/tasks/bump/history.rb +0 -32
- data/tasks/bump/links.rb +0 -69
- data/tasks/bump/manifest.rb +0 -33
- data/tasks/bump/ruby_gem.rb +0 -49
- data/tasks/bump/sem_ver.rb +0 -40
- data/tasks/bump/unreleased_section.rb +0 -56
- data/tasks/bump.rake +0 -51
- data/tasks/doc.rake +0 -887
- data/tasks/example_viewer.html.erb +0 -172
- data/tasks/extension.rake +0 -14
- data/tasks/license/headers_md.rb +0 -223
- data/tasks/license/headers_rb.rb +0 -210
- data/tasks/license/license_utils.rb +0 -130
- data/tasks/license/snippets_md.rb +0 -315
- data/tasks/license/snippets_rdoc.rb +0 -150
- data/tasks/license.rake +0 -91
- data/tasks/lint.rake +0 -170
- data/tasks/rdoc_config.rb +0 -29
- data/tasks/resources/build.yml.erb +0 -60
- data/tasks/resources/index.html.erb +0 -141
- data/tasks/resources/rubies.yml +0 -7
- data/tasks/sourcehut.rake +0 -110
- data/tasks/steep.rake +0 -11
- data/tasks/terminal_preview/app_screenshot.rb +0 -45
- data/tasks/terminal_preview/crash_report.rb +0 -54
- data/tasks/terminal_preview/example_app.rb +0 -27
- data/tasks/terminal_preview/launcher_script.rb +0 -48
- data/tasks/terminal_preview/preview_collection.rb +0 -60
- data/tasks/terminal_preview/preview_timing.rb +0 -24
- data/tasks/terminal_preview/safety_confirmation.rb +0 -58
- data/tasks/terminal_preview/saved_screenshot.rb +0 -56
- data/tasks/terminal_preview/system_appearance.rb +0 -13
- data/tasks/terminal_preview/terminal_window.rb +0 -138
- data/tasks/terminal_preview/window_id.rb +0 -16
- data/tasks/terminal_preview.rake +0 -30
- data/tasks/test.rake +0 -33
- data/tasks/website/index_page.rb +0 -30
- data/tasks/website/version.rb +0 -127
- data/tasks/website/version_menu.rb +0 -68
- data/tasks/website/versioned_documentation.rb +0 -83
- data/tasks/website/website.rb +0 -53
- data/tasks/website.rake +0 -28
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: MIT-0
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
9
|
-
|
|
10
|
-
require "ratatui_ruby"
|
|
11
|
-
|
|
12
|
-
class VerifyQuickstartLifecycle
|
|
13
|
-
def run
|
|
14
|
-
# [SYNC:START:main]
|
|
15
|
-
# 1. Initialize the terminal
|
|
16
|
-
RatatuiRuby.init_terminal
|
|
17
|
-
|
|
18
|
-
begin
|
|
19
|
-
# The Main Loop
|
|
20
|
-
loop do
|
|
21
|
-
# 2. Create your UI (Immediate Mode)
|
|
22
|
-
# We define a Paragraph widget inside a Block with a title and borders.
|
|
23
|
-
view = RatatuiRuby::Widgets::Paragraph.new(
|
|
24
|
-
text: "Hello, Ratatui! Press 'q' to quit.",
|
|
25
|
-
alignment: :center,
|
|
26
|
-
block: RatatuiRuby::Widgets::Block.new(
|
|
27
|
-
title: "My Ruby TUI App",
|
|
28
|
-
title_alignment: :center,
|
|
29
|
-
borders: [:all],
|
|
30
|
-
border_style: { fg: "cyan" },
|
|
31
|
-
style: { fg: "white" }
|
|
32
|
-
)
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
# 3. Draw the UI
|
|
36
|
-
RatatuiRuby.draw do |frame|
|
|
37
|
-
frame.render_widget(view, frame.area)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# 4. Poll for events
|
|
41
|
-
case RatatuiRuby.poll_event
|
|
42
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
43
|
-
break
|
|
44
|
-
else
|
|
45
|
-
nil
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# 5. Guard against accidental output (optional but recommended)
|
|
49
|
-
# Wrap any code that might puts/warn to prevent screen corruption.
|
|
50
|
-
RatatuiRuby.guard_io do
|
|
51
|
-
# SomeChattyGem.do_something
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
ensure
|
|
55
|
-
# 6. Restore the terminal to its original state
|
|
56
|
-
RatatuiRuby.restore_terminal
|
|
57
|
-
end
|
|
58
|
-
# [SYNC:END:main]
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
VerifyQuickstartLifecycle.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# README Usage Verification
|
|
7
|
-
|
|
8
|
-
Verifies the primary usage example in the project [README](../../README.md#usage).
|
|
9
|
-
|
|
10
|
-
This example exists as a documentation regression test. It ensures that the very first code snippet a user sees actually works.
|
|
11
|
-
|
|
12
|
-
## Usage
|
|
13
|
-
|
|
14
|
-
<!-- SPDX-SnippetBegin -->
|
|
15
|
-
<!--
|
|
16
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
17
|
-
SPDX-License-Identifier: MIT-0
|
|
18
|
-
-->
|
|
19
|
-
<!-- SYNC:START:app.rb:main -->
|
|
20
|
-
```ruby
|
|
21
|
-
RatatuiRuby.run do |tui|
|
|
22
|
-
loop do
|
|
23
|
-
tui.draw do |frame|
|
|
24
|
-
frame.render_widget(
|
|
25
|
-
tui.paragraph(
|
|
26
|
-
text: "Hello, Ratatui! Press 'q' to quit.",
|
|
27
|
-
alignment: :center,
|
|
28
|
-
block: tui.block(
|
|
29
|
-
title: "My Ruby TUI App",
|
|
30
|
-
borders: [:all],
|
|
31
|
-
border_color: "cyan"
|
|
32
|
-
)
|
|
33
|
-
),
|
|
34
|
-
frame.area
|
|
35
|
-
)
|
|
36
|
-
end
|
|
37
|
-
case tui.poll_event
|
|
38
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
39
|
-
break
|
|
40
|
-
else
|
|
41
|
-
nil
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
```
|
|
46
|
-
<!-- SYNC:END -->
|
|
47
|
-
<!-- SPDX-SnippetEnd -->
|
|
48
|
-
|
|
49
|
-
[](../../README.md#usage)
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: MIT-0
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
9
|
-
|
|
10
|
-
require "ratatui_ruby"
|
|
11
|
-
class VerifyReadmeUsage
|
|
12
|
-
def run
|
|
13
|
-
# [SYNC:START:main]
|
|
14
|
-
RatatuiRuby.run do |tui|
|
|
15
|
-
loop do
|
|
16
|
-
tui.draw do |frame|
|
|
17
|
-
frame.render_widget(
|
|
18
|
-
tui.paragraph(
|
|
19
|
-
text: "Hello, Ratatui! Press 'q' to quit.",
|
|
20
|
-
alignment: :center,
|
|
21
|
-
block: tui.block(
|
|
22
|
-
title: "My Ruby TUI App",
|
|
23
|
-
borders: [:all],
|
|
24
|
-
border_style: { fg: "cyan" }
|
|
25
|
-
)
|
|
26
|
-
),
|
|
27
|
-
frame.area
|
|
28
|
-
)
|
|
29
|
-
end
|
|
30
|
-
case tui.poll_event
|
|
31
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
32
|
-
break
|
|
33
|
-
else
|
|
34
|
-
nil
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
# [SYNC:END:main]
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
VerifyReadmeUsage.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Website Managed Loop Verification
|
|
7
|
-
|
|
8
|
-
Verifies the full-screen managed loop example on the [RatatuiRuby website](https://ratatui-ruby.dev).
|
|
9
|
-
|
|
10
|
-
This example exists as a documentation regression test. It ensures the website's "Build Something Real" managed loop demo remains functional.
|
|
11
|
-
|
|
12
|
-
## Usage
|
|
13
|
-
|
|
14
|
-
```ruby
|
|
15
|
-
RatatuiRuby.run do |tui|
|
|
16
|
-
loop do
|
|
17
|
-
tui.draw do |frame|
|
|
18
|
-
frame.render_widget(
|
|
19
|
-
tui.paragraph(
|
|
20
|
-
text: "Hello, RatatuiRuby!",
|
|
21
|
-
alignment: :center,
|
|
22
|
-
block: tui.block(
|
|
23
|
-
title: "My App",
|
|
24
|
-
titles: [{ content: "q: Quit", position: :bottom, alignment: :right }],
|
|
25
|
-
borders: [:all],
|
|
26
|
-
border_style: { fg: "cyan" }
|
|
27
|
-
)
|
|
28
|
-
),
|
|
29
|
-
frame.area
|
|
30
|
-
)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
case tui.poll_event
|
|
34
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
35
|
-
break
|
|
36
|
-
else nil
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Features Demonstrated
|
|
43
|
-
|
|
44
|
-
- **Full-screen mode**: Alternate screen with automatic terminal restoration
|
|
45
|
-
- **Managed lifecycle**: `RatatuiRuby.run` handles setup/teardown
|
|
46
|
-
- **Block with titles**: Top title and bottom key hints
|
|
47
|
-
- **Keyboard handling**: `q` and `Ctrl+C` to quit
|
|
48
|
-
- **Pattern matching**: Ruby 3.x pattern matching for event handling
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
#
|
|
6
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
7
|
-
#++
|
|
8
|
-
|
|
9
|
-
# Test 3: Managed loop example
|
|
10
|
-
require "ratatui_ruby"
|
|
11
|
-
|
|
12
|
-
RatatuiRuby.run do |tui|
|
|
13
|
-
loop do
|
|
14
|
-
tui.draw do |frame|
|
|
15
|
-
frame.render_widget(
|
|
16
|
-
tui.paragraph(
|
|
17
|
-
text: "Hello, RatatuiRuby!",
|
|
18
|
-
alignment: :center,
|
|
19
|
-
block: tui.block(
|
|
20
|
-
title: "My App",
|
|
21
|
-
titles: [{ content: "q: Quit", position: :bottom, alignment: :right }],
|
|
22
|
-
borders: [:all],
|
|
23
|
-
border_style: { fg: "cyan" }
|
|
24
|
-
)
|
|
25
|
-
),
|
|
26
|
-
frame.area
|
|
27
|
-
)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
case tui.poll_event
|
|
31
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
32
|
-
break
|
|
33
|
-
else nil
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Website Menu Verification
|
|
7
|
-
|
|
8
|
-
Verifies the inline menu example on the [RatatuiRuby website](https://ratatui-ruby.dev).
|
|
9
|
-
|
|
10
|
-
This example exists as a documentation regression test. It ensures the website's inline viewport menu demo remains functional.
|
|
11
|
-
|
|
12
|
-
## Usage
|
|
13
|
-
|
|
14
|
-
```ruby
|
|
15
|
-
choices = ["Production", "Staging", "Development"]
|
|
16
|
-
index = 0
|
|
17
|
-
|
|
18
|
-
RatatuiRuby.run(viewport: :inline, height: 5) do |tui|
|
|
19
|
-
loop do
|
|
20
|
-
tui.draw do |frame|
|
|
21
|
-
items = choices.map.with_index do |c, i|
|
|
22
|
-
prefix = i == index ? "● " : "○ "
|
|
23
|
-
"#{prefix}#{c}"
|
|
24
|
-
end
|
|
25
|
-
widget = tui.paragraph(
|
|
26
|
-
text: items.join("\n"),
|
|
27
|
-
block: tui.block(
|
|
28
|
-
borders: :all,
|
|
29
|
-
title: "Select Environment",
|
|
30
|
-
titles: [{ content: "↑/↓ Enter | Ctrl+C", position: :bottom, alignment: :right }]
|
|
31
|
-
)
|
|
32
|
-
)
|
|
33
|
-
frame.render_widget(widget, frame.area)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
case tui.poll_event
|
|
37
|
-
in { type: :key, code: "up" }
|
|
38
|
-
index = (index - 1) % choices.size
|
|
39
|
-
in { type: :key, code: "down" }
|
|
40
|
-
index = (index + 1) % choices.size
|
|
41
|
-
in { type: :key, code: "enter" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
42
|
-
area = tui.viewport_area
|
|
43
|
-
RatatuiRuby.cursor_position = [0, area.y + area.height]
|
|
44
|
-
break
|
|
45
|
-
else nil
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
puts
|
|
51
|
-
puts "Deploying to #{choices[index]}..."
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Features Demonstrated
|
|
55
|
-
|
|
56
|
-
- **Inline viewport**: 5-line viewport with bordered menu
|
|
57
|
-
- **Keyboard navigation**: Arrow keys for selection, Enter to confirm
|
|
58
|
-
- **Ctrl+C handling**: Graceful exit on cancellation
|
|
59
|
-
- **Bottom title**: Key hints rendered on the bottom border
|
|
60
|
-
- **Cursor positioning**: Proper cursor placement after inline viewport exit
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
# rubocop:disable all
|
|
3
|
-
|
|
4
|
-
#--
|
|
5
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
6
|
-
#
|
|
7
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
8
|
-
#++
|
|
9
|
-
|
|
10
|
-
require "ratatui_ruby"
|
|
11
|
-
|
|
12
|
-
# This example renders an inline menu. Arrow keys select, enter confirms.
|
|
13
|
-
# The menu appears in-place, preserving scrollback. When the user chooses,
|
|
14
|
-
# the TUI closes and the script continues with the selected value.
|
|
15
|
-
class RadioMenu
|
|
16
|
-
CHOICES = ["Production", "Staging", "Development"] # ASCII strings are universally supported.
|
|
17
|
-
PREFIXES = { active: "●", inactive: "○" } # Some terminals may not support Unicode.
|
|
18
|
-
CONTROLS = "↑/↓: Select | Enter: Choose | Ctrl+C: Cancel" # Let users know what keys you handle.
|
|
19
|
-
TITLES = ["Select Environment", # The default title position is top left.
|
|
20
|
-
{ content: CONTROLS, # Multiple titles can save space.
|
|
21
|
-
position: :bottom, # Titles go on the top or bottom,
|
|
22
|
-
alignment: :right }] # aligned left, right, or center
|
|
23
|
-
|
|
24
|
-
def call # This method blocks until a choice is made.
|
|
25
|
-
RatatuiRuby.run(viewport: :inline, height: 5) do |tui| # RatauiRuby.run manages the terminal.
|
|
26
|
-
@tui = tui # The TUI instance is safe to store.
|
|
27
|
-
show_menu until chosen? # You can use any loop keyword you like.
|
|
28
|
-
end # `run` won't return until your block does,
|
|
29
|
-
RadioMenu::CHOICES[@choice] # so you can use it synchronously.
|
|
30
|
-
end
|
|
31
|
-
# Classes like RadioMenu are convenient for
|
|
32
|
-
private # CLI authors to offer "rich moments."
|
|
33
|
-
|
|
34
|
-
def show_menu = @tui.draw do |frame| # RatatuiRuby gives you low-level access.
|
|
35
|
-
widget = @tui.paragraph( # But the TUI facade makes it easy to use.
|
|
36
|
-
text: menu_items, # Text can be spans, lines, or paragraphs.
|
|
37
|
-
block: @tui.block(borders: :all, titles: TITLES) # Blocks give you boxes and titles, and hold
|
|
38
|
-
) # one or more widgets. We only use one here,
|
|
39
|
-
frame.render_widget(widget, frame.area) # but "area" lets you compose sub-views.
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def chosen? # You are responsible for handling input.
|
|
43
|
-
interaction = @tui.poll_event # Every frame, you receive an event object:
|
|
44
|
-
return choose if interaction.enter? # Key, Mouse, Resize, Paste, FocusGained,
|
|
45
|
-
# FocusLost, or None objects. They come with
|
|
46
|
-
move_by(-1) if interaction.up? # predicates, support pattern matching, and
|
|
47
|
-
move_by(1) if interaction.down? # can be inspected for properties directly.
|
|
48
|
-
quit! if interaction.ctrl_c? # Your application must handle every input,
|
|
49
|
-
false # even interrupts and other exit patterns.
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def choose # Here, the loop is about to exit, and the
|
|
53
|
-
prepare_next_line # block will return. The inline viewport
|
|
54
|
-
@choice # will be torn down and the terminal will
|
|
55
|
-
end # be restored, but you are responsible for
|
|
56
|
-
# positioning the cursor.
|
|
57
|
-
def prepare_next_line # To ensure the next output is on a new
|
|
58
|
-
area = @tui.viewport_area # line, query the viewport area and move
|
|
59
|
-
RatatuiRuby.cursor_position = [0, area.y + area.height] # the cursor to the start of the last line.
|
|
60
|
-
puts # Then print a newline.
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def quit! # All of your familiar Ruby control flow
|
|
64
|
-
prepare_next_line # keywords work as expected, so we can
|
|
65
|
-
exit 0 # use them to leave the TUI.
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def move_by(line_count) # You are in full control of your UX, so
|
|
69
|
-
@choice = (@choice + line_count) % CHOICES.size # you can implement any logic you need:
|
|
70
|
-
end # Would you "wrap around" here, or not?
|
|
71
|
-
#
|
|
72
|
-
def menu_items = CHOICES.map.with_index do |choice, i| # Notably, RatatuiRuby has no concept of
|
|
73
|
-
"#{prefix_for(i)} #{choice}" # "menus" or "radio buttons". You are in
|
|
74
|
-
end # full control, but it also means you must
|
|
75
|
-
def prefix_for(choice_index) # implement the logic yourself. For larger
|
|
76
|
-
return PREFIXES[:active] if choice_index == @choice # applications, consider using Rooibos,
|
|
77
|
-
PREFIXES[:inactive] # an MVU framework built with RatatuiRuby.
|
|
78
|
-
end # Or, use the upcoming ratatui-ruby-kit,
|
|
79
|
-
# our object-oriented component library.
|
|
80
|
-
def initialize = @choice = 0 # However, those are both optional, and
|
|
81
|
-
end # designed for full-screen Terminal UIs.
|
|
82
|
-
# RatatuiRuby will always give you the most
|
|
83
|
-
choice = RadioMenu.new.call # control, and is enough for "rich CLI
|
|
84
|
-
puts "You chose #{choice}!" # moments" like this one.
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Website Spinner Verification
|
|
7
|
-
|
|
8
|
-
Verifies the inline spinner example on the [RatatuiRuby website](https://ratatui-ruby.dev).
|
|
9
|
-
|
|
10
|
-
This example exists as a documentation regression test. It ensures the website's inline viewport spinner demo remains functional.
|
|
11
|
-
|
|
12
|
-
## Usage
|
|
13
|
-
|
|
14
|
-
```ruby
|
|
15
|
-
class Spinner
|
|
16
|
-
def main
|
|
17
|
-
RatatuiRuby.run(viewport: :inline, height: 1) do |tui|
|
|
18
|
-
until connected?
|
|
19
|
-
status = tui.paragraph(text: "#{spin} Connecting...")
|
|
20
|
-
tui.draw { |frame| frame.render_widget(status, frame.area) }
|
|
21
|
-
return ending(tui, "Canceled!", :red) if tui.poll_event.ctrl_c?
|
|
22
|
-
end
|
|
23
|
-
ending(tui, "Connected!", :green)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def ending(tui, message, color) = tui.draw do |frame|
|
|
28
|
-
frame.render_widget(tui.paragraph(text: message, fg: color), frame.area)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def initialize = (@i, @end = 0, Time.now + 2)
|
|
32
|
-
def connected? = Time.now >= @end
|
|
33
|
-
def spin = SPINNER[(@i += 1) % SPINNER.length]
|
|
34
|
-
SPINNER = %w[⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏]
|
|
35
|
-
end
|
|
36
|
-
Spinner.new.main; puts
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Features Demonstrated
|
|
40
|
-
|
|
41
|
-
- **Inline viewport**: 1-line viewport that preserves terminal scrollback
|
|
42
|
-
- **Ctrl+C handling**: Graceful cancellation with `poll_event.ctrl_c?`
|
|
43
|
-
- **Colored output**: Status messages with `:red` and `:green` colors
|
|
44
|
-
- **Timeout pattern**: Uses `Time.now` for connection simulation
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
#
|
|
6
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
7
|
-
#++
|
|
8
|
-
|
|
9
|
-
# Test 1: Inline spinner example
|
|
10
|
-
require "ratatui_ruby"
|
|
11
|
-
|
|
12
|
-
class Spinner
|
|
13
|
-
def main
|
|
14
|
-
RatatuiRuby.run(viewport: :inline, height: 1) do |tui|
|
|
15
|
-
until connected?
|
|
16
|
-
status = tui.paragraph(text: "#{spin} Connecting...")
|
|
17
|
-
tui.draw { |frame| frame.render_widget(status, frame.area) }
|
|
18
|
-
return ending(tui, "Canceled!", :red) if tui.poll_event.ctrl_c?
|
|
19
|
-
end
|
|
20
|
-
ending(tui, "Connected!", :green)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def ending(tui, text, fg) = tui.draw do |frame|
|
|
25
|
-
frame.render_widget(tui.paragraph(text:, fg:), frame.area)
|
|
26
|
-
puts # Prepare a new line for the shell prompt
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def initialize = (@frame, @finish = 0, Time.now + 2)
|
|
30
|
-
def connected? = Time.now >= @finish # Simulate work
|
|
31
|
-
def spin = SPINNER[(@frame += 1) % SPINNER.length]
|
|
32
|
-
SPINNER = %w[⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏]
|
|
33
|
-
end
|
|
34
|
-
Spinner.new.main
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# BarChart (Bar, BarGroup) Example
|
|
7
|
-
|
|
8
|
-
[](app.rb)
|
|
9
|
-
|
|
10
|
-
Visualizes categorical data with interactive attribute cycling.
|
|
11
|
-
|
|
12
|
-
Comparing magnitudes in raw tables requires mental arithmetic. Bar charts make these comparisons instant and intuitive.
|
|
13
|
-
|
|
14
|
-
## Features Demonstrated
|
|
15
|
-
|
|
16
|
-
- **Data Formats**: Supports simple Hashes, Arrays with individual styles, and Groups (stacked/grouped bars).
|
|
17
|
-
- **Orientation**: Switch between Vertical and Horizontal layouts.
|
|
18
|
-
- **Customization**:
|
|
19
|
-
- Adjustable bar widths and gaps.
|
|
20
|
-
- Custom characters for bars (ASCII art support).
|
|
21
|
-
- Detailed styling for labels and values.
|
|
22
|
-
- **Mini Mode**: Compact rendering for dashboard widgets.
|
|
23
|
-
|
|
24
|
-
## Hotkeys
|
|
25
|
-
|
|
26
|
-
- **d**: Cycle Data Source (`data`)
|
|
27
|
-
- **v**: Toggle Direction (`direction`)
|
|
28
|
-
- **w**: Adjust Bar Width (`bar_width`)
|
|
29
|
-
- **a**: Adjust Bar Gap (`bar_gap`)
|
|
30
|
-
- **g**: Adjust Group Gap (`group_gap`)
|
|
31
|
-
- **b**: Cycle Bar Character Set (`bar_set`)
|
|
32
|
-
- **s**: Cycle Chart Style (`style`)
|
|
33
|
-
- **x**: Cycle Label Style (`label_style`)
|
|
34
|
-
- **z**: Cycle Value Style (`value_style`)
|
|
35
|
-
- **m**: Toggle Mini Mode (Compact View)
|
|
36
|
-
- **q**: Quit
|
|
37
|
-
|
|
38
|
-
## Usage
|
|
39
|
-
|
|
40
|
-
<!-- SPDX-SnippetBegin -->
|
|
41
|
-
<!--
|
|
42
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
43
|
-
SPDX-License-Identifier: MIT-0
|
|
44
|
-
-->
|
|
45
|
-
```bash
|
|
46
|
-
ruby examples/widget_barchart/app.rb
|
|
47
|
-
```
|
|
48
|
-
<!-- SPDX-SnippetEnd -->
|
|
49
|
-
|
|
50
|
-
## Learning Outcomes
|
|
51
|
-
|
|
52
|
-
Use this example if you need to...
|
|
53
|
-
|
|
54
|
-
- Visualize categorical data (e.g., sales by quarter, CPU usage by core).
|
|
55
|
-
- Create "stats" dashboards with compact visualizations.
|
|
56
|
-
- Understand how `RatatuiRuby::BarChart` handles different data structures.
|
|
57
|
-
|
|
58
|
-
[Read the source code →](app.rb)
|