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,112 +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
- require "ratatui_ruby"
10
-
11
- # A custom widget that fills its area with a checkered pattern using Cell objects.
12
- class CheckeredBackground
13
- def initialize(tui)
14
- @tui = tui
15
- end
16
-
17
- def render(area)
18
- cell = @tui.cell(char: "░", fg: :dark_gray)
19
- commands = []
20
- area.height.times do |y|
21
- area.width.times do |x|
22
- # Checkerboard logic
23
- if (x + y).even?
24
- # Use a dim cell for the background pattern
25
- commands << @tui.draw_cell(area.x + x, area.y + y, cell)
26
- end
27
- end
28
- end
29
- commands
30
- end
31
- end
32
-
33
- class WidgetCell
34
- def run
35
- RatatuiRuby.run do |tui|
36
- @tui = tui
37
- # Define some reusable cells for our table
38
- ok_cell = @tui.cell(char: "OK", fg: :green)
39
- fail_cell = @tui.cell(char: "FAIL", fg: :red, modifiers: ["bold"])
40
- pending_cell = @tui.cell(char: "...", fg: :yellow, modifiers: ["dim"])
41
-
42
- # A mix of Strings and Cells in rows
43
- rows = [
44
- ["Database", ok_cell],
45
- ["Cache", ok_cell],
46
- ["Worker", fail_cell],
47
- ["Analytics", pending_cell],
48
- ["Web Server", @tui.cell(char: "RESTARTING", fg: :blue, modifiers: ["rapid_blink"])],
49
- ]
50
-
51
- table = @tui.table(
52
- header: ["Service", @tui.cell(char: "Status", modifiers: ["underlined"])],
53
- rows:,
54
- widths: [
55
- @tui.constraint_percentage(70),
56
- @tui.constraint_percentage(30),
57
- ],
58
- block: @tui.block(title: "System Status", borders: :all),
59
- column_spacing: 1
60
- )
61
-
62
- # Main loop
63
- loop do
64
- @tui.draw do |frame|
65
- # Create a layout that holds both widgets
66
- # We use a vertical layout:
67
- # Top: Custom CheckeredBackground with specific height
68
- # Bottom: Table using remaining space
69
- top_area, bottom_area = @tui.layout_split(
70
- frame.area,
71
- direction: :vertical,
72
- constraints: [
73
- @tui.constraint_length(10), # Top section
74
- @tui.constraint_min(0), # Bottom section
75
- ]
76
- )
77
-
78
- # Top Child: An Overlay of Paragraph on top of CheckeredBackground
79
- overlay = @tui.overlay(
80
- layers: [
81
- CheckeredBackground.new(@tui),
82
- @tui.center(
83
- width_percent: 50,
84
- height_percent: 50,
85
- child: @tui.paragraph(
86
- text: "Custom Widget\n(CheckeredBackground)",
87
- alignment: :center,
88
- block: @tui.block(borders: :all, title: "Overlay")
89
- )
90
- ),
91
- ]
92
- )
93
- frame.render_widget(overlay, top_area)
94
-
95
- # Bottom Child: The Table
96
- frame.render_widget(table, bottom_area)
97
- end
98
-
99
- case @tui.poll_event
100
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
101
- break
102
- else
103
- nil
104
- end
105
- end
106
- end
107
- end
108
- end
109
-
110
- if __FILE__ == $0
111
- WidgetCell.new.run
112
- end
@@ -1,33 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
- # Center Example
6
-
7
- [![widget_center](../../doc/images/widget_center.png)](app.rb)
8
-
9
- <!--
10
- SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
11
- SPDX-License-Identifier: CC-BY-SA-4.0
12
- -->
13
-
14
- This example demonstrates the `Center` widget, which positions a child widget in the center of the available area.
15
-
16
- ## Key Concepts
17
-
18
- - **Centering**: The widget automatically calculates the necessary padding to center its child.
19
- - **Sizing**: You can control the size of the centered area using `width_percent` and `height_percent`.
20
- - **Composition**: The `Center` widget wraps another widget (the child), making it easy to compose layouts.
21
-
22
- ## Controls
23
-
24
- | Key | Action |
25
- | --- | --- |
26
- | `←` / `→` | Decrease / Increase width percentage |
27
- | `↑` / `↓` | Increase / Decrease height percentage |
28
- | `q` | Quit |
29
-
30
- ## Screenshot
31
- ## Source Code
32
-
33
- - [app.rb](app.rb)
@@ -1,118 +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
- require "ratatui_ruby"
10
-
11
- # Center Widget
12
- # Demonstrates how to center content horizontally and vertically
13
- # with adjustable width/height percentages.
14
- class WidgetCenter
15
- def initialize
16
- @width_percent = 50
17
- @height_percent = 50
18
- end
19
-
20
- def run
21
- RatatuiRuby.run do |tui|
22
- @tui = tui
23
- loop do
24
- render
25
- break if handle_input == :quit
26
- end
27
- end
28
- end
29
-
30
- private def render
31
- @tui.draw do |frame|
32
- layout = @tui.layout_split(
33
- frame.area,
34
- direction: :vertical,
35
- constraints: [
36
- @tui.constraint_fill(1),
37
- @tui.constraint_length(3),
38
- ]
39
- )
40
-
41
- # 1. Main Area
42
- # Background block frames the centered content
43
- bg_block = @tui.block(
44
- title: "Center Widget",
45
- borders: [:all],
46
- style: @tui.style(fg: :gray)
47
- )
48
- frame.render_widget(bg_block, layout[0])
49
-
50
- # 2. Centered Content
51
- # The content itself is just a block with some text
52
- content = @tui.paragraph(
53
- text: [
54
- @tui.text_line(
55
- spans: [
56
- @tui.text_span(content: "Centered Area", style: @tui.style(modifiers: [:bold])),
57
- ],
58
- alignment: :center
59
- ),
60
- @tui.text_line(spans: []),
61
- @tui.text_line(spans: [@tui.text_span(content: "Width: #{@width_percent}%", style: @tui.style(fg: :cyan))], alignment: :center),
62
- @tui.text_line(spans: [@tui.text_span(content: "Height: #{@height_percent}%", style: @tui.style(fg: :magenta))], alignment: :center),
63
- ],
64
- block: @tui.block(
65
- title: "Child Widget",
66
- borders: [:all],
67
- style: @tui.style(fg: :white)
68
- ),
69
- alignment: :center
70
- )
71
-
72
- # Create the Center widget
73
- center_widget = @tui.center(
74
- child: content,
75
- width_percent: @width_percent,
76
- height_percent: @height_percent
77
- )
78
-
79
- # Render center widget into the main layout area
80
- frame.render_widget(center_widget, layout[0])
81
-
82
- # 3. Controls
83
- control_text = @tui.paragraph(
84
- text: [
85
- @tui.text_line(spans: [
86
- @tui.text_span(content: "←/→", style: @tui.style(modifiers: [:bold, :underlined])),
87
- @tui.text_span(content: ": Width "),
88
- @tui.text_span(content: "↑/↓", style: @tui.style(modifiers: [:bold, :underlined])),
89
- @tui.text_span(content: ": Height "),
90
- @tui.text_span(content: "q", style: @tui.style(modifiers: [:bold, :underlined])),
91
- @tui.text_span(content: ": Quit"),
92
- ]),
93
- ],
94
- block: @tui.block(borders: [:top], style: @tui.style(bg: :black))
95
- )
96
- frame.render_widget(control_text, layout[1])
97
- end
98
- end
99
-
100
- def handle_input
101
- case @tui.poll_event
102
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
103
- :quit
104
- in { type: :key, code: "left" }
105
- @width_percent = [@width_percent - 5, 5].max
106
- in { type: :key, code: "right" }
107
- @width_percent = [@width_percent + 5, 100].min
108
- in { type: :key, code: "up" }
109
- @height_percent = [@height_percent + 5, 100].min
110
- in { type: :key, code: "down" }
111
- @height_percent = [@height_percent - 5, 5].max
112
- else
113
- # Ignore other events
114
- end
115
- end
116
- end
117
-
118
- WidgetCenter.new.run if __FILE__ == $0
@@ -1,50 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Chart (Dataset, Axis) Example
7
-
8
- [![widget_chart](../../doc/images/widget_chart.png)](app.rb)
9
-
10
- Demonstrates Cartesian plotting with interactive styling and configuration.
11
-
12
- Trends and patterns are invisible in raw logs. Charts visualize X/Y datasets to reveal the story behind the data.
13
-
14
- ## Features Demonstrated
15
-
16
- - **Dataset Types**: Line charts and Scatter plots.
17
- - **Markers**: Braille patterns, dots, blocks, and bars.
18
- - **Axis Configuration**: Controlling labels, bounds, and alignment (Left/Center/Right).
19
- - **Legend**: Positioning the legend in any of the four corners or hiding it based on constraints.
20
-
21
- ## Hotkeys
22
-
23
- - **m**: Cycle Marker Type (`marker`)
24
- - **s**: Cycle Dataset Style (`style`)
25
- - **x**: Cycle X-Axis Alignment (`labels_alignment`)
26
- - **y**: Cycle Y-Axis Alignment (`labels_alignment`)
27
- - **l**: Cycle Legend Position (`legend_position`)
28
- - **q**: Quit
29
-
30
- ## Usage
31
-
32
- <!-- SPDX-SnippetBegin -->
33
- <!--
34
- SPDX-FileCopyrightText: 2026 Kerrick Long
35
- SPDX-License-Identifier: MIT-0
36
- -->
37
- ```bash
38
- ruby examples/widget_chart/app.rb
39
- ```
40
- <!-- SPDX-SnippetEnd -->
41
-
42
- ## Learning Outcomes
43
-
44
- Use this example if you need to...
45
-
46
- - Plot real-time data monitoring (CPU history, request latency).
47
- - Visualize mathematical functions.
48
- - Compare multiple datasets on the same axis.
49
-
50
- [Read the source code →](app.rb)
@@ -1,220 +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
- require "ratatui_ruby"
10
-
11
- # Demonstrates Cartesian plotting attributes with interactive cycling.
12
- #
13
- # Trends and patterns are invisible in raw logs. You need to see the shape of the data to understand the story it tells.
14
- #
15
- # This demo showcases the <tt>Chart</tt> widget. It provides an interactive playground where you can toggle marker types, axis alignments, and legend positions in real-time.
16
- #
17
- # Use it to understand how to visualize complex X/Y datasets and trends efficiently.
18
- #
19
- # === Example
20
- #
21
- # Run the demo from the terminal:
22
- #
23
- # ruby examples/widget_chart/app.rb
24
- #
25
- # rdoc-image:/doc/images/widget_chart.png
26
- class WidgetChart
27
- MARKERS = [
28
- { name: "Dot (·)", marker: :dot },
29
- { name: "Braille", marker: :braille },
30
- { name: "Block (█)", marker: :block },
31
- { name: "Bar", marker: :bar },
32
- ].freeze
33
-
34
- X_ALIGNMENTS = [
35
- { name: "Left", alignment: :left },
36
- { name: "Center", alignment: :center },
37
- { name: "Right", alignment: :right },
38
- ].freeze
39
-
40
- Y_ALIGNMENTS = [
41
- { name: "Left", alignment: :left },
42
- { name: "Center", alignment: :center },
43
- { name: "Right", alignment: :right },
44
- ].freeze
45
-
46
- LEGEND_POSITIONS = [
47
- { name: "Top Right", position: :top_right },
48
- { name: "Top Left", position: :top_left },
49
- { name: "Bottom Right", position: :bottom_right },
50
- { name: "Bottom Left", position: :bottom_left },
51
- ].freeze
52
-
53
- def run
54
- RatatuiRuby.run do |tui|
55
- @tui = tui
56
- init_styles
57
-
58
- # Support seeded random for deterministic testing
59
- # Set RATA_SEED=42 for reproducible scatter plot data
60
- seed = ENV.fetch("RATA_SEED", nil)
61
- @rng = seed ? Random.new(seed.to_i) : Random.new
62
-
63
- @marker_index = 0
64
- @dataset_style_index = 0
65
- @x_alignment_index = 1
66
- @y_alignment_index = 2
67
- @legend_position_index = 0
68
-
69
- loop do
70
- render
71
- break if handle_input == :quit
72
- sleep 0.05
73
- end
74
- end
75
- end
76
-
77
- private def init_styles
78
- @hotkey_style = @tui.style(modifiers: [:bold, :underlined])
79
- @dataset_styles = [
80
- { name: "Yellow", style: @tui.style(fg: :yellow) },
81
- { name: "Green", style: @tui.style(fg: :green) },
82
- { name: "Cyan", style: @tui.style(fg: :cyan) },
83
- { name: "Red", style: @tui.style(fg: :red) },
84
- { name: "Magenta", style: @tui.style(fg: :magenta) },
85
- { name: "Bold Blue", style: @tui.style(fg: :blue, modifiers: [:bold]) },
86
- { name: "Dim White", style: @tui.style(fg: :white, modifiers: [:dim]) },
87
- { name: "Italic Green", style: @tui.style(fg: :green, modifiers: [:italic]) },
88
- { name: "Alert (Red/White/Bar)", style: @tui.style(fg: :white, bg: :red, modifiers: [:bold]) },
89
- ]
90
- end
91
-
92
- private def render
93
- # Static sample data: sine wave with wider range for better visibility
94
- line_data = (0..50).map do |i|
95
- x = i / 5.0
96
- [x, Math.sin(x)]
97
- end
98
-
99
- # Scatter: Random points (deterministic when RATA_SEED is set)
100
- scatter_data = (0..20).map do |_|
101
- [@rng.rand(0.0..10.0), @rng.rand(-1.0..1.0)]
102
- end
103
-
104
- style = @dataset_styles[@dataset_style_index][:style]
105
- # Ensure the second dataset has a different style
106
- scatter_style = @dataset_styles[(@dataset_style_index + 2) % @dataset_styles.length][:style]
107
-
108
- datasets = [
109
- @tui.dataset(
110
- name: "Line",
111
- data: line_data,
112
- style:,
113
- marker: (style.modifiers.include?(:bold) && style.bg) ? :bar : MARKERS[@marker_index][:marker],
114
- graph_type: :line
115
- ),
116
- @tui.dataset(
117
- name: "Scatter",
118
- data: scatter_data,
119
- style: scatter_style,
120
- marker: (scatter_style.modifiers.include?(:bold) && scatter_style.bg) ? :bar : MARKERS[@marker_index][:marker],
121
- graph_type: :scatter
122
- ),
123
- ]
124
-
125
- chart = @tui.chart(
126
- datasets:,
127
- x_axis: @tui.axis(
128
- title: "Time",
129
- bounds: [0.0, 10.0],
130
- labels: %w[0 5 10],
131
- style: @tui.style(fg: :yellow),
132
- labels_alignment: X_ALIGNMENTS[@x_alignment_index][:alignment]
133
- ),
134
- y_axis: @tui.axis(
135
- title: "Amplitude",
136
- bounds: [-1.0, 1.0],
137
- labels: %w[-1 0 1],
138
- style: @tui.style(fg: :cyan),
139
- labels_alignment: Y_ALIGNMENTS[@y_alignment_index][:alignment]
140
- ),
141
- block: @tui.block(
142
- title: "Chart Widget",
143
- borders: [:all]
144
- ),
145
- legend_position: LEGEND_POSITIONS[@legend_position_index][:position],
146
- hidden_legend_constraints: [
147
- @tui.constraint_min(20),
148
- @tui.constraint_min(10),
149
- ]
150
- )
151
-
152
- controls = @tui.block(
153
- title: "Controls",
154
- borders: [:all],
155
- children: [
156
- @tui.paragraph(
157
- text: [
158
- # Line 1: Markers & Colors
159
- @tui.text_line(spans: [
160
- @tui.text_span(content: "m", style: @hotkey_style),
161
- @tui.text_span(content: ": Marker (#{MARKERS[@marker_index][:name]}) "),
162
- @tui.text_span(content: "s", style: @hotkey_style),
163
- @tui.text_span(content: ": Style (#{@dataset_styles[@dataset_style_index][:name]})"),
164
- ]),
165
- # Line 2: Axis alignments
166
- @tui.text_line(spans: [
167
- @tui.text_span(content: "x", style: @hotkey_style),
168
- @tui.text_span(content: ": X Align (#{X_ALIGNMENTS[@x_alignment_index][:name]}) "),
169
- @tui.text_span(content: "y", style: @hotkey_style),
170
- @tui.text_span(content: ": Y Align (#{Y_ALIGNMENTS[@y_alignment_index][:name]}) "),
171
- @tui.text_span(content: "l", style: @hotkey_style),
172
- @tui.text_span(content: ": Legend (#{LEGEND_POSITIONS[@legend_position_index][:name]})"),
173
- ]),
174
- # Line 3: Quit
175
- @tui.text_line(spans: [
176
- @tui.text_span(content: "q", style: @hotkey_style),
177
- @tui.text_span(content: ": Quit"),
178
- ]),
179
- ]
180
- ),
181
- ]
182
- )
183
-
184
- @tui.draw do |frame|
185
- chart_area, controls_area = @tui.layout_split(
186
- frame.area,
187
- direction: :vertical,
188
- constraints: [
189
- @tui.constraint_fill(1),
190
- @tui.constraint_length(5),
191
- ]
192
- )
193
- frame.render_widget(chart, chart_area)
194
- frame.render_widget(controls, controls_area)
195
- end
196
- end
197
-
198
- private def handle_input
199
- event = @tui.poll_event
200
-
201
- case event
202
- in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
203
- :quit
204
- in type: :key, code: "m"
205
- @marker_index = (@marker_index + 1) % MARKERS.length
206
- in type: :key, code: "s"
207
- @dataset_style_index = (@dataset_style_index + 1) % @dataset_styles.length
208
- in type: :key, code: "x"
209
- @x_alignment_index = (@x_alignment_index + 1) % X_ALIGNMENTS.length
210
- in type: :key, code: "y"
211
- @y_alignment_index = (@y_alignment_index + 1) % Y_ALIGNMENTS.length
212
- in type: :key, code: "l"
213
- @legend_position_index = (@legend_position_index + 1) % LEGEND_POSITIONS.length
214
- else
215
- nil
216
- end
217
- end
218
- end
219
-
220
- WidgetChart.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,50 +0,0 @@
1
- <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- SPDX-License-Identifier: CC-BY-SA-4.0
4
- -->
5
-
6
- # Gauge Widget Example
7
-
8
- [![widget_gauge](../../doc/images/widget_gauge.png)](app.rb)
9
-
10
- Demonstrates progress bars with interactive configuration.
11
-
12
- Long-running tasks create anxiety. Users need to know the system is working. Gauges provide visual feedback on completion status.
13
-
14
- ## Features Demonstrated
15
-
16
- - **Progress styles**: standard block characters or Unicode bars.
17
- - **Labels**: Customizing the text overlay (Percentage, Ratio, etc.).
18
- - **Styling**: Independent control of the filled gauge color and the background track.
19
- - **Thresholds**: Implementing multi-colored gauges based on values.
20
-
21
- ## Hotkeys
22
-
23
- - **Arrows (←/→)**: Adjust Ratio (`ratio`)
24
- - **g**: Cycle Gauge Color (`gauge_style`)
25
- - **b**: Cycle Background Style (`style`)
26
- - **u**: Toggle Unicode Mode (`use_unicode`)
27
- - **l**: Cycle Label Mode (`label`)
28
- - **q**: Quit
29
-
30
- ## Usage
31
-
32
- <!-- SPDX-SnippetBegin -->
33
- <!--
34
- SPDX-FileCopyrightText: 2026 Kerrick Long
35
- SPDX-License-Identifier: MIT-0
36
- -->
37
- ```bash
38
- ruby examples/widget_gauge/app.rb
39
- ```
40
- <!-- SPDX-SnippetEnd -->
41
-
42
- ## Learning Outcomes
43
-
44
- Use this example if you need to...
45
-
46
- - Show download or upload progress.
47
- - Visualize resource quotas (disk space, memory usage).
48
- - Create "health bars" or status indicators.
49
-
50
- [Read the source code →](app.rb)