ratatui_ruby 1.4.0-x86_64-linux

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 (292) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +15 -0
  3. data/LICENSES/AGPL-3.0-or-later.txt +661 -0
  4. data/LICENSES/CC-BY-SA-4.0.txt +427 -0
  5. data/LICENSES/CC0-1.0.txt +121 -0
  6. data/LICENSES/LGPL-3.0-or-later.txt +304 -0
  7. data/LICENSES/MIT-0.txt +16 -0
  8. data/LICENSES/MIT.txt +21 -0
  9. data/REUSE.toml +42 -0
  10. data/exe/.gitkeep +0 -0
  11. data/ext/ratatui_ruby/.cargo/config.toml +13 -0
  12. data/ext/ratatui_ruby/.gitignore +4 -0
  13. data/ext/ratatui_ruby/Cargo.lock +1737 -0
  14. data/ext/ratatui_ruby/Cargo.toml +24 -0
  15. data/ext/ratatui_ruby/clippy.toml +7 -0
  16. data/ext/ratatui_ruby/extconf.rb +21 -0
  17. data/ext/ratatui_ruby/src/color.rs +82 -0
  18. data/ext/ratatui_ruby/src/errors.rs +28 -0
  19. data/ext/ratatui_ruby/src/events.rs +700 -0
  20. data/ext/ratatui_ruby/src/frame.rs +241 -0
  21. data/ext/ratatui_ruby/src/lib.rs +343 -0
  22. data/ext/ratatui_ruby/src/lib_header.rs +11 -0
  23. data/ext/ratatui_ruby/src/rendering.rs +158 -0
  24. data/ext/ratatui_ruby/src/string_width.rs +101 -0
  25. data/ext/ratatui_ruby/src/style.rs +469 -0
  26. data/ext/ratatui_ruby/src/terminal/capabilities.rs +46 -0
  27. data/ext/ratatui_ruby/src/terminal/init.rs +233 -0
  28. data/ext/ratatui_ruby/src/terminal/mod.rs +42 -0
  29. data/ext/ratatui_ruby/src/terminal/mutations.rs +158 -0
  30. data/ext/ratatui_ruby/src/terminal/queries.rs +231 -0
  31. data/ext/ratatui_ruby/src/terminal/query.rs +400 -0
  32. data/ext/ratatui_ruby/src/terminal/storage.rs +109 -0
  33. data/ext/ratatui_ruby/src/terminal/wrapper.rs +16 -0
  34. data/ext/ratatui_ruby/src/text.rs +225 -0
  35. data/ext/ratatui_ruby/src/widgets/barchart.rs +169 -0
  36. data/ext/ratatui_ruby/src/widgets/block.rs +41 -0
  37. data/ext/ratatui_ruby/src/widgets/calendar.rs +84 -0
  38. data/ext/ratatui_ruby/src/widgets/canvas.rs +183 -0
  39. data/ext/ratatui_ruby/src/widgets/center.rs +79 -0
  40. data/ext/ratatui_ruby/src/widgets/chart.rs +222 -0
  41. data/ext/ratatui_ruby/src/widgets/clear.rs +39 -0
  42. data/ext/ratatui_ruby/src/widgets/cursor.rs +32 -0
  43. data/ext/ratatui_ruby/src/widgets/gauge.rs +65 -0
  44. data/ext/ratatui_ruby/src/widgets/layout.rs +379 -0
  45. data/ext/ratatui_ruby/src/widgets/line_gauge.rs +100 -0
  46. data/ext/ratatui_ruby/src/widgets/list.rs +378 -0
  47. data/ext/ratatui_ruby/src/widgets/list_state.rs +173 -0
  48. data/ext/ratatui_ruby/src/widgets/mod.rs +26 -0
  49. data/ext/ratatui_ruby/src/widgets/overlay.rs +24 -0
  50. data/ext/ratatui_ruby/src/widgets/paragraph.rs +87 -0
  51. data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +40 -0
  52. data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +55 -0
  53. data/ext/ratatui_ruby/src/widgets/scrollbar.rs +214 -0
  54. data/ext/ratatui_ruby/src/widgets/scrollbar_state.rs +169 -0
  55. data/ext/ratatui_ruby/src/widgets/sparkline.rs +127 -0
  56. data/ext/ratatui_ruby/src/widgets/table.rs +415 -0
  57. data/ext/ratatui_ruby/src/widgets/table_state.rs +203 -0
  58. data/ext/ratatui_ruby/src/widgets/tabs.rs +194 -0
  59. data/lib/ratatui_ruby/backend/window_size.rb +50 -0
  60. data/lib/ratatui_ruby/backend.rb +59 -0
  61. data/lib/ratatui_ruby/buffer/cell.rb +212 -0
  62. data/lib/ratatui_ruby/buffer.rb +149 -0
  63. data/lib/ratatui_ruby/cell.rb +208 -0
  64. data/lib/ratatui_ruby/debug.rb +215 -0
  65. data/lib/ratatui_ruby/draw.rb +63 -0
  66. data/lib/ratatui_ruby/event/focus_gained.rb +125 -0
  67. data/lib/ratatui_ruby/event/focus_lost.rb +127 -0
  68. data/lib/ratatui_ruby/event/key/character.rb +53 -0
  69. data/lib/ratatui_ruby/event/key/dwim.rb +301 -0
  70. data/lib/ratatui_ruby/event/key/media.rb +46 -0
  71. data/lib/ratatui_ruby/event/key/modifier.rb +107 -0
  72. data/lib/ratatui_ruby/event/key/navigation.rb +72 -0
  73. data/lib/ratatui_ruby/event/key/system.rb +47 -0
  74. data/lib/ratatui_ruby/event/key.rb +479 -0
  75. data/lib/ratatui_ruby/event/mouse.rb +291 -0
  76. data/lib/ratatui_ruby/event/none.rb +53 -0
  77. data/lib/ratatui_ruby/event/paste.rb +130 -0
  78. data/lib/ratatui_ruby/event/resize.rb +221 -0
  79. data/lib/ratatui_ruby/event/sync.rb +52 -0
  80. data/lib/ratatui_ruby/event.rb +163 -0
  81. data/lib/ratatui_ruby/frame.rb +257 -0
  82. data/lib/ratatui_ruby/labs/a11y.rb +182 -0
  83. data/lib/ratatui_ruby/labs/frame_a11y_capture.rb +50 -0
  84. data/lib/ratatui_ruby/labs.rb +47 -0
  85. data/lib/ratatui_ruby/layout/alignment.rb +91 -0
  86. data/lib/ratatui_ruby/layout/constraint.rb +337 -0
  87. data/lib/ratatui_ruby/layout/layout.rb +258 -0
  88. data/lib/ratatui_ruby/layout/position.rb +81 -0
  89. data/lib/ratatui_ruby/layout/rect.rb +733 -0
  90. data/lib/ratatui_ruby/layout/size.rb +62 -0
  91. data/lib/ratatui_ruby/layout.rb +29 -0
  92. data/lib/ratatui_ruby/list_state.rb +201 -0
  93. data/lib/ratatui_ruby/output_guard.rb +171 -0
  94. data/lib/ratatui_ruby/ratatui_ruby.so +0 -0
  95. data/lib/ratatui_ruby/scrollbar_state.rb +122 -0
  96. data/lib/ratatui_ruby/style/color.rb +149 -0
  97. data/lib/ratatui_ruby/style/style.rb +147 -0
  98. data/lib/ratatui_ruby/style.rb +19 -0
  99. data/lib/ratatui_ruby/symbols.rb +435 -0
  100. data/lib/ratatui_ruby/synthetic_events.rb +106 -0
  101. data/lib/ratatui_ruby/table_state.rb +251 -0
  102. data/lib/ratatui_ruby/terminal/capabilities.rb +316 -0
  103. data/lib/ratatui_ruby/terminal/viewport.rb +80 -0
  104. data/lib/ratatui_ruby/terminal.rb +66 -0
  105. data/lib/ratatui_ruby/terminal_lifecycle.rb +303 -0
  106. data/lib/ratatui_ruby/terminal_lifecycle.rb.bak +197 -0
  107. data/lib/ratatui_ruby/test_helper/event_injection.rb +241 -0
  108. data/lib/ratatui_ruby/test_helper/global_state.rb +111 -0
  109. data/lib/ratatui_ruby/test_helper/snapshot.rb +568 -0
  110. data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.ansi +24 -0
  111. data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.txt +24 -0
  112. data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.ansi +5 -0
  113. data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.txt +5 -0
  114. data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.ansi +24 -0
  115. data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.txt +24 -0
  116. data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.ansi +12 -0
  117. data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.txt +12 -0
  118. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.ansi +12 -0
  119. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.txt +12 -0
  120. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.ansi +12 -0
  121. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.txt +12 -0
  122. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.ansi +12 -0
  123. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.txt +12 -0
  124. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.ansi +12 -0
  125. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.txt +12 -0
  126. data/lib/ratatui_ruby/test_helper/snapshots/my_snapshot.txt +1 -0
  127. data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.ansi +10 -0
  128. data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.txt +10 -0
  129. data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.ansi +10 -0
  130. data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.txt +10 -0
  131. data/lib/ratatui_ruby/test_helper/style_assertions.rb +449 -0
  132. data/lib/ratatui_ruby/test_helper/subprocess_timeout.rb +35 -0
  133. data/lib/ratatui_ruby/test_helper/terminal.rb +187 -0
  134. data/lib/ratatui_ruby/test_helper/test_doubles.rb +86 -0
  135. data/lib/ratatui_ruby/test_helper.rb +115 -0
  136. data/lib/ratatui_ruby/text/line.rb +245 -0
  137. data/lib/ratatui_ruby/text/span.rb +158 -0
  138. data/lib/ratatui_ruby/text.rb +99 -0
  139. data/lib/ratatui_ruby/tui/buffer_factories.rb +22 -0
  140. data/lib/ratatui_ruby/tui/canvas_factories.rb +149 -0
  141. data/lib/ratatui_ruby/tui/core.rb +67 -0
  142. data/lib/ratatui_ruby/tui/layout_factories.rb +153 -0
  143. data/lib/ratatui_ruby/tui/state_factories.rb +77 -0
  144. data/lib/ratatui_ruby/tui/style_factories.rb +22 -0
  145. data/lib/ratatui_ruby/tui/text_factories.rb +86 -0
  146. data/lib/ratatui_ruby/tui/widget_factories.rb +272 -0
  147. data/lib/ratatui_ruby/tui.rb +106 -0
  148. data/lib/ratatui_ruby/version.rb +12 -0
  149. data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +51 -0
  150. data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +29 -0
  151. data/lib/ratatui_ruby/widgets/bar_chart.rb +308 -0
  152. data/lib/ratatui_ruby/widgets/block.rb +266 -0
  153. data/lib/ratatui_ruby/widgets/calendar.rb +88 -0
  154. data/lib/ratatui_ruby/widgets/canvas.rb +297 -0
  155. data/lib/ratatui_ruby/widgets/cell.rb +59 -0
  156. data/lib/ratatui_ruby/widgets/center.rb +71 -0
  157. data/lib/ratatui_ruby/widgets/chart.rb +172 -0
  158. data/lib/ratatui_ruby/widgets/clear.rb +66 -0
  159. data/lib/ratatui_ruby/widgets/coerceable_widget.rb +77 -0
  160. data/lib/ratatui_ruby/widgets/cursor.rb +54 -0
  161. data/lib/ratatui_ruby/widgets/gauge.rb +146 -0
  162. data/lib/ratatui_ruby/widgets/line_gauge.rb +158 -0
  163. data/lib/ratatui_ruby/widgets/list.rb +252 -0
  164. data/lib/ratatui_ruby/widgets/list_item.rb +55 -0
  165. data/lib/ratatui_ruby/widgets/overlay.rb +55 -0
  166. data/lib/ratatui_ruby/widgets/paragraph.rb +113 -0
  167. data/lib/ratatui_ruby/widgets/ratatui_logo.rb +35 -0
  168. data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +40 -0
  169. data/lib/ratatui_ruby/widgets/row.rb +123 -0
  170. data/lib/ratatui_ruby/widgets/scrollbar.rb +147 -0
  171. data/lib/ratatui_ruby/widgets/shape/label.rb +80 -0
  172. data/lib/ratatui_ruby/widgets/sparkline.rb +153 -0
  173. data/lib/ratatui_ruby/widgets/table.rb +213 -0
  174. data/lib/ratatui_ruby/widgets/tabs.rb +91 -0
  175. data/lib/ratatui_ruby/widgets.rb +43 -0
  176. data/lib/ratatui_ruby.rb +555 -0
  177. data/sig/examples/app_all_events/app.rbs +11 -0
  178. data/sig/examples/app_all_events/model/app_model.rbs +23 -0
  179. data/sig/examples/app_all_events/model/event_entry.rbs +23 -0
  180. data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
  181. data/sig/examples/app_all_events/view/app_view.rbs +8 -0
  182. data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
  183. data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
  184. data/sig/examples/app_all_events/view/live_view.rbs +6 -0
  185. data/sig/examples/app_all_events/view/log_view.rbs +6 -0
  186. data/sig/examples/app_all_events/view.rbs +14 -0
  187. data/sig/examples/app_cli_rich_moments/app.rbs +12 -0
  188. data/sig/examples/app_color_picker/app.rbs +17 -0
  189. data/sig/examples/app_external_editor/app.rbs +12 -0
  190. data/sig/examples/app_login_form/app.rbs +11 -0
  191. data/sig/examples/app_stateful_interaction/app.rbs +39 -0
  192. data/sig/examples/verify_quickstart_dsl/app.rbs +17 -0
  193. data/sig/examples/verify_quickstart_lifecycle/app.rbs +17 -0
  194. data/sig/examples/verify_readme_usage/app.rbs +17 -0
  195. data/sig/examples/widget_block_demo/app.rbs +38 -0
  196. data/sig/examples/widget_box_demo/app.rbs +17 -0
  197. data/sig/examples/widget_calendar_demo/app.rbs +17 -0
  198. data/sig/examples/widget_cell_demo/app.rbs +17 -0
  199. data/sig/examples/widget_chart_demo/app.rbs +17 -0
  200. data/sig/examples/widget_gauge_demo/app.rbs +17 -0
  201. data/sig/examples/widget_layout_split/app.rbs +16 -0
  202. data/sig/examples/widget_line_gauge_demo/app.rbs +17 -0
  203. data/sig/examples/widget_list_demo/app.rbs +17 -0
  204. data/sig/examples/widget_map_demo/app.rbs +17 -0
  205. data/sig/examples/widget_popup_demo/app.rbs +17 -0
  206. data/sig/examples/widget_ratatui_logo_demo/app.rbs +17 -0
  207. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +17 -0
  208. data/sig/examples/widget_rect/app.rbs +18 -0
  209. data/sig/examples/widget_render/app.rbs +16 -0
  210. data/sig/examples/widget_rich_text/app.rbs +17 -0
  211. data/sig/examples/widget_scroll_text/app.rbs +17 -0
  212. data/sig/examples/widget_scrollbar_demo/app.rbs +17 -0
  213. data/sig/examples/widget_sparkline_demo/app.rbs +16 -0
  214. data/sig/examples/widget_style_colors/app.rbs +20 -0
  215. data/sig/examples/widget_table_demo/app.rbs +17 -0
  216. data/sig/examples/widget_text_width/app.rbs +16 -0
  217. data/sig/generated/event_key_predicates.rbs +1348 -0
  218. data/sig/manifest.yaml +5 -0
  219. data/sig/patches/data.rbs +26 -0
  220. data/sig/patches/debugger__.rbs +8 -0
  221. data/sig/ratatui_ruby/backend/window_size.rbs +17 -0
  222. data/sig/ratatui_ruby/backend.rbs +12 -0
  223. data/sig/ratatui_ruby/buffer/cell.rbs +46 -0
  224. data/sig/ratatui_ruby/buffer.rbs +18 -0
  225. data/sig/ratatui_ruby/cell.rbs +44 -0
  226. data/sig/ratatui_ruby/clear.rbs +18 -0
  227. data/sig/ratatui_ruby/constraint.rbs +26 -0
  228. data/sig/ratatui_ruby/debug.rbs +45 -0
  229. data/sig/ratatui_ruby/draw.rbs +30 -0
  230. data/sig/ratatui_ruby/event.rbs +249 -0
  231. data/sig/ratatui_ruby/frame.rbs +23 -0
  232. data/sig/ratatui_ruby/interfaces.rbs +25 -0
  233. data/sig/ratatui_ruby/labs.rbs +90 -0
  234. data/sig/ratatui_ruby/layout/alignment.rbs +26 -0
  235. data/sig/ratatui_ruby/layout/constraint.rbs +39 -0
  236. data/sig/ratatui_ruby/layout/layout.rbs +45 -0
  237. data/sig/ratatui_ruby/layout/position.rbs +18 -0
  238. data/sig/ratatui_ruby/layout/rect.rbs +64 -0
  239. data/sig/ratatui_ruby/layout/size.rbs +18 -0
  240. data/sig/ratatui_ruby/list_state.rbs +23 -0
  241. data/sig/ratatui_ruby/output_guard.rbs +23 -0
  242. data/sig/ratatui_ruby/ratatui_ruby.rbs +113 -0
  243. data/sig/ratatui_ruby/rect.rbs +17 -0
  244. data/sig/ratatui_ruby/scrollbar_state.rbs +24 -0
  245. data/sig/ratatui_ruby/session.rbs +93 -0
  246. data/sig/ratatui_ruby/style/color.rbs +22 -0
  247. data/sig/ratatui_ruby/style/style.rbs +29 -0
  248. data/sig/ratatui_ruby/symbols.rbs +141 -0
  249. data/sig/ratatui_ruby/synthetic_events.rbs +24 -0
  250. data/sig/ratatui_ruby/table_state.rbs +27 -0
  251. data/sig/ratatui_ruby/terminal/capabilities.rbs +38 -0
  252. data/sig/ratatui_ruby/terminal/viewport.rbs +33 -0
  253. data/sig/ratatui_ruby/terminal_lifecycle.rbs +39 -0
  254. data/sig/ratatui_ruby/test_helper/event_injection.rbs +22 -0
  255. data/sig/ratatui_ruby/test_helper/snapshot.rbs +37 -0
  256. data/sig/ratatui_ruby/test_helper/style_assertions.rbs +77 -0
  257. data/sig/ratatui_ruby/test_helper/terminal.rbs +20 -0
  258. data/sig/ratatui_ruby/test_helper/test_doubles.rbs +32 -0
  259. data/sig/ratatui_ruby/test_helper.rbs +18 -0
  260. data/sig/ratatui_ruby/text/line.rbs +27 -0
  261. data/sig/ratatui_ruby/text/span.rbs +23 -0
  262. data/sig/ratatui_ruby/text.rbs +12 -0
  263. data/sig/ratatui_ruby/tui/buffer_factories.rbs +16 -0
  264. data/sig/ratatui_ruby/tui/canvas_factories.rbs +38 -0
  265. data/sig/ratatui_ruby/tui/core.rbs +23 -0
  266. data/sig/ratatui_ruby/tui/layout_factories.rbs +39 -0
  267. data/sig/ratatui_ruby/tui/state_factories.rbs +23 -0
  268. data/sig/ratatui_ruby/tui/style_factories.rbs +18 -0
  269. data/sig/ratatui_ruby/tui/text_factories.rbs +23 -0
  270. data/sig/ratatui_ruby/tui/widget_factories.rbs +138 -0
  271. data/sig/ratatui_ruby/tui.rbs +25 -0
  272. data/sig/ratatui_ruby/version.rbs +12 -0
  273. data/sig/ratatui_ruby/widgets/bar_chart.rbs +95 -0
  274. data/sig/ratatui_ruby/widgets/block.rbs +51 -0
  275. data/sig/ratatui_ruby/widgets/calendar.rbs +45 -0
  276. data/sig/ratatui_ruby/widgets/canvas.rbs +95 -0
  277. data/sig/ratatui_ruby/widgets/chart.rbs +91 -0
  278. data/sig/ratatui_ruby/widgets/coerceable_widget.rbs +26 -0
  279. data/sig/ratatui_ruby/widgets/gauge.rbs +44 -0
  280. data/sig/ratatui_ruby/widgets/line_gauge.rbs +48 -0
  281. data/sig/ratatui_ruby/widgets/list.rbs +63 -0
  282. data/sig/ratatui_ruby/widgets/misc.rbs +158 -0
  283. data/sig/ratatui_ruby/widgets/paragraph.rbs +45 -0
  284. data/sig/ratatui_ruby/widgets/row.rbs +43 -0
  285. data/sig/ratatui_ruby/widgets/scrollbar.rbs +53 -0
  286. data/sig/ratatui_ruby/widgets/shape/label.rbs +37 -0
  287. data/sig/ratatui_ruby/widgets/sparkline.rbs +45 -0
  288. data/sig/ratatui_ruby/widgets/table.rbs +78 -0
  289. data/sig/ratatui_ruby/widgets/tabs.rbs +44 -0
  290. data/sig/ratatui_ruby/widgets.rbs +16 -0
  291. data/vendor/goodcop/base.yml +1047 -0
  292. metadata +729 -0
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ class TUI
10
+ # State object factory methods for Session.
11
+ #
12
+ # Provides convenient access to stateful widget state objects
13
+ # (ListState, TableState, ScrollbarState) without fully
14
+ # qualifying the class names.
15
+ module StateFactories
16
+ # Creates a ListState.
17
+ # @return [ListState]
18
+ def list_state(...)
19
+ ListState.new(...)
20
+ end
21
+
22
+ # Creates a TableState.
23
+ # @return [TableState]
24
+ def table_state(...)
25
+ TableState.new(...)
26
+ end
27
+
28
+ # Creates a ScrollbarState.
29
+ # @return [ScrollbarState]
30
+ def scrollbar_state(...)
31
+ ScrollbarState.new(...)
32
+ end
33
+
34
+ # =====================================
35
+ # State Dispatcher (TIMTOWTDI)
36
+ # =====================================
37
+
38
+ # Creates a state object by type symbol.
39
+ #
40
+ # Stateful widgets need companion state objects. When building dynamic UIs,
41
+ # the state type must be determined at runtime.
42
+ #
43
+ # This dispatcher routes state creation through a single entry point.
44
+ # Pass the type as a symbol and the remaining parameters.
45
+ #
46
+ # Use it for generic list/table factories or config-driven components.
47
+ #
48
+ # Also available as: <tt>tui.list_state</tt>, <tt>tui.table_state</tt>
49
+ #
50
+ # === Examples
51
+ #
52
+ #--
53
+ # SPDX-SnippetBegin
54
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
55
+ # SPDX-License-Identifier: MIT-0
56
+ #++
57
+ # tui.state(:list, nil) # => ListState with no selection
58
+ # tui.state(:table, 0) # => TableState with row 0 selected
59
+ # tui.state(:scrollbar, 100) # => ScrollbarState with 100 content length
60
+ #--
61
+ # SPDX-SnippetEnd
62
+ #++
63
+ #
64
+ # @param type [Symbol] State type: :list, :table, :scrollbar
65
+ # @return [ListState, TableState, ScrollbarState]
66
+ def state(type, arg = nil)
67
+ case type
68
+ when :list then list_state(arg)
69
+ when :table then table_state(arg)
70
+ when :scrollbar then scrollbar_state(arg || 0)
71
+ else
72
+ raise ArgumentError, "Unknown state type: :#{type}. Valid types: :list, :table, :scrollbar"
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ class TUI
10
+ # Style factory methods for Session.
11
+ #
12
+ # Provides convenient access to Style::Style without fully
13
+ # qualifying the class name.
14
+ module StyleFactories
15
+ # Creates a Style::Style.
16
+ # @return [Style::Style]
17
+ def style(...)
18
+ Style::Style.new(...)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ class TUI
10
+ # Text factory methods for Session.
11
+ #
12
+ # Provides convenient access to Text::Span and Text::Line
13
+ # without fully qualifying the class names.
14
+ module TextFactories
15
+ # Creates a Text::Span.
16
+ # @return [Text::Span]
17
+ def text_span(...)
18
+ Text::Span.new(...)
19
+ end
20
+
21
+ # Creates a Text::Span (alias).
22
+ # @return [Text::Span]
23
+ def span(...)
24
+ Text::Span.new(...)
25
+ end
26
+
27
+ # Creates a Text::Line.
28
+ # @return [Text::Line]
29
+ def text_line(...)
30
+ Text::Line.new(...)
31
+ end
32
+
33
+ # Creates a Text::Line (alias).
34
+ # @return [Text::Line]
35
+ def line(...)
36
+ Text::Line.new(...)
37
+ end
38
+
39
+ # Calculates the display width of a string.
40
+ # @return [Integer]
41
+ def text_width(string)
42
+ Text.width(string)
43
+ end
44
+
45
+ # =====================================
46
+ # Text Dispatcher (TIMTOWTDI)
47
+ # =====================================
48
+
49
+ # Creates a text element by type symbol.
50
+ #
51
+ # Building text programmatically requires knowing which method to call.
52
+ # When the text type comes from config or user input, you need a dispatcher.
53
+ #
54
+ # This method routes text creation through a single entry point.
55
+ # Pass the type as a symbol and the remaining parameters as kwargs.
56
+ #
57
+ # Use it for dynamic text generation or config-driven rendering.
58
+ #
59
+ # Also available as: <tt>tui.span</tt>, <tt>tui.text_span</tt>
60
+ #
61
+ # === Examples
62
+ #
63
+ #--
64
+ # SPDX-SnippetBegin
65
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
66
+ # SPDX-License-Identifier: MIT-0
67
+ #++
68
+ # tui.text(:span, content: "Hello", style: Style.with(fg: :blue))
69
+ # tui.text(:line, spans: [tui.span(content: "World")])
70
+ #--
71
+ # SPDX-SnippetEnd
72
+ #++
73
+ #
74
+ # @param type [Symbol] Text type: :span, :line
75
+ # @return [Text::Span, Text::Line]
76
+ def text(type, **)
77
+ case type
78
+ when :span then text_span(**)
79
+ when :line then text_line(**)
80
+ else
81
+ raise ArgumentError, "Unknown text type: #{type.inspect}. Valid types: :span, :line"
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,272 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ class TUI
10
+ # Widget factory methods for Session.
11
+ #
12
+ # Provides convenient access to all Widgets::* classes without
13
+ # fully qualifying the class names. This is the largest mixin,
14
+ # covering all renderable UI components.
15
+ #
16
+ # All factories use DWIM hash coercion: both `tui.table(hash)` and
17
+ # `tui.table(**hash)` work correctly.
18
+ module WidgetFactories
19
+ # Creates a Widgets::Block.
20
+ # @return [Widgets::Block]
21
+ def block(first = nil, **kwargs)
22
+ Widgets::Block.coerce_args(first, kwargs)
23
+ end
24
+
25
+ # Creates a Widgets::Paragraph.
26
+ # @return [Widgets::Paragraph]
27
+ def paragraph(first = nil, **kwargs)
28
+ Widgets::Paragraph.coerce_args(first, kwargs)
29
+ end
30
+
31
+ # Creates a Widgets::List.
32
+ # @return [Widgets::List]
33
+ def list(first = nil, **kwargs)
34
+ Widgets::List.coerce_args(first, kwargs)
35
+ end
36
+
37
+ # Creates a Widgets::ListItem.
38
+ # @return [Widgets::ListItem]
39
+ def list_item(first = nil, **kwargs)
40
+ Widgets::ListItem.coerce_args(first, kwargs)
41
+ end
42
+
43
+ # Creates a Widgets::ListItem (DWIM alias).
44
+ #
45
+ # Terse alias for list_item. Clear in list context.
46
+ #
47
+ # @return [Widgets::ListItem]
48
+ alias item list_item
49
+
50
+ # Creates a Widgets::Table.
51
+ # @return [Widgets::Table]
52
+ def table(first = nil, **kwargs)
53
+ Widgets::Table.coerce_args(first, kwargs)
54
+ end
55
+
56
+ # Creates a Widgets::Row (for Table rows).
57
+ # @return [Widgets::Row]
58
+ def row(first = nil, **kwargs)
59
+ Widgets::Row.coerce_args(first, kwargs)
60
+ end
61
+
62
+ # Creates a Widgets::Row (alias for table row).
63
+ # @return [Widgets::Row]
64
+ def table_row(first = nil, **kwargs)
65
+ Widgets::Row.coerce_args(first, kwargs)
66
+ end
67
+
68
+ # Creates a Widgets::Cell (for Table cells).
69
+ # @return [Widgets::Cell]
70
+ def table_cell(first = nil, **kwargs)
71
+ Widgets::Cell.coerce_args(first, kwargs)
72
+ end
73
+
74
+ # Creates a Widgets::Tabs.
75
+ # @return [Widgets::Tabs]
76
+ def tabs(first = nil, **kwargs)
77
+ Widgets::Tabs.coerce_args(first, kwargs)
78
+ end
79
+
80
+ # Creates a Widgets::Gauge.
81
+ # @return [Widgets::Gauge]
82
+ def gauge(first = nil, **kwargs)
83
+ Widgets::Gauge.coerce_args(first, kwargs)
84
+ end
85
+
86
+ # Creates a Widgets::LineGauge.
87
+ # @return [Widgets::LineGauge]
88
+ def line_gauge(first = nil, **kwargs)
89
+ Widgets::LineGauge.coerce_args(first, kwargs)
90
+ end
91
+
92
+ # Creates a Widgets::Sparkline.
93
+ # @return [Widgets::Sparkline]
94
+ def sparkline(first = nil, **kwargs)
95
+ Widgets::Sparkline.coerce_args(first, kwargs)
96
+ end
97
+
98
+ # Creates a Widgets::BarChart.
99
+ # @return [Widgets::BarChart]
100
+ def bar_chart(first = nil, **kwargs)
101
+ Widgets::BarChart.coerce_args(first, kwargs)
102
+ end
103
+
104
+ # Creates a Widgets::BarChart::Bar.
105
+ # @return [Widgets::BarChart::Bar]
106
+ def bar(first = nil, **kwargs)
107
+ Widgets::BarChart::Bar.coerce_args(first, kwargs)
108
+ end
109
+
110
+ # Creates a Widgets::BarChart::BarGroup.
111
+ # @return [Widgets::BarChart::BarGroup]
112
+ def bar_group(first = nil, **kwargs)
113
+ Widgets::BarChart::BarGroup.coerce_args(first, kwargs)
114
+ end
115
+
116
+ # Creates a Widgets::BarChart::Bar (alias).
117
+ # @return [Widgets::BarChart::Bar]
118
+ def bar_chart_bar(first = nil, **kwargs)
119
+ Widgets::BarChart::Bar.coerce_args(first, kwargs)
120
+ end
121
+
122
+ # Creates a Widgets::BarChart::BarGroup (alias).
123
+ # @return [Widgets::BarChart::BarGroup]
124
+ def bar_chart_bar_group(first = nil, **kwargs)
125
+ Widgets::BarChart::BarGroup.coerce_args(first, kwargs)
126
+ end
127
+
128
+ # Creates a Widgets::Chart.
129
+ # @return [Widgets::Chart]
130
+ def chart(first = nil, **kwargs)
131
+ Widgets::Chart.coerce_args(first, kwargs)
132
+ end
133
+
134
+ # Creates a Widgets::Dataset.
135
+ # @return [Widgets::Dataset]
136
+ def dataset(first = nil, **kwargs)
137
+ Widgets::Dataset.coerce_args(first, kwargs)
138
+ end
139
+
140
+ # Creates a Widgets::Axis.
141
+ # @return [Widgets::Axis]
142
+ def axis(first = nil, **kwargs)
143
+ Widgets::Axis.coerce_args(first, kwargs)
144
+ end
145
+
146
+ # Creates a Widgets::Scrollbar.
147
+ # @return [Widgets::Scrollbar]
148
+ def scrollbar(first = nil, **kwargs)
149
+ Widgets::Scrollbar.coerce_args(first, kwargs)
150
+ end
151
+
152
+ # Creates a Widgets::Calendar.
153
+ # @return [Widgets::Calendar]
154
+ def calendar(first = nil, **kwargs)
155
+ Widgets::Calendar.coerce_args(first, kwargs)
156
+ end
157
+
158
+ # Creates a Widgets::Canvas.
159
+ # @return [Widgets::Canvas]
160
+ def canvas(first = nil, **kwargs)
161
+ Widgets::Canvas.coerce_args(first, kwargs)
162
+ end
163
+
164
+ # Creates a Widgets::Clear.
165
+ # @return [Widgets::Clear]
166
+ def clear(first = nil, **kwargs)
167
+ Widgets::Clear.coerce_args(first, kwargs)
168
+ end
169
+
170
+ # Creates a Widgets::Cursor.
171
+ # @return [Widgets::Cursor]
172
+ def cursor(first = nil, **kwargs)
173
+ Widgets::Cursor.coerce_args(first, kwargs)
174
+ end
175
+
176
+ # Creates a Widgets::Overlay.
177
+ # @return [Widgets::Overlay]
178
+ def overlay(first = nil, **kwargs)
179
+ Widgets::Overlay.coerce_args(first, kwargs)
180
+ end
181
+
182
+ # Creates a Widgets::Center.
183
+ # @return [Widgets::Center]
184
+ def center(first = nil, **kwargs)
185
+ Widgets::Center.coerce_args(first, kwargs)
186
+ end
187
+
188
+ # Creates a Widgets::RatatuiLogo.
189
+ # @return [Widgets::RatatuiLogo]
190
+ def ratatui_logo(first = nil, **kwargs)
191
+ Widgets::RatatuiLogo.coerce_args(first, kwargs)
192
+ end
193
+
194
+ # Creates a Widgets::RatatuiMascot.
195
+ # @return [Widgets::RatatuiMascot]
196
+ def ratatui_mascot(first = nil, **kwargs)
197
+ Widgets::RatatuiMascot.coerce_args(first, kwargs)
198
+ end
199
+
200
+ # Creates a Widgets::Shape::Label.
201
+ # @return [Widgets::Shape::Label]
202
+ def shape_label(first = nil, **kwargs)
203
+ Widgets::Shape::Label.coerce_args(first, kwargs)
204
+ end
205
+
206
+ # =====================================
207
+ # Widget Dispatcher (TIMTOWTDI)
208
+ # =====================================
209
+
210
+ # Creates a widget by type symbol.
211
+ #
212
+ # Plugin systems and config-driven UIs need to instantiate widgets by name.
213
+ # Without a dispatcher, you need tedious case statements or reflection.
214
+ #
215
+ # This method routes widget creation through a single entry point.
216
+ # Pass the type as a symbol and the remaining parameters as kwargs.
217
+ #
218
+ # Use it for dynamic UI generation, dashboard builders, or plugin architectures.
219
+ #
220
+ # Also available as: <tt>tui.paragraph</tt>, <tt>tui.list</tt>, etc.
221
+ #
222
+ # === Examples
223
+ #
224
+ #--
225
+ # SPDX-SnippetBegin
226
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
227
+ # SPDX-License-Identifier: MIT-0
228
+ #++
229
+ # tui.widget(:paragraph, text: "Hello World")
230
+ # tui.widget(:list, items: %w[One Two Three])
231
+ #
232
+ # # Config-driven widget creation
233
+ # widgets_config.each do |cfg|
234
+ # frame.render_widget(tui.widget(cfg[:type], **cfg[:options]), area)
235
+ # end
236
+ #--
237
+ # SPDX-SnippetEnd
238
+ #++
239
+ #
240
+ # @param type [Symbol] Widget type (see error message for full list)
241
+ # @return [Widgets::*]
242
+ def widget(type, first = nil, **)
243
+ case type
244
+ when :block then block(first, **)
245
+ when :paragraph then paragraph(first, **)
246
+ when :list then list(first, **)
247
+ when :table then table(first, **)
248
+ when :tabs then tabs(first, **)
249
+ when :gauge then gauge(first, **)
250
+ when :line_gauge then line_gauge(first, **)
251
+ when :sparkline then sparkline(first, **)
252
+ when :bar_chart then bar_chart(first, **)
253
+ when :chart then chart(first, **)
254
+ when :scrollbar then scrollbar(first, **)
255
+ when :calendar then calendar(first, **)
256
+ when :canvas then canvas(first, **)
257
+ when :clear then clear(first, **)
258
+ when :cursor then cursor(first, **)
259
+ when :overlay then overlay(first, **)
260
+ when :center then center(first, **)
261
+ when :ratatui_logo then ratatui_logo(first, **)
262
+ when :ratatui_mascot then ratatui_mascot(first, **)
263
+ else
264
+ raise ArgumentError, "Unknown widget type: #{type.inspect}. " \
265
+ "Valid types: :block, :paragraph, :list, :table, :tabs, :gauge, :line_gauge, " \
266
+ ":sparkline, :bar_chart, :chart, :scrollbar, :calendar, :canvas, :clear, " \
267
+ ":cursor, :overlay, :center, :ratatui_logo, :ratatui_mascot"
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ require_relative "tui/core"
9
+ require_relative "tui/layout_factories"
10
+ require_relative "tui/style_factories"
11
+ require_relative "tui/widget_factories"
12
+ require_relative "tui/text_factories"
13
+ require_relative "tui/state_factories"
14
+ require_relative "tui/canvas_factories"
15
+ require_relative "tui/buffer_factories"
16
+
17
+ module RatatuiRuby
18
+ # Manages the terminal lifecycle and provides a concise API for the render loop.
19
+ #
20
+ # Writing a TUI loop involves repetitive boilerplate. You constantly instantiate widgets
21
+ # (<tt>RatatuiRuby::Widgets::Paragraph.new</tt>) and call global methods (<tt>RatatuiRuby.draw</tt>).
22
+ # This is verbose and hard to read.
23
+ #
24
+ # The Session object simplifies this. It acts as a factory and a facade. It provides short helper
25
+ # methods for every widget and delegates core commands to the main module.
26
+ #
27
+ # Use it within <tt>RatatuiRuby.run</tt> to build your interface cleanly.
28
+ #
29
+ # == "Do What I Mean" (DWIM) Coercion
30
+ #
31
+ # The TUI factories add a *DWIM argument coercion layer* that the underlying
32
+ # Widget classes don't have. This means:
33
+ #
34
+ # - <tt>tui.table(rows: [...])</tt> coerces types, normalizes arrays, etc.
35
+ # - <tt>RatatuiRuby::Widgets::Table.new(rows: [...])</tt> passes arguments directly
36
+ #--
37
+ # SPDX-SnippetBegin
38
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
39
+ # SPDX-License-Identifier: MIT-0
40
+ #++
41
+ # to Rust without coercion — invalid types will raise <tt>TypeError</tt>.
42
+ #
43
+ #--
44
+ # SPDX-SnippetEnd
45
+ #++
46
+ # If you bypass the factories and call <tt>Widgets::Table.new</tt> directly,
47
+ # you're responsible for providing correctly-typed arguments. This is useful
48
+ # for debugging (to trigger real Rust TypeErrors) or performance-critical code.
49
+ #
50
+ # == Thread/Ractor Safety
51
+ #
52
+ # Session is an *I/O handle*, not a data object. It has side effects (draw,
53
+ # poll_event) and is intentionally *not* Ractor-shareable. Caching it in
54
+ # instance variables (<tt>@tui = tui</tt>) during your application's run loop
55
+ # is fine. However, do not include it in immutable Models/Messages or
56
+ # pass it to other Ractors.
57
+ #
58
+ # == Included Mixins
59
+ #
60
+ # [Core] Terminal operations: draw, poll_event, get_cell_at, draw_cell.
61
+ # [LayoutFactories] Layout helpers: rect, constraint_*, layout, layout_split.
62
+ # [StyleFactories] Style helpers: style.
63
+ # [WidgetFactories] Widget creation: block, paragraph, list, table, etc. (DWIM coercion)
64
+ # [TextFactories] Text helpers: span, line, text_width.
65
+ # [StateFactories] State objects: list_state, table_state, scrollbar_state.
66
+ # [CanvasFactories] Canvas shapes: shape_map, shape_line, shape_point, etc.
67
+ # [BufferFactories] Buffer inspection: cell.
68
+ #
69
+ # === Examples
70
+ #
71
+ # ==== Basic Usage (Recommended)
72
+ #
73
+ #--
74
+ # SPDX-SnippetBegin
75
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
76
+ # SPDX-License-Identifier: MIT-0
77
+ #++
78
+ # RatatuiRuby.run do |tui|
79
+ # loop do
80
+ # tui.draw \
81
+ # tui.paragraph \
82
+ # text: "Hello, Ratatui! Press 'q' to quit.",
83
+ # alignment: :center,
84
+ # block: tui.block(
85
+ # title: "My Ruby TUI App",
86
+ # borders: [:all],
87
+ # border_style: { fg: \"cyan\" }
88
+ # )
89
+ # event = tui.poll_event
90
+ # break if event == "q" || event == :ctrl_c
91
+ # end
92
+ # end
93
+ #--
94
+ # SPDX-SnippetEnd
95
+ #++
96
+ class TUI
97
+ include Core
98
+ include LayoutFactories
99
+ include StyleFactories
100
+ include WidgetFactories
101
+ include TextFactories
102
+ include StateFactories
103
+ include CanvasFactories
104
+ include BufferFactories
105
+ end
106
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ # The version of the ratatui_ruby gem.
10
+ # See https://semver.org/spec/v2.0.0.html
11
+ VERSION = "1.4.0"
12
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ module Widgets
10
+ class BarChart
11
+ # A bar in a grouped bar chart.
12
+ #
13
+ # === Examples
14
+ #
15
+ # BarChart::Bar.new(value: 10, style: Style.new(fg: :red), label: "A")
16
+ class Bar < Data.define(:value, :label, :style, :value_style, :text_value)
17
+ include CoerceableWidget
18
+
19
+ ##
20
+ # :attr_reader: value
21
+ # The value of the bar (Integer).
22
+
23
+ ##
24
+ # :attr_reader: label
25
+ # The label of the bar (optional String, Text::Span, or Text::Line for rich styling).
26
+
27
+ ##
28
+ # :attr_reader: style
29
+ # The style of the bar (optional Style).
30
+
31
+ ##
32
+ # :attr_reader: value_style
33
+ # The style of the value (optional Style).
34
+
35
+ ##
36
+ # :attr_reader: text_value
37
+ # The text to display as the value (optional String, Text::Span, or Text::Line for rich styling).
38
+
39
+ def initialize(value:, label: nil, style: nil, value_style: nil, text_value: nil)
40
+ super(
41
+ value: Integer(value),
42
+ label:,
43
+ style:,
44
+ value_style:,
45
+ text_value:
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
+ #++
7
+
8
+ module RatatuiRuby
9
+ module Widgets
10
+ class BarChart
11
+ # A group of bars in a grouped bar chart.
12
+ #
13
+ # === Examples
14
+ #
15
+ # BarChart::BarGroup.new(label: "Q1", bars: [BarChart::Bar.new(value: 10), BarChart::Bar.new(value: 20)])
16
+ class BarGroup < Data.define(:label, :bars)
17
+ include CoerceableWidget
18
+
19
+ ##
20
+ # :attr_reader: label
21
+ # The label of the group (String).
22
+
23
+ ##
24
+ # :attr_reader: bars
25
+ # The bars in the group (Array of Bar).
26
+ end
27
+ end
28
+ end
29
+ end