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,435 @@
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
+ # Symbol constants from Ratatui's symbols module.
10
+ #
11
+ # Ratatui provides various character sets for rendering UI elements.
12
+ # Hardcoding these characters is error-prone and makes code less readable.
13
+ #
14
+ # This module exposes those constants for Ruby apps to use directly.
15
+ # Use them for gradients, fills, or custom widget styling.
16
+ module Symbols
17
+ # Shade characters for creating gradient or density effects.
18
+ #
19
+ # Terminal UIs often need to show density levels or create visual gradients.
20
+ # Memorizing Unicode block characters is tedious and error-prone.
21
+ #
22
+ # These constants provide named access to the standard shade characters.
23
+ # Use them to fill areas with varying visual densities.
24
+ #
25
+ # === Examples
26
+ #
27
+ #--
28
+ # SPDX-SnippetBegin
29
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
30
+ # SPDX-License-Identifier: MIT-0
31
+ #++
32
+ # # Create a density gradient
33
+ # gradient = [Shade::EMPTY, Shade::LIGHT, Shade::MEDIUM, Shade::DARK, Shade::FULL]
34
+ #
35
+ # # Use in a progress indicator
36
+ # filled = Shade::FULL * progress
37
+ # empty = Shade::LIGHT * (total - progress)
38
+ #--
39
+ # SPDX-SnippetEnd
40
+ #++
41
+ module Shade
42
+ # Empty space - 0% density.
43
+ EMPTY = " "
44
+
45
+ # Light shading - approximately 25% density.
46
+ LIGHT = "░"
47
+
48
+ # Medium shading - approximately 50% density.
49
+ MEDIUM = "▒"
50
+
51
+ # Dark shading - approximately 75% density.
52
+ DARK = "▓"
53
+
54
+ # Full block - 100% density.
55
+ FULL = "█"
56
+ end
57
+
58
+ # Box-drawing characters for borders and lines.
59
+ #
60
+ # Terminal UIs need consistent box-drawing characters for borders and dividers.
61
+ # Memorizing Unicode box-drawing characters is tedious and error-prone.
62
+ #
63
+ # This module exposes both individual characters and predefined sets.
64
+ # Use the sets with widgets that accept a line_set parameter, or use
65
+ # individual characters for custom drawing.
66
+ #
67
+ # === Examples
68
+ #
69
+ #--
70
+ # SPDX-SnippetBegin
71
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
72
+ # SPDX-License-Identifier: MIT-0
73
+ #++
74
+ # # Use a predefined set for drawing boxes
75
+ # line_set = Symbols::Line::ROUNDED
76
+ #
77
+ # # Draw a simple frame
78
+ # top = "#{line_set[:top_left]}#{line_set[:horizontal] * 10}#{line_set[:top_right]}"
79
+ # mid = "#{line_set[:vertical]}#{' ' * 10}#{line_set[:vertical]}"
80
+ # bot = "#{line_set[:bottom_left]}#{line_set[:horizontal] * 10}#{line_set[:bottom_right]}"
81
+ #
82
+ # # Use individual characters for custom drawing
83
+ # corner = Symbols::Line::ROUNDED_TOP_LEFT # => "╭"
84
+ #--
85
+ # SPDX-SnippetEnd
86
+ #++
87
+ module Line
88
+ # Standard vertical line.
89
+ VERTICAL = "│"
90
+ # Double vertical line.
91
+ DOUBLE_VERTICAL = "║"
92
+ # Thick (heavy) vertical line.
93
+ THICK_VERTICAL = "┃"
94
+
95
+ # Standard horizontal line.
96
+ HORIZONTAL = "─"
97
+ # Double horizontal line.
98
+ DOUBLE_HORIZONTAL = "═"
99
+ # Thick (heavy) horizontal line.
100
+ THICK_HORIZONTAL = "━"
101
+
102
+ # Standard top-right corner.
103
+ TOP_RIGHT = "┐"
104
+ # Rounded top-right corner.
105
+ ROUNDED_TOP_RIGHT = "╮"
106
+ # Double top-right corner.
107
+ DOUBLE_TOP_RIGHT = "╗"
108
+ # Thick top-right corner.
109
+ THICK_TOP_RIGHT = "┓"
110
+
111
+ # Standard top-left corner.
112
+ TOP_LEFT = "┌"
113
+ # Rounded top-left corner.
114
+ ROUNDED_TOP_LEFT = "╭"
115
+ # Double top-left corner.
116
+ DOUBLE_TOP_LEFT = "╔"
117
+ # Thick top-left corner.
118
+ THICK_TOP_LEFT = "┏"
119
+
120
+ # Standard bottom-right corner.
121
+ BOTTOM_RIGHT = "┘"
122
+ # Rounded bottom-right corner.
123
+ ROUNDED_BOTTOM_RIGHT = "╯"
124
+ # Double bottom-right corner.
125
+ DOUBLE_BOTTOM_RIGHT = "╝"
126
+ # Thick bottom-right corner.
127
+ THICK_BOTTOM_RIGHT = "┛"
128
+
129
+ # Standard bottom-left corner.
130
+ BOTTOM_LEFT = "└"
131
+ # Rounded bottom-left corner.
132
+ ROUNDED_BOTTOM_LEFT = "╰"
133
+ # Double bottom-left corner.
134
+ DOUBLE_BOTTOM_LEFT = "╚"
135
+ # Thick bottom-left corner.
136
+ THICK_BOTTOM_LEFT = "┗"
137
+
138
+ # Standard T-junction pointing left.
139
+ VERTICAL_LEFT = "┤"
140
+ # Double T-junction pointing left.
141
+ DOUBLE_VERTICAL_LEFT = "╣"
142
+ # Thick T-junction pointing left.
143
+ THICK_VERTICAL_LEFT = "┫"
144
+
145
+ # Standard T-junction pointing right.
146
+ VERTICAL_RIGHT = "├"
147
+ # Double T-junction pointing right.
148
+ DOUBLE_VERTICAL_RIGHT = "╠"
149
+ # Thick T-junction pointing right.
150
+ THICK_VERTICAL_RIGHT = "┣"
151
+
152
+ # Standard T-junction pointing down.
153
+ HORIZONTAL_DOWN = "┬"
154
+ # Double T-junction pointing down.
155
+ DOUBLE_HORIZONTAL_DOWN = "╦"
156
+ # Thick T-junction pointing down.
157
+ THICK_HORIZONTAL_DOWN = "┳"
158
+
159
+ # Standard T-junction pointing up.
160
+ HORIZONTAL_UP = "┴"
161
+ # Double T-junction pointing up.
162
+ DOUBLE_HORIZONTAL_UP = "╩"
163
+ # Thick T-junction pointing up.
164
+ THICK_HORIZONTAL_UP = "┻"
165
+
166
+ # Standard cross (4-way intersection).
167
+ CROSS = "┼"
168
+ # Double cross (4-way intersection).
169
+ DOUBLE_CROSS = "╬"
170
+ # Thick cross (4-way intersection).
171
+ THICK_CROSS = "╋"
172
+
173
+ # Standard box-drawing set with straight corners.
174
+ NORMAL = {
175
+ vertical: VERTICAL,
176
+ horizontal: HORIZONTAL,
177
+ top_right: TOP_RIGHT,
178
+ top_left: TOP_LEFT,
179
+ bottom_right: BOTTOM_RIGHT,
180
+ bottom_left: BOTTOM_LEFT,
181
+ vertical_left: VERTICAL_LEFT,
182
+ vertical_right: VERTICAL_RIGHT,
183
+ horizontal_down: HORIZONTAL_DOWN,
184
+ horizontal_up: HORIZONTAL_UP,
185
+ cross: CROSS,
186
+ }.freeze
187
+
188
+ # Box-drawing set with rounded corners.
189
+ ROUNDED = {
190
+ vertical: VERTICAL,
191
+ horizontal: HORIZONTAL,
192
+ top_right: ROUNDED_TOP_RIGHT,
193
+ top_left: ROUNDED_TOP_LEFT,
194
+ bottom_right: ROUNDED_BOTTOM_RIGHT,
195
+ bottom_left: ROUNDED_BOTTOM_LEFT,
196
+ vertical_left: VERTICAL_LEFT,
197
+ vertical_right: VERTICAL_RIGHT,
198
+ horizontal_down: HORIZONTAL_DOWN,
199
+ horizontal_up: HORIZONTAL_UP,
200
+ cross: CROSS,
201
+ }.freeze
202
+
203
+ # Double-line box-drawing set.
204
+ DOUBLE = {
205
+ vertical: DOUBLE_VERTICAL,
206
+ horizontal: DOUBLE_HORIZONTAL,
207
+ top_right: DOUBLE_TOP_RIGHT,
208
+ top_left: DOUBLE_TOP_LEFT,
209
+ bottom_right: DOUBLE_BOTTOM_RIGHT,
210
+ bottom_left: DOUBLE_BOTTOM_LEFT,
211
+ vertical_left: DOUBLE_VERTICAL_LEFT,
212
+ vertical_right: DOUBLE_VERTICAL_RIGHT,
213
+ horizontal_down: DOUBLE_HORIZONTAL_DOWN,
214
+ horizontal_up: DOUBLE_HORIZONTAL_UP,
215
+ cross: DOUBLE_CROSS,
216
+ }.freeze
217
+
218
+ # Thick (heavy) box-drawing set.
219
+ THICK = {
220
+ vertical: THICK_VERTICAL,
221
+ horizontal: THICK_HORIZONTAL,
222
+ top_right: THICK_TOP_RIGHT,
223
+ top_left: THICK_TOP_LEFT,
224
+ bottom_right: THICK_BOTTOM_RIGHT,
225
+ bottom_left: THICK_BOTTOM_LEFT,
226
+ vertical_left: THICK_VERTICAL_LEFT,
227
+ vertical_right: THICK_VERTICAL_RIGHT,
228
+ horizontal_down: THICK_HORIZONTAL_DOWN,
229
+ horizontal_up: THICK_HORIZONTAL_UP,
230
+ cross: THICK_CROSS,
231
+ }.freeze
232
+ end
233
+
234
+ # Vertical bar characters for sparklines and bar charts.
235
+ #
236
+ # Sparklines and vertical bar charts need characters that show partial fill.
237
+ # Memorizing Unicode lower block characters is tedious and error-prone.
238
+ #
239
+ # This module exposes both individual characters and predefined sets.
240
+ # Use the sets with Sparkline widget, or use individual characters for
241
+ # custom visualizations.
242
+ #
243
+ # === Examples
244
+ #
245
+ #--
246
+ # SPDX-SnippetBegin
247
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
248
+ # SPDX-License-Identifier: MIT-0
249
+ #++
250
+ # # Use NINE_LEVELS for high-resolution sparklines (default)
251
+ # sparkline = tui.sparkline(data: [1, 2, 3], bar_set: Symbols::Bar::NINE_LEVELS)
252
+ #
253
+ # # Use THREE_LEVELS for simpler rendering
254
+ # sparkline = tui.sparkline(data: [1, 2, 3], bar_set: Symbols::Bar::THREE_LEVELS)
255
+ #--
256
+ # SPDX-SnippetEnd
257
+ #++
258
+ module Bar
259
+ # Full height bar (8/8).
260
+ FULL = "█"
261
+ # 7/8 height bar.
262
+ SEVEN_EIGHTHS = "▇"
263
+ # 3/4 height bar (6/8).
264
+ THREE_QUARTERS = "▆"
265
+ # 5/8 height bar.
266
+ FIVE_EIGHTHS = "▅"
267
+ # Half height bar (4/8).
268
+ HALF = "▄"
269
+ # 3/8 height bar.
270
+ THREE_EIGHTHS = "▃"
271
+ # 1/4 height bar (2/8).
272
+ ONE_QUARTER = "▂"
273
+ # 1/8 height bar.
274
+ ONE_EIGHTH = "▁"
275
+
276
+ # High-resolution bar set with 9 distinct levels.
277
+ NINE_LEVELS = {
278
+ full: FULL,
279
+ seven_eighths: SEVEN_EIGHTHS,
280
+ three_quarters: THREE_QUARTERS,
281
+ five_eighths: FIVE_EIGHTHS,
282
+ half: HALF,
283
+ three_eighths: THREE_EIGHTHS,
284
+ one_quarter: ONE_QUARTER,
285
+ one_eighth: ONE_EIGHTH,
286
+ empty: " ",
287
+ }.freeze
288
+
289
+ # Low-resolution bar set with 3 levels (full, half, empty).
290
+ THREE_LEVELS = {
291
+ full: FULL,
292
+ seven_eighths: FULL, # collapsed to full
293
+ three_quarters: HALF, # collapsed to half
294
+ five_eighths: HALF, # collapsed to half
295
+ half: HALF,
296
+ three_eighths: HALF, # collapsed to half
297
+ one_quarter: HALF, # collapsed to half
298
+ one_eighth: " ", # collapsed to empty
299
+ empty: " ",
300
+ }.freeze
301
+ end
302
+
303
+ # Horizontal block characters for gauges and progress indicators.
304
+ #
305
+ # Progress bars and gauges need characters that show partial fill from left to right.
306
+ # Memorizing Unicode left block characters is tedious and error-prone.
307
+ #
308
+ # This module exposes both individual characters and predefined sets.
309
+ # Use the sets with Gauge widget, or use individual characters for
310
+ # custom progress indicators.
311
+ #
312
+ # Note: Block uses LEFT block characters (fill from left) while Bar uses
313
+ # LOWER block characters (fill from bottom). They look similar but are different.
314
+ #
315
+ # === Examples
316
+ #
317
+ #--
318
+ # SPDX-SnippetBegin
319
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
320
+ # SPDX-License-Identifier: MIT-0
321
+ #++
322
+ # # Use NINE_LEVELS for high-resolution gauges (default)
323
+ # gauge = tui.gauge(percent: 50, block_set: Symbols::Block::NINE_LEVELS)
324
+ #
325
+ # # Use THREE_LEVELS for simpler rendering
326
+ # gauge = tui.gauge(percent: 50, block_set: Symbols::Block::THREE_LEVELS)
327
+ #--
328
+ # SPDX-SnippetEnd
329
+ #++
330
+ module Block
331
+ # Full width block (8/8).
332
+ FULL = "█"
333
+ # 7/8 width block.
334
+ SEVEN_EIGHTHS = "▉"
335
+ # 3/4 width block (6/8).
336
+ THREE_QUARTERS = "▊"
337
+ # 5/8 width block.
338
+ FIVE_EIGHTHS = "▋"
339
+ # Half width block (4/8).
340
+ HALF = "▌"
341
+ # 3/8 width block.
342
+ THREE_EIGHTHS = "▍"
343
+ # 1/4 width block (2/8).
344
+ ONE_QUARTER = "▎"
345
+ # 1/8 width block.
346
+ ONE_EIGHTH = "▏"
347
+
348
+ # High-resolution block set with 9 distinct levels.
349
+ NINE_LEVELS = {
350
+ full: FULL,
351
+ seven_eighths: SEVEN_EIGHTHS,
352
+ three_quarters: THREE_QUARTERS,
353
+ five_eighths: FIVE_EIGHTHS,
354
+ half: HALF,
355
+ three_eighths: THREE_EIGHTHS,
356
+ one_quarter: ONE_QUARTER,
357
+ one_eighth: ONE_EIGHTH,
358
+ empty: " ",
359
+ }.freeze
360
+
361
+ # Low-resolution block set with 3 levels (full, half, empty).
362
+ THREE_LEVELS = {
363
+ full: FULL,
364
+ seven_eighths: FULL, # collapsed to full
365
+ three_quarters: HALF, # collapsed to half
366
+ five_eighths: HALF, # collapsed to half
367
+ half: HALF,
368
+ three_eighths: HALF, # collapsed to half
369
+ one_quarter: HALF, # collapsed to half
370
+ one_eighth: " ", # collapsed to empty
371
+ empty: " ",
372
+ }.freeze
373
+ end
374
+
375
+ # Scrollbar symbol sets for the Scrollbar widget.
376
+ #
377
+ # Scrollbars need consistent visual elements: a track, a thumb, and arrow indicators.
378
+ # Memorizing Unicode scroll characters is tedious and error-prone.
379
+ #
380
+ # This module exposes predefined sets with different visual styles.
381
+ # Use them with the Scrollbar widget to customize its appearance.
382
+ #
383
+ # Note: Uses <tt>begin_char</tt> and <tt>end_char</tt> instead of Rust's
384
+ # <tt>begin</tt>/<tt>end</tt> to avoid Ruby reserved word conflicts.
385
+ #
386
+ # === Examples
387
+ #
388
+ #--
389
+ # SPDX-SnippetBegin
390
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
391
+ # SPDX-License-Identifier: MIT-0
392
+ #++
393
+ # # Use DOUBLE_VERTICAL for bold vertical scrollbars (default)
394
+ # scrollbar = tui.scrollbar(symbols: Symbols::Scrollbar::DOUBLE_VERTICAL)
395
+ #
396
+ # # Use VERTICAL for lighter appearance
397
+ # scrollbar = tui.scrollbar(symbols: Symbols::Scrollbar::VERTICAL)
398
+ #--
399
+ # SPDX-SnippetEnd
400
+ #++
401
+ module Scrollbar
402
+ # Double-line vertical scrollbar with triangle arrows.
403
+ DOUBLE_VERTICAL = {
404
+ track: Line::DOUBLE_VERTICAL,
405
+ thumb: Block::FULL,
406
+ begin_char: "▲",
407
+ end_char: "▼",
408
+ }.freeze
409
+
410
+ # Double-line horizontal scrollbar with triangle arrows.
411
+ DOUBLE_HORIZONTAL = {
412
+ track: Line::DOUBLE_HORIZONTAL,
413
+ thumb: Block::FULL,
414
+ begin_char: "◄",
415
+ end_char: "►",
416
+ }.freeze
417
+
418
+ # Single-line vertical scrollbar with arrow characters.
419
+ VERTICAL = {
420
+ track: Line::VERTICAL,
421
+ thumb: Block::FULL,
422
+ begin_char: "↑",
423
+ end_char: "↓",
424
+ }.freeze
425
+
426
+ # Single-line horizontal scrollbar with arrow characters.
427
+ HORIZONTAL = {
428
+ track: Line::HORIZONTAL,
429
+ thumb: Block::FULL,
430
+ begin_char: "←",
431
+ end_char: "→",
432
+ }.freeze
433
+ end
434
+ end
435
+ 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
+ module RatatuiRuby
9
+ ##
10
+ # Ruby-only event queue for synthetic events.
11
+ #
12
+ # Native events flow through the Rust backend. Synthetic events bypass it.
13
+ # Runtimes (Tea, Kit) check this queue and handle events like
14
+ # <tt>Event::Sync</tt> specially.
15
+ #
16
+ # *For runtime authors:* Check <tt>pending?</tt> each loop iteration after
17
+ # polling native events. When true, pop the event and handle it. For
18
+ # <tt>Event::Sync</tt>, wait for pending threads and process background
19
+ # results before continuing.
20
+ #
21
+ # *For app developers:* Push <tt>Event::Sync</tt> when you need async
22
+ # results before continuing. The runtime will block until all pending
23
+ # work completes. Use this for "ensure saves complete before quit."
24
+ #
25
+ # *For test authors:* Use <tt>inject_sync</tt> between events to create
26
+ # synchronization points. This enables deterministic testing of async
27
+ # behavior.
28
+ #
29
+ # === Example
30
+ #
31
+ #--
32
+ # SPDX-SnippetBegin
33
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
34
+ # SPDX-License-Identifier: MIT-0
35
+ #++
36
+ # # Production: ensure async saves finish before exiting
37
+ # RatatuiRuby::SyntheticEvents.push(RatatuiRuby::Event::Sync.new)
38
+ #
39
+ # # Runtime authors: check in your event loop
40
+ # if RatatuiRuby::SyntheticEvents.pending?
41
+ # event = RatatuiRuby::SyntheticEvents.pop
42
+ # handle_sync if event.sync?
43
+ # end
44
+ #
45
+ #--
46
+ # SPDX-SnippetEnd
47
+ #++
48
+ module SyntheticEvents
49
+ @queue = [] #: Array[Event]
50
+ @mutex = Mutex.new
51
+ @inline_sync = false #: bool
52
+
53
+ class << self
54
+ ##
55
+ # Enables inline sync mode for deterministic event ordering.
56
+ #
57
+ # Call once at startup. Cannot be disabled.
58
+ #
59
+ # When enabled, +inject_sync+ routes through the native event queue
60
+ # and +poll_event+ returns +Event::Sync+ like any other event.
61
+ # This ensures sync events are processed in sequence with key events.
62
+ #
63
+ # Runtimes that need ordering guarantees (like Rooibos) should call
64
+ # this before entering their event loop.
65
+ def inline_sync!
66
+ @inline_sync = true
67
+ end
68
+
69
+ def inline_sync? # :nodoc:
70
+ @inline_sync
71
+ end
72
+
73
+ ##
74
+ # Pushes an event to the synthetic queue.
75
+ #
76
+ # [event] An <tt>Event</tt> object (typically <tt>Event::Sync</tt>).
77
+ def push(event)
78
+ @mutex.synchronize { @queue << event }
79
+ end
80
+
81
+ ##
82
+ # Pops an event from the synthetic queue.
83
+ #
84
+ # Returns the oldest pending event, or <tt>nil</tt> if empty.
85
+ def pop
86
+ @mutex.synchronize { @queue.shift }
87
+ end
88
+
89
+ ##
90
+ # Clears all pending synthetic events.
91
+ #
92
+ # Test helpers call this during teardown to reset state between tests.
93
+ def clear
94
+ @mutex.synchronize { @queue.clear }
95
+ end
96
+
97
+ ##
98
+ # Checks for pending synthetic events.
99
+ #
100
+ # Returns <tt>true</tt> if the queue has events waiting.
101
+ def pending?
102
+ @mutex.synchronize { !@queue.empty? }
103
+ end
104
+ end
105
+ end
106
+ end