ratatui_ruby 1.2.0 → 1.2.2

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