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
@@ -0,0 +1,172 @@
1
+ <%#
2
+ SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: AGPL-3.0-or-later
4
+ %>
5
+ <!DOCTYPE html>
6
+ <html lang="en">
7
+ <head>
8
+ <meta charset="UTF-8">
9
+ <meta name="viewport" content="width=device-width, initial-scale=1">
10
+ <title><%= page_title %> - Example Viewer</title>
11
+
12
+ <script>
13
+ var rdoc_rel_prefix = "<%= doc_root_link.sub('index.html', '') %>";
14
+ var index_rel_prefix = "<%= '../' * (relative_path.split('/').size - 1) %>";
15
+ </script>
16
+
17
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/search_navigation.js" defer></script>
18
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/search_data.js" defer></script>
19
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/search_ranker.js" defer></script>
20
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/search_controller.js" defer></script>
21
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/aliki.js" defer></script>
22
+
23
+ <link href="<%= doc_root_link.sub('index.html', '') %>css/rdoc.css" rel="stylesheet">
24
+ <link href="<%= doc_root_link.sub('index.html', '') %>custom.css" rel="stylesheet">
25
+ </head>
26
+ <body class="file<%= ' has-toc' unless toc_items.empty? %>">
27
+ <%= icons_svg %>
28
+ <header class="top-navbar">
29
+ <div class="navbar-brand">
30
+ Example Viewer
31
+ </div>
32
+
33
+ <!-- Desktop search bar -->
34
+ <div class="navbar-search navbar-search-desktop" role="search">
35
+ <form action="#" method="get" accept-charset="utf-8">
36
+ <input id="search-field" role="combobox" aria-label="Search"
37
+ aria-autocomplete="list" aria-controls="search-results-desktop"
38
+ type="text" name="search" placeholder="Search (/) examples..."
39
+ spellcheck="false" autocomplete="off"
40
+ title="Type to search, Up and Down to navigate, Enter to load">
41
+ <ul id="search-results-desktop" aria-label="Search Results"
42
+ aria-busy="false" aria-expanded="false"
43
+ aria-atomic="false" class="initially-hidden search-results"></ul>
44
+ </form>
45
+ </div>
46
+
47
+ <!-- Mobile search icon button -->
48
+ <button id="search-toggle" class="navbar-search-mobile" aria-label="Open search" type="button">
49
+ <span aria-hidden="true">🔍</span>
50
+ </button>
51
+
52
+ <button id="theme-toggle" class="theme-toggle" aria-label="Switch to dark mode" type="button" onclick="cycleColorMode()">
53
+ <span class="theme-toggle-icon" aria-hidden="true">🌙</span>
54
+ </button>
55
+ </header>
56
+
57
+ <!-- Search Modal (Mobile) -->
58
+ <div id="search-modal" class="search-modal" hidden aria-modal="true" role="dialog" aria-label="Search">
59
+ <div class="search-modal-backdrop"></div>
60
+ <div class="search-modal-content">
61
+ <div class="search-modal-header">
62
+ <form class="search-modal-form" action="#" method="get" accept-charset="utf-8">
63
+ <span class="search-modal-icon" aria-hidden="true">🔍</span>
64
+ <input id="search-field-mobile" role="combobox" aria-label="Search"
65
+ aria-autocomplete="list" aria-controls="search-results-mobile"
66
+ type="text" name="search" placeholder="Search examples"
67
+ spellcheck="false" autocomplete="off">
68
+ <button type="button" class="search-modal-close" aria-label="Close search" id="search-modal-close">
69
+ <span aria-hidden="true">esc</span>
70
+ </button>
71
+ </form>
72
+ </div>
73
+ <div class="search-modal-body">
74
+ <ul id="search-results-mobile" aria-label="Search Results"
75
+ aria-busy="false" aria-expanded="false"
76
+ aria-atomic="false" class="search-results search-modal-results initially-hidden"></ul>
77
+ <div class="search-modal-empty">
78
+ <p>No recent searches</p>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </div>
83
+
84
+ <nav id="navigation" role="navigation">
85
+ <div id="fileindex-section" class="nav-section">
86
+ <details class="nav-section-collapsible" open>
87
+ <summary class="nav-section-header">
88
+ <span class="nav-section-icon">
89
+ <svg><use href="#icon-file"></use></svg>
90
+ </span>
91
+ <span class="nav-section-title">Examples</span>
92
+ <span class="nav-section-chevron">
93
+ <svg><use href="#icon-chevron"></use></svg>
94
+ </span>
95
+ </summary>
96
+ <ul class="nav-list">
97
+ <li><a href="<%= doc_root_link %>">← Back to Docs</a></li>
98
+ </ul>
99
+ </details>
100
+ </div>
101
+ <div class="nav-section">
102
+ <details class="nav-section-collapsible" open>
103
+ <summary class="nav-section-header">
104
+ <span class="nav-section-icon">
105
+ <svg><use href="#icon-layers"></use></svg>
106
+ </span>
107
+ <span class="nav-section-title">Files</span>
108
+ <span class="nav-section-chevron">
109
+ <svg><use href="#icon-chevron"></use></svg>
110
+ </span>
111
+ </summary>
112
+ <ul class="link-list nav-list">
113
+ <%= render_tree(tree_data, relative_path, current_file_html) %>
114
+ </ul>
115
+ </details>
116
+ </div>
117
+ </nav>
118
+
119
+ <main role="main">
120
+ <div class="breadcrumb">
121
+ <%= breadcrumb_path %>
122
+ </div>
123
+ <%= file_header_html %>
124
+ <div class="content">
125
+ <%= file_content_html %>
126
+ </div>
127
+ </main>
128
+
129
+ <% unless toc_items.empty? %>
130
+ <aside class="table-of-contents" role="complementary" aria-label="Table of Contents">
131
+ <div class="toc-sticky">
132
+ <div class="toc-list">
133
+ <h3>On This Page</h3>
134
+ <%= render_toc(toc_items) %>
135
+ </div>
136
+ </div>
137
+ </aside>
138
+ <% end %>
139
+
140
+
141
+ <script>
142
+ const modes = ['auto', 'light', 'dark'];
143
+ const icons = { auto: '🌓', light: '☀️', dark: '🌙' };
144
+
145
+ function setColorMode(mode) {
146
+ if (mode === 'auto') {
147
+ document.documentElement.removeAttribute('data-theme');
148
+ const systemTheme = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
149
+ document.documentElement.setAttribute('data-theme', systemTheme);
150
+ } else {
151
+ document.documentElement.setAttribute('data-theme', mode);
152
+ }
153
+
154
+ const icon = icons[mode];
155
+ const toggle = document.getElementById('theme-toggle');
156
+ toggle.querySelector('.theme-toggle-icon').textContent = icon;
157
+
158
+ localStorage.setItem('rdoc-theme', mode);
159
+ }
160
+
161
+ function cycleColorMode() {
162
+ const current = localStorage.getItem('rdoc-theme') || 'auto';
163
+ const currentIndex = modes.indexOf(current);
164
+ const nextMode = modes[(currentIndex + 1) % modes.length];
165
+ setColorMode(nextMode);
166
+ }
167
+
168
+ const savedMode = localStorage.getItem('rdoc-theme') || 'auto';
169
+ setColorMode(savedMode);
170
+ </script>
171
+ </body>
172
+ </html>
data/tasks/lint.rake CHANGED
@@ -9,9 +9,9 @@ require "inch/rake"
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
12
- RubyCritic::RakeTask.new do |task|
13
- task.options = "--no-browser"
14
- task.paths = FileList.new.include("exe/**/*.rb", "lib/**/*.rb", "sig/**/*.rbs")
12
+ # Run rubycritic in a shell to prevent it from exiting the rake process
13
+ task :rubycritic do
14
+ sh "bundle exec rubycritic --no-browser exe lib sig"
15
15
  end
16
16
 
17
17
  Inch::Rake::Suggest.new("doc:suggest", "exe/**/*.rb", "lib/**/*.rb", "sig/**/*.rbs") do |suggest|
@@ -39,7 +39,11 @@ end
39
39
  task(:reuse) { Rake::Task["reuse:lint"].invoke }
40
40
 
41
41
  namespace :lint do
42
- task docs: %w[rubycritic rdoc:coverage reuse:lint]
42
+ task :safe_rdoc_coverage do
43
+ sh "bundle exec rake rdoc:coverage"
44
+ end
45
+
46
+ task docs: %w[autodoc rubycritic safe_rdoc_coverage reuse:lint]
43
47
  task code: %w[rubocop rubycritic cargo:fmt cargo:clippy cargo:test]
44
48
  task licenses: %w[reuse:lint]
45
49
  task all: %w[docs code licenses]
@@ -1,3 +1,9 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
+
4
+ SPDX-License-Identifier: AGPL-3.0-or-later
5
+ -->
6
+
1
7
  <!DOCTYPE html>
2
8
  <html>
3
9
  <head>
data/tasks/sourcehut.rake CHANGED
@@ -4,35 +4,75 @@
4
4
  # SPDX-License-Identifier: AGPL-3.0-or-later
5
5
 
6
6
  desc "Generate SourceHut build manifests from template"
7
- task :sourcehut do
8
- require "erb"
9
- require "yaml"
10
-
11
- spec = Gem::Specification.load("ratatui_ruby.gemspec")
12
-
13
- # Read version directly from file to ensure we get the latest version
14
- # even if it was just bumped in the same Rake execution
15
- version_content = File.read("lib/ratatui_ruby/version.rb")
16
- version = version_content.match(/VERSION = "(.+?)"/)[1]
17
-
18
- gem_filename = "#{spec.name}-#{version}.gem"
19
-
20
- rubies = YAML.load_file("tasks/resources/rubies.yml")
21
-
22
- bundler_version = File.read("Gemfile.lock").match(/BUNDLED WITH\n\s+([\d.]+)/)[1]
23
-
24
- template = File.read("tasks/resources/build.yml.erb")
25
- erb = ERB.new(template, trim_mode: "-")
26
-
27
- FileUtils.mkdir_p ".builds"
28
-
29
- # Remove old generated files to ensure a clean state
30
- Dir.glob(".builds/*.yml").each { |f| File.delete(f) }
31
-
32
- rubies.each do |ruby_version|
33
- filename = ".builds/ruby-#{ruby_version}.yml"
34
- puts "Generating #{filename}..."
35
- content = erb.result_with_hash(ruby_version:, gem_filename:, bundler_version:)
36
- File.write(filename, content)
7
+ task sourcehut: "sourcehut:build"
8
+
9
+ namespace :sourcehut do
10
+ desc "Build SourceHut manifests"
11
+ task build: "sourcehut:build:manifest"
12
+
13
+ namespace :build do
14
+ desc "Generate SourceHut build manifests from template"
15
+ task :manifest do
16
+ require "erb"
17
+ require "yaml"
18
+
19
+ spec = Gem::Specification.load("ratatui_ruby.gemspec")
20
+
21
+ # Read version directly from file to ensure we get the latest version
22
+ # even if it was just bumped in the same Rake execution
23
+ version_content = File.read("lib/ratatui_ruby/version.rb")
24
+ version = version_content.match(/VERSION = "(.+?)"/)[1]
25
+
26
+ gem_filename = "#{spec.name}-#{version}.gem"
27
+
28
+ rubies = YAML.load_file("tasks/resources/rubies.yml")
29
+
30
+ bundler_version = File.read("Gemfile.lock").match(/BUNDLED WITH\n\s+([\d.]+)/)[1]
31
+
32
+ template = File.read("tasks/resources/build.yml.erb")
33
+ erb = ERB.new(template, trim_mode: "-")
34
+
35
+ FileUtils.mkdir_p ".builds"
36
+
37
+ # Remove old generated files to ensure a clean state
38
+ Dir.glob(".builds/*.yml").each { |f| File.delete(f) }
39
+
40
+ rubies.each do |ruby_version|
41
+ filename = ".builds/ruby-#{ruby_version}.yml"
42
+ puts "Generating #{filename}..."
43
+ content = erb.result_with_hash(ruby_version:, gem_filename:, bundler_version:)
44
+ File.write(filename, content)
45
+ end
46
+ end
47
+ end
48
+
49
+ desc "Update stable branch to match release and set as default"
50
+ task :update_stable do
51
+ # Read version to determine tag
52
+ version_content = File.read("lib/ratatui_ruby/version.rb")
53
+ version = version_content.match(/VERSION = "(.+?)"/)[1]
54
+ tag_name = "v#{version}"
55
+
56
+ # Verify that the version file matches the actual git tag
57
+ # This prevents updating stable to the wrong version if the release failed
58
+ latest_tag = `git describe --tags --abbrev=0`.strip
59
+ if latest_tag != tag_name
60
+ abort "Fatal: Version mismatch! 'lib/ratatui_ruby/version.rb' says #{tag_name}, but the latest git tag is #{latest_tag}."
61
+ end
62
+
63
+ puts "Updating stable branch to point to #{tag_name}..."
64
+ # Resolve the tag to a commit hash (peel annotated tags)
65
+ # This renders a commit SHA that can be pushed to a branch head
66
+ commit_sha = `git rev-parse #{tag_name}^{}`.strip
67
+
68
+ # Push the commit to stable branch
69
+ # This creates 'stable' if it doesn't exist, or fast-forwards it.
70
+ sh "git push origin #{commit_sha}:stable"
71
+ end
72
+ end
73
+
74
+ if Rake::Task.task_defined?("release")
75
+ Rake::Task["release"].enhance do
76
+ Rake::Task["sourcehut:update_stable"].invoke
37
77
  end
38
78
  end
@@ -15,8 +15,18 @@ class AppScreenshot < Data.define(:app, :output_path)
15
15
  LauncherScript.new(app.app_path, Dir.pwd).run do |launcher|
16
16
  TerminalWindow.new(launcher.path, launcher.pid_file).open do |window|
17
17
  take_snapshot(window.window_id)
18
- puts " done."
19
- true
18
+
19
+ if File.size?(output_path)
20
+ puts " done."
21
+ true
22
+ else
23
+ FileUtils.rm_f(output_path)
24
+ puts " FAILED"
25
+ puts
26
+ puts " Window rendered nothing (app may have crashed before drawing)"
27
+ puts
28
+ false
29
+ end
20
30
  end
21
31
  end
22
32
  rescue => e
@@ -27,9 +37,7 @@ class AppScreenshot < Data.define(:app, :output_path)
27
37
  false
28
38
  end
29
39
 
30
- private
31
-
32
- def take_snapshot(window_id)
33
- system("screencapture -l #{window_id} -o -x '#{output_path}'")
40
+ private def take_snapshot(window_id)
41
+ system("screencapture", "-l", window_id.to_s, "-o", "-x", output_path)
34
42
  end
35
43
  end
@@ -26,29 +26,27 @@ class CrashReport < Data.define(:app, :error, :preamble)
26
26
  TEXT
27
27
  end
28
28
 
29
- private
30
-
31
- def box_top
32
- "┌" + "─" * (width - 2) + "┐"
29
+ private def box_top
30
+ "┌#{'─' * (width - 2)}┐"
33
31
  end
34
32
 
35
- def box_bottom
36
- "└" + "" * (width - 2) + "┘"
33
+ private def box_bottom
34
+ "└#{'' * (width - 2)}┘"
37
35
  end
38
36
 
39
- def border_top(title)
37
+ private def border_top(title)
40
38
  left = "┌─ #{title} "
41
39
  right = "┐"
42
40
  dashes = "─" * (width - left.length - right.length)
43
41
  left + dashes + right
44
42
  end
45
43
 
46
- def format_line(line)
44
+ private def format_line(line)
47
45
  truncated = line[0...(width - 4)]
48
46
  "│ #{truncated.ljust(width - 4)} │"
49
47
  end
50
48
 
51
- def width
49
+ private def width
52
50
  80
53
51
  end
54
52
  end
@@ -26,16 +26,14 @@ class LauncherScript < Data.define(:app_path, :repo_root)
26
26
  File.join(Dir.tmpdir, "preview_launcher.pid")
27
27
  end
28
28
 
29
- private
30
-
31
- def cleanup
32
- File.delete(path) if File.exist?(path)
33
- File.delete(pid_file) if File.exist?(pid_file)
29
+ private def cleanup
30
+ FileUtils.rm_f(path)
31
+ FileUtils.rm_f(pid_file)
34
32
  rescue Errno::ENOENT
35
33
  # Already deleted
36
34
  end
37
35
 
38
- def write
36
+ private def write
39
37
  File.open(path, "w") do |f|
40
38
  f.puts "#!/bin/zsh"
41
39
  f.puts "cd '#{repo_root}'"
@@ -31,7 +31,7 @@ class PreviewCollection
31
31
 
32
32
  puts "\nHere we go!"
33
33
  failures = apps.count { |app| !capture_app(app) }
34
-
34
+
35
35
  if failures.zero?
36
36
  puts "\n✨ All captures complete. Check doc/images/."
37
37
  else
@@ -39,13 +39,11 @@ class PreviewCollection
39
39
  end
40
40
  end
41
41
 
42
- private
43
-
44
- def count_stale_apps(apps)
42
+ private def count_stale_apps(apps)
45
43
  apps.count { |app| SavedScreenshot.for(app, @output_dir).stale? }
46
44
  end
47
45
 
48
- def capture_app(app)
46
+ private def capture_app(app)
49
47
  saved = SavedScreenshot.for(app, @output_dir)
50
48
 
51
49
  if saved.stale?
@@ -57,4 +55,4 @@ class PreviewCollection
57
55
  true
58
56
  end
59
57
  end
60
- end
58
+ end
@@ -17,11 +17,9 @@ class SafetyConfirmation
17
17
  wait_for_user
18
18
  end
19
19
 
20
- private
21
-
22
- def print_warning
20
+ private def print_warning
23
21
  unchanged_count = @total_count - @stale_count
24
- puts "\n" + "=" * 60
22
+ puts "\n#{'=' * 60}"
25
23
  puts " 📸 NATIVE TERMINAL CAPTURE 📸"
26
24
  puts "=" * 60
27
25
  puts "This task will:"
@@ -41,7 +39,7 @@ class SafetyConfirmation
41
39
  puts
42
40
  end
43
41
 
44
- def wait_for_user
42
+ private def wait_for_user
45
43
  loop do
46
44
  print "Continue? [Y/n]: "
47
45
  response = $stdin.gets.strip.downcase
@@ -11,18 +11,17 @@ class SavedScreenshot < Data.define(:app, :path)
11
11
  end
12
12
 
13
13
  def stale?
14
- return true unless exists?
14
+ return true unless valid?
15
15
 
16
16
  app_last_modified > screenshot_last_commit_time
17
17
  end
18
18
 
19
- private
20
-
21
- def exists?
22
- File.exist?(path)
19
+ private def valid?
20
+ # File must exist and have content (not 0 bytes)
21
+ File.size?(path) || false
23
22
  end
24
23
 
25
- def app_last_modified
24
+ private def app_last_modified
26
25
  # If the file has staged or unstaged changes, it's definitely stale
27
26
  return Time.now.to_i if changed?
28
27
 
@@ -30,26 +29,26 @@ class SavedScreenshot < Data.define(:app, :path)
30
29
  app_last_commit_time
31
30
  end
32
31
 
33
- def changed?
32
+ private def changed?
34
33
  system("git diff HEAD --quiet #{app.app_path} 2>/dev/null")
35
34
  !$?.success?
36
35
  end
37
36
 
38
- def app_last_commit_time
37
+ private def app_last_commit_time
39
38
  output = `git log -1 --format=%cI "#{app.app_path}" 2>/dev/null`.strip
40
39
  return 0 if output.empty?
41
40
 
42
41
  Time.iso8601(output).to_i
43
- rescue StandardError
42
+ rescue
44
43
  0
45
44
  end
46
45
 
47
- def screenshot_last_commit_time
46
+ private def screenshot_last_commit_time
48
47
  output = `git log -1 --format=%cI "#{path}" 2>/dev/null`.strip
49
48
  return Time.now.to_i if output.empty?
50
49
 
51
50
  Time.iso8601(output).to_i
52
- rescue StandardError
51
+ rescue
53
52
  Time.now.to_i
54
53
  end
55
54
  end
@@ -41,9 +41,7 @@ class TerminalWindow
41
41
  @window_id
42
42
  end
43
43
 
44
- private
45
-
46
- def close
44
+ private def close
47
45
  try_graceful_shutdown
48
46
  kill_process if process_still_alive?
49
47
 
@@ -60,7 +58,7 @@ class TerminalWindow
60
58
  system("osascript", "-e", delay_script, out: File::NULL, err: File::NULL)
61
59
  end
62
60
 
63
- def wait_for_startup
61
+ private def wait_for_startup
64
62
  sleep PreviewTiming.window_startup
65
63
 
66
64
  unless @window_id.valid?
@@ -73,7 +71,7 @@ class TerminalWindow
73
71
  end
74
72
  end
75
73
 
76
- def try_graceful_shutdown
74
+ private def try_graceful_shutdown
77
75
  shutdown_script = <<~APPLESCRIPT
78
76
  tell application "Terminal"
79
77
  try
@@ -86,7 +84,7 @@ class TerminalWindow
86
84
  sleep 0.2
87
85
  end
88
86
 
89
- def process_still_alive?
87
+ private def process_still_alive?
90
88
  return false unless @pid_file && File.exist?(@pid_file)
91
89
 
92
90
  pid = File.read(@pid_file).strip.to_i
@@ -96,7 +94,7 @@ class TerminalWindow
96
94
  false
97
95
  end
98
96
 
99
- def kill_process
97
+ private def kill_process
100
98
  return unless @pid_file && File.exist?(@pid_file)
101
99
 
102
100
  pid = File.read(@pid_file).strip.to_i
@@ -105,7 +103,7 @@ class TerminalWindow
105
103
  # Process already gone or PID file doesn't exist
106
104
  end
107
105
 
108
- def process_running?
106
+ private def process_running?
109
107
  check_script = <<~APPLESCRIPT
110
108
  tell application "Terminal"
111
109
  try
@@ -121,7 +119,7 @@ class TerminalWindow
121
119
  result == "true"
122
120
  end
123
121
 
124
- def contents
122
+ private def contents
125
123
  read_script = <<~APPLESCRIPT
126
124
  tell application "Terminal"
127
125
  try
data/tasks/test.rake CHANGED
@@ -26,6 +26,6 @@ namespace :test do
26
26
 
27
27
  # Create a specific Minitest task for Ruby tests
28
28
  Minitest::TestTask.create(:ruby) do |t|
29
- t.test_globs = ["test/**/test_*.rb", "examples/**/test_*.rb"]
29
+ t.test_globs = ["test/**/*.rb", "examples/**/test_*.rb"]
30
30
  end
31
31
  end
@@ -8,17 +8,17 @@ require "erb"
8
8
  class IndexPage
9
9
  def initialize(versions)
10
10
  @versions = versions
11
-
11
+
12
12
  latest_version = @versions.find { |v| v.is_a?(Tagged) }
13
13
  latest_version.is_latest = true if latest_version
14
14
  end
15
15
 
16
16
  def publish_to(path, project_name:)
17
17
  puts "Generating index page..."
18
-
18
+
19
19
  template_path = File.expand_path("../resources/index.html.erb", __dir__)
20
20
  template = File.read(template_path)
21
-
21
+
22
22
  versions = @versions
23
23
  # project_name is used in the ERB
24
24
  html_content = ERB.new(template).result(binding)
@@ -10,9 +10,9 @@ class Version
10
10
  def self.all
11
11
  tags = `git tag`.split.grep(/^v\d/)
12
12
  sorted_versions = tags.map { |t| Tagged.new(t) }
13
- .sort_by { |v| v.semver }
14
- .reverse
15
-
13
+ .sort_by(&:semver)
14
+ .reverse
15
+
16
16
  [Edge.new] + sorted_versions
17
17
  end
18
18
 
@@ -31,11 +31,11 @@ class Version
31
31
  def checkout(globs:, &block)
32
32
  raise NotImplementedError
33
33
  end
34
-
34
+
35
35
  def latest?
36
36
  false
37
37
  end
38
-
38
+
39
39
  def edge?
40
40
  false
41
41
  end
@@ -53,7 +53,7 @@ class Edge < Version
53
53
  def type
54
54
  :edge
55
55
  end
56
-
56
+
57
57
  def edge?
58
58
  true
59
59
  end
@@ -64,14 +64,14 @@ class Edge < Version
64
64
  files = `git ls-files`.split("\n").select do |f|
65
65
  globs.any? { |glob| File.fnmatch(glob, f, File::FNM_PATHNAME) }
66
66
  end
67
-
67
+
68
68
  files.each do |file|
69
69
  dest = File.join(path, file)
70
70
  next unless File.exist?(file) # Skip files that are in the index but deleted in the working tree
71
71
  FileUtils.mkdir_p(File.dirname(dest))
72
72
  FileUtils.cp(file, dest)
73
73
  end
74
-
74
+
75
75
  yield path
76
76
  end
77
77
  end
@@ -99,9 +99,9 @@ class Tagged < Version
99
99
  def semver
100
100
  Gem::Version.new(@tag.sub(/^v/, ""))
101
101
  end
102
-
102
+
103
103
  attr_accessor :is_latest
104
-
104
+
105
105
  def latest?
106
106
  @is_latest
107
107
  end