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,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
- # SPDX-License-Identifier: CC-BY-SA-4.0
5
-
6
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
- require "ratatui_ruby"
8
-
9
- class RatatuiMascotDemoApp
10
- def initialize
11
- @show_block = true
12
- end
13
-
14
- def run
15
- RatatuiRuby.run do |tui|
16
- loop do
17
- render(tui)
18
- break if handle_input(tui) == :quit
19
- end
20
- end
21
- end
22
-
23
- private
24
-
25
- def render(tui)
26
- # Layout: Top (Mascot), Bottom (Controls)
27
- # Mascot Widget
28
- block = if @show_block
29
- tui.block(
30
- title: "Ratatui Mascot",
31
- borders: [:all],
32
- border_type: :rounded,
33
- border_style: { fg: :green }
34
- )
35
- end
36
-
37
- mascot = tui.ratatui_mascot(block: block)
38
-
39
- # Controls
40
- controls_text = [
41
- tui.text_span(content: "q", style: tui.style(modifiers: [:bold, :underlined])),
42
- tui.text_span(content: " Quit"),
43
- tui.text_span(content: " "),
44
- tui.text_span(content: "b", style: tui.style(modifiers: [:bold, :underlined])),
45
- tui.text_span(content: " Toggle Block #{@show_block ? '(On)' : '(Off)'}")
46
- ]
47
-
48
- controls_paragraph = tui.paragraph(
49
- text: tui.text_line(spans: controls_text),
50
- block: tui.block(borders: [:top], title: "Controls")
51
- )
52
-
53
- # Layout: Top (Mascot), Bottom (Controls)
54
- layout = tui.layout(
55
- direction: :vertical,
56
- constraints: [
57
- RatatuiRuby::Constraint.fill(1),
58
- RatatuiRuby::Constraint.length(4)
59
- ],
60
- children: [
61
- mascot,
62
- controls_paragraph
63
- ]
64
- )
65
-
66
- tui.draw(layout)
67
- end
68
-
69
- def handle_input(tui)
70
- event = tui.poll_event
71
- return unless event
72
-
73
- if event.key?
74
- case event.char
75
- when "q" then return :quit
76
- when "b" then @show_block = !@show_block
77
- end
78
- elsif event.ctrl_c?
79
- return :quit
80
- end
81
- end
82
- end
83
-
84
- RatatuiMascotDemoApp.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,7 +0,0 @@
1
- class RatatuiMascotDemoApp
2
- # @public
3
- def self.new: () -> RatatuiMascotDemoApp
4
-
5
- # @public
6
- def run: () -> void
7
- end
@@ -1,47 +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 TestRatatuiMascotDemoApp < Minitest::Test
13
- include RatatuiRuby::TestHelper
14
-
15
- def setup
16
- @app = RatatuiMascotDemoApp.new
17
- end
18
-
19
- def test_initial_render
20
- with_test_terminal do
21
- inject_key(:q)
22
- @app.run
23
-
24
- content = buffer_content.join("\n")
25
- assert_includes content, "Ratatui Mascot" # Title implying block is on
26
- assert_includes content, "Toggle Block (On)"
27
- # Mascot contains block characters
28
- assert_includes content, "█"
29
- end
30
- end
31
-
32
- def test_toggle_block
33
- with_test_terminal do
34
- inject_key("b")
35
- inject_key(:q)
36
- @app.run
37
-
38
- content = buffer_content.join("\n")
39
- assert_includes content, "Toggle Block (Off)"
40
- # Title should be gone if block is gone (unless internal rendering keeps it, but our logic removes the block)
41
- # Wait, if block is nil, no border/title.
42
- refute_includes content, "Ratatui Mascot"
43
- # Mascot should still be there
44
- assert_includes content, "█"
45
- end
46
- end
47
- end
@@ -1,29 +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
-
8
- require "ratatui_ruby"
9
- class ReadmeUsageApp
10
- def run
11
- RatatuiRuby.run do |tui|
12
- loop do
13
- tui.draw \
14
- tui.paragraph \
15
- text: "Hello, Ratatui! Press 'q' to quit.",
16
- alignment: :center,
17
- block: tui.block(
18
- title: "My Ruby TUI App",
19
- borders: [:all],
20
- border_color: "cyan"
21
- )
22
- event = tui.poll_event
23
- break if event == "q" || event == :ctrl_c
24
- end
25
- end
26
- end
27
- end
28
-
29
- ReadmeUsageApp.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,7 +0,0 @@
1
- class ReadmeUsageApp
2
- # @public
3
- def self.new: () -> ReadmeUsageApp
4
-
5
- # @public
6
- def run: () -> void
7
- end
@@ -1,29 +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 TestReadmeUsage < Minitest::Test
13
- include RatatuiRuby::TestHelper
14
-
15
- def setup
16
- @app = ReadmeUsageApp.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, "Hello, Ratatui!"
26
- assert_includes content, "My Ruby TUI App"
27
- end
28
- end
29
- end
@@ -1,141 +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
- # Rich Text Example
10
- # Demonstrates the Span and Line objects for styling individual words
11
- # within a block of text.
12
- class RichTextApp
13
- def initialize
14
- @scroll_pos = 0
15
- end
16
-
17
- def run
18
- RatatuiRuby.run do
19
- loop do
20
- render
21
- event = handle_input
22
- break if event == :quit
23
- sleep 0.05
24
- end
25
- end
26
- end
27
-
28
- private
29
-
30
- def render
31
- RatatuiRuby.draw(
32
- RatatuiRuby::Layout.new(
33
- direction: :vertical,
34
- constraints: [
35
- RatatuiRuby::Constraint.percentage(50),
36
- RatatuiRuby::Constraint.percentage(50)
37
- ],
38
- children: [
39
- simple_text_line_example,
40
- complex_example
41
- ]
42
- )
43
- )
44
- end
45
-
46
- def simple_text_line_example
47
- # Example 1: A line with mixed styles
48
- RatatuiRuby::Paragraph.new(
49
- text: RatatuiRuby::Text::Line.new(
50
- spans: [
51
- RatatuiRuby::Text::Span.new(
52
- content: "Normal text, ",
53
- style: nil
54
- ),
55
- RatatuiRuby::Text::Span.new(
56
- content: "Bold Text",
57
- style: RatatuiRuby::Style.new(modifiers: [:bold])
58
- ),
59
- RatatuiRuby::Text::Span.new(
60
- content: ", ",
61
- style: nil
62
- ),
63
- RatatuiRuby::Text::Span.new(
64
- content: "Italic Text",
65
- style: RatatuiRuby::Style.new(modifiers: [:italic])
66
- ),
67
- RatatuiRuby::Text::Span.new(
68
- content: ", ",
69
- style: nil
70
- ),
71
- RatatuiRuby::Text::Span.new(
72
- content: "Red Text",
73
- style: RatatuiRuby::Style.new(fg: :red)
74
- ),
75
- RatatuiRuby::Text::Span.new(
76
- content: ".",
77
- style: nil
78
- )
79
- ]
80
- ),
81
- block: RatatuiRuby::Block.new(
82
- title: "Simple Rich Text",
83
- borders: [:all]
84
- )
85
- )
86
- end
87
-
88
- def complex_example
89
- # Example 2: Multiple lines with different styles
90
- RatatuiRuby::Paragraph.new(
91
- text: [
92
- RatatuiRuby::Text::Line.new(
93
- spans: [
94
- RatatuiRuby::Text::Span.new(content: "✓ ", style: RatatuiRuby::Style.new(fg: :green, modifiers: [:bold])),
95
- RatatuiRuby::Text::Span.new(content: "Feature Complete", style: nil),
96
- RatatuiRuby::Text::Span.new(content: " - All tests passing", style: RatatuiRuby::Style.new(fg: :gray))
97
- ]
98
- ),
99
- RatatuiRuby::Text::Line.new(
100
- spans: [
101
- RatatuiRuby::Text::Span.new(content: "⚠ ", style: RatatuiRuby::Style.new(fg: :yellow, modifiers: [:bold])),
102
- RatatuiRuby::Text::Span.new(content: "Warning", style: nil),
103
- RatatuiRuby::Text::Span.new(content: " - Documentation pending", style: RatatuiRuby::Style.new(fg: :gray))
104
- ]
105
- ),
106
- RatatuiRuby::Text::Line.new(
107
- spans: [
108
- RatatuiRuby::Text::Span.new(content: "✗ ", style: RatatuiRuby::Style.new(fg: :red, modifiers: [:bold])),
109
- RatatuiRuby::Text::Span.new(content: "Not Started", style: nil),
110
- RatatuiRuby::Text::Span.new(content: " - Performance benchmarks", style: RatatuiRuby::Style.new(fg: :gray))
111
- ]
112
- ),
113
- RatatuiRuby::Text::Line.new(spans: []),
114
- RatatuiRuby::Text::Line.new(
115
- spans: [
116
- RatatuiRuby::Text::Span.new(content: "Press ", style: nil),
117
- RatatuiRuby::Text::Span.new(content: "Q", style: RatatuiRuby::Style.new(modifiers: [:bold])),
118
- RatatuiRuby::Text::Span.new(content: " to quit", style: nil)
119
- ]
120
- )
121
- ],
122
- block: RatatuiRuby::Block.new(
123
- title: "Status Report",
124
- borders: [:all]
125
- )
126
- )
127
- end
128
-
129
- def handle_input
130
- event = RatatuiRuby.poll_event
131
- return nil unless event
132
-
133
- return :quit if event == "q" || event == :esc || event == :ctrl_c
134
-
135
- nil
136
- end
137
- end
138
-
139
- if __FILE__ == $0
140
- RichTextApp.new.run
141
- end
@@ -1,7 +0,0 @@
1
- class RichTextApp
2
- # @public
3
- def self.new: () -> RichTextApp
4
-
5
- # @public
6
- def run: () -> void
7
- end
@@ -1,166 +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 "test_helper"
9
- require_relative "app"
10
-
11
- class TestRichTextApp < Minitest::Test
12
- include RatatuiRuby::TestHelper
13
-
14
- include RatatuiRuby::TestHelper
15
-
16
- def test_simple_span
17
- span = RatatuiRuby::Text::Span.new(content: "hello", style: nil)
18
- assert_equal "hello", span.content
19
- assert_nil span.style
20
- end
21
-
22
- def test_styled_span
23
- style = RatatuiRuby::Style.new(fg: :red, modifiers: [:bold])
24
- span = RatatuiRuby::Text::Span.new(content: "error", style:)
25
- assert_equal "error", span.content
26
- assert_equal style, span.style
27
- end
28
-
29
- def test_span_styled_helper
30
- style = RatatuiRuby::Style.new(modifiers: [:italic])
31
- span = RatatuiRuby::Text::Span.styled("italic text", style)
32
- assert_equal "italic text", span.content
33
- assert_equal style, span.style
34
- end
35
-
36
- def test_span_styled_helper_without_style
37
- span = RatatuiRuby::Text::Span.styled("plain")
38
- assert_equal "plain", span.content
39
- assert_nil span.style
40
- end
41
-
42
- def test_simple_line
43
- spans = [
44
- RatatuiRuby::Text::Span.new(content: "hello", style: nil),
45
- RatatuiRuby::Text::Span.new(content: " world", style: nil)
46
- ]
47
- line = RatatuiRuby::Text::Line.new(spans:)
48
- assert_equal spans, line.spans
49
- assert_nil line.alignment
50
- end
51
-
52
- def test_line_with_alignment
53
- spans = [RatatuiRuby::Text::Span.new(content: "centered", style: nil)]
54
- line = RatatuiRuby::Text::Line.new(spans:, alignment: :center)
55
- assert_equal :center, line.alignment
56
- end
57
-
58
- def test_line_from_string
59
- line = RatatuiRuby::Text::Line.from_string("test content")
60
- assert_equal 1, line.spans.length
61
- assert_equal "test content", line.spans[0].content
62
- assert_nil line.spans[0].style
63
- end
64
-
65
- def test_line_from_string_with_alignment
66
- line = RatatuiRuby::Text::Line.from_string("right aligned", alignment: :right)
67
- assert_equal :right, line.alignment
68
- end
69
-
70
- def test_paragraph_with_string
71
- para = RatatuiRuby::Paragraph.new(text: "simple text")
72
- assert_equal "simple text", para.text
73
- end
74
-
75
- def test_paragraph_with_span
76
- span = RatatuiRuby::Text::Span.new(content: "bold", style: RatatuiRuby::Style.new(modifiers: [:bold]))
77
- para = RatatuiRuby::Paragraph.new(text: span)
78
- assert_equal span, para.text
79
- end
80
-
81
- def test_paragraph_with_line
82
- line = RatatuiRuby::Text::Line.new(
83
- spans: [
84
- RatatuiRuby::Text::Span.new(content: "hello ", style: nil),
85
- RatatuiRuby::Text::Span.new(content: "world", style: RatatuiRuby::Style.new(fg: :green))
86
- ]
87
- )
88
- para = RatatuiRuby::Paragraph.new(text: line)
89
- assert_equal line, para.text
90
- end
91
-
92
- def test_paragraph_with_multiple_lines
93
- lines = [
94
- RatatuiRuby::Text::Line.new(
95
- spans: [RatatuiRuby::Text::Span.new(content: "line 1", style: nil)]
96
- ),
97
- RatatuiRuby::Text::Line.new(
98
- spans: [RatatuiRuby::Text::Span.new(content: "line 2", style: RatatuiRuby::Style.new(fg: :red))]
99
- )
100
- ]
101
- para = RatatuiRuby::Paragraph.new(text: lines)
102
- assert_equal lines, para.text
103
- end
104
-
105
- def test_paragraph_renders_with_rich_text
106
- with_test_terminal do
107
- # Test that a paragraph with rich text can be rendered without error
108
- line = RatatuiRuby::Text::Line.new(
109
- spans: [
110
- RatatuiRuby::Text::Span.new(content: "normal ", style: nil),
111
- RatatuiRuby::Text::Span.new(content: "bold", style: RatatuiRuby::Style.new(modifiers: [:bold])),
112
- RatatuiRuby::Text::Span.new(content: " text", style: nil)
113
- ]
114
- )
115
- para = RatatuiRuby::Paragraph.new(
116
- text: line,
117
- block: RatatuiRuby::Block.new(title: "Test", borders: [:all])
118
- )
119
- # Should not raise an error when rendering
120
- RatatuiRuby.draw(para)
121
- end
122
- end
123
-
124
- def test_paragraph_renders_multiple_rich_lines
125
- with_test_terminal do
126
- lines = [
127
- RatatuiRuby::Text::Line.new(
128
- spans: [
129
- RatatuiRuby::Text::Span.new(content: "✓ ", style: RatatuiRuby::Style.new(fg: :green, modifiers: [:bold])),
130
- RatatuiRuby::Text::Span.new(content: "Complete", style: nil)
131
- ]
132
- ),
133
- RatatuiRuby::Text::Line.new(
134
- spans: [
135
- RatatuiRuby::Text::Span.new(content: "✗ ", style: RatatuiRuby::Style.new(fg: :red, modifiers: [:bold])),
136
- RatatuiRuby::Text::Span.new(content: "Failed", style: nil)
137
- ]
138
- )
139
- ]
140
- para = RatatuiRuby::Paragraph.new(text: lines)
141
- # Should not raise an error when rendering
142
- RatatuiRuby.draw(para)
143
- end
144
- end
145
- end
146
-
147
- require_relative "app"
148
-
149
- class TestRichTextApp < Minitest::Test
150
- include RatatuiRuby::TestHelper
151
-
152
- include RatatuiRuby::TestHelper
153
-
154
- def test_app_runs
155
- with_test_terminal do
156
- inject_key(:q)
157
- RichTextApp.new.run
158
-
159
- assert buffer_content.any? { |line| line.include?("Simple Rich Text") }
160
- assert buffer_content.any? { |line| line.include?("Status Report") }
161
- end
162
- end
163
- end
164
-
165
-
166
-
@@ -1,103 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
6
-
7
- $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
8
- require "ratatui_ruby"
9
-
10
- # Demo: Scrollable Paragraph
11
- # Shows how to scroll through long text content using arrow keys
12
- class ScrollTextApp
13
- def initialize
14
- @scroll_x = 0
15
- @scroll_y = 0
16
-
17
- @lines = (1..100).map { |i| "Line #{i}: This is a long line of text that can be scrolled horizontally" }
18
- @hotkey_style = RatatuiRuby::Style.new(modifiers: [:bold, :underlined])
19
- end
20
-
21
- def run
22
- RatatuiRuby.run do
23
- loop do
24
- draw
25
- break if handle_input == :quit
26
- end
27
- end
28
- end
29
-
30
- def render
31
- draw
32
- end
33
-
34
- def handle_input
35
- case RatatuiRuby.poll_event
36
- in {type: :key, code: "q"} | {type: :key, code: "c", modifiers: ["ctrl"]}
37
- :quit
38
- in type: :key, code: "up"
39
- @scroll_y = [@scroll_y - 1, 0].max
40
- in type: :key, code: "down"
41
- @scroll_y = [@scroll_y + 1, @lines.length].min
42
- in type: :key, code: "left"
43
- @scroll_x = [@scroll_x - 1, 0].max
44
- in type: :key, code: "right"
45
- @scroll_x = [@scroll_x + 1, 100].min
46
- else
47
- nil
48
- end
49
- end
50
-
51
- private
52
-
53
- def draw
54
- text = @lines.join("\n")
55
-
56
- # Main content
57
- main_paragraph = RatatuiRuby::Paragraph.new(
58
- text: text,
59
- scroll: [@scroll_y, @scroll_x],
60
- block: RatatuiRuby::Block.new(
61
- title: "Scrollable Text (#{text.lines.count} lines)",
62
- borders: [:all]
63
- )
64
- )
65
-
66
- # Bottom control panel
67
- control_panel = RatatuiRuby::Block.new(
68
- title: "Controls",
69
- borders: [:all],
70
- children: [
71
- RatatuiRuby::Paragraph.new(
72
- text: [
73
- RatatuiRuby::Text::Line.new(spans: [
74
- RatatuiRuby::Text::Span.new(content: "NAVIGATION (Size: #{main_paragraph.line_count(65535)}x#{main_paragraph.line_width})", style: RatatuiRuby::Style.new(modifiers: [:bold]))
75
- ]),
76
- RatatuiRuby::Text::Line.new(spans: [
77
- RatatuiRuby::Text::Span.new(content: "↑/↓", style: @hotkey_style),
78
- RatatuiRuby::Text::Span.new(content: ": Vert Scroll (#{@scroll_y}/#{main_paragraph.line_count(65535)}) "),
79
- RatatuiRuby::Text::Span.new(content: "←/→", style: @hotkey_style),
80
- RatatuiRuby::Text::Span.new(content: ": Horz Scroll (#{@scroll_x}/#{main_paragraph.line_width}) "),
81
- RatatuiRuby::Text::Span.new(content: "q", style: @hotkey_style),
82
- RatatuiRuby::Text::Span.new(content: ": Quit")
83
- ])
84
- ]
85
- )
86
- ]
87
- )
88
-
89
- # Vertical Layout
90
- layout = RatatuiRuby::Layout.new(
91
- direction: :vertical,
92
- constraints: [
93
- RatatuiRuby::Constraint.fill(1),
94
- RatatuiRuby::Constraint.length(5),
95
- ],
96
- children: [main_paragraph, control_panel]
97
- )
98
-
99
- RatatuiRuby.draw(layout)
100
- end
101
- end
102
-
103
- ScrollTextApp.new.run if __FILE__ == $PROGRAM_NAME
@@ -1,7 +0,0 @@
1
- class ScrollTextApp
2
- # @public
3
- def self.new: () -> ScrollTextApp
4
-
5
- # @public
6
- def run: () -> void
7
- end