ratatui_ruby 0.4.0 → 0.6.0

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 (441) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +1 -1
  3. data/.builds/ruby-3.3.yml +1 -1
  4. data/.builds/ruby-3.4.yml +1 -1
  5. data/.builds/ruby-4.0.0.yml +1 -1
  6. data/AGENTS.md +98 -176
  7. data/CHANGELOG.md +80 -6
  8. data/README.md +19 -7
  9. data/REUSE.toml +15 -0
  10. data/doc/application_architecture.md +179 -45
  11. data/doc/application_testing.md +80 -32
  12. data/doc/contributors/design/ruby_frontend.md +48 -8
  13. data/doc/contributors/design/rust_backend.md +1 -0
  14. data/doc/contributors/developing_examples.md +191 -48
  15. data/doc/contributors/documentation_style.md +7 -0
  16. data/doc/contributors/examples_audit/p1_high.md +21 -0
  17. data/doc/contributors/examples_audit/p2_moderate.md +81 -0
  18. data/doc/contributors/examples_audit.md +41 -0
  19. data/doc/contributors/index.md +2 -0
  20. data/doc/event_handling.md +21 -7
  21. data/doc/images/app_all_events.png +0 -0
  22. data/doc/images/app_color_picker.png +0 -0
  23. data/doc/images/app_login_form.png +0 -0
  24. data/doc/images/app_stateful_interaction.png +0 -0
  25. data/doc/images/verify_quickstart_dsl.png +0 -0
  26. data/doc/images/verify_quickstart_layout.png +0 -0
  27. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  28. data/doc/images/verify_readme_usage.png +0 -0
  29. data/doc/images/widget_barchart_demo.png +0 -0
  30. data/doc/images/widget_block_demo.png +0 -0
  31. data/doc/images/widget_box_demo.png +0 -0
  32. data/doc/images/widget_calendar_demo.png +0 -0
  33. data/doc/images/widget_canvas_demo.png +0 -0
  34. data/doc/images/widget_cell_demo.png +0 -0
  35. data/doc/images/widget_center_demo.png +0 -0
  36. data/doc/images/widget_chart_demo.png +0 -0
  37. data/doc/images/widget_gauge_demo.png +0 -0
  38. data/doc/images/widget_layout_split.png +0 -0
  39. data/doc/images/widget_line_gauge_demo.png +0 -0
  40. data/doc/images/widget_list_demo.png +0 -0
  41. data/doc/images/widget_overlay_demo.png +0 -0
  42. data/doc/images/widget_ratatui_logo_demo.png +0 -0
  43. data/doc/images/widget_ratatui_mascot_demo.png +0 -0
  44. data/doc/images/widget_render.png +0 -0
  45. data/doc/images/widget_rich_text.png +0 -0
  46. data/doc/images/widget_scroll_text.png +0 -0
  47. data/doc/images/widget_scrollbar_demo.png +0 -0
  48. data/doc/images/widget_sparkline_demo.png +0 -0
  49. data/doc/images/widget_style_colors.png +0 -0
  50. data/doc/images/widget_table_demo.png +0 -0
  51. data/doc/images/widget_table_flex.png +0 -0
  52. data/doc/images/widget_tabs_demo.png +0 -0
  53. data/doc/images/widget_text_width.png +0 -0
  54. data/doc/interactive_design.md +25 -30
  55. data/doc/quickstart.md +150 -130
  56. data/doc/terminal_limitations.md +92 -0
  57. data/examples/app_all_events/README.md +99 -0
  58. data/examples/app_all_events/app.rb +96 -0
  59. data/examples/app_all_events/model/app_model.rb +157 -0
  60. data/examples/app_all_events/model/event_color_cycle.rb +41 -0
  61. data/examples/app_all_events/model/event_entry.rb +92 -0
  62. data/examples/app_all_events/model/msg.rb +37 -0
  63. data/examples/app_all_events/model/timestamp.rb +54 -0
  64. data/examples/app_all_events/update.rb +73 -0
  65. data/examples/app_all_events/view/app_view.rb +78 -0
  66. data/examples/app_all_events/view/controls_view.rb +52 -0
  67. data/examples/app_all_events/view/counts_view.rb +59 -0
  68. data/examples/app_all_events/view/live_view.rb +70 -0
  69. data/examples/app_all_events/view/log_view.rb +55 -0
  70. data/examples/app_all_events/view.rb +7 -0
  71. data/examples/app_color_picker/README.md +134 -0
  72. data/examples/app_color_picker/app.rb +74 -0
  73. data/examples/app_color_picker/clipboard.rb +84 -0
  74. data/examples/app_color_picker/color.rb +191 -0
  75. data/examples/app_color_picker/controls.rb +90 -0
  76. data/examples/app_color_picker/copy_dialog.rb +166 -0
  77. data/examples/app_color_picker/export_pane.rb +126 -0
  78. data/examples/app_color_picker/harmony.rb +56 -0
  79. data/examples/app_color_picker/input.rb +174 -0
  80. data/examples/app_color_picker/main_container.rb +178 -0
  81. data/examples/app_color_picker/palette.rb +109 -0
  82. data/examples/app_login_form/README.md +47 -0
  83. data/examples/{login_form → app_login_form}/app.rb +38 -42
  84. data/examples/app_stateful_interaction/README.md +31 -0
  85. data/examples/app_stateful_interaction/app.rb +272 -0
  86. data/examples/timeout_demo.rb +43 -0
  87. data/examples/verify_quickstart_dsl/README.md +48 -0
  88. data/examples/{quickstart_dsl → verify_quickstart_dsl}/app.rb +17 -6
  89. data/examples/verify_quickstart_layout/README.md +71 -0
  90. data/examples/verify_quickstart_layout/app.rb +71 -0
  91. data/examples/verify_quickstart_lifecycle/README.md +56 -0
  92. data/examples/verify_quickstart_lifecycle/app.rb +54 -0
  93. data/examples/verify_readme_usage/README.md +43 -0
  94. data/examples/verify_readme_usage/app.rb +40 -0
  95. data/examples/widget_barchart_demo/README.md +49 -0
  96. data/examples/widget_barchart_demo/app.rb +238 -0
  97. data/examples/widget_block_demo/README.md +34 -0
  98. data/examples/widget_block_demo/app.rb +256 -0
  99. data/examples/widget_box_demo/README.md +45 -0
  100. data/examples/{box_demo → widget_box_demo}/app.rb +99 -65
  101. data/examples/widget_calendar_demo/README.md +39 -0
  102. data/examples/widget_calendar_demo/app.rb +109 -0
  103. data/examples/widget_canvas_demo/README.md +27 -0
  104. data/examples/widget_canvas_demo/app.rb +123 -0
  105. data/examples/widget_cell_demo/README.md +36 -0
  106. data/examples/widget_cell_demo/app.rb +111 -0
  107. data/examples/widget_center_demo/README.md +29 -0
  108. data/examples/widget_center_demo/app.rb +116 -0
  109. data/examples/widget_chart_demo/README.md +41 -0
  110. data/examples/widget_chart_demo/app.rb +218 -0
  111. data/examples/widget_gauge_demo/README.md +41 -0
  112. data/examples/widget_gauge_demo/app.rb +212 -0
  113. data/examples/widget_layout_split/README.md +44 -0
  114. data/examples/widget_layout_split/app.rb +246 -0
  115. data/examples/widget_line_gauge_demo/README.md +41 -0
  116. data/examples/widget_line_gauge_demo/app.rb +217 -0
  117. data/examples/widget_list_demo/README.md +49 -0
  118. data/examples/widget_list_demo/app.rb +366 -0
  119. data/examples/widget_map_demo/README.md +39 -0
  120. data/examples/{map_demo → widget_map_demo}/app.rb +24 -21
  121. data/examples/widget_overlay_demo/app.rb +248 -0
  122. data/examples/widget_popup_demo/README.md +36 -0
  123. data/examples/widget_popup_demo/app.rb +104 -0
  124. data/examples/widget_ratatui_logo_demo/README.md +34 -0
  125. data/examples/widget_ratatui_logo_demo/app.rb +103 -0
  126. data/examples/widget_ratatui_mascot_demo/README.md +34 -0
  127. data/examples/widget_ratatui_mascot_demo/app.rb +93 -0
  128. data/examples/widget_rect/README.md +38 -0
  129. data/examples/widget_rect/app.rb +205 -0
  130. data/examples/widget_render/README.md +37 -0
  131. data/examples/widget_render/app.rb +184 -0
  132. data/examples/widget_rich_text/README.md +35 -0
  133. data/examples/widget_rich_text/app.rb +166 -0
  134. data/examples/widget_scroll_text/README.md +37 -0
  135. data/examples/widget_scroll_text/app.rb +107 -0
  136. data/examples/widget_scrollbar_demo/README.md +37 -0
  137. data/examples/widget_scrollbar_demo/app.rb +153 -0
  138. data/examples/widget_sparkline_demo/README.md +42 -0
  139. data/examples/widget_sparkline_demo/app.rb +275 -0
  140. data/examples/widget_style_colors/README.md +34 -0
  141. data/examples/widget_style_colors/app.rb +19 -21
  142. data/examples/widget_table_demo/README.md +48 -0
  143. data/examples/widget_table_demo/app.rb +239 -0
  144. data/examples/widget_tabs_demo/README.md +41 -0
  145. data/examples/widget_tabs_demo/app.rb +181 -0
  146. data/examples/widget_text_width/README.md +35 -0
  147. data/examples/widget_text_width/app.rb +106 -0
  148. data/ext/ratatui_ruby/Cargo.lock +11 -4
  149. data/ext/ratatui_ruby/Cargo.toml +2 -1
  150. data/ext/ratatui_ruby/src/events.rs +359 -62
  151. data/ext/ratatui_ruby/src/frame.rs +227 -0
  152. data/ext/ratatui_ruby/src/lib.rs +110 -27
  153. data/ext/ratatui_ruby/src/rendering.rs +8 -4
  154. data/ext/ratatui_ruby/src/string_width.rs +101 -0
  155. data/ext/ratatui_ruby/src/style.rs +138 -57
  156. data/ext/ratatui_ruby/src/terminal.rs +42 -22
  157. data/ext/ratatui_ruby/src/text.rs +14 -7
  158. data/ext/ratatui_ruby/src/widgets/barchart.rs +74 -54
  159. data/ext/ratatui_ruby/src/widgets/block.rs +7 -6
  160. data/ext/ratatui_ruby/src/widgets/canvas.rs +21 -3
  161. data/ext/ratatui_ruby/src/widgets/chart.rs +20 -10
  162. data/ext/ratatui_ruby/src/widgets/gauge.rs +9 -2
  163. data/ext/ratatui_ruby/src/widgets/layout.rs +9 -4
  164. data/ext/ratatui_ruby/src/widgets/line_gauge.rs +9 -2
  165. data/ext/ratatui_ruby/src/widgets/list.rs +211 -12
  166. data/ext/ratatui_ruby/src/widgets/list_state.rs +137 -0
  167. data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
  168. data/ext/ratatui_ruby/src/widgets/overlay.rs +2 -1
  169. data/ext/ratatui_ruby/src/widgets/paragraph.rs +1 -1
  170. data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +19 -8
  171. data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +17 -10
  172. data/ext/ratatui_ruby/src/widgets/scrollbar.rs +97 -3
  173. data/ext/ratatui_ruby/src/widgets/scrollbar_state.rs +169 -0
  174. data/ext/ratatui_ruby/src/widgets/sparkline.rs +14 -11
  175. data/ext/ratatui_ruby/src/widgets/table.rs +121 -5
  176. data/ext/ratatui_ruby/src/widgets/table_state.rs +121 -0
  177. data/ext/ratatui_ruby/src/widgets/tabs.rs +11 -11
  178. data/lib/ratatui_ruby/cell.rb +7 -7
  179. data/lib/ratatui_ruby/event/key/character.rb +35 -0
  180. data/lib/ratatui_ruby/event/key/media.rb +44 -0
  181. data/lib/ratatui_ruby/event/key/modifier.rb +95 -0
  182. data/lib/ratatui_ruby/event/key/navigation.rb +55 -0
  183. data/lib/ratatui_ruby/event/key/system.rb +45 -0
  184. data/lib/ratatui_ruby/event/key.rb +112 -52
  185. data/lib/ratatui_ruby/event/mouse.rb +3 -3
  186. data/lib/ratatui_ruby/event/none.rb +43 -0
  187. data/lib/ratatui_ruby/event/paste.rb +1 -1
  188. data/lib/ratatui_ruby/event.rb +56 -4
  189. data/lib/ratatui_ruby/frame.rb +183 -0
  190. data/lib/ratatui_ruby/list_state.rb +88 -0
  191. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +13 -13
  192. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +1 -5
  193. data/lib/ratatui_ruby/schema/bar_chart.rb +217 -217
  194. data/lib/ratatui_ruby/schema/block.rb +163 -168
  195. data/lib/ratatui_ruby/schema/calendar.rb +66 -67
  196. data/lib/ratatui_ruby/schema/canvas.rb +63 -63
  197. data/lib/ratatui_ruby/schema/center.rb +46 -46
  198. data/lib/ratatui_ruby/schema/chart.rb +135 -143
  199. data/lib/ratatui_ruby/schema/clear.rb +42 -42
  200. data/lib/ratatui_ruby/schema/constraint.rb +76 -76
  201. data/lib/ratatui_ruby/schema/cursor.rb +30 -25
  202. data/lib/ratatui_ruby/schema/gauge.rb +54 -52
  203. data/lib/ratatui_ruby/schema/layout.rb +87 -87
  204. data/lib/ratatui_ruby/schema/line_gauge.rb +62 -62
  205. data/lib/ratatui_ruby/schema/list.rb +103 -80
  206. data/lib/ratatui_ruby/schema/list_item.rb +41 -0
  207. data/lib/ratatui_ruby/schema/overlay.rb +31 -31
  208. data/lib/ratatui_ruby/schema/paragraph.rb +80 -80
  209. data/lib/ratatui_ruby/schema/ratatui_logo.rb +10 -6
  210. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +10 -5
  211. data/lib/ratatui_ruby/schema/rect.rb +99 -56
  212. data/lib/ratatui_ruby/schema/scrollbar.rb +119 -119
  213. data/lib/ratatui_ruby/schema/shape/label.rb +1 -1
  214. data/lib/ratatui_ruby/schema/sparkline.rb +111 -110
  215. data/lib/ratatui_ruby/schema/style.rb +66 -46
  216. data/lib/ratatui_ruby/schema/table.rb +126 -115
  217. data/lib/ratatui_ruby/schema/tabs.rb +66 -67
  218. data/lib/ratatui_ruby/schema/text.rb +69 -1
  219. data/lib/ratatui_ruby/scrollbar_state.rb +112 -0
  220. data/lib/ratatui_ruby/session/autodoc.rb +482 -0
  221. data/lib/ratatui_ruby/session.rb +55 -23
  222. data/lib/ratatui_ruby/table_state.rb +90 -0
  223. data/lib/ratatui_ruby/test_helper/event_injection.rb +169 -0
  224. data/lib/ratatui_ruby/test_helper/snapshot.rb +390 -0
  225. data/lib/ratatui_ruby/test_helper/style_assertions.rb +351 -0
  226. data/lib/ratatui_ruby/test_helper/terminal.rb +127 -0
  227. data/lib/ratatui_ruby/test_helper/test_doubles.rb +68 -0
  228. data/lib/ratatui_ruby/test_helper.rb +66 -193
  229. data/lib/ratatui_ruby/version.rb +1 -1
  230. data/lib/ratatui_ruby.rb +100 -51
  231. data/{examples/sparkline_demo → sig/examples/app_all_events}/app.rbs +3 -2
  232. data/sig/examples/app_all_events/model/event_entry.rbs +16 -0
  233. data/sig/examples/app_all_events/model/events.rbs +15 -0
  234. data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
  235. data/sig/examples/app_all_events/view/app_view.rbs +8 -0
  236. data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
  237. data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
  238. data/sig/examples/app_all_events/view/live_view.rbs +6 -0
  239. data/sig/examples/app_all_events/view/log_view.rbs +6 -0
  240. data/sig/examples/app_all_events/view.rbs +8 -0
  241. data/sig/examples/app_all_events/view_state.rbs +15 -0
  242. data/{examples/list_demo → sig/examples/app_color_picker}/app.rbs +2 -2
  243. data/sig/examples/app_login_form/app.rbs +11 -0
  244. data/sig/examples/app_stateful_interaction/app.rbs +33 -0
  245. data/sig/examples/verify_quickstart_dsl/app.rbs +11 -0
  246. data/sig/examples/verify_quickstart_lifecycle/app.rbs +11 -0
  247. data/sig/examples/verify_readme_usage/app.rbs +11 -0
  248. data/sig/examples/widget_block_demo/app.rbs +32 -0
  249. data/sig/examples/widget_box_demo/app.rbs +11 -0
  250. data/sig/examples/widget_calendar_demo/app.rbs +11 -0
  251. data/sig/examples/widget_cell_demo/app.rbs +11 -0
  252. data/sig/examples/widget_chart_demo/app.rbs +11 -0
  253. data/{examples/gauge_demo → sig/examples/widget_gauge_demo}/app.rbs +4 -0
  254. data/sig/examples/widget_layout_split/app.rbs +10 -0
  255. data/sig/examples/widget_line_gauge_demo/app.rbs +11 -0
  256. data/sig/examples/widget_list_demo/app.rbs +12 -0
  257. data/sig/examples/widget_map_demo/app.rbs +11 -0
  258. data/sig/examples/widget_popup_demo/app.rbs +11 -0
  259. data/sig/examples/widget_ratatui_logo_demo/app.rbs +11 -0
  260. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +11 -0
  261. data/sig/examples/widget_rect/app.rbs +12 -0
  262. data/sig/examples/widget_render/app.rbs +10 -0
  263. data/sig/examples/widget_rich_text/app.rbs +11 -0
  264. data/sig/examples/widget_scroll_text/app.rbs +11 -0
  265. data/sig/examples/widget_scrollbar_demo/app.rbs +11 -0
  266. data/sig/examples/widget_sparkline_demo/app.rbs +10 -0
  267. data/{examples → sig/examples}/widget_style_colors/app.rbs +1 -1
  268. data/sig/examples/widget_table_demo/app.rbs +11 -0
  269. data/sig/examples/widget_text_width/app.rbs +10 -0
  270. data/sig/ratatui_ruby/event.rbs +11 -1
  271. data/sig/ratatui_ruby/frame.rbs +11 -0
  272. data/sig/ratatui_ruby/list_state.rbs +13 -0
  273. data/sig/ratatui_ruby/ratatui_ruby.rbs +5 -4
  274. data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +3 -3
  275. data/sig/ratatui_ruby/schema/draw.rbs +4 -0
  276. data/sig/ratatui_ruby/schema/gauge.rbs +2 -2
  277. data/sig/ratatui_ruby/schema/layout.rbs +1 -1
  278. data/sig/ratatui_ruby/schema/line_gauge.rbs +2 -2
  279. data/sig/ratatui_ruby/schema/list.rbs +4 -2
  280. data/sig/ratatui_ruby/schema/list_item.rbs +10 -0
  281. data/sig/ratatui_ruby/schema/rect.rbs +3 -0
  282. data/sig/ratatui_ruby/schema/style.rbs +3 -3
  283. data/sig/ratatui_ruby/schema/table.rbs +3 -1
  284. data/sig/ratatui_ruby/schema/text.rbs +8 -6
  285. data/sig/ratatui_ruby/scrollbar_state.rbs +18 -0
  286. data/sig/ratatui_ruby/session.rbs +107 -0
  287. data/sig/ratatui_ruby/table_state.rbs +15 -0
  288. data/sig/ratatui_ruby/test_helper/event_injection.rbs +16 -0
  289. data/sig/ratatui_ruby/test_helper/snapshot.rbs +12 -0
  290. data/sig/ratatui_ruby/test_helper/style_assertions.rbs +64 -0
  291. data/sig/ratatui_ruby/test_helper/terminal.rbs +14 -0
  292. data/sig/ratatui_ruby/test_helper/test_doubles.rbs +22 -0
  293. data/sig/ratatui_ruby/test_helper.rbs +5 -4
  294. data/tasks/autodoc/examples.rb +79 -0
  295. data/tasks/autodoc/inventory.rb +63 -0
  296. data/tasks/autodoc/member.rb +56 -0
  297. data/tasks/autodoc/name.rb +19 -0
  298. data/tasks/autodoc/notice.rb +26 -0
  299. data/tasks/autodoc/rbs.rb +38 -0
  300. data/tasks/autodoc/rdoc.rb +45 -0
  301. data/tasks/autodoc.rake +53 -0
  302. data/tasks/bump/changelog.rb +3 -3
  303. data/tasks/bump/history.rb +2 -2
  304. data/tasks/bump/links.rb +67 -0
  305. data/tasks/doc.rake +600 -6
  306. data/tasks/example_viewer.html.erb +172 -0
  307. data/tasks/lint.rake +8 -4
  308. data/tasks/resources/index.html.erb +6 -0
  309. data/tasks/sourcehut.rake +70 -30
  310. data/tasks/terminal_preview/app_screenshot.rb +14 -6
  311. data/tasks/terminal_preview/crash_report.rb +7 -9
  312. data/tasks/terminal_preview/launcher_script.rb +4 -6
  313. data/tasks/terminal_preview/preview_collection.rb +4 -6
  314. data/tasks/terminal_preview/safety_confirmation.rb +3 -5
  315. data/tasks/terminal_preview/saved_screenshot.rb +10 -11
  316. data/tasks/terminal_preview/terminal_window.rb +7 -9
  317. data/tasks/test.rake +1 -1
  318. data/tasks/website/index_page.rb +3 -3
  319. data/tasks/website/version.rb +10 -10
  320. data/tasks/website/version_menu.rb +10 -12
  321. data/tasks/website/versioned_documentation.rb +49 -17
  322. data/tasks/website/website.rb +6 -8
  323. data/tasks/website.rake +4 -4
  324. metadata +232 -127
  325. data/LICENSES/BSD-2-Clause.txt +0 -9
  326. data/doc/contributors/better_dx.md +0 -543
  327. data/doc/contributors/example_analysis.md +0 -82
  328. data/doc/images/all_events.png +0 -0
  329. data/doc/images/block_padding.png +0 -0
  330. data/doc/images/block_titles.png +0 -0
  331. data/doc/images/box_demo.png +0 -0
  332. data/doc/images/calendar_demo.png +0 -0
  333. data/doc/images/cell_demo.png +0 -0
  334. data/doc/images/chart_demo.png +0 -0
  335. data/doc/images/flex_layout.png +0 -0
  336. data/doc/images/gauge_demo.png +0 -0
  337. data/doc/images/line_gauge_demo.png +0 -0
  338. data/doc/images/list_demo.png +0 -0
  339. data/doc/images/list_styles.png +0 -0
  340. data/doc/images/login_form.png +0 -0
  341. data/doc/images/quickstart_dsl.png +0 -0
  342. data/doc/images/quickstart_lifecycle.png +0 -0
  343. data/doc/images/readme_usage.png +0 -0
  344. data/doc/images/rich_text.png +0 -0
  345. data/doc/images/scroll_text.png +0 -0
  346. data/doc/images/scrollbar_demo.png +0 -0
  347. data/doc/images/sparkline_demo.png +0 -0
  348. data/doc/images/table_flex.png +0 -0
  349. data/doc/images/table_select.png +0 -0
  350. data/examples/all_events/app.rb +0 -169
  351. data/examples/all_events/app.rbs +0 -7
  352. data/examples/all_events/test_app.rb +0 -139
  353. data/examples/analytics/app.rb +0 -258
  354. data/examples/analytics/app.rbs +0 -7
  355. data/examples/analytics/test_app.rb +0 -132
  356. data/examples/block_padding/app.rb +0 -63
  357. data/examples/block_padding/app.rbs +0 -7
  358. data/examples/block_padding/test_app.rb +0 -31
  359. data/examples/block_titles/app.rb +0 -61
  360. data/examples/block_titles/app.rbs +0 -7
  361. data/examples/block_titles/test_app.rb +0 -34
  362. data/examples/box_demo/app.rbs +0 -7
  363. data/examples/box_demo/test_app.rb +0 -88
  364. data/examples/calendar_demo/app.rb +0 -101
  365. data/examples/calendar_demo/app.rbs +0 -7
  366. data/examples/calendar_demo/test_app.rb +0 -108
  367. data/examples/cell_demo/app.rb +0 -108
  368. data/examples/cell_demo/app.rbs +0 -7
  369. data/examples/cell_demo/test_app.rb +0 -36
  370. data/examples/chart_demo/app.rb +0 -203
  371. data/examples/chart_demo/app.rbs +0 -7
  372. data/examples/chart_demo/test_app.rb +0 -102
  373. data/examples/custom_widget/app.rb +0 -51
  374. data/examples/custom_widget/app.rbs +0 -7
  375. data/examples/custom_widget/test_app.rb +0 -30
  376. data/examples/flex_layout/app.rb +0 -156
  377. data/examples/flex_layout/app.rbs +0 -7
  378. data/examples/flex_layout/test_app.rb +0 -65
  379. data/examples/gauge_demo/app.rb +0 -182
  380. data/examples/gauge_demo/test_app.rb +0 -120
  381. data/examples/hit_test/app.rb +0 -175
  382. data/examples/hit_test/app.rbs +0 -7
  383. data/examples/hit_test/test_app.rb +0 -102
  384. data/examples/line_gauge_demo/app.rb +0 -190
  385. data/examples/line_gauge_demo/app.rbs +0 -7
  386. data/examples/line_gauge_demo/test_app.rb +0 -129
  387. data/examples/list_demo/app.rb +0 -253
  388. data/examples/list_demo/test_app.rb +0 -237
  389. data/examples/list_styles/app.rb +0 -140
  390. data/examples/list_styles/app.rbs +0 -7
  391. data/examples/list_styles/test_app.rb +0 -157
  392. data/examples/login_form/app.rbs +0 -7
  393. data/examples/login_form/test_app.rb +0 -51
  394. data/examples/map_demo/app.rbs +0 -7
  395. data/examples/map_demo/test_app.rb +0 -149
  396. data/examples/mouse_events/app.rb +0 -97
  397. data/examples/mouse_events/app.rbs +0 -7
  398. data/examples/mouse_events/test_app.rb +0 -53
  399. data/examples/popup_demo/app.rb +0 -103
  400. data/examples/popup_demo/app.rbs +0 -7
  401. data/examples/popup_demo/test_app.rb +0 -54
  402. data/examples/quickstart_dsl/app.rbs +0 -7
  403. data/examples/quickstart_dsl/test_app.rb +0 -29
  404. data/examples/quickstart_lifecycle/app.rb +0 -39
  405. data/examples/quickstart_lifecycle/app.rbs +0 -7
  406. data/examples/quickstart_lifecycle/test_app.rb +0 -29
  407. data/examples/ratatui_logo_demo/app.rb +0 -79
  408. data/examples/ratatui_logo_demo/app.rbs +0 -7
  409. data/examples/ratatui_logo_demo/test_app.rb +0 -51
  410. data/examples/ratatui_mascot_demo/app.rb +0 -84
  411. data/examples/ratatui_mascot_demo/app.rbs +0 -7
  412. data/examples/ratatui_mascot_demo/test_app.rb +0 -47
  413. data/examples/readme_usage/app.rb +0 -29
  414. data/examples/readme_usage/app.rbs +0 -7
  415. data/examples/readme_usage/test_app.rb +0 -29
  416. data/examples/rich_text/app.rb +0 -141
  417. data/examples/rich_text/app.rbs +0 -7
  418. data/examples/rich_text/test_app.rb +0 -166
  419. data/examples/scroll_text/app.rb +0 -103
  420. data/examples/scroll_text/app.rbs +0 -7
  421. data/examples/scroll_text/test_app.rb +0 -110
  422. data/examples/scrollbar_demo/app.rb +0 -143
  423. data/examples/scrollbar_demo/app.rbs +0 -7
  424. data/examples/scrollbar_demo/test_app.rb +0 -77
  425. data/examples/sparkline_demo/app.rb +0 -240
  426. data/examples/sparkline_demo/test_app.rb +0 -107
  427. data/examples/table_flex/app.rb +0 -65
  428. data/examples/table_flex/app.rbs +0 -7
  429. data/examples/table_flex/test_app.rb +0 -36
  430. data/examples/table_select/app.rb +0 -198
  431. data/examples/table_select/app.rbs +0 -7
  432. data/examples/table_select/test_app.rb +0 -180
  433. data/examples/widget_style_colors/test_app.rb +0 -48
  434. data/tasks/bump/comparison_links.rb +0 -41
  435. /data/doc/images/{analytics.png → app_analytics.png} +0 -0
  436. /data/doc/images/{custom_widget.png → app_custom_widget.png} +0 -0
  437. /data/doc/images/{mouse_events.png → app_mouse_events.png} +0 -0
  438. /data/doc/images/{map_demo.png → widget_map_demo.png} +0 -0
  439. /data/doc/images/{popup_demo.png → widget_popup_demo.png} +0 -0
  440. /data/doc/images/{hit_test.png → widget_rect.png} +0 -0
  441. /data/{doc/images/ratatui_logo_demo.png → exe/.gitkeep} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f566d7a4eb721ae0c356c7f19f60b5a91a2dd908d03b3711c655cbe61c6410b8
4
- data.tar.gz: dd5fddbd898e842aef046aab8f58c85f507418edfccc6d7ff903b129329b3d3e
3
+ metadata.gz: c8e3aed93d74250af44d1b7169dcf7d31575b8b6a24c65d40b4067edb1cf46ea
4
+ data.tar.gz: e5f3d70e418bc9af98a1926838030aa934b13f64d617ed5c5a1809e91d17d72a
5
5
  SHA512:
6
- metadata.gz: c24e93fb6fc88103b336eef4283c5d434f2625529e0a2aac8b5951fb8ae52c5ac05009beef8f72e6acd4a38534bb7b075bb21cc469c039d198b3f7fd87cfa8e7
7
- data.tar.gz: 8ac6aaf12d96cba46f4ae9f6af3f7fb5e0ad9bdfacda6bef381d31a857c0f9d8c65cd7fb079f22e2961a31dad68f39744dfe7d3842b9e0e879ba568f0e820d3a
6
+ metadata.gz: c1742d63643a1ebef6063097e3755e819da39354b631d70ba72ead21d48d8a9199a5421184698fb41a56ee0991a7411adfbcf125f6ec9e18aa980eeb6d4e03fe
7
+ data.tar.gz: 995f166470814f6ec2a0e073bc658eb52b5a5381a5c19539d4b6ef575e601eb3ac8c3b000a23b4c226b6708a5387024b71a84c43cd69a5240f538aca261a815b
data/.builds/ruby-3.2.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - ratatui_ruby/pkg/ratatui_ruby-0.4.0.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-0.6.0.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
data/.builds/ruby-3.3.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - ratatui_ruby/pkg/ratatui_ruby-0.4.0.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-0.6.0.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
data/.builds/ruby-3.4.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - ratatui_ruby/pkg/ratatui_ruby-0.4.0.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-0.6.0.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - ratatui_ruby/pkg/ratatui_ruby-0.4.0.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-0.6.0.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
data/AGENTS.md CHANGED
@@ -13,203 +13,125 @@ Description: A high-performance Ruby wrapper for the Ratatui TUI library.
13
13
 
14
14
  Architecture:
15
15
 
16
- - **Frontend (Ruby):** Pure `Data` objects (Ruby 3.2+) defining the View Tree. Immediate mode.
17
- - **Backend (Rust):** A generic renderer using `ratatui` and `magnus` that traverses the Ruby `Data` tree and renders to the terminal buffer.
16
+ - **Frontend (Ruby):** Pure `Data` objects (Ruby 3.2+) used in Frames and/or defining the View Tree. Immediate mode.
17
+ - **Backend (Rust):** A generic renderer using `ratatui` and `magnus` that traverses the Ruby `Data` tree and renders to the terminal buffer.
18
18
 
19
19
  ## Stability & Compatibility
20
20
 
21
- - **Project Status:** Pre-1.0.
22
- - **User Base:** 0 users (internal/experimental).
23
- - **Breaking Changes:** Backward compatibility is **NOT** a priority at this stage. Since there are no external users, you are encouraged to refactor APIs for better ergonomics and performance even if it breaks existing code.
24
- - **Requirement:** All breaking changes **MUST** be explicitly documented in the [CHANGELOG.md](CHANGELOG.md)'s **Unreleased** section to ensure transparency as the project evolves toward 1.0.
25
-
26
- ## 1. File & Coding Standards
27
-
28
- ### Licensing & Copyright (Strict)
29
-
30
- Every file must begin with an SPDX-compliant header. Use the following format:
31
-
32
- ```ruby
33
- # frozen_string_literal: true
34
-
35
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
36
- # SPDX-License-Identifier: AGPL-3.0-or-later
37
- ```
38
-
39
- - **Ruby/Rust/Config files:** Use comments appropriate for the language (`#` or `//`).
40
- - **Markdown:** Use HTML comment style `<!-- -->`.
41
- - **Exceptions:** `REUSE.toml` manages exceptions (e.g., binary files or `.gitignore`).
21
+ - **Project Status:** Pre-1.0.
22
+ - **User Base:** 0 users (internal/experimental).
23
+ - **Breaking Changes:** Backward compatibility is **NOT** a priority at this stage. Since there are no external users, you are encouraged to refactor APIs for better ergonomics and performance even if it breaks existing code.
24
+ - **Requirement:** All breaking changes **MUST** be explicitly documented in the [CHANGELOG.md](CHANGELOG.md)'s **Unreleased** section to ensure transparency as the project evolves toward 1.0.
25
+
26
+ ## 1. Standards
27
+
28
+ ### STRICT REQUIREMENTS
29
+
30
+ - Every file MUST begin with an SPDX-compliant header. Use `AGPL-3.0-or-later` for code; `CC-BY-SA-4.0` for documentation. `reuse annotate` can help you generate the header.
31
+ - Every line of Ruby MUST be covered by tests that would stand up to mutation testing.
32
+ - Tests must be meaningful and verify specific behavior or rendering output; simply verifying that code "doesn't crash" is insufficient and unacceptable.
33
+ - For UI widgets, this means using `with_test_terminal` to verify EVERY character of the terminal buffer's content.
34
+ - Every line of Rust MUST be covered by tests that would stand up to mutation testing.
35
+ - Tests must be meaningful; simply verifying that code "doesn't crash" or "compiles" is insufficient and unacceptable.
36
+ - Each widget implementation must have a `tests` module with unit tests verifying basic rendering.
37
+ - **Pre-commit:** Use `bin/agent_rake` to ensure commit-readiness. See Tools for detailed instructions.
38
+ - **Git Pager:** ALWAYS set `PAGER=cat` for ALL `git` commands (e.g., `PAGER=cat git diff`). This is mandatory.
39
+
40
+ ### Tools
41
+
42
+ - **NEVER** run `bundle exec rake` directly. **NEVER** run `bundle exec ruby -Ilib:test ...` directly.
43
+ - **ALWAYS use `bin/agent_rake`** for running tests, linting, or checking compilation.
44
+ - **Usage:**
45
+ - Runs default task (compile + test + lint): `bin/agent_rake`
46
+ - Runs specific task: `bin/agent_rake test:ruby` (for example)
47
+ - **Snapshot Testing:** When tests fail due to intentional behavior changes (not bugs), update snapshots:
48
+ - **Command:** `UPDATE_SNAPSHOTS=1 bin/agent_rake test:ruby`
49
+ - This regenerates all `snapshot/*{txt,ansi}` files to match current output
50
+ - **When to use:** After modifying widget rendering, changing default values, or updating UI behavior
51
+ - **When NOT to use:** For actual test failures that indicate bugs in your code
52
+ - After updating, verify the changes make sense by reviewing the diff of `.snapshot` files
53
+ - **Setup:** `bin/setup` must handle both Bundler and Cargo dependencies.
54
+ - **Git:** ALWAYS set `PAGER=cat` with `git`, `git`, etc.. **THIS IS CRITICAL!**
55
+ - **Rake:** Our rake tasks use `git ls-files`, so errors happen when you move or delete files. In this case, ask the user to stage changes for you.
42
56
 
43
57
  ### Ruby Standards
44
58
 
45
- - **Version:** Tested against the latest releases of Ruby 3.2, 3.3, 3.4, and 4.0, and must work on all of them. Local development happens on the latest stable release.
46
- - **Linter & Testing (CRITICAL):**
47
- - **ALWAYS use `bin/agent_rake`** for running tests, linting, or checking compilation.
48
- - **NEVER** run `bundle exec rake` directly. **NEVER** run `bundle exec ruby -Ilib:test ...` directly.
49
- - **VIOLATION OF THIS RULE IS A CRITICAL ERROR.**
50
- - **Why?**
51
- 1. **Noise Reduction:** Standard `rake` output includes massive amounts of Rust compilation noise that floods your context window, truncating the actual error message. `bin/agent_rake` captures this silently.
52
- 2. **Atomic Dump:** Agents work best with a single "Atomic Dump" of the failure. `bin/agent_rake` provides this by swallowing successful output and only printing the failure log if something goes wrong.
53
- 3. **Merged Output:** It correctly merges stdout (Minitest failures) and stderr (Rust warnings) so you see them in temporal order.
54
- - **Usage:**
55
- - Runs default task (compile + test + lint): `bin/agent_rake`
56
- - Runs specific task: `bin/agent_rake test:ruby` (for example)
57
- - **Interpretation:** If the User says "rake test fails" or "fix the build" or "bin/agent_rake fails", they IMPLICITLY mean "run `bin/agent_rake` and fix the reported errors". Do not ask for clarification; just use `bin/agent_rake`.
58
- - **Style:**
59
- - Use `Data.define` for all value objects (UI Nodes). (Prefer `class Foo < Data.define()` over `Foo = Data.define() do`).
60
- - Prefer `frozen_string_literal: true`.
61
- - Use `Minitest` for testing.
62
- - Define types in `.rbs` files. Don't use `untyped` just because it's easy; be comprehensive and accurate. Do not include `initialize` in `.rbs` files; use `self.new` for constructors instead.
63
- - Every line of Ruby must be covered by tests that would stand up to mutation testing. This includes all examples in the `examples/` directory; they should have corresponding tests in `examples/` to ensure they continue to work as intended and serve as reliable documentation. Tests must be meaningful and verify specific behavior or rendering output; simply verifying that code "doesn't crash" is insufficient and unacceptable. For UI widgets, this means using `with_test_terminal` to verify every character of the terminal buffer's content.
64
- - Every public Ruby class/method must be documented for humans in RDoc (preferred)--**not** YARD--or markdown files (fallback), and must have `*.rbs` types defined.
65
- - Every significant architectural and design decision must be documented for contributors in markdown files. Mermaid is allowed.
59
+ - Use `Data.define` for all value objects (UI Nodes). (Prefer `class Foo < Data.define()` over `Foo = Data.define() do`).
60
+ - Define types in `.rbs` files. Don't use `untyped` just because it's easy; be comprehensive and accurate. Do not include `initialize` in `.rbs` files; use `self.new` for constructors instead.
61
+ - Every public Ruby class/method must be documented for humans in RDoc (preferred)--**not** YARD--or markdown files (fallback), and must have `*.rbs` types defined.
62
+ - Every significant architectural and design decision must be documented for contributors in markdown files. Mermaid is allowed.
63
+ - **Rust-backed methods:** For methods implemented in Rust (magnus bindings), use RDoc directives instead of empty method bodies. Use `##` followed by `:method:`, `:call-seq:`, and prose. End with `(Native method implemented in Rust)`. See `lib/ratatui_ruby.rb` for examples.
64
+ - Refer to [docs/contributors/design/ruby_frontend.md](docs/contributors/design/ruby_frontend.md) for detailed design philosophy regarding the Immediate Mode paradigm including Data-Driven UI and Frames.
66
65
 
67
66
  ### Rust Standards
68
67
 
69
- - **Crate Type:** `cdylib`.
70
- - **Linter:** `clippy` and `rustfmt`.
71
- - **Bindings:** Use [magnus](https://github.com/matsadler/magnus).
72
- - **Platform:** Support macOS (Apple Silicon), Linux, and Windows.
73
- - **Linker Flags:** Must handle macOS `-undefined dynamic_lookup`.
74
- - Every line of Rust must be covered by tests that would stand up to mutation testing. This includes every widget implementation in `ext/ratatui_ruby/src/widgets/`; each must have a `tests` module with unit tests verifying basic rendering. Tests must be meaningful; simply verifying that code "doesn't crash" or "compiles" is insufficient.
68
+ - **Crate Type:** `cdylib`.
69
+ - **Bindings:** Use [magnus](https://github.com/matsadler/magnus).
70
+ - **Platform:** Support macOS (Apple Silicon), Linux, and Windows.
71
+ - Refer to [docs/contributors/design/rust_backend.md](docs/contributors/design/rust_backend.md) for detailed implementation guidelines, module structure, and rendering logic.
75
72
 
76
73
  ## 2. Directory Structure Convention
77
74
 
78
- The project follows a standard Gem layout with an `ext/` directory for Rust code.
79
-
80
- ```plaintext
81
- /
82
- ├── .cargo/ # Cargo configuration (linker flags)
83
- ├── .github/ # CI/CD workflows
84
- ├── bin/ # Executables (console, setup)
85
- ├── doc/ # Documentation source (markdown for RDoc)
86
- │ ├── contributors/ # Design docs, ecosystem notes
87
- │ └── index.md
88
- ├── ext/
89
- │ └── ratatui_ruby/ # RUST SOURCE CODE GOES HERE
90
- │ ├── src/
91
- │ │ └── lib.rs # Entry point
92
- │ ├── Cargo.toml
93
- │ └── extconf.rb # Makefile generator
94
- ├── lib/
95
- │ ├── ratatui_ruby/
96
- │ │ ├── schema/ # Ruby Data definitions
97
- │ │ └── version.rb
98
- │ └── ratatui_ruby.rb # Main loader
99
- ├── test/
100
- │ ├── data/ # Data-driven test files
101
- │ └── ratatui_ruby/ # Unit tests
102
- ├── vendor/ # Vendorized style configs (goodcop)
103
- ├── AGENTS.md # Context for AI agents
104
- ├── Gemfile
105
- ├── Rakefile
106
- ├── REUSE.toml # Compliance definition
107
- └── ratatui_ruby.gemspec
108
- ```
75
+ The project follows a standard Gem layout with an `ext/` directory for Rust code and `examples/` for example application-level code.
109
76
 
110
77
  ## 3. Configuration & Tooling
111
78
 
112
79
  ### Development Environment
113
80
 
114
- - **Setup:** `bin/setup` must handle both Bundler and Cargo dependencies.
115
- - **Pre-commit:** Use `bin/agent_rake` to ensure commit-readiness. See Ruby Standards for detailed instructions.
116
81
 
117
82
  ### Documentation
118
83
 
119
- - **The `doc/` folder contains source markdown files** that are included in RDoc output. Follow the structure: `index.md` -> `contributors/` | `quickstart.md`.
120
- - **The `tmp/rdoc/` folder is auto-generated** by `bundle exec rake rerdoc`. Never edit files in `tmp/rdoc/` directly.
121
- - Documentation should separate "User Guide" (Ruby API for TUI developers) from "Contributor Guide" (Ruby/Rust/Magnus internals).
122
- - **Style Guide:** You **MUST** follow the [Documentation Style Guide](doc/contributors/documentation_style.md). This dictates the Alexandrian/Zinsser prose style and strict RDoc formatting required for all public API documentation.
123
- - Don't write .md files for something RDoc (Ruby) or rustdoc (Rust) can generate.
124
-
125
- ## 4. The Ruby <-> Rust Bridge Contract
126
-
127
- ### The Ruby Side (`lib/`)
128
-
129
- - Refer to [docs/contributors/design/ruby_frontend.md](docs/contributors/design/ruby_frontend.md) for detailed design philosophy regarding the Data-Driven UI and Immediate Mode paradigm.
130
-
131
- ### The Rust Side (`ext/`)
132
-
133
- - Refer to [docs/contributors/design/rust_backend.md](docs/contributors/design/rust_backend.md) for detailed implementation guidelines, module structure, and rendering logic.
134
-
135
- ## 5. Deployment / Release
136
-
137
- - The gem builds a native extension.
138
- - Artifact naming: Ensure the output shared library matches Ruby's expectation on macOS (rename `.dylib`to `.bundle` if necessary during the build process in `extconf.rb` or `Rakefile`).
139
-
140
- ## 6. Commit Message
141
-
142
- - **Commits:**
143
- - Who commits: Only humans should affect the git index and history. Do not stage (do not `git add`). Do not commit. Just suggest a commit message.
144
- - When: At the end of each task, before reporting the task as complete to the user, suggest the commit message.
145
- - What: Consider not just what you remember, but also everything in the `git diff` and `git diff --cached`.
146
- - **Format:**
147
- - Format: Use [Conventional Commits](https://www.conventionalcommits.org/).
148
- - Structure: `type(scope): description` (e.g., `feat(widget): add Gauge widget`).
149
- - Subject line: Concise summary (50 chars or less).
150
- - Body: Explanation if necessary (wrap at 72 chars).
151
- - Explain why this is the implementation, as opposed to other possible implementations.
152
- - Skip the body entirely if it's rote, a duplication of the diff, or otherwise unhelpful.
153
- - **DO NOT list the files changed or the edits made in the body.** Do not provide a bulleted list of changes. Use prose to explain the problem and the solution.
154
- - **Do not use markdown syntax** (no backticks, no bolding, no lists, no links), except as required in AI Attribution. The commit message must be plain text.
155
- - Footer: AI attribution if generated by an agent, sourcehut ticket if implemented by a ticket, or both.
156
- - **AI Attribution:**
157
- - **Always include AI attribution** in the footer if the commit was generated or significantly assisted by an AI agent. This is mandatory for transparency and compliance. **This is NOT optional.**
158
- - **Amp:**
159
- ```
160
- Generated with [Amp](https://ampcode.com)
161
-
162
- Co-Authored-By: Amp <noreply@ampcode.com>
163
- ```
164
- - **Antigravity:**
165
- Specify the model used in the footer. Examples:
166
- ```
167
- Generated with [Antigravity](https://antigravity.google)
168
-
169
- Co-Authored-By: Gemini 3 Pro (High) <noreply@google.com>
170
- ```
171
- ```
172
- Generated with [Antigravity](https://antigravity.google)
173
-
174
- Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
175
- ```
176
- - **Gemini 3:**
177
- ```
178
- Generated with [Gemini 3 Pro](https://gemini.google.com/)
179
-
180
- Co-Authored-By: Gemini 3 Pro <noreply@google.com>
181
- ```
182
- - **JetBrains Junie:**
183
- ```
184
- Generated with [JetBrains Junie](https://www.jetbrains.com/ai/)
185
-
186
- Co-Authored-By: Junie <junie@jetbrains.com>
187
- ```
188
- - **Sourcehut Tickets:**
189
- - If the commit implements a specific ticket, include a footer: `Implements: https://todo.sr.ht/~kerrick/ratatui_ruby/<id>`
190
- - **Do NOT** include this footer if you were not given a specific ticket ID or URL. Do not hallucinate or guess ticket URLs.
191
- - This must be the **last** item in the footer, if present.
192
-
193
- ## 7. Definition of Done
84
+ - **The `doc/` folder contains source markdown files** that are included in RDoc output.
85
+ - Documentation should separate "User Guide" (Ruby API for TUI developers) from "Contributor Guide" (Ruby/Rust/Magnus internals).
86
+ - Files within `doc/contributors/` are for library developers.
87
+ - Files within `doc/` outside of `conttributors/` are for application developers and users of this RubyGEm.
88
+ - **Style Guide:** You **MUST** follow the [Documentation Style Guide](doc/contributors/documentation_style.md). This dictates the Alexandrian/Zinsser prose style and strict RDoc formatting required for all public API documentation.
89
+ - DON'T write .md files for something RDoc (Ruby) or rustdoc (Rust) can generate. DO use RDoc and rustdoc for documentation.
90
+
91
+
92
+ ## 4. Committing
93
+
94
+ - Who commits: DON'T stage (DON'T `git add`). DON'T commit. DO suggest a commit message.
95
+ - When: Before reporting the task as complete to the user, suggest the commit message.
96
+ - What: Consider not what you remember, but EVERYTHING in the `git diff` and `git diff --cached`.
97
+ - **Format:**
98
+ - Format: Use [Conventional Commits](https://www.conventionalcommits.org/).
99
+ - Body: Explanation if necessary (wrap at 72 chars).
100
+ - Explain why this is the implementation, as opposed to other possible implementations.
101
+ - Skip the body entirely if it's rote, a duplication of the diff, or otherwise unhelpful.
102
+ - **DON'T list the files changed or the edits made in the body.** Don't provide a bulleted list of changes. Use prose to explain the problem and the solution.
103
+ - **DON'T use markdown syntax** (no backticks, no bolding, no lists, no links). The commit message must be plain text.
104
+
105
+ ### 5. Changelog
106
+
107
+ - Follow [Semantic Versioning](https://semver.org/)
108
+ - Follow the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) specification.
109
+ - **What belongs in CHANGELOG:** Only changes that affect **application developers** or **higher-level library developers** who use or depend on `ratatui_ruby`:
110
+ - New public APIs or widget parameters
111
+ - Backwards-incompatible type signature changes, or behavioral additions to type signature changes
112
+ - Observable behavior changes (rendering, styling, layout)
113
+ - Deprecations and removals
114
+ - Breaking changes
115
+ - **What does NOT belong in CHANGELOG:** Internal or non-behavioral changes that don't affect downstream users:
116
+ - Test additions or improvements
117
+ - Documentation updates, RDoc fixes, markdown clarifications
118
+ - Refactors of internal code
119
+ - New or modified example code
120
+ - Internal tooling, CI/CD, or build configuration changes
121
+ - Code style or linting changes
122
+ - Performance improvements that affect applications
123
+ - Changelogs should be useful to downstream developers (both app and library developers), not simple restatements of diffs or commit messages.
124
+ - The Unreleased section MUST be considered "since the last git tag". Therefore, if a change was done in one commit and undone in another (both since the last tag), the second commit should remove its changelog entry.
125
+ - **Location:** New entries ALWAYS go in `## [Unreleased]`. Never edit past version sections (e.g., `## [0.4.0]`)—those are frozen history.
126
+
127
+ ## 6. Definition of Done (DoD)
194
128
 
195
129
  Before considering a task complete and returning control to the user, you **MUST** ensure:
196
130
 
197
- 1. **Default Rake Task Passes:** Run `bin/agent_rake` to execute **ALL** tests and linting. Do not rely on partial test runs, or `rake test`, or `rake lint` alone. Confirm it passes with no new errors **or warnings**.
198
- 2. **Documentation Updated:** If public APIs or observable behavior changed, update relevant `doc/` files, `README.md`, and/or `ratatui_ruby-wiki` files,.
199
- 3. **Changelog Updated:** If public APIs, observable behavior, or gemspec dependencies changed, update [CHANGELOG.md](CHANGELOG.md)'s **Unreleased** section according to the [Semantic Versioning](https://semver.org/) and [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) specifications.
200
- - **What belongs in CHANGELOG:** Only changes that affect **application developers** or **library developers** who use or depend on ratatui_ruby:
201
- - New public APIs or widget parameters
202
- - Observable behavior changes (rendering, styling, layout)
203
- - Deprecations and removals
204
- - Breaking changes
205
- - New public examples (if they demonstrate significant features)
206
- - Performance improvements that affect applications
207
- - **What does NOT belong in CHANGELOG:** Internal changes that don't affect downstream users:
208
- - Test additions or improvements
209
- - Documentation updates, RDoc fixes, markdown clarifications
210
- - Refactors of internal code
211
- - New or modified example code (unless the example itself is a major feature)
212
- - Internal tooling, CI/CD, or build configuration changes
213
- - Code style, linting, or type signature changes
214
- - Changelogs should be useful to downstream developers (both app and library developers), not simple restatements of diffs or commit messages.
131
+ 1. **Default Rake Task Passes:** Run `bin/agent_rake` (no args). Confirm it passes with ZERO errors **or warnings**.
132
+ - You will save time if you run `bin/agent_rake rubocop:autocorrect` first.
133
+ - If you think the build is looking for deleted files, it is not. Instead, tell the user and **ask them to stage changes**.
134
+ 2. **Documentation Updated:** If public APIs or observable behavior changed, update relevant RDoc, rustdoc, `doc/` files, `README.md`, and/or `ratatui_ruby-wiki` files.
135
+ 3. **Changelog Updated:** If public APIs, observable behavior, or gemspec dependencies have changed, update [CHANGELOG.md](CHANGELOG.md)'s **Unreleased** section.
215
136
  4. **Commit Message Suggested:** You **MUST** ensure the final message to the user includes a suggested commit message block. This is NOT optional.
137
+ - You MUST also remind the user to add an AI attribution footer.
data/CHANGELOG.md CHANGED
@@ -18,6 +18,78 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
18
18
 
19
19
  ### Removed
20
20
 
21
+ ## [0.6.0] - 2026-01-03
22
+
23
+ ### Added
24
+
25
+ - **Rich Text Support**: `List`, `Gauge`, `LineGauge`, and `BarChart` widgets now accept rich text objects (`Text::Span`, `Text::Line`) in addition to plain strings. This enables per-character styling, multi-colored labels, and complex text formatting matching Ratatui 0.30.0 capabilities.
26
+ - **ListItem Wrapper**: New `ListItem` data class allows applying row-level styling (background color) independent of text content. `List` items can now be `String`, `Text::Span`, `Text::Line`, or `ListItem` objects.
27
+ - **Non-Blocking Event Polling**: `RatatuiRuby.poll_event` now accepts an optional `timeout:` parameter (Float seconds). Use `timeout: 0.0` for non-blocking checks, or `timeout: 0.1` for fixed timesteps. Defaults to `0.016` (16ms) to preserve existing behavior.
28
+ - **Cursor Positioning**: `Frame#set_cursor_position(x, y)` sets the terminal's hardware cursor position. Using this method is essential for input fields where the user expects visual feedback on their cursor location.
29
+ - **Text Measurement**: `RatatuiRuby::Text.width(string)` calculates the display width of a string in terminal cells, correctly handling unicode including ASCII (1 cell), CJK full-width characters (2 cells), emoji (typically 2 cells), and zero-width combining marks (0 cells). This is essential for auto-sizing widgets and responsive layouts. Delegates to the same unicode-width logic that Ratatui uses internally.
30
+ - **Scroll Offset Control**: `List` and `Table` widgets now accept an optional `offset` parameter to control the viewport's scroll position. Use this for passive scrolling (viewing without selection) or calculating click-to-item mappings. When combined with a selection, Ratatui's natural scrolling may still adjust the viewport to keep the selection visible; set selection to `nil` for fully manual scroll control.
31
+ - **Rect Geometry Helpers**: `Rect#intersects?(other)` tests whether two rectangles overlap. `Rect#intersection(other)` returns the overlapping area as a new `Rect`, or `nil` if disjoint. Essential for viewport clipping and hit testing in component architectures.
32
+ - **Stateful Rendering**: `Frame#render_stateful_widget(widget, area, state)` renders widgets with mutable state objects (`ListState`, `TableState`, `ScrollbarState`). State objects persist across frames, enabling scroll offset read-back and selection tracking. Essential for mouse click-to-row hit testing. **Precedence rule:** State object properties override widget properties (`selected_index`, `offset`).
33
+ - **Full Keyboard Support**: Key events now recognize all keys supported by crossterm: function keys (`f1`–`f24`), navigation (`home`, `end`, `page_up`, `page_down`, `insert`, `delete`), locks (`caps_lock`, `scroll_lock`, `num_lock`), system (`print_screen`, `pause`, `menu`), media controls (`play`, `play_pause`, `track_next`, etc.), and individual modifier keys (`left_shift`, `right_control`, etc.). Previously unmapped keys returned `"unknown"`; they now return proper `snake_case` strings.
34
+ - **Key Categories**: `Event::Key` now has a `kind` attribute (`:standard`, `:function`, `:media`, `:modifier`, `:system`) for logical grouping. Category predicates (`media?`, `system?`, `function?`, `modifier?`, `standard?`) enable clean event routing without string parsing. The `unmodified?` method is an alias for `standard?`.
35
+ - **Smart Predicates (DWIM)**: Key predicates now "Do What I Mean" for media keys. `pause?` returns `true` for both system `pause` and `media_pause` keys. For strict matching, use `media_pause?` or compare `event.code` directly. This reduces boilerplate when responding to conceptual actions regardless of input method.
36
+ - **Modifier Key Predicates**: New methods `super?`, `hyper?`, and `meta?` check for these modifier keys. Platform aliases are provided for `super?`: `command?`/`cmd?` (macOS), `win?` (Windows), and `tux?` (Linux). These work for both modifier flags AND individual modifier key events (e.g., `left_super`). Additionally, `control?` aliases `ctrl?` and `option?` aliases `alt?`.
37
+ - **Navigation Aliases**: Convenient predicate aliases for common keys: `return?` for Enter, `back?` for Backspace, `del?` for Delete, `ins?` for Insert, `escape?` for Esc, `pgup?`/`pageup?` for Page Up, `pgdn?`/`pagedown?` for Page Down. The special `reverse_tab?` predicate matches both the `back_tab` key and `shift+tab` combinations.
38
+ - **Indexed Color Support**: `Style` now supports `Integer` values for `fg` and `bg`, allowing use of the Xterm 256-color palette (0-255). This includes standard ANSI colors (0-15), the 6x6x6 color cube (16-231), and the grayscale ramp (232-255).
39
+ - **Rich Snapshots**: `RatatuiRuby::TestHelper#assert_rich_snapshot` validates both content and styling by comparing against stored ANSI snapshots. This allows for visual regression testing that respects colors, bold, italics, and other terminal modifiers.
40
+ - **Semantic Style Assertions**: New testing helpers `assert_color(expected, x:, y:)`, `assert_cell_style(x, y, **style)`, and `assert_area_style(area, **style)` allow precise verification of terminal cell attributes without full-screen snapshots. Punchy convenience aliases like `assert_fg`/`assert_bg`, `assert_bold`, `assert_italic`, `assert_underlined`, and color-specific assertions (e.g., `assert_red`, `assert_bg_blue`) provide a more natural API for common testing patterns.
41
+ - **Buffer Debugging**: `RatatuiRuby::TestHelper#print_buffer` outputs the current terminal state to STDOUT with full ANSI color support, making it easier to debug rendering issues during test execution.
42
+
43
+
44
+ ### Changed
45
+
46
+ - **Frozen Data Objects (Breaking)**: Events returned by `RatatuiRuby.poll_event` and `Cell` objects from `RatatuiRuby.get_cell_at` are now deeply frozen for Ractor compatibility. Code that mutates these objects (e.g., `event.modifiers << "custom"`) must copy the data before modifying. `Rect` was already frozen. Note: `Frame` and `Session` are *I/O handles* with side effects and remain intentionally non-shareable.
47
+ - **Semantic Exceptions (Breaking)**: Replaced generic `RuntimeError` with `RatatuiRuby::Error::Terminal` for backend/terminal failures and `RatatuiRuby::Error::Safety` for API contract violations (like using `Frame` outside `draw`). This allows finer-grained error handling but breaks code explicitly rescuing `RuntimeError`. `ArgumentError` works as before.
48
+ - **Media Key Codes (Breaking)**: All media key codes now use a consistent `media_` prefix: `play` → `media_play`, `stop` → `media_stop`, `play_pause` → `media_play_pause`, etc. Code comparing against literal media key strings must be updated. Use the Smart Predicates (`play?`, `stop?`) for backward-compatible behavior.
49
+ - **`Key#char` Return Value (Breaking)**: `char` now returns `nil` for non-printable keys (previously returned `""`). Code relying on `event.char.empty?` must change to `event.char.nil?` or use `event.text?` instead.
50
+
51
+ ### Fixed
52
+
53
+ - **Frame Safety**: Calling methods on a `Frame` stored outside of a `draw` block now correctly raises a `RatatuiRuby::Error::Safety` (subclass of `RatatuiRuby::Error`) instead instead of causing undefined behavior or crashes. This ensures memory safety by preventing use-after-free scenarios with the underlying Rust frame.
54
+
55
+ ### Removed
56
+
57
+ ## [0.5.0] - 2026-01-01
58
+
59
+ ### Added
60
+
61
+ #### Frame API
62
+
63
+ - **`RatatuiRuby.draw { |frame| ... }`**: New block-based drawing API that yields a `Frame` object for explicit widget placement. Enables hit testing without duplicating layout calculations.
64
+ - **`Frame#area`**: Returns the terminal area as a `Rect`.
65
+ - **`Frame#render_widget(widget, rect)`**: Renders a widget at a specific position. Works with all existing widgets and `Rect` objects.
66
+
67
+ #### Testing
68
+
69
+ - **`RatatuiRuby::TestHelper#inject_mouse`**: comprehensive mouse event injection helper supporting coordinates, buttons, and modifiers.
70
+ - **`RatatuiRuby::TestHelper#inject_click`**: Helper for left-click events.
71
+ - **`RatatuiRuby::TestHelper#inject_right_click`**: Helper for right-click events.
72
+ - **`RatatuiRuby::TestHelper#inject_drag`**: Helper for mouse drag events.
73
+ - **`RatatuiRuby::TestHelper#assert_screen_matches`**: Assert that the current terminal content matches a stored golden snapshot.
74
+
75
+ #### Session API
76
+
77
+ - **Convenience Methods**: `Session` now wraps class methods from `Layout`, `Constraint`, and other schema classes as instance methods (e.g., `layout_split` delegates to `Layout.split`, `constraint_percentage` to `Constraint.percentage`). This enables a more fluent API in `RatatuiRuby.run` blocks.
78
+
79
+ ### Changed
80
+
81
+ #### Event System
82
+
83
+ - **`Event::None` (Breaking)**: `RatatuiRuby.poll_event` now returns `Event::None` instead of `nil` when no event is available. This null-object responds safely to all event predicates with `false`. Use `event.none?` or pattern-match on `type: :none`. Code using `while (event = poll_event)` must change to `while (event = poll_event) && !event.none?`.
84
+
85
+ ### Fixed
86
+
87
+ #### Session API
88
+
89
+ - **Missing Convenience Methods**: Fixed `Session` convenience methods (e.g., `bar_chart`) being missed by replacing the manual list with automatic runtime introspection of the `RatatuiRuby` module.
90
+
91
+ ### Removed
92
+
21
93
  ## [0.4.0] - 2025-12-30
22
94
 
23
95
  ### Added
@@ -249,9 +321,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
249
321
  - **Input Handling**: Robust handling for both Keyboard and Mouse events.
250
322
  - **Testing Support**: Included `RatatuiRuby::TestHelper` and RSpec integration to make testing your TUI applications possible.
251
323
 
252
- [Unreleased]: https://git.sr.ht/~kerrick/ratatui_ruby/compare/v0.4.0...HEAD
253
- [0.4.0]: https://git.sr.ht/~kerrick/ratatui_ruby/compare/v0.3.1...v0.4.0
254
- [0.3.1]: https://git.sr.ht/~kerrick/ratatui_ruby/compare/v0.3.0...v0.3.1
255
- [0.3.0]: https://git.sr.ht/~kerrick/ratatui_ruby/compare/v0.2.0...v0.3.0
256
- [0.2.0]: https://git.sr.ht/~kerrick/ratatui_ruby/compare/v0.1.0...v0.2.0
257
- [0.1.0]: https://git.sr.ht/~kerrick/ratatui_ruby/tree/v0.1.0
324
+ [Unreleased]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/HEAD
325
+ [0.6.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.6.0
326
+ [0.5.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.5.0
327
+ [0.4.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.4.0
328
+ [0.3.1]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.3.1
329
+ [0.3.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.3.0
330
+ [0.2.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.2.0
331
+ [0.1.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.1.0
data/README.md CHANGED
@@ -20,10 +20,10 @@ Mailing List: Announcements](https://img.shields.io/badge/mailing_list-announcem
20
20
  **ratatui_ruby** is a Ruby wrapper for [Ratatui](https://ratatui.rs). It allows you to cook up Terminal User Interfaces in Ruby.
21
21
  **ratatui_ruby** is a community wrapper that is not affiliated with [the Ratatui team](https://github.com/orgs/ratatui/people).
22
22
 
23
- > [!WARNING]
23
+ > [!WARNING]
24
24
  > **ratatui_ruby** is currently in **BETA**. The API may change between minor versions.
25
25
 
26
- Please join the **announce** mailing list at https://lists.sr.ht/~kerrick/ratatui_ruby-announce to stay up-to-date on new releases and announcements.
26
+ Please join the **announce** mailing list at https://lists.sr.ht/~kerrick/ratatui_ruby-announce to stay up-to-date on new releases and announcements. See the [`trunk` branch](https://git.sr.ht/~kerrick/ratatui_ruby/tree/trunk) for pre-release updates.
27
27
 
28
28
 
29
29
  ## Compatibility
@@ -63,12 +63,13 @@ gem install ratatui_ruby
63
63
 
64
64
  **ratatui_ruby** uses an immediate-mode API. You describe your UI using Ruby objects and call `draw` in a loop.
65
65
 
66
+ <!-- SYNC:START:examples/verify_readme_usage/app.rb:main -->
66
67
  ```ruby
67
- require "ratatui_ruby"
68
68
  RatatuiRuby.run do |tui|
69
69
  loop do
70
- tui.draw \
71
- tui.paragraph \
70
+ tui.draw do |frame|
71
+ frame.render_widget(
72
+ tui.paragraph(
72
73
  text: "Hello, Ratatui! Press 'q' to quit.",
73
74
  alignment: :center,
74
75
  block: tui.block(
@@ -76,11 +77,20 @@ RatatuiRuby.run do |tui|
76
77
  borders: [:all],
77
78
  border_color: "cyan"
78
79
  )
79
- event = tui.poll_event
80
- break if event == "q" || event == :ctrl_c
80
+ ),
81
+ frame.area
82
+ )
83
+ end
84
+ case tui.poll_event
85
+ in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
86
+ break
87
+ else
88
+ nil
89
+ end
81
90
  end
82
91
  end
83
92
  ```
93
+ <!-- SYNC:END -->
84
94
 
85
95
  For a full tutorial, see [the Quickstart](./doc/quickstart.md). For an explanation of the application architecture, see [Application Architecture](./doc/application_architecture.md).
86
96
 
@@ -98,6 +108,8 @@ Issues for the underlying Rust library should be filed at [ratatui/ratatui](http
98
108
 
99
109
  Want to help develop **ratatui_ruby**? Check out the [contribution guide on the wiki](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md).
100
110
 
111
+ **Note**: Active development happens on the `trunk` branch. Use `trunk` if you are a contributor or want the latest cutting-edge features. `stable` is for stable releases only.
112
+
101
113
 
102
114
  ## Copyright & License
103
115
 
data/REUSE.toml CHANGED
@@ -15,3 +15,18 @@ SPDX-License-Identifier = "CC0-1.0"
15
15
  path = 'doc/images/*.png'
16
16
  SPDX-FileCopyrightText = "2025 Kerrick Long <me@kerricklong.com>"
17
17
  SPDX-License-Identifier = "CC-BY-SA-4.0"
18
+
19
+ [[annotations]]
20
+ path = 'test/fixtures/*.txt'
21
+ SPDX-FileCopyrightText = "2025 Kerrick Long <me@kerricklong.com>"
22
+ SPDX-License-Identifier = "AGPL-3.0-or-later"
23
+
24
+ [[annotations]]
25
+ path = '**/snapshots/*.txt'
26
+ SPDX-FileCopyrightText = "2025 Kerrick Long <me@kerricklong.com>"
27
+ SPDX-License-Identifier = "AGPL-3.0-or-later"
28
+
29
+ [[annotations]]
30
+ path = '**/snapshots/*.ansi'
31
+ SPDX-FileCopyrightText = "2025 Kerrick Long <me@kerricklong.com>"
32
+ SPDX-License-Identifier = "AGPL-3.0-or-later"