ratatui_ruby 1.1.0 → 1.1.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.
Files changed (259) hide show
  1. checksums.yaml +4 -4
  2. data/ext/ratatui_ruby/Cargo.lock +1 -1
  3. data/ext/ratatui_ruby/Cargo.toml +1 -1
  4. data/lib/ratatui_ruby/version.rb +1 -1
  5. metadata +1 -255
  6. data/.builds/ruby-3.2.yml +0 -54
  7. data/.builds/ruby-3.3.yml +0 -54
  8. data/.builds/ruby-3.4.yml +0 -54
  9. data/.builds/ruby-4.0.0.yml +0 -54
  10. data/.pre-commit-config.yaml +0 -16
  11. data/.rubocop.yml +0 -10
  12. data/AGENTS.md +0 -147
  13. data/CHANGELOG.md +0 -736
  14. data/README.md +0 -187
  15. data/README.rdoc +0 -302
  16. data/Rakefile +0 -11
  17. data/Steepfile +0 -50
  18. data/doc/concepts/application_architecture.md +0 -321
  19. data/doc/concepts/application_testing.md +0 -193
  20. data/doc/concepts/async.md +0 -190
  21. data/doc/concepts/custom_widgets.md +0 -247
  22. data/doc/concepts/debugging.md +0 -401
  23. data/doc/concepts/event_handling.md +0 -162
  24. data/doc/concepts/interactive_design.md +0 -146
  25. data/doc/contributors/auditing/parity.md +0 -239
  26. data/doc/contributors/design/ruby_frontend.md +0 -448
  27. data/doc/contributors/design/rust_backend.md +0 -434
  28. data/doc/contributors/design.md +0 -11
  29. data/doc/contributors/developing_examples.md +0 -400
  30. data/doc/contributors/documentation_style.md +0 -121
  31. data/doc/contributors/index.md +0 -21
  32. data/doc/contributors/releasing.md +0 -215
  33. data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -381
  34. data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -200
  35. data/doc/contributors/todo/align/term.md +0 -351
  36. data/doc/contributors/todo/align/terminal.md +0 -647
  37. data/doc/contributors/todo/future_work.md +0 -169
  38. data/doc/contributors/upstream_requests/paragraph_span_rects.md +0 -259
  39. data/doc/contributors/upstream_requests/tab_rects.md +0 -173
  40. data/doc/contributors/upstream_requests/title_rects.md +0 -132
  41. data/doc/custom.css +0 -22
  42. data/doc/getting_started/quickstart.md +0 -291
  43. data/doc/getting_started/why.md +0 -93
  44. data/doc/images/app_all_events.png +0 -0
  45. data/doc/images/app_cli_rich_moments.gif +0 -0
  46. data/doc/images/app_color_picker.png +0 -0
  47. data/doc/images/app_debugging_showcase.gif +0 -0
  48. data/doc/images/app_debugging_showcase.png +0 -0
  49. data/doc/images/app_external_editor.gif +0 -0
  50. data/doc/images/app_login_form.png +0 -0
  51. data/doc/images/app_stateful_interaction.png +0 -0
  52. data/doc/images/verify_quickstart_dsl.png +0 -0
  53. data/doc/images/verify_quickstart_layout.png +0 -0
  54. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  55. data/doc/images/verify_readme_usage.png +0 -0
  56. data/doc/images/widget_barchart.png +0 -0
  57. data/doc/images/widget_block.png +0 -0
  58. data/doc/images/widget_box.png +0 -0
  59. data/doc/images/widget_calendar.png +0 -0
  60. data/doc/images/widget_canvas.png +0 -0
  61. data/doc/images/widget_cell.png +0 -0
  62. data/doc/images/widget_center.png +0 -0
  63. data/doc/images/widget_chart.png +0 -0
  64. data/doc/images/widget_gauge.png +0 -0
  65. data/doc/images/widget_layout_split.png +0 -0
  66. data/doc/images/widget_line_gauge.png +0 -0
  67. data/doc/images/widget_list.png +0 -0
  68. data/doc/images/widget_map.png +0 -0
  69. data/doc/images/widget_overlay.png +0 -0
  70. data/doc/images/widget_popup.png +0 -0
  71. data/doc/images/widget_ratatui_logo.png +0 -0
  72. data/doc/images/widget_ratatui_mascot.png +0 -0
  73. data/doc/images/widget_rect.png +0 -0
  74. data/doc/images/widget_render.png +0 -0
  75. data/doc/images/widget_rich_text.png +0 -0
  76. data/doc/images/widget_scroll_text.png +0 -0
  77. data/doc/images/widget_scrollbar.png +0 -0
  78. data/doc/images/widget_sparkline.png +0 -0
  79. data/doc/images/widget_style_colors.png +0 -0
  80. data/doc/images/widget_table.png +0 -0
  81. data/doc/images/widget_tabs.png +0 -0
  82. data/doc/images/widget_text_width.png +0 -0
  83. data/doc/index.md +0 -34
  84. data/doc/troubleshooting/async.md +0 -4
  85. data/doc/troubleshooting/terminal_limitations.md +0 -131
  86. data/doc/troubleshooting/tui_output.md +0 -197
  87. data/examples/app_all_events/README.md +0 -114
  88. data/examples/app_all_events/app.rb +0 -98
  89. data/examples/app_all_events/model/app_model.rb +0 -159
  90. data/examples/app_all_events/model/event_color_cycle.rb +0 -43
  91. data/examples/app_all_events/model/event_entry.rb +0 -94
  92. data/examples/app_all_events/model/msg.rb +0 -39
  93. data/examples/app_all_events/model/timestamp.rb +0 -56
  94. data/examples/app_all_events/update.rb +0 -75
  95. data/examples/app_all_events/view/app_view.rb +0 -80
  96. data/examples/app_all_events/view/controls_view.rb +0 -54
  97. data/examples/app_all_events/view/counts_view.rb +0 -61
  98. data/examples/app_all_events/view/live_view.rb +0 -72
  99. data/examples/app_all_events/view/log_view.rb +0 -57
  100. data/examples/app_all_events/view.rb +0 -9
  101. data/examples/app_cli_rich_moments/README.md +0 -81
  102. data/examples/app_cli_rich_moments/app.rb +0 -189
  103. data/examples/app_color_picker/README.md +0 -156
  104. data/examples/app_color_picker/app.rb +0 -76
  105. data/examples/app_color_picker/clipboard.rb +0 -86
  106. data/examples/app_color_picker/color.rb +0 -193
  107. data/examples/app_color_picker/controls.rb +0 -92
  108. data/examples/app_color_picker/copy_dialog.rb +0 -168
  109. data/examples/app_color_picker/export_pane.rb +0 -128
  110. data/examples/app_color_picker/harmony.rb +0 -58
  111. data/examples/app_color_picker/input.rb +0 -176
  112. data/examples/app_color_picker/main_container.rb +0 -180
  113. data/examples/app_color_picker/palette.rb +0 -111
  114. data/examples/app_debugging_showcase/README.md +0 -119
  115. data/examples/app_debugging_showcase/app.rb +0 -318
  116. data/examples/app_external_editor/README.md +0 -62
  117. data/examples/app_external_editor/app.rb +0 -344
  118. data/examples/app_login_form/README.md +0 -58
  119. data/examples/app_login_form/app.rb +0 -109
  120. data/examples/app_stateful_interaction/README.md +0 -35
  121. data/examples/app_stateful_interaction/app.rb +0 -328
  122. data/examples/timeout_demo.rb +0 -45
  123. data/examples/verify_quickstart_dsl/README.md +0 -55
  124. data/examples/verify_quickstart_dsl/app.rb +0 -49
  125. data/examples/verify_quickstart_layout/README.md +0 -77
  126. data/examples/verify_quickstart_layout/app.rb +0 -73
  127. data/examples/verify_quickstart_lifecycle/README.md +0 -68
  128. data/examples/verify_quickstart_lifecycle/app.rb +0 -62
  129. data/examples/verify_readme_usage/README.md +0 -49
  130. data/examples/verify_readme_usage/app.rb +0 -42
  131. data/examples/verify_website_managed/README.md +0 -48
  132. data/examples/verify_website_managed/app.rb +0 -36
  133. data/examples/verify_website_menu/README.md +0 -60
  134. data/examples/verify_website_menu/app.rb +0 -84
  135. data/examples/verify_website_spinner/README.md +0 -44
  136. data/examples/verify_website_spinner/app.rb +0 -34
  137. data/examples/widget_barchart/README.md +0 -58
  138. data/examples/widget_barchart/app.rb +0 -240
  139. data/examples/widget_block/README.md +0 -44
  140. data/examples/widget_block/app.rb +0 -258
  141. data/examples/widget_box/README.md +0 -54
  142. data/examples/widget_box/app.rb +0 -255
  143. data/examples/widget_calendar/README.md +0 -48
  144. data/examples/widget_calendar/app.rb +0 -115
  145. data/examples/widget_canvas/README.md +0 -31
  146. data/examples/widget_canvas/app.rb +0 -130
  147. data/examples/widget_cell/README.md +0 -45
  148. data/examples/widget_cell/app.rb +0 -112
  149. data/examples/widget_center/README.md +0 -33
  150. data/examples/widget_center/app.rb +0 -118
  151. data/examples/widget_chart/README.md +0 -50
  152. data/examples/widget_chart/app.rb +0 -220
  153. data/examples/widget_gauge/README.md +0 -50
  154. data/examples/widget_gauge/app.rb +0 -229
  155. data/examples/widget_layout_split/README.md +0 -53
  156. data/examples/widget_layout_split/app.rb +0 -260
  157. data/examples/widget_line_gauge/README.md +0 -50
  158. data/examples/widget_line_gauge/app.rb +0 -219
  159. data/examples/widget_list/README.md +0 -58
  160. data/examples/widget_list/app.rb +0 -382
  161. data/examples/widget_map/README.md +0 -48
  162. data/examples/widget_map/app.rb +0 -95
  163. data/examples/widget_overlay/README.md +0 -45
  164. data/examples/widget_overlay/app.rb +0 -250
  165. data/examples/widget_popup/README.md +0 -45
  166. data/examples/widget_popup/app.rb +0 -106
  167. data/examples/widget_ratatui_logo/README.md +0 -43
  168. data/examples/widget_ratatui_logo/app.rb +0 -104
  169. data/examples/widget_ratatui_mascot/README.md +0 -43
  170. data/examples/widget_ratatui_mascot/app.rb +0 -95
  171. data/examples/widget_rect/README.md +0 -53
  172. data/examples/widget_rect/app.rb +0 -222
  173. data/examples/widget_render/README.md +0 -46
  174. data/examples/widget_render/app.rb +0 -186
  175. data/examples/widget_render/app.rbs +0 -41
  176. data/examples/widget_rich_text/README.md +0 -44
  177. data/examples/widget_rich_text/app.rb +0 -193
  178. data/examples/widget_scroll_text/README.md +0 -46
  179. data/examples/widget_scroll_text/app.rb +0 -109
  180. data/examples/widget_scrollbar/README.md +0 -46
  181. data/examples/widget_scrollbar/app.rb +0 -155
  182. data/examples/widget_sparkline/README.md +0 -51
  183. data/examples/widget_sparkline/app.rb +0 -277
  184. data/examples/widget_style_colors/README.md +0 -43
  185. data/examples/widget_style_colors/app.rb +0 -83
  186. data/examples/widget_table/README.md +0 -57
  187. data/examples/widget_table/app.rb +0 -285
  188. data/examples/widget_tabs/README.md +0 -50
  189. data/examples/widget_tabs/app.rb +0 -183
  190. data/examples/widget_text_width/README.md +0 -44
  191. data/examples/widget_text_width/app.rb +0 -117
  192. data/migrate_to_buffer.rb +0 -145
  193. data/mise.toml +0 -8
  194. data/tasks/autodoc/examples.rb +0 -87
  195. data/tasks/autodoc/member.rb +0 -58
  196. data/tasks/autodoc/name.rb +0 -21
  197. data/tasks/autodoc.rake +0 -21
  198. data/tasks/bump/bump_workflow.rb +0 -49
  199. data/tasks/bump/cargo_lockfile.rb +0 -21
  200. data/tasks/bump/changelog.rb +0 -104
  201. data/tasks/bump/header.rb +0 -32
  202. data/tasks/bump/history.rb +0 -32
  203. data/tasks/bump/links.rb +0 -69
  204. data/tasks/bump/manifest.rb +0 -33
  205. data/tasks/bump/patch_release.rb +0 -19
  206. data/tasks/bump/release_branch.rb +0 -17
  207. data/tasks/bump/release_from_trunk.rb +0 -49
  208. data/tasks/bump/repository.rb +0 -54
  209. data/tasks/bump/ruby_gem.rb +0 -29
  210. data/tasks/bump/sem_ver.rb +0 -44
  211. data/tasks/bump/unreleased_section.rb +0 -73
  212. data/tasks/bump.rake +0 -61
  213. data/tasks/doc/documentation.rb +0 -59
  214. data/tasks/doc/link/file_url.rb +0 -30
  215. data/tasks/doc/link/relative_path.rb +0 -61
  216. data/tasks/doc/link/web_url.rb +0 -55
  217. data/tasks/doc/link.rb +0 -52
  218. data/tasks/doc/link_audit.rb +0 -116
  219. data/tasks/doc/problem.rb +0 -40
  220. data/tasks/doc/source_file.rb +0 -93
  221. data/tasks/doc.rake +0 -905
  222. data/tasks/example_viewer.html.erb +0 -172
  223. data/tasks/extension.rake +0 -14
  224. data/tasks/license/headers_md.rb +0 -223
  225. data/tasks/license/headers_rb.rb +0 -210
  226. data/tasks/license/license_utils.rb +0 -130
  227. data/tasks/license/snippets_md.rb +0 -315
  228. data/tasks/license/snippets_rdoc.rb +0 -150
  229. data/tasks/license.rake +0 -91
  230. data/tasks/lint.rake +0 -170
  231. data/tasks/rbs_predicates/predicate_catalog.rb +0 -52
  232. data/tasks/rbs_predicates/predicate_tests.rb +0 -124
  233. data/tasks/rbs_predicates/rbs_signature.rb +0 -63
  234. data/tasks/rbs_predicates.rake +0 -31
  235. data/tasks/rdoc_config.rb +0 -29
  236. data/tasks/resources/build.yml.erb +0 -60
  237. data/tasks/resources/index.html.erb +0 -141
  238. data/tasks/resources/rubies.yml +0 -7
  239. data/tasks/sourcehut.rake +0 -110
  240. data/tasks/steep.rake +0 -11
  241. data/tasks/terminal_preview/app_screenshot.rb +0 -45
  242. data/tasks/terminal_preview/crash_report.rb +0 -54
  243. data/tasks/terminal_preview/example_app.rb +0 -27
  244. data/tasks/terminal_preview/launcher_script.rb +0 -48
  245. data/tasks/terminal_preview/preview_collection.rb +0 -60
  246. data/tasks/terminal_preview/preview_timing.rb +0 -24
  247. data/tasks/terminal_preview/safety_confirmation.rb +0 -58
  248. data/tasks/terminal_preview/saved_screenshot.rb +0 -56
  249. data/tasks/terminal_preview/system_appearance.rb +0 -13
  250. data/tasks/terminal_preview/terminal_window.rb +0 -138
  251. data/tasks/terminal_preview/window_id.rb +0 -16
  252. data/tasks/terminal_preview.rake +0 -30
  253. data/tasks/test.rake +0 -36
  254. data/tasks/website/index_page.rb +0 -30
  255. data/tasks/website/version.rb +0 -122
  256. data/tasks/website/version_menu.rb +0 -68
  257. data/tasks/website/versioned_documentation.rb +0 -83
  258. data/tasks/website/website.rb +0 -53
  259. 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
- [![verify_readme_usage](../../doc/images/verify_readme_usage.png)](../../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
- [![](../../doc/images/widget_barchart.png)](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)