ratatui_ruby 0.4.0 → 0.5.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 (351) 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 +87 -171
  7. data/CHANGELOG.md +38 -1
  8. data/README.md +8 -3
  9. data/REUSE.toml +20 -0
  10. data/doc/application_architecture.md +105 -45
  11. data/doc/application_testing.md +5 -3
  12. data/doc/contributors/design/ruby_frontend.md +9 -5
  13. data/doc/contributors/developing_examples.md +76 -18
  14. data/doc/contributors/documentation_style.md +7 -0
  15. data/doc/contributors/index.md +2 -0
  16. data/doc/event_handling.md +10 -4
  17. data/doc/images/app_all_events.png +0 -0
  18. data/doc/images/app_color_picker.png +0 -0
  19. data/doc/images/verify_readme_usage.png +0 -0
  20. data/doc/images/widget_barchart_demo.png +0 -0
  21. data/doc/images/widget_block_padding.png +0 -0
  22. data/doc/images/widget_block_titles.png +0 -0
  23. data/doc/images/widget_box_demo.png +0 -0
  24. data/doc/images/widget_calendar_demo.png +0 -0
  25. data/doc/images/widget_cell_demo.png +0 -0
  26. data/doc/images/widget_chart_demo.png +0 -0
  27. data/doc/images/widget_gauge_demo.png +0 -0
  28. data/doc/images/widget_layout_split.png +0 -0
  29. data/doc/images/widget_line_gauge_demo.png +0 -0
  30. data/doc/images/widget_list_demo.png +0 -0
  31. data/doc/images/widget_ratatui_logo_demo.png +0 -0
  32. data/doc/images/widget_ratatui_mascot_demo.png +0 -0
  33. data/doc/images/widget_render.png +0 -0
  34. data/doc/images/widget_scrollbar_demo.png +0 -0
  35. data/doc/images/widget_sparkline_demo.png +0 -0
  36. data/doc/images/widget_style_colors.png +0 -0
  37. data/doc/images/widget_table_flex.png +0 -0
  38. data/doc/images/widget_tabs_demo.png +0 -0
  39. data/doc/interactive_design.md +25 -30
  40. data/doc/quickstart.md +147 -120
  41. data/examples/app_all_events/README.md +81 -0
  42. data/examples/app_all_events/app.rb +93 -0
  43. data/examples/app_all_events/model/event_color_cycle.rb +41 -0
  44. data/examples/app_all_events/model/event_entry.rb +75 -0
  45. data/examples/app_all_events/model/events.rb +180 -0
  46. data/examples/app_all_events/model/highlight.rb +57 -0
  47. data/examples/app_all_events/model/timestamp.rb +54 -0
  48. data/examples/app_all_events/test/snapshots/after_focus_lost.txt +24 -0
  49. data/examples/app_all_events/test/snapshots/after_focus_regained.txt +24 -0
  50. data/examples/app_all_events/test/snapshots/after_horizontal_resize.txt +24 -0
  51. data/examples/app_all_events/test/snapshots/after_key_a.txt +24 -0
  52. data/examples/app_all_events/test/snapshots/after_key_ctrl_x.txt +24 -0
  53. data/examples/app_all_events/test/snapshots/after_mouse_click.txt +24 -0
  54. data/examples/app_all_events/test/snapshots/after_mouse_drag.txt +24 -0
  55. data/examples/app_all_events/test/snapshots/after_multiple_events.txt +24 -0
  56. data/examples/app_all_events/test/snapshots/after_paste.txt +24 -0
  57. data/examples/app_all_events/test/snapshots/after_resize.txt +24 -0
  58. data/examples/app_all_events/test/snapshots/after_right_click.txt +24 -0
  59. data/examples/app_all_events/test/snapshots/after_vertical_resize.txt +24 -0
  60. data/examples/app_all_events/test/snapshots/initial_state.txt +24 -0
  61. data/examples/app_all_events/view/app_view.rb +78 -0
  62. data/examples/app_all_events/view/controls_view.rb +50 -0
  63. data/examples/app_all_events/view/counts_view.rb +55 -0
  64. data/examples/app_all_events/view/live_view.rb +69 -0
  65. data/examples/app_all_events/view/log_view.rb +60 -0
  66. data/examples/app_all_events/view.rb +7 -0
  67. data/examples/app_all_events/view_state.rb +42 -0
  68. data/examples/app_color_picker/README.md +94 -0
  69. data/examples/app_color_picker/app.rb +112 -0
  70. data/examples/app_color_picker/clipboard.rb +84 -0
  71. data/examples/app_color_picker/color.rb +191 -0
  72. data/examples/app_color_picker/copy_dialog.rb +170 -0
  73. data/examples/app_color_picker/harmony.rb +56 -0
  74. data/examples/app_color_picker/input.rb +142 -0
  75. data/examples/app_color_picker/palette.rb +80 -0
  76. data/examples/app_color_picker/scene.rb +201 -0
  77. data/examples/{login_form → app_login_form}/app.rb +39 -42
  78. data/examples/{map_demo → app_map_demo}/app.rb +24 -21
  79. data/examples/{table_select → app_table_select}/app.rb +68 -65
  80. data/examples/{quickstart_dsl → verify_quickstart_dsl}/app.rb +15 -6
  81. data/examples/verify_quickstart_layout/app.rb +69 -0
  82. data/examples/{quickstart_lifecycle → verify_quickstart_lifecycle}/app.rb +19 -10
  83. data/examples/verify_readme_usage/app.rb +34 -0
  84. data/examples/widget_barchart_demo/app.rb +238 -0
  85. data/examples/{block_padding → widget_block_padding}/app.rb +17 -13
  86. data/examples/{block_titles → widget_block_titles}/app.rb +25 -17
  87. data/examples/{box_demo → widget_box_demo}/app.rb +99 -65
  88. data/examples/widget_calendar_demo/app.rb +109 -0
  89. data/examples/widget_cell_demo/app.rb +104 -0
  90. data/examples/widget_chart_demo/app.rb +213 -0
  91. data/examples/widget_gauge_demo/app.rb +212 -0
  92. data/examples/widget_layout_split/app.rb +246 -0
  93. data/examples/widget_line_gauge_demo/app.rb +217 -0
  94. data/examples/widget_list_demo/app.rb +382 -0
  95. data/examples/widget_list_styles/app.rb +141 -0
  96. data/examples/widget_popup_demo/app.rb +104 -0
  97. data/examples/widget_ratatui_logo_demo/app.rb +103 -0
  98. data/examples/widget_ratatui_mascot_demo/app.rb +93 -0
  99. data/examples/widget_rect/app.rb +205 -0
  100. data/examples/widget_render/app.rb +184 -0
  101. data/examples/widget_rich_text/app.rb +137 -0
  102. data/examples/widget_scroll_text/app.rb +108 -0
  103. data/examples/widget_scrollbar_demo/app.rb +153 -0
  104. data/examples/widget_sparkline_demo/app.rb +274 -0
  105. data/examples/widget_style_colors/app.rb +19 -21
  106. data/examples/widget_table_flex/app.rb +95 -0
  107. data/examples/widget_tabs_demo/app.rb +167 -0
  108. data/ext/ratatui_ruby/Cargo.lock +1 -1
  109. data/ext/ratatui_ruby/Cargo.toml +1 -1
  110. data/ext/ratatui_ruby/src/events.rs +121 -36
  111. data/ext/ratatui_ruby/src/frame.rs +115 -0
  112. data/ext/ratatui_ruby/src/lib.rs +79 -26
  113. data/ext/ratatui_ruby/src/rendering.rs +8 -4
  114. data/ext/ratatui_ruby/src/style.rs +138 -57
  115. data/ext/ratatui_ruby/src/terminal.rs +5 -9
  116. data/ext/ratatui_ruby/src/text.rs +13 -6
  117. data/ext/ratatui_ruby/src/widgets/barchart.rs +56 -54
  118. data/ext/ratatui_ruby/src/widgets/block.rs +7 -6
  119. data/ext/ratatui_ruby/src/widgets/canvas.rs +21 -3
  120. data/ext/ratatui_ruby/src/widgets/chart.rs +20 -10
  121. data/ext/ratatui_ruby/src/widgets/layout.rs +9 -4
  122. data/ext/ratatui_ruby/src/widgets/list.rs +32 -9
  123. data/ext/ratatui_ruby/src/widgets/overlay.rs +2 -1
  124. data/ext/ratatui_ruby/src/widgets/paragraph.rs +1 -1
  125. data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +19 -8
  126. data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +17 -10
  127. data/ext/ratatui_ruby/src/widgets/scrollbar.rs +4 -2
  128. data/ext/ratatui_ruby/src/widgets/sparkline.rs +14 -11
  129. data/ext/ratatui_ruby/src/widgets/table.rs +8 -4
  130. data/ext/ratatui_ruby/src/widgets/tabs.rs +11 -11
  131. data/lib/ratatui_ruby/cell.rb +3 -3
  132. data/lib/ratatui_ruby/event/key.rb +1 -1
  133. data/lib/ratatui_ruby/event/none.rb +43 -0
  134. data/lib/ratatui_ruby/event.rb +56 -4
  135. data/lib/ratatui_ruby/frame.rb +87 -0
  136. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +11 -11
  137. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +1 -5
  138. data/lib/ratatui_ruby/schema/bar_chart.rb +217 -217
  139. data/lib/ratatui_ruby/schema/block.rb +163 -168
  140. data/lib/ratatui_ruby/schema/calendar.rb +66 -67
  141. data/lib/ratatui_ruby/schema/canvas.rb +63 -63
  142. data/lib/ratatui_ruby/schema/center.rb +46 -46
  143. data/lib/ratatui_ruby/schema/chart.rb +135 -143
  144. data/lib/ratatui_ruby/schema/clear.rb +42 -42
  145. data/lib/ratatui_ruby/schema/constraint.rb +76 -76
  146. data/lib/ratatui_ruby/schema/cursor.rb +25 -25
  147. data/lib/ratatui_ruby/schema/gauge.rb +53 -53
  148. data/lib/ratatui_ruby/schema/layout.rb +87 -87
  149. data/lib/ratatui_ruby/schema/line_gauge.rb +62 -62
  150. data/lib/ratatui_ruby/schema/list.rb +86 -84
  151. data/lib/ratatui_ruby/schema/overlay.rb +31 -31
  152. data/lib/ratatui_ruby/schema/paragraph.rb +80 -80
  153. data/lib/ratatui_ruby/schema/ratatui_logo.rb +10 -6
  154. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +10 -5
  155. data/lib/ratatui_ruby/schema/rect.rb +60 -60
  156. data/lib/ratatui_ruby/schema/scrollbar.rb +119 -119
  157. data/lib/ratatui_ruby/schema/shape/label.rb +1 -1
  158. data/lib/ratatui_ruby/schema/sparkline.rb +111 -110
  159. data/lib/ratatui_ruby/schema/style.rb +46 -46
  160. data/lib/ratatui_ruby/schema/table.rb +112 -119
  161. data/lib/ratatui_ruby/schema/tabs.rb +66 -67
  162. data/lib/ratatui_ruby/session/autodoc.rb +417 -0
  163. data/lib/ratatui_ruby/session.rb +40 -23
  164. data/lib/ratatui_ruby/test_helper.rb +185 -19
  165. data/lib/ratatui_ruby/version.rb +1 -1
  166. data/lib/ratatui_ruby.rb +65 -39
  167. data/{examples/sparkline_demo → sig/examples/app_all_events}/app.rbs +3 -2
  168. data/sig/examples/app_all_events/model/event_entry.rbs +16 -0
  169. data/sig/examples/app_all_events/model/events.rbs +15 -0
  170. data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
  171. data/sig/examples/app_all_events/view/app_view.rbs +8 -0
  172. data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
  173. data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
  174. data/sig/examples/app_all_events/view/live_view.rbs +6 -0
  175. data/sig/examples/app_all_events/view/log_view.rbs +6 -0
  176. data/sig/examples/app_all_events/view.rbs +8 -0
  177. data/sig/examples/app_all_events/view_state.rbs +15 -0
  178. data/{examples/list_demo → sig/examples/app_color_picker}/app.rbs +2 -2
  179. data/sig/examples/app_login_form/app.rbs +11 -0
  180. data/sig/examples/app_map_demo/app.rbs +11 -0
  181. data/sig/examples/app_table_select/app.rbs +11 -0
  182. data/sig/examples/verify_quickstart_dsl/app.rbs +11 -0
  183. data/sig/examples/verify_quickstart_lifecycle/app.rbs +11 -0
  184. data/sig/examples/verify_readme_usage/app.rbs +11 -0
  185. data/sig/examples/widget_block_padding/app.rbs +11 -0
  186. data/sig/examples/widget_block_titles/app.rbs +11 -0
  187. data/sig/examples/widget_box_demo/app.rbs +11 -0
  188. data/sig/examples/widget_calendar_demo/app.rbs +11 -0
  189. data/sig/examples/widget_cell_demo/app.rbs +11 -0
  190. data/sig/examples/widget_chart_demo/app.rbs +11 -0
  191. data/{examples/gauge_demo → sig/examples/widget_gauge_demo}/app.rbs +4 -0
  192. data/sig/examples/widget_layout_split/app.rbs +10 -0
  193. data/sig/examples/widget_line_gauge_demo/app.rbs +11 -0
  194. data/sig/examples/widget_list_demo/app.rbs +12 -0
  195. data/sig/examples/widget_list_styles/app.rbs +11 -0
  196. data/sig/examples/widget_popup_demo/app.rbs +11 -0
  197. data/sig/examples/widget_ratatui_logo_demo/app.rbs +11 -0
  198. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +11 -0
  199. data/sig/examples/widget_rect/app.rbs +12 -0
  200. data/sig/examples/widget_render/app.rbs +10 -0
  201. data/sig/examples/widget_rich_text/app.rbs +11 -0
  202. data/sig/examples/widget_scroll_text/app.rbs +11 -0
  203. data/sig/examples/widget_scrollbar_demo/app.rbs +11 -0
  204. data/sig/examples/widget_sparkline_demo/app.rbs +10 -0
  205. data/{examples → sig/examples}/widget_style_colors/app.rbs +1 -1
  206. data/sig/examples/widget_table_flex/app.rbs +11 -0
  207. data/sig/ratatui_ruby/frame.rbs +9 -0
  208. data/sig/ratatui_ruby/ratatui_ruby.rbs +3 -2
  209. data/sig/ratatui_ruby/schema/draw.rbs +4 -0
  210. data/sig/ratatui_ruby/schema/layout.rbs +1 -1
  211. data/sig/ratatui_ruby/session.rbs +94 -0
  212. data/tasks/autodoc/inventory.rb +61 -0
  213. data/tasks/autodoc/member.rb +56 -0
  214. data/tasks/autodoc/name.rb +19 -0
  215. data/tasks/autodoc/notice.rb +26 -0
  216. data/tasks/autodoc/rbs.rb +38 -0
  217. data/tasks/autodoc/rdoc.rb +45 -0
  218. data/tasks/autodoc.rake +47 -0
  219. data/tasks/bump/history.rb +2 -2
  220. data/tasks/doc.rake +600 -6
  221. data/tasks/example_viewer.html.erb +172 -0
  222. data/tasks/lint.rake +8 -4
  223. data/tasks/resources/index.html.erb +6 -0
  224. data/tasks/sourcehut.rake +4 -4
  225. data/tasks/terminal_preview/app_screenshot.rb +1 -3
  226. data/tasks/terminal_preview/crash_report.rb +7 -9
  227. data/tasks/terminal_preview/launcher_script.rb +4 -6
  228. data/tasks/terminal_preview/preview_collection.rb +4 -6
  229. data/tasks/terminal_preview/safety_confirmation.rb +3 -5
  230. data/tasks/terminal_preview/saved_screenshot.rb +7 -9
  231. data/tasks/terminal_preview/terminal_window.rb +7 -9
  232. data/tasks/test.rake +1 -1
  233. data/tasks/website/index_page.rb +3 -3
  234. data/tasks/website/version.rb +10 -10
  235. data/tasks/website/version_menu.rb +10 -12
  236. data/tasks/website/versioned_documentation.rb +49 -17
  237. data/tasks/website/website.rb +6 -8
  238. data/tasks/website.rake +4 -4
  239. metadata +156 -125
  240. data/LICENSES/BSD-2-Clause.txt +0 -9
  241. data/doc/contributors/better_dx.md +0 -543
  242. data/doc/contributors/example_analysis.md +0 -82
  243. data/doc/images/all_events.png +0 -0
  244. data/doc/images/block_padding.png +0 -0
  245. data/doc/images/block_titles.png +0 -0
  246. data/doc/images/box_demo.png +0 -0
  247. data/doc/images/calendar_demo.png +0 -0
  248. data/doc/images/cell_demo.png +0 -0
  249. data/doc/images/chart_demo.png +0 -0
  250. data/doc/images/flex_layout.png +0 -0
  251. data/doc/images/gauge_demo.png +0 -0
  252. data/doc/images/line_gauge_demo.png +0 -0
  253. data/doc/images/list_demo.png +0 -0
  254. data/doc/images/readme_usage.png +0 -0
  255. data/doc/images/scrollbar_demo.png +0 -0
  256. data/doc/images/sparkline_demo.png +0 -0
  257. data/doc/images/table_flex.png +0 -0
  258. data/examples/all_events/app.rb +0 -169
  259. data/examples/all_events/app.rbs +0 -7
  260. data/examples/all_events/test_app.rb +0 -139
  261. data/examples/analytics/app.rb +0 -258
  262. data/examples/analytics/app.rbs +0 -7
  263. data/examples/analytics/test_app.rb +0 -132
  264. data/examples/block_padding/app.rbs +0 -7
  265. data/examples/block_padding/test_app.rb +0 -31
  266. data/examples/block_titles/app.rbs +0 -7
  267. data/examples/block_titles/test_app.rb +0 -34
  268. data/examples/box_demo/app.rbs +0 -7
  269. data/examples/box_demo/test_app.rb +0 -88
  270. data/examples/calendar_demo/app.rb +0 -101
  271. data/examples/calendar_demo/app.rbs +0 -7
  272. data/examples/calendar_demo/test_app.rb +0 -108
  273. data/examples/cell_demo/app.rb +0 -108
  274. data/examples/cell_demo/app.rbs +0 -7
  275. data/examples/cell_demo/test_app.rb +0 -36
  276. data/examples/chart_demo/app.rb +0 -203
  277. data/examples/chart_demo/app.rbs +0 -7
  278. data/examples/chart_demo/test_app.rb +0 -102
  279. data/examples/custom_widget/app.rb +0 -51
  280. data/examples/custom_widget/app.rbs +0 -7
  281. data/examples/custom_widget/test_app.rb +0 -30
  282. data/examples/flex_layout/app.rb +0 -156
  283. data/examples/flex_layout/app.rbs +0 -7
  284. data/examples/flex_layout/test_app.rb +0 -65
  285. data/examples/gauge_demo/app.rb +0 -182
  286. data/examples/gauge_demo/test_app.rb +0 -120
  287. data/examples/hit_test/app.rb +0 -175
  288. data/examples/hit_test/app.rbs +0 -7
  289. data/examples/hit_test/test_app.rb +0 -102
  290. data/examples/line_gauge_demo/app.rb +0 -190
  291. data/examples/line_gauge_demo/app.rbs +0 -7
  292. data/examples/line_gauge_demo/test_app.rb +0 -129
  293. data/examples/list_demo/app.rb +0 -253
  294. data/examples/list_demo/test_app.rb +0 -237
  295. data/examples/list_styles/app.rb +0 -140
  296. data/examples/list_styles/app.rbs +0 -7
  297. data/examples/list_styles/test_app.rb +0 -157
  298. data/examples/login_form/app.rbs +0 -7
  299. data/examples/login_form/test_app.rb +0 -51
  300. data/examples/map_demo/app.rbs +0 -7
  301. data/examples/map_demo/test_app.rb +0 -149
  302. data/examples/mouse_events/app.rb +0 -97
  303. data/examples/mouse_events/app.rbs +0 -7
  304. data/examples/mouse_events/test_app.rb +0 -53
  305. data/examples/popup_demo/app.rb +0 -103
  306. data/examples/popup_demo/app.rbs +0 -7
  307. data/examples/popup_demo/test_app.rb +0 -54
  308. data/examples/quickstart_dsl/app.rbs +0 -7
  309. data/examples/quickstart_dsl/test_app.rb +0 -29
  310. data/examples/quickstart_lifecycle/app.rbs +0 -7
  311. data/examples/quickstart_lifecycle/test_app.rb +0 -29
  312. data/examples/ratatui_logo_demo/app.rb +0 -79
  313. data/examples/ratatui_logo_demo/app.rbs +0 -7
  314. data/examples/ratatui_logo_demo/test_app.rb +0 -51
  315. data/examples/ratatui_mascot_demo/app.rb +0 -84
  316. data/examples/ratatui_mascot_demo/app.rbs +0 -7
  317. data/examples/ratatui_mascot_demo/test_app.rb +0 -47
  318. data/examples/readme_usage/app.rb +0 -29
  319. data/examples/readme_usage/app.rbs +0 -7
  320. data/examples/readme_usage/test_app.rb +0 -29
  321. data/examples/rich_text/app.rb +0 -141
  322. data/examples/rich_text/app.rbs +0 -7
  323. data/examples/rich_text/test_app.rb +0 -166
  324. data/examples/scroll_text/app.rb +0 -103
  325. data/examples/scroll_text/app.rbs +0 -7
  326. data/examples/scroll_text/test_app.rb +0 -110
  327. data/examples/scrollbar_demo/app.rb +0 -143
  328. data/examples/scrollbar_demo/app.rbs +0 -7
  329. data/examples/scrollbar_demo/test_app.rb +0 -77
  330. data/examples/sparkline_demo/app.rb +0 -240
  331. data/examples/sparkline_demo/test_app.rb +0 -107
  332. data/examples/table_flex/app.rb +0 -65
  333. data/examples/table_flex/app.rbs +0 -7
  334. data/examples/table_flex/test_app.rb +0 -36
  335. data/examples/table_select/app.rbs +0 -7
  336. data/examples/table_select/test_app.rb +0 -180
  337. data/examples/widget_style_colors/test_app.rb +0 -48
  338. /data/doc/images/{analytics.png → app_analytics.png} +0 -0
  339. /data/doc/images/{custom_widget.png → app_custom_widget.png} +0 -0
  340. /data/doc/images/{login_form.png → app_login_form.png} +0 -0
  341. /data/doc/images/{map_demo.png → app_map_demo.png} +0 -0
  342. /data/doc/images/{mouse_events.png → app_mouse_events.png} +0 -0
  343. /data/doc/images/{table_select.png → app_table_select.png} +0 -0
  344. /data/doc/images/{quickstart_dsl.png → verify_quickstart_dsl.png} +0 -0
  345. /data/doc/images/{ratatui_logo_demo.png → verify_quickstart_layout.png} +0 -0
  346. /data/doc/images/{quickstart_lifecycle.png → verify_quickstart_lifecycle.png} +0 -0
  347. /data/doc/images/{list_styles.png → widget_list_styles.png} +0 -0
  348. /data/doc/images/{popup_demo.png → widget_popup_demo.png} +0 -0
  349. /data/doc/images/{hit_test.png → widget_rect.png} +0 -0
  350. /data/doc/images/{rich_text.png → widget_rich_text.png} +0 -0
  351. /data/doc/images/{scroll_text.png → widget_scroll_text.png} +0 -0
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
- # SPDX-License-Identifier: AGPL-3.0-or-later
5
-
6
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
- require "ratatui_ruby"
8
- require "ratatui_ruby/test_helper"
9
- require "minitest/autorun"
10
- require_relative "app"
11
-
12
- class TestAnalytics < Minitest::Test
13
- include RatatuiRuby::TestHelper
14
-
15
- def setup
16
- @app = AnalyticsApp.new
17
- end
18
-
19
- def test_render_initial_state
20
- with_test_terminal do
21
- # Queue quit
22
- inject_key(:q)
23
-
24
- @app.run
25
-
26
- # Check Tabs
27
- assert buffer_content.any? { |line| line.include?("Revenue") }
28
- assert buffer_content.any? { |line| line.include?("Traffic") }
29
- assert buffer_content.any? { |line| line.include?("Errors") }
30
-
31
- # Check initial selected tab content
32
- assert buffer_content.any? { |line| line.include?("Analytics: Revenue") }
33
-
34
- # Check help text visibility (join to handle potential wrapping)
35
- content_str = buffer_content.join("\n")
36
- assert_includes content_str, "q: Quit"
37
- end
38
- end
39
-
40
- def test_navigation_right
41
- with_test_terminal do
42
- inject_keys(:right, :q)
43
-
44
- @app.run
45
-
46
- assert buffer_content.any? { |line| line.include?("Analytics: Traffic") }
47
- end
48
- end
49
-
50
- def test_navigation_left
51
- with_test_terminal do
52
- # Move right to Traffic
53
- inject_keys(:a, :b, :c)
54
-
55
- # Then queue quit
56
- inject_key(:q)
57
-
58
- @app.run
59
-
60
- assert buffer_content.any? { |line| line.include?("Analytics: Revenue") }
61
- end
62
- end
63
-
64
- def test_quit
65
- with_test_terminal do
66
- inject_key(:q)
67
- @app.run
68
- # Success if returns
69
- end
70
- end
71
-
72
- def test_switch_divider
73
- with_test_terminal do
74
- # Switch divider (d) then quit (q)
75
- inject_keys(:d, :q)
76
- @app.run
77
-
78
- # Default is " | ", next is " • "
79
- assert buffer_content.any? { |line| line.include?(" • ") }
80
- end
81
- end
82
-
83
- def test_switch_style
84
- with_test_terminal do
85
- # Switch style (space) then quit (q)
86
- inject_keys(:" ", :q)
87
- @app.run
88
-
89
- # Verify it runs without error.
90
- # Style visual verification is limited with simple string buffer checks,
91
- # but this ensures the event handling works.
92
- end
93
- end
94
-
95
- def test_padding_controls
96
- with_test_terminal do
97
- # Increase padding_left (l) and padding_right (k) then quit
98
- inject_keys(:l, :l, :k, :k, :k, :q)
99
- @app.run
100
-
101
- # Verify that padding values are shown in status with hotkeys
102
- # Use join to match even if wrapped or if "Pad Left" logic changed
103
- content_str = buffer_content.join("\n")
104
- assert_includes content_str, "h/l: Pad Left (2)"
105
- assert_includes content_str, "j/k: Pad Right (3)"
106
- end
107
- end
108
-
109
- def test_styling_controls
110
- with_test_terminal do
111
- # Cycle label style (x) and value style (z)
112
- inject_keys(:x, :z, :z, :q)
113
- @app.run
114
- # Verify expected content
115
- content = buffer_content.join
116
- assert_includes content, "Analytics: Revenue"
117
- assert_includes content, "Views"
118
- assert_includes content, "Controls"
119
- assert_includes content, "Width:"
120
- end
121
- end
122
-
123
- def test_direction_toggle
124
- with_test_terminal do
125
- # Switch to horizontal (v) then quit
126
- inject_keys(:v, :q)
127
- @app.run
128
-
129
- assert buffer_content.any? { |line| line.include?("v: Direction (horizontal)") }
130
- end
131
- end
132
- end
@@ -1,7 +0,0 @@
1
- class BlockPaddingApp
2
- # @public
3
- def self.new: () -> BlockPaddingApp
4
-
5
- # @public
6
- def run: () -> void
7
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
- # SPDX-License-Identifier: AGPL-3.0-or-later
5
-
6
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
- require "ratatui_ruby"
8
- require "ratatui_ruby/test_helper"
9
- require "minitest/autorun"
10
- require_relative "app"
11
-
12
- class TestBlockPadding < Minitest::Test
13
- include RatatuiRuby::TestHelper
14
-
15
- def setup
16
- @app = BlockPaddingApp.new
17
- end
18
-
19
- def test_render
20
- with_test_terminal do
21
- inject_key(:q)
22
- @app.run
23
-
24
- content = buffer_content.join("\n")
25
- assert_includes content, "Uniform Padding (2)"
26
- assert_includes content, "This text is padded by 2 on all sides."
27
- assert_includes content, "Directional Padding [Left: 4, Right: 0, Top: 2, Bottom: 0]"
28
- assert_includes content, "Left: 4, Top: 2."
29
- end
30
- end
31
- end
@@ -1,7 +0,0 @@
1
- class BlockTitlesApp
2
- # @public
3
- def self.new: () -> BlockTitlesApp
4
-
5
- # @public
6
- def run: () -> void
7
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
- # SPDX-License-Identifier: AGPL-3.0-or-later
5
-
6
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
- require "ratatui_ruby"
8
- require "ratatui_ruby/test_helper"
9
- require "minitest/autorun"
10
- require_relative "app"
11
-
12
- class TestBlockTitles < Minitest::Test
13
- include RatatuiRuby::TestHelper
14
-
15
- def setup
16
- @app = BlockTitlesApp.new
17
- end
18
-
19
- def test_render
20
- with_test_terminal do
21
- inject_key(:q)
22
- @app.run
23
-
24
- content = buffer_content.join("\n")
25
- assert_includes content, "Top Left"
26
- assert_includes content, "Top Right"
27
- assert_includes content, "Bottom Left"
28
- assert_includes content, "Bottom Center"
29
- assert_includes content, "Bottom Right"
30
- assert_includes content, "Simple String Title (Top Left Default)"
31
- assert_includes content, "Mixed Title"
32
- end
33
- end
34
- end
@@ -1,7 +0,0 @@
1
- class BoxDemoApp
2
- # @public
3
- def self.new: () -> BoxDemoApp
4
-
5
- # @public
6
- def run: () -> void
7
- end
@@ -1,88 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
- # SPDX-License-Identifier: AGPL-3.0-or-later
5
-
6
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
- require "ratatui_ruby"
8
- require "ratatui_ruby/test_helper"
9
- require "minitest/autorun"
10
- require_relative "app"
11
-
12
- class TestBoxDemo < Minitest::Test
13
- include RatatuiRuby::TestHelper
14
-
15
- def setup
16
- @app = BoxDemoApp.new
17
- end
18
-
19
- def test_render_initial_state
20
- with_test_terminal do
21
- inject_key(:q)
22
- @app.run
23
-
24
- assert buffer_content.any? { |line| line.include?("Box Demo") }
25
- assert buffer_content.any? { |line| line.include?("Controls") }
26
- assert buffer_content.any? { |line| line.include?("Green") }
27
- end
28
- end
29
-
30
- def test_color_cycling_changes_color
31
- with_test_terminal do
32
- # Pressing up should cycle colors backwards
33
- inject_keys(:up, :q)
34
- @app.run
35
-
36
- # At least the Controls section should be rendered
37
- assert buffer_content.any? { |line| line.include?("Controls") }
38
- end
39
- end
40
-
41
- def test_border_type_cycling
42
- with_test_terminal do
43
- inject_keys(" ", :q)
44
- @app.run
45
-
46
- assert buffer_content.any? { |line| line.include?("Rounded") }
47
- end
48
- end
49
-
50
- def test_title_alignment_cycling
51
- with_test_terminal do
52
- inject_keys(:enter, :q)
53
- @app.run
54
-
55
- assert buffer_content.any? { |line| line.include?("Center") }
56
- end
57
- end
58
-
59
- def test_content_style_changes
60
- with_test_terminal do
61
- inject_keys(:s, :q)
62
- @app.run
63
-
64
- # At least the Controls section should be rendered
65
- assert buffer_content.any? { |line| line.include?("Controls") }
66
- end
67
- end
68
-
69
- def test_title_style_changes
70
- with_test_terminal do
71
- inject_keys(:t, :q)
72
- @app.run
73
-
74
- # At least the Controls section should be rendered
75
- assert buffer_content.any? { |line| line.include?("Controls") }
76
- end
77
- end
78
-
79
- def test_border_style_cycling
80
- with_test_terminal do
81
- inject_keys(:b, :q)
82
- @app.run
83
-
84
- # At least the Controls section should be rendered
85
- assert buffer_content.any? { |line| line.include?("Controls") }
86
- end
87
- end
88
- end
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
- # SPDX-License-Identifier: AGPL-3.0-or-later
5
-
6
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
- require "ratatui_ruby"
8
-
9
- # A demo application for the Calendar widget.
10
- class CalendarDemoApp
11
- def run
12
- RatatuiRuby.run do
13
- show_header = true
14
- show_weekdays = true
15
- show_surrounding = false
16
- show_events = true
17
-
18
- loop do
19
- now = Time.now
20
- surrounding_style = if show_surrounding
21
- RatatuiRuby::Style.new(fg: "gray", modifiers: [:dim])
22
- else
23
- nil
24
- end
25
-
26
- events_map = if show_events
27
- {
28
- now => RatatuiRuby::Style.new(fg: "green", modifiers: [:bold]),
29
- (now + 86400 * 2) => RatatuiRuby::Style.new(fg: "red", modifiers: [:underlined]),
30
- (now - 86400 * 5) => RatatuiRuby::Style.new(fg: "blue", bg: "white"),
31
- }
32
- else
33
- {}
34
- end
35
-
36
- calendar = RatatuiRuby::Calendar.new(
37
- year: now.year,
38
- month: now.month,
39
- events: events_map,
40
- header_style: RatatuiRuby::Style.new(fg: "yellow", modifiers: [:bold]),
41
- show_month_header: show_header,
42
- show_weekdays_header: show_weekdays,
43
- show_surrounding: surrounding_style,
44
- block: RatatuiRuby::Block.new(borders: [:top, :left, :right])
45
- )
46
-
47
- controls_text = [
48
- RatatuiRuby::Text::Line.new(
49
- spans: [
50
- RatatuiRuby::Text::Span.new(content: " h/w/s/e", style: RatatuiRuby::Style.new(modifiers: [:bold])),
51
- RatatuiRuby::Text::Span.new(content: ": Toggle Header/Weekdays/Surrounding/Events "),
52
- RatatuiRuby::Text::Span.new(content: "q", style: RatatuiRuby::Style.new(modifiers: [:bold])),
53
- RatatuiRuby::Text::Span.new(content: ": Quit"),
54
- ]
55
- ),
56
- RatatuiRuby::Text::Line.new(
57
- spans: [
58
- RatatuiRuby::Text::Span.new(content: " Events: ", style: RatatuiRuby::Style.new(modifiers: [:bold])),
59
- RatatuiRuby::Text::Span.new(content: "Today (Green), +2d (Red), -5d (Blue) (#{show_events ? "On" : "Off"})"),
60
- ]
61
- )
62
- ]
63
- controls = RatatuiRuby::Paragraph.new(
64
- text: controls_text,
65
- block: RatatuiRuby::Block.new(title: " Controls ", borders: [:all])
66
- )
67
-
68
- RatatuiRuby.draw(
69
- RatatuiRuby::Layout.new(
70
- direction: :vertical,
71
- constraints: [
72
- RatatuiRuby::Constraint.min(0),
73
- RatatuiRuby::Constraint.length(4),
74
- ],
75
- children: [calendar, controls]
76
- )
77
- )
78
-
79
- event = RatatuiRuby.poll_event
80
- case event
81
- in {type: :key, code: "q"} | {type: :key, code: "c", modifiers: ["ctrl"]}
82
- break
83
- in type: :key, code: "h"
84
- show_header = !show_header
85
- in type: :key, code: "w"
86
- show_weekdays = !show_weekdays
87
- in type: :key, code: "s"
88
- show_surrounding = !show_surrounding
89
- in type: :key, code: "e"
90
- show_events = !show_events
91
- else
92
- nil
93
- end
94
-
95
- sleep 0.05
96
- end
97
- end
98
- end
99
- end
100
-
101
- CalendarDemoApp.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,7 +0,0 @@
1
- class CalendarDemoApp
2
- # @public
3
- def self.new: () -> CalendarDemoApp
4
-
5
- # @public
6
- def run: () -> void
7
- end
@@ -1,108 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
- # SPDX-License-Identifier: AGPL-3.0-or-later
5
-
6
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
- require "minitest/autorun"
8
- require "ratatui_ruby"
9
- require "ratatui_ruby/test_helper"
10
- require_relative "app"
11
-
12
- class TestCalendarDemoApp < Minitest::Test
13
- include RatatuiRuby::TestHelper
14
-
15
- def setup
16
- @app = CalendarDemoApp.new
17
- end
18
-
19
- def test_demo_renders
20
- with_test_terminal do
21
- inject_keys(:down, :down, :q)
22
-
23
- @app.run
24
-
25
- content = buffer_content
26
- rendered_text = content.join("\n")
27
-
28
- # Verify the bottom controls are present
29
- assert_match(/h\/w\/s\/e: Toggle Header\/Weekdays\/Surrounding\/Events/, rendered_text)
30
- assert_match(/q: Quit/, rendered_text)
31
-
32
- # Verify the calendar content is present
33
- assert_match(/#{Time.now.year}/, rendered_text)
34
-
35
- # Verify layout structure (calendar taking up most space, controls at bottom)
36
- # The controls are on the last line (index 23 for 24 lines) if the terminal is 24 lines high
37
- # but standard terminal might be different. with_test_terminal defaults to 80x24.
38
- # assert_match(/q: Quit/, content[23]) if content[23]
39
- end
40
- end
41
-
42
- def test_toggle_weekdays_header
43
- with_test_terminal do
44
- inject_keys("w", :q)
45
-
46
- @app.run
47
-
48
- content = buffer_content
49
- rendered_text = content.join("\n")
50
-
51
- # The app should render successfully with weekdays toggled
52
- assert_match(/#{Time.now.year}/, rendered_text)
53
- end
54
- end
55
-
56
- def test_toggle_header
57
- with_test_terminal do
58
- inject_keys("h", :q)
59
-
60
- @app.run
61
-
62
- content = buffer_content
63
- rendered_text = content.join("\n")
64
-
65
- # The app should render successfully with header toggled (hidden)
66
- refute_match(/#{Time.now.year}/, rendered_text)
67
-
68
- # Inject h again to show it (h -> off, h -> on)
69
- inject_keys("h", "h", :q)
70
- @app.run
71
- content = buffer_content
72
- rendered_text = content.join("\n")
73
- assert_match(/#{Time.now.year}/, rendered_text)
74
- end
75
- end
76
-
77
- def test_toggle_surrounding
78
- with_test_terminal do
79
- inject_keys("s", :q)
80
-
81
- @app.run
82
-
83
- content = buffer_content
84
- rendered_text = content.join("\n")
85
-
86
- # The app should render successfully with surrounding toggled
87
- assert_match(/#{Time.now.year}/, rendered_text)
88
- end
89
- end
90
-
91
- def test_events_render
92
- with_test_terminal do
93
- inject_keys("e", :q)
94
-
95
- @app.run
96
-
97
- content = buffer_content
98
- # We just check that the app runs without crashing and renders the calendar.
99
- # Verifying specific color codes in the buffer content is harder without
100
- # exposing the underlying buffer cells' style.
101
- # But we can at least assert the content is still correct.
102
- assert_match(/#{Time.now.year}/, content.join("\n"))
103
-
104
- # Verify the legend is present and shows Off status after toggle
105
- assert_match(/Events: .* \(Off\)/, content.join("\n"))
106
- end
107
- end
108
- end
@@ -1,108 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
4
- require "ratatui_ruby"
5
-
6
- # A custom widget that fills its area with a checkered pattern using Cell objects.
7
- class CheckeredBackground
8
- def render(area)
9
- cell = RatatuiRuby::Cell.new(char: "░", fg: :dark_gray)
10
- commands = []
11
- area.height.times do |y|
12
- area.width.times do |x|
13
- # Checkerboard logic
14
- if (x + y).even?
15
- # Use a dim cell for the background pattern
16
- commands << RatatuiRuby::Draw.cell(area.x + x, area.y + y, cell)
17
- end
18
- end
19
- end
20
- commands
21
- end
22
- end
23
-
24
- class CellDemoApp
25
- def main
26
- RatatuiRuby.run do |tui|
27
- # Define some reusable cells for our table
28
- ok_cell = RatatuiRuby::Cell.new(char: "OK", fg: :green)
29
- fail_cell = RatatuiRuby::Cell.new(char: "FAIL", fg: :red, modifiers: ["bold"])
30
- pending_cell = RatatuiRuby::Cell.new(char: "...", fg: :yellow, modifiers: ["dim"])
31
-
32
- # A mix of Strings and Cells in rows
33
- rows = [
34
- ["Database", ok_cell],
35
- ["Cache", ok_cell],
36
- ["Worker", fail_cell],
37
- ["Analytics", pending_cell],
38
- ["Web Server", RatatuiRuby::Cell.new(char: "RESTARTING", fg: :blue, modifiers: ["rapid_blink"])]
39
- ]
40
-
41
- table = RatatuiRuby::Table.new(
42
- header: ["Service", RatatuiRuby::Cell.new(char: "Status", modifiers: ["underlined"])],
43
- rows: rows,
44
- widths: [
45
- RatatuiRuby::Constraint.percentage(70),
46
- RatatuiRuby::Constraint.percentage(30)
47
- ],
48
- block: RatatuiRuby::Block.new(title: "System Status", borders: :all),
49
- column_spacing: 1
50
- )
51
-
52
- # Main loop
53
- loop do
54
- # Create a layout that holds both widgets
55
- # We use a vertical layout:
56
- # Top: Custom CheckeredBackground with specific height
57
- # Bottom: Table using remaining space
58
-
59
- # Note: CheckeredBackground renders to the area implicitly if passed as a child.
60
- # However, to overlay the paragraph, we might need a more complex structure or
61
- # wrapper. RatatuiRuby::Layout handles non-overlapping children.
62
- # To get the "Overlay" effect from my previous code (Paragraph over Background),
63
- # we would need to composite them. For now, let's just show them stacked or
64
- # using 'Overlay' widget if it exists.
65
-
66
- # Checking schema: Overlay exists? Yes: require_relative "ratatui_ruby/schema/overlay" in lib/ratatui_ruby.rb
67
-
68
- layout = RatatuiRuby::Layout.new(
69
- direction: :vertical,
70
- constraints: [
71
- RatatuiRuby::Constraint.length(10), # Top section
72
- RatatuiRuby::Constraint.min(0) # Bottom section
73
- ],
74
- children: [
75
- # Top Child: An Overlay of Paragraph on top of CheckeredBackground
76
- RatatuiRuby::Overlay.new(
77
- layers: [
78
- CheckeredBackground.new,
79
- RatatuiRuby::Center.new(
80
- width_percent: 50,
81
- height_percent: 50,
82
- child: RatatuiRuby::Paragraph.new(
83
- text: "Custom Widget Demo\n(CheckeredBackground)",
84
- alignment: :center,
85
- block: RatatuiRuby::Block.new(borders: :all, title: "Overlay")
86
- )
87
- )
88
- ]
89
- ),
90
- # Bottom Child: The Table
91
- table
92
- ]
93
- )
94
-
95
- tui.draw(layout)
96
-
97
- event = RatatuiRuby.poll_event
98
- if event.is_a?(RatatuiRuby::Event::Key)
99
- break if event.code == "q" || (event.code == "c" && event.modifiers.include?("ctrl"))
100
- end
101
- end
102
- end
103
- end
104
- end
105
-
106
- if __FILE__ == $0
107
- CellDemoApp.new.main
108
- end
@@ -1,7 +0,0 @@
1
- class CellDemoApp
2
- # @public
3
- def self.new: () -> CellDemoApp
4
-
5
- # @public
6
- def run: () -> void
7
- end
@@ -1,36 +0,0 @@
1
- require "minitest/autorun"
2
- require "ratatui_ruby"
3
- require "ratatui_ruby/test_helper"
4
- require_relative "app"
5
-
6
- class TestCellDemoApp < Minitest::Test
7
- include RatatuiRuby::TestHelper
8
-
9
- include RatatuiRuby::TestHelper
10
-
11
- def test_cell_demo_output
12
- # Run the demo in a test terminal
13
- # We'll inject a 'q' key to exit the loop immediately after the first draw
14
- with_test_terminal(timeout: 5) do
15
- inject_key("q")
16
- CellDemoApp.new.main
17
-
18
- # Verify Custom Widget Output
19
- # Check for "░" character from CheckeredBackground
20
- # It should be visible around the centered widget
21
- assert_includes buffer_content.join("\n"), "░"
22
-
23
- # Verify Table Output
24
- # Content strings
25
- assert_includes buffer_content.join("\n"), "System Status"
26
- assert_includes buffer_content.join("\n"), "Database"
27
- assert_includes buffer_content.join("\n"), "Worker"
28
-
29
- # We can't easily grep for "FAIL" with color in simple string content check,
30
- # but we can check the text presence.
31
- assert_includes buffer_content.join("\n"), "FAIL"
32
- assert_includes buffer_content.join("\n"), "OK"
33
- assert_includes buffer_content.join("\n"), "RESTARTING"
34
- end
35
- end
36
- end