ratatui_ruby 0.3.1 → 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 (350) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +14 -12
  3. data/.builds/ruby-3.3.yml +14 -12
  4. data/.builds/ruby-3.4.yml +14 -12
  5. data/.builds/ruby-4.0.0.yml +14 -12
  6. data/AGENTS.md +89 -132
  7. data/CHANGELOG.md +223 -1
  8. data/README.md +23 -16
  9. data/REUSE.toml +20 -0
  10. data/doc/application_architecture.md +176 -0
  11. data/doc/application_testing.md +17 -10
  12. data/doc/contributors/design/ruby_frontend.md +11 -7
  13. data/doc/contributors/developing_examples.md +261 -0
  14. data/doc/contributors/documentation_style.md +104 -0
  15. data/doc/contributors/dwim_dx.md +366 -0
  16. data/doc/contributors/index.md +2 -0
  17. data/doc/custom.css +14 -0
  18. data/doc/event_handling.md +125 -0
  19. data/doc/images/app_all_events.png +0 -0
  20. data/doc/images/app_analytics.png +0 -0
  21. data/doc/images/app_color_picker.png +0 -0
  22. data/doc/images/app_custom_widget.png +0 -0
  23. data/doc/images/app_login_form.png +0 -0
  24. data/doc/images/app_map_demo.png +0 -0
  25. data/doc/images/app_mouse_events.png +0 -0
  26. data/doc/images/app_table_select.png +0 -0
  27. data/doc/images/verify_quickstart_dsl.png +0 -0
  28. data/doc/images/verify_quickstart_layout.png +0 -0
  29. data/doc/images/verify_quickstart_lifecycle.png +0 -0
  30. data/doc/images/verify_readme_usage.png +0 -0
  31. data/doc/images/widget_barchart_demo.png +0 -0
  32. data/doc/images/widget_block_padding.png +0 -0
  33. data/doc/images/widget_block_titles.png +0 -0
  34. data/doc/images/widget_box_demo.png +0 -0
  35. data/doc/images/widget_calendar_demo.png +0 -0
  36. data/doc/images/widget_cell_demo.png +0 -0
  37. data/doc/images/widget_chart_demo.png +0 -0
  38. data/doc/images/widget_gauge_demo.png +0 -0
  39. data/doc/images/widget_layout_split.png +0 -0
  40. data/doc/images/widget_line_gauge_demo.png +0 -0
  41. data/doc/images/widget_list_demo.png +0 -0
  42. data/doc/images/widget_list_styles.png +0 -0
  43. data/doc/images/widget_popup_demo.png +0 -0
  44. data/doc/images/widget_ratatui_logo_demo.png +0 -0
  45. data/doc/images/widget_ratatui_mascot_demo.png +0 -0
  46. data/doc/images/widget_rect.png +0 -0
  47. data/doc/images/widget_render.png +0 -0
  48. data/doc/images/widget_rich_text.png +0 -0
  49. data/doc/images/widget_scroll_text.png +0 -0
  50. data/doc/images/widget_scrollbar_demo.png +0 -0
  51. data/doc/images/widget_sparkline_demo.png +0 -0
  52. data/doc/images/widget_style_colors.png +0 -0
  53. data/doc/images/widget_table_flex.png +0 -0
  54. data/doc/images/widget_tabs_demo.png +0 -0
  55. data/doc/index.md +1 -0
  56. data/doc/interactive_design.md +116 -0
  57. data/doc/quickstart.md +186 -84
  58. data/examples/app_all_events/README.md +81 -0
  59. data/examples/app_all_events/app.rb +93 -0
  60. data/examples/app_all_events/model/event_color_cycle.rb +41 -0
  61. data/examples/app_all_events/model/event_entry.rb +75 -0
  62. data/examples/app_all_events/model/events.rb +180 -0
  63. data/examples/app_all_events/model/highlight.rb +57 -0
  64. data/examples/app_all_events/model/timestamp.rb +54 -0
  65. data/examples/app_all_events/test/snapshots/after_focus_lost.txt +24 -0
  66. data/examples/app_all_events/test/snapshots/after_focus_regained.txt +24 -0
  67. data/examples/app_all_events/test/snapshots/after_horizontal_resize.txt +24 -0
  68. data/examples/app_all_events/test/snapshots/after_key_a.txt +24 -0
  69. data/examples/app_all_events/test/snapshots/after_key_ctrl_x.txt +24 -0
  70. data/examples/app_all_events/test/snapshots/after_mouse_click.txt +24 -0
  71. data/examples/app_all_events/test/snapshots/after_mouse_drag.txt +24 -0
  72. data/examples/app_all_events/test/snapshots/after_multiple_events.txt +24 -0
  73. data/examples/app_all_events/test/snapshots/after_paste.txt +24 -0
  74. data/examples/app_all_events/test/snapshots/after_resize.txt +24 -0
  75. data/examples/app_all_events/test/snapshots/after_right_click.txt +24 -0
  76. data/examples/app_all_events/test/snapshots/after_vertical_resize.txt +24 -0
  77. data/examples/app_all_events/test/snapshots/initial_state.txt +24 -0
  78. data/examples/app_all_events/view/app_view.rb +78 -0
  79. data/examples/app_all_events/view/controls_view.rb +50 -0
  80. data/examples/app_all_events/view/counts_view.rb +55 -0
  81. data/examples/app_all_events/view/live_view.rb +69 -0
  82. data/examples/app_all_events/view/log_view.rb +60 -0
  83. data/{lib/ratatui_ruby/output.rb → examples/app_all_events/view.rb} +1 -1
  84. data/examples/app_all_events/view_state.rb +42 -0
  85. data/examples/app_color_picker/README.md +94 -0
  86. data/examples/app_color_picker/app.rb +112 -0
  87. data/examples/app_color_picker/clipboard.rb +84 -0
  88. data/examples/app_color_picker/color.rb +191 -0
  89. data/examples/app_color_picker/copy_dialog.rb +170 -0
  90. data/examples/app_color_picker/harmony.rb +56 -0
  91. data/examples/app_color_picker/input.rb +142 -0
  92. data/examples/app_color_picker/palette.rb +80 -0
  93. data/examples/app_color_picker/scene.rb +201 -0
  94. data/examples/app_login_form/app.rb +108 -0
  95. data/examples/app_map_demo/app.rb +93 -0
  96. data/examples/app_table_select/app.rb +201 -0
  97. data/examples/verify_quickstart_dsl/app.rb +45 -0
  98. data/examples/verify_quickstart_layout/app.rb +69 -0
  99. data/examples/verify_quickstart_lifecycle/app.rb +48 -0
  100. data/examples/verify_readme_usage/app.rb +34 -0
  101. data/examples/widget_barchart_demo/app.rb +238 -0
  102. data/examples/widget_block_padding/app.rb +67 -0
  103. data/examples/widget_block_titles/app.rb +69 -0
  104. data/examples/widget_box_demo/app.rb +250 -0
  105. data/examples/widget_calendar_demo/app.rb +109 -0
  106. data/examples/widget_cell_demo/app.rb +104 -0
  107. data/examples/widget_chart_demo/app.rb +213 -0
  108. data/examples/widget_gauge_demo/app.rb +212 -0
  109. data/examples/widget_layout_split/app.rb +246 -0
  110. data/examples/widget_line_gauge_demo/app.rb +217 -0
  111. data/examples/widget_list_demo/app.rb +382 -0
  112. data/examples/widget_list_styles/app.rb +141 -0
  113. data/examples/widget_popup_demo/app.rb +104 -0
  114. data/examples/widget_ratatui_logo_demo/app.rb +103 -0
  115. data/examples/widget_ratatui_mascot_demo/app.rb +93 -0
  116. data/examples/widget_rect/app.rb +205 -0
  117. data/examples/widget_render/app.rb +184 -0
  118. data/examples/widget_rich_text/app.rb +137 -0
  119. data/examples/widget_scroll_text/app.rb +108 -0
  120. data/examples/widget_scrollbar_demo/app.rb +153 -0
  121. data/examples/widget_sparkline_demo/app.rb +274 -0
  122. data/examples/widget_style_colors/app.rb +102 -0
  123. data/examples/widget_table_flex/app.rb +95 -0
  124. data/examples/widget_tabs_demo/app.rb +167 -0
  125. data/ext/ratatui_ruby/Cargo.lock +889 -115
  126. data/ext/ratatui_ruby/Cargo.toml +4 -3
  127. data/ext/ratatui_ruby/clippy.toml +7 -0
  128. data/ext/ratatui_ruby/extconf.rb +7 -0
  129. data/ext/ratatui_ruby/src/events.rs +293 -219
  130. data/ext/ratatui_ruby/src/frame.rs +115 -0
  131. data/ext/ratatui_ruby/src/lib.rs +105 -24
  132. data/ext/ratatui_ruby/src/rendering.rs +94 -10
  133. data/ext/ratatui_ruby/src/style.rs +357 -93
  134. data/ext/ratatui_ruby/src/terminal.rs +121 -31
  135. data/ext/ratatui_ruby/src/text.rs +178 -0
  136. data/ext/ratatui_ruby/src/widgets/barchart.rs +99 -24
  137. data/ext/ratatui_ruby/src/widgets/block.rs +32 -3
  138. data/ext/ratatui_ruby/src/widgets/calendar.rs +45 -44
  139. data/ext/ratatui_ruby/src/widgets/canvas.rs +44 -9
  140. data/ext/ratatui_ruby/src/widgets/chart.rs +79 -27
  141. data/ext/ratatui_ruby/src/widgets/clear.rs +3 -1
  142. data/ext/ratatui_ruby/src/widgets/gauge.rs +11 -4
  143. data/ext/ratatui_ruby/src/widgets/layout.rs +223 -15
  144. data/ext/ratatui_ruby/src/widgets/line_gauge.rs +92 -0
  145. data/ext/ratatui_ruby/src/widgets/list.rs +114 -11
  146. data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
  147. data/ext/ratatui_ruby/src/widgets/overlay.rs +4 -2
  148. data/ext/ratatui_ruby/src/widgets/paragraph.rs +35 -13
  149. data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +40 -0
  150. data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +51 -0
  151. data/ext/ratatui_ruby/src/widgets/scrollbar.rs +61 -7
  152. data/ext/ratatui_ruby/src/widgets/sparkline.rs +73 -6
  153. data/ext/ratatui_ruby/src/widgets/table.rs +177 -64
  154. data/ext/ratatui_ruby/src/widgets/tabs.rs +105 -5
  155. data/lib/ratatui_ruby/cell.rb +166 -0
  156. data/lib/ratatui_ruby/event/focus_gained.rb +49 -0
  157. data/lib/ratatui_ruby/event/focus_lost.rb +50 -0
  158. data/lib/ratatui_ruby/event/key.rb +211 -0
  159. data/lib/ratatui_ruby/event/mouse.rb +124 -0
  160. data/lib/ratatui_ruby/event/none.rb +43 -0
  161. data/lib/ratatui_ruby/event/paste.rb +71 -0
  162. data/lib/ratatui_ruby/event/resize.rb +80 -0
  163. data/lib/ratatui_ruby/event.rb +131 -0
  164. data/lib/ratatui_ruby/frame.rb +87 -0
  165. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +45 -0
  166. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +23 -0
  167. data/lib/ratatui_ruby/schema/bar_chart.rb +226 -17
  168. data/lib/ratatui_ruby/schema/block.rb +178 -11
  169. data/lib/ratatui_ruby/schema/calendar.rb +70 -14
  170. data/lib/ratatui_ruby/schema/canvas.rb +213 -46
  171. data/lib/ratatui_ruby/schema/center.rb +46 -8
  172. data/lib/ratatui_ruby/schema/chart.rb +134 -32
  173. data/lib/ratatui_ruby/schema/clear.rb +22 -53
  174. data/lib/ratatui_ruby/schema/constraint.rb +72 -12
  175. data/lib/ratatui_ruby/schema/cursor.rb +23 -5
  176. data/lib/ratatui_ruby/schema/draw.rb +53 -0
  177. data/lib/ratatui_ruby/schema/gauge.rb +56 -12
  178. data/lib/ratatui_ruby/schema/layout.rb +91 -9
  179. data/lib/ratatui_ruby/schema/line_gauge.rb +78 -0
  180. data/lib/ratatui_ruby/schema/list.rb +92 -16
  181. data/lib/ratatui_ruby/schema/overlay.rb +29 -3
  182. data/lib/ratatui_ruby/schema/paragraph.rb +82 -25
  183. data/lib/ratatui_ruby/schema/ratatui_logo.rb +29 -0
  184. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +34 -0
  185. data/lib/ratatui_ruby/schema/rect.rb +59 -10
  186. data/lib/ratatui_ruby/schema/scrollbar.rb +127 -19
  187. data/lib/ratatui_ruby/schema/shape/label.rb +66 -0
  188. data/lib/ratatui_ruby/schema/sparkline.rb +120 -12
  189. data/lib/ratatui_ruby/schema/style.rb +39 -11
  190. data/lib/ratatui_ruby/schema/table.rb +109 -18
  191. data/lib/ratatui_ruby/schema/tabs.rb +71 -10
  192. data/lib/ratatui_ruby/schema/text.rb +90 -0
  193. data/lib/ratatui_ruby/session/autodoc.rb +417 -0
  194. data/lib/ratatui_ruby/session.rb +163 -0
  195. data/lib/ratatui_ruby/test_helper.rb +322 -13
  196. data/lib/ratatui_ruby/version.rb +1 -1
  197. data/lib/ratatui_ruby.rb +184 -38
  198. data/sig/examples/app_all_events/app.rbs +11 -0
  199. data/sig/examples/app_all_events/model/event_entry.rbs +16 -0
  200. data/sig/examples/app_all_events/model/events.rbs +15 -0
  201. data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
  202. data/sig/examples/app_all_events/view/app_view.rbs +8 -0
  203. data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
  204. data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
  205. data/sig/examples/app_all_events/view/live_view.rbs +6 -0
  206. data/sig/examples/app_all_events/view/log_view.rbs +6 -0
  207. data/sig/examples/app_all_events/view.rbs +8 -0
  208. data/sig/examples/app_all_events/view_state.rbs +15 -0
  209. data/sig/examples/app_color_picker/app.rbs +12 -0
  210. data/sig/examples/app_login_form/app.rbs +11 -0
  211. data/sig/examples/app_map_demo/app.rbs +11 -0
  212. data/sig/examples/app_table_select/app.rbs +11 -0
  213. data/sig/examples/verify_quickstart_dsl/app.rbs +11 -0
  214. data/sig/examples/verify_quickstart_lifecycle/app.rbs +11 -0
  215. data/sig/examples/verify_readme_usage/app.rbs +11 -0
  216. data/sig/examples/widget_block_padding/app.rbs +11 -0
  217. data/sig/examples/widget_block_titles/app.rbs +11 -0
  218. data/sig/examples/widget_box_demo/app.rbs +11 -0
  219. data/sig/examples/widget_calendar_demo/app.rbs +11 -0
  220. data/sig/examples/widget_cell_demo/app.rbs +11 -0
  221. data/sig/examples/widget_chart_demo/app.rbs +11 -0
  222. data/sig/examples/widget_gauge_demo/app.rbs +11 -0
  223. data/sig/examples/widget_layout_split/app.rbs +10 -0
  224. data/sig/examples/widget_line_gauge_demo/app.rbs +11 -0
  225. data/sig/examples/widget_list_demo/app.rbs +12 -0
  226. data/sig/examples/widget_list_styles/app.rbs +11 -0
  227. data/sig/examples/widget_popup_demo/app.rbs +11 -0
  228. data/sig/examples/widget_ratatui_logo_demo/app.rbs +11 -0
  229. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +11 -0
  230. data/sig/examples/widget_rect/app.rbs +12 -0
  231. data/sig/examples/widget_render/app.rbs +10 -0
  232. data/sig/examples/widget_rich_text/app.rbs +11 -0
  233. data/sig/examples/widget_scroll_text/app.rbs +11 -0
  234. data/sig/examples/widget_scrollbar_demo/app.rbs +11 -0
  235. data/sig/examples/widget_sparkline_demo/app.rbs +10 -0
  236. data/sig/examples/widget_style_colors/app.rbs +14 -0
  237. data/sig/examples/widget_table_flex/app.rbs +11 -0
  238. data/sig/ratatui_ruby/event.rbs +69 -0
  239. data/sig/ratatui_ruby/frame.rbs +9 -0
  240. data/sig/ratatui_ruby/ratatui_ruby.rbs +5 -3
  241. data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +16 -0
  242. data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +13 -0
  243. data/sig/ratatui_ruby/schema/bar_chart.rbs +20 -2
  244. data/sig/ratatui_ruby/schema/block.rbs +5 -4
  245. data/sig/ratatui_ruby/schema/calendar.rbs +6 -2
  246. data/sig/ratatui_ruby/schema/canvas.rbs +52 -39
  247. data/sig/ratatui_ruby/schema/center.rbs +3 -3
  248. data/sig/ratatui_ruby/schema/chart.rbs +8 -5
  249. data/sig/ratatui_ruby/schema/constraint.rbs +8 -5
  250. data/sig/ratatui_ruby/schema/cursor.rbs +1 -1
  251. data/sig/ratatui_ruby/schema/draw.rbs +27 -0
  252. data/sig/ratatui_ruby/schema/gauge.rbs +4 -2
  253. data/sig/ratatui_ruby/schema/layout.rbs +11 -1
  254. data/sig/ratatui_ruby/schema/line_gauge.rbs +16 -0
  255. data/sig/ratatui_ruby/schema/list.rbs +5 -1
  256. data/sig/ratatui_ruby/schema/paragraph.rbs +4 -1
  257. data/sig/ratatui_ruby/schema/ratatui_logo.rbs +8 -0
  258. data/sig/ratatui_ruby/{buffer.rbs → schema/ratatui_mascot.rbs} +4 -3
  259. data/sig/ratatui_ruby/schema/rect.rbs +2 -1
  260. data/sig/ratatui_ruby/schema/scrollbar.rbs +18 -2
  261. data/sig/ratatui_ruby/schema/sparkline.rbs +6 -2
  262. data/sig/ratatui_ruby/schema/table.rbs +8 -1
  263. data/sig/ratatui_ruby/schema/tabs.rbs +5 -1
  264. data/sig/ratatui_ruby/schema/text.rbs +22 -0
  265. data/sig/ratatui_ruby/session.rbs +94 -0
  266. data/tasks/autodoc/inventory.rb +61 -0
  267. data/tasks/autodoc/member.rb +56 -0
  268. data/tasks/autodoc/name.rb +19 -0
  269. data/tasks/autodoc/notice.rb +26 -0
  270. data/tasks/autodoc/rbs.rb +38 -0
  271. data/tasks/autodoc/rdoc.rb +45 -0
  272. data/tasks/autodoc.rake +47 -0
  273. data/tasks/bump/history.rb +2 -2
  274. data/tasks/doc.rake +600 -6
  275. data/tasks/example_viewer.html.erb +172 -0
  276. data/tasks/lint.rake +8 -4
  277. data/tasks/resources/build.yml.erb +13 -11
  278. data/tasks/resources/index.html.erb +6 -0
  279. data/tasks/sourcehut.rake +4 -4
  280. data/tasks/terminal_preview/app_screenshot.rb +33 -0
  281. data/tasks/terminal_preview/crash_report.rb +52 -0
  282. data/tasks/terminal_preview/example_app.rb +25 -0
  283. data/tasks/terminal_preview/launcher_script.rb +46 -0
  284. data/tasks/terminal_preview/preview_collection.rb +58 -0
  285. data/tasks/terminal_preview/preview_timing.rb +22 -0
  286. data/tasks/terminal_preview/safety_confirmation.rb +56 -0
  287. data/tasks/terminal_preview/saved_screenshot.rb +53 -0
  288. data/tasks/terminal_preview/system_appearance.rb +11 -0
  289. data/tasks/terminal_preview/terminal_window.rb +136 -0
  290. data/tasks/terminal_preview/window_id.rb +14 -0
  291. data/tasks/terminal_preview.rake +28 -0
  292. data/tasks/test.rake +2 -2
  293. data/tasks/website/index_page.rb +3 -3
  294. data/tasks/website/version.rb +10 -10
  295. data/tasks/website/version_menu.rb +10 -12
  296. data/tasks/website/versioned_documentation.rb +49 -17
  297. data/tasks/website/website.rb +6 -8
  298. data/tasks/website.rake +4 -4
  299. metadata +206 -54
  300. data/LICENSES/BSD-2-Clause.txt +0 -9
  301. data/doc/images/examples-analytics.rb.png +0 -0
  302. data/doc/images/examples-box_demo.rb.png +0 -0
  303. data/doc/images/examples-calendar_demo.rb.png +0 -0
  304. data/doc/images/examples-chart_demo.rb.png +0 -0
  305. data/doc/images/examples-custom_widget.rb.png +0 -0
  306. data/doc/images/examples-dashboard.rb.png +0 -0
  307. data/doc/images/examples-list_styles.rb.png +0 -0
  308. data/doc/images/examples-login_form.rb.png +0 -0
  309. data/doc/images/examples-map_demo.rb.png +0 -0
  310. data/doc/images/examples-mouse_events.rb.png +0 -0
  311. data/doc/images/examples-popup_demo.rb.gif +0 -0
  312. data/doc/images/examples-quickstart_lifecycle.rb.png +0 -0
  313. data/doc/images/examples-scroll_text.rb.png +0 -0
  314. data/doc/images/examples-scrollbar_demo.rb.png +0 -0
  315. data/doc/images/examples-stock_ticker.rb.png +0 -0
  316. data/doc/images/examples-system_monitor.rb.png +0 -0
  317. data/doc/images/examples-table_select.rb.png +0 -0
  318. data/examples/analytics.rb +0 -88
  319. data/examples/box_demo.rb +0 -71
  320. data/examples/calendar_demo.rb +0 -55
  321. data/examples/chart_demo.rb +0 -84
  322. data/examples/custom_widget.rb +0 -43
  323. data/examples/dashboard.rb +0 -72
  324. data/examples/list_styles.rb +0 -66
  325. data/examples/login_form.rb +0 -115
  326. data/examples/map_demo.rb +0 -58
  327. data/examples/mouse_events.rb +0 -95
  328. data/examples/popup_demo.rb +0 -105
  329. data/examples/quickstart_dsl.rb +0 -30
  330. data/examples/quickstart_lifecycle.rb +0 -40
  331. data/examples/readme_usage.rb +0 -21
  332. data/examples/scroll_text.rb +0 -74
  333. data/examples/scrollbar_demo.rb +0 -75
  334. data/examples/stock_ticker.rb +0 -93
  335. data/examples/system_monitor.rb +0 -94
  336. data/examples/table_select.rb +0 -70
  337. data/examples/test_analytics.rb +0 -65
  338. data/examples/test_box_demo.rb +0 -38
  339. data/examples/test_calendar_demo.rb +0 -66
  340. data/examples/test_dashboard.rb +0 -38
  341. data/examples/test_list_styles.rb +0 -61
  342. data/examples/test_login_form.rb +0 -63
  343. data/examples/test_map_demo.rb +0 -100
  344. data/examples/test_popup_demo.rb +0 -62
  345. data/examples/test_scroll_text.rb +0 -130
  346. data/examples/test_stock_ticker.rb +0 -39
  347. data/examples/test_system_monitor.rb +0 -40
  348. data/examples/test_table_select.rb +0 -37
  349. data/ext/ratatui_ruby/src/buffer.rs +0 -54
  350. data/lib/ratatui_ruby/dsl.rb +0 -64
@@ -0,0 +1,41 @@
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
+ # Cycles through a set of colors for event logging.
7
+ #
8
+ # Sequential events in a log are hard to distinguish if they all look the same.
9
+ # Manually assigning colors to every event type or entry is repetitive.
10
+ #
11
+ # This class automatically cycles through a predefined list of vibrant colors.
12
+ #
13
+ # Use it to give each event in a log a distinct visual identity.
14
+ #
15
+ # === Examples
16
+ #
17
+ # cycler = EventColorCycle.new
18
+ # cycler.next_color #=> :cyan
19
+ # cycler.next_color #=> :magenta
20
+ # cycler.next_color #=> :yellow
21
+ # cycler.next_color #=> :cyan
22
+ class EventColorCycle
23
+ # List of colors to cycle through.
24
+ COLORS = %i[cyan magenta yellow].freeze
25
+
26
+ # Creates a new EventColorCycle.
27
+ def initialize
28
+ @index = 0
29
+ end
30
+
31
+ # Returns the next color in the cycle.
32
+ #
33
+ # === Example
34
+ #
35
+ # cycler.next_color #=> :cyan
36
+ def next_color
37
+ color = COLORS[@index]
38
+ @index = (@index + 1) % COLORS.length
39
+ color
40
+ end
41
+ end
@@ -0,0 +1,75 @@
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
+ require_relative "timestamp"
7
+ require "ratatui_ruby"
8
+
9
+ # Stores details about a single event in the history log.
10
+ #
11
+ # Event logs need to store diverse data including types, keys, colors, and timestamps.
12
+ # Managing loose hashes or arrays for event history is error-prone and hard to query.
13
+ #
14
+ # This class provides a structured data object for every recorded event.
15
+ #
16
+ # Use it to represent mouse clicks, key presses, or resize events in a log.
17
+ #
18
+ # === Examples
19
+ #
20
+ # # Typically created via Events.record
21
+ # entry = EventEntry.create(key_event, :cyan, Timestamp.now)
22
+ # puts entry.type #=> :key
23
+ # puts entry.description #=> '#<RatatuiRuby::Event::Key ...>'
24
+ class EventEntry < Data.define(:event, :color, :timestamp)
25
+ # Creates a new EventEntry.
26
+ #
27
+ # [event] RatatuiRuby::Event object.
28
+ # [color] Symbol color for the log display.
29
+ # [timestamp] Timestamp of when the event occurred.
30
+ def self.create(event, color, timestamp)
31
+ new(
32
+ event:,
33
+ color:,
34
+ timestamp:
35
+ )
36
+ end
37
+
38
+ # Returns the event type.
39
+ #
40
+ # === Example
41
+ #
42
+ # entry.type #=> :key
43
+ def type
44
+ case event
45
+ when RatatuiRuby::Event::Key then :key
46
+ when RatatuiRuby::Event::Mouse then :mouse
47
+ when RatatuiRuby::Event::Resize then :resize
48
+ when RatatuiRuby::Event::Paste then :paste
49
+ when RatatuiRuby::Event::FocusGained then :focus_gained
50
+ when RatatuiRuby::Event::FocusLost then :focus_lost
51
+ else :unknown
52
+ end
53
+ end
54
+
55
+ # Returns the event description using inspect.
56
+ #
57
+ # === Example
58
+ #
59
+ # entry.description #=> '#<RatatuiRuby::Event::Key code="a" modifiers=[]>'
60
+ def description
61
+ event.inspect
62
+ end
63
+
64
+ # Checks if the entry matches the given type.
65
+ #
66
+ # [check_type] Symbol type to check against.
67
+ #
68
+ # === Example
69
+ #
70
+ # entry.matches_type?(:key) #=> true
71
+ def matches_type?(check_type)
72
+ return true if check_type == :focus && (type == :focus_gained || type == :focus_lost)
73
+ type == check_type
74
+ end
75
+ end
@@ -0,0 +1,180 @@
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
+ require_relative "timestamp"
7
+ require_relative "event_color_cycle"
8
+ require_relative "event_entry"
9
+
10
+ # Manages the history and state of all application events.
11
+ #
12
+ # Applications need to track, count, and display event history for debugging and feedback.
13
+ # Direct management of event arrays and counters across the app leads to scattered state.
14
+ #
15
+ # This class centralizes event storage. It records new events, maintains counts, and manages temporary highlights.
16
+ #
17
+ # Use it to store key presses, mouse clicks, and window resizes for display in a log or counter.
18
+ #
19
+ # === Examples
20
+ #
21
+ # events = Events.new
22
+ # events.record(key_event)
23
+ # puts events.count(:key) #=> 1
24
+ #
25
+ # if events.lit?(:key)
26
+ # puts "Key event just happened!"
27
+ # end
28
+ class Events
29
+ # Duration in milliseconds for an event to remain highlighted in the UI.
30
+ HIGHLIGHT_DURATION_MS = 300
31
+
32
+ # Creates a new Events manager.
33
+ def initialize
34
+ @entries = []
35
+ @color_cycle = EventColorCycle.new
36
+ @none_count = 0
37
+ @lit_type = nil
38
+ @lit_until = Timestamp.now
39
+ @live = {}
40
+ end
41
+
42
+ # Records a new event.
43
+ #
44
+ # [event] RatatuiRuby::Event object.
45
+ # [context] Hash of additional context (e.g., last_dimensions).
46
+ #
47
+ # === Example
48
+ #
49
+ # events.record(mouse_event)
50
+ def record(event, context: {})
51
+ if event.is_a?(RatatuiRuby::Event::None) || event == :none
52
+ @none_count += 1
53
+ return
54
+ end
55
+
56
+ color = @color_cycle.next_color
57
+ timestamp = Timestamp.now
58
+ entry = EventEntry.create(event, color, timestamp)
59
+ @entries << entry
60
+ update_lit_type(entry)
61
+
62
+ display_type = live_type_for(entry.type)
63
+ @live[display_type] = { time: Time.now, description: entry.description }
64
+ end
65
+
66
+ private def live_type_for(type)
67
+ case type
68
+ when :focus_gained, :focus_lost
69
+ :focus
70
+ else
71
+ type
72
+ end
73
+ end
74
+
75
+ # Returns the most recent live event data for a type.
76
+ #
77
+ # [type] Symbol event type to look up.
78
+ #
79
+ # === Example
80
+ #
81
+ # events.live_event(:key) #=> { time: ..., description: "..." }
82
+ def live_event(type)
83
+ @live[type]
84
+ end
85
+
86
+ # Returns all recorded live event data.
87
+ #
88
+ # === Example
89
+ #
90
+ # events.live_events #=> { key: { ... }, mouse: { ... } }
91
+ def live_events
92
+ @live
93
+ end
94
+
95
+ # Returns the most recent entries up to the given limit.
96
+ #
97
+ # [max_entries] Integer maximum number of entries to return.
98
+ #
99
+ # === Example
100
+ #
101
+ # events.visible(10) #=> [#<EventEntry ...>, ...]
102
+ def visible(max_entries)
103
+ @entries.last(max_entries)
104
+ end
105
+
106
+ # Checks if any events have been recorded.
107
+ #
108
+ # === Example
109
+ #
110
+ # events.empty? #=> true
111
+ def empty?
112
+ @entries.empty?
113
+ end
114
+
115
+ # Returns the count of events for a type.
116
+ #
117
+ # [type] Symbol event type.
118
+ #
119
+ # === Example
120
+ #
121
+ # events.count(:key) #=> 5
122
+ def count(type)
123
+ return @none_count if type == :none
124
+
125
+ @entries.count { |e| e.matches_type?(type) }
126
+ end
127
+
128
+ # Returns counts grouped by subtype (kind or modifier status).
129
+ #
130
+ # [type] Symbol event type.
131
+ #
132
+ # === Example
133
+ #
134
+ # events.sub_counts(:mouse) #=> { "down" => 1, "up" => 2 }
135
+ def sub_counts(type)
136
+ return {} if type == :none
137
+
138
+ entries = @entries.select { |e| e.matches_type?(type) }
139
+
140
+ defaults = { key: %w[unmodified modified], focus: %w[gained lost], mouse: %w[down up drag moved scroll_up scroll_down] }
141
+ entries.each_with_object(defaults.fetch(type, []).to_h { |k| [k, 0] }) do |entry, counts|
142
+ group = if entry.event.respond_to?(:kind)
143
+ entry.event.kind.to_s
144
+ elsif entry.event.respond_to?(:modifiers)
145
+ entry.event.modifiers.empty? ? "unmodified" : "modified"
146
+ elsif type == :focus
147
+ entry.type.to_s.sub("focus_", "")
148
+ end
149
+
150
+ counts[group] += 1 if group
151
+ end
152
+ end
153
+
154
+ # Checks if a type should be highlighted.
155
+ #
156
+ # [type] Symbol event type.
157
+ #
158
+ # === Example
159
+ #
160
+ # events.lit?(:key) #=> true
161
+ def lit?(type)
162
+ return false if Timestamp.now.milliseconds >= @lit_until.milliseconds
163
+
164
+ @lit_type == type
165
+ end
166
+
167
+ # Returns all event entries.
168
+ #
169
+ # === Example
170
+ #
171
+ # events.entries #=> [#<EventEntry ...>, ...]
172
+ def entries
173
+ @entries
174
+ end
175
+
176
+ private def update_lit_type(entry)
177
+ @lit_type = live_type_for(entry.type)
178
+ @lit_until = Timestamp.new(milliseconds: Timestamp.now.milliseconds + HIGHLIGHT_DURATION_MS)
179
+ end
180
+ end
@@ -0,0 +1,57 @@
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
+ require_relative "timestamp"
7
+
8
+ # Manages temporary visual highlights for different event types.
9
+ #
10
+ # Users need visual feedback when an event occurs, but highlights should fade.
11
+ # Manually tracking timers for every highlightable element is complex.
12
+ #
13
+ # This class manages the "lit" state of multiple keys with a consistent duration.
14
+ #
15
+ # Use it to trigger and check for temporary UI highlights.
16
+ #
17
+ # === Examples
18
+ #
19
+ # highlight = Highlight.new
20
+ # highlight.light_up(:key)
21
+ # highlight.lit?(:key) #=> true
22
+ # sleep(0.4)
23
+ # highlight.lit?(:key) #=> false
24
+ class Highlight
25
+ # Duration in milliseconds that a highlight remains active.
26
+ DURATION_MS = 300
27
+
28
+ # Creates a new Highlight manager.
29
+ def initialize
30
+ @lit_types = {}
31
+ end
32
+
33
+ # Triggers a highlight for the given type.
34
+ #
35
+ # [type] Symbol to highlight.
36
+ #
37
+ # === Example
38
+ #
39
+ # highlight.light_up(:mouse)
40
+ def light_up(type)
41
+ @lit_types[type] = Timestamp.now
42
+ end
43
+
44
+ # Checks if a highlight is currently active for the given type.
45
+ #
46
+ # [type] Symbol to check.
47
+ #
48
+ # === Example
49
+ #
50
+ # highlight.lit?(:mouse) #=> true
51
+ def lit?(type)
52
+ timestamp = @lit_types[type]
53
+ return false unless timestamp
54
+
55
+ !timestamp.elapsed?(DURATION_MS)
56
+ end
57
+ end
@@ -0,0 +1,54 @@
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
+ # Represents a high-resolution point in time.
7
+ #
8
+ # Comparing events and calculating durations requires consistent time measurement.
9
+ # Standard Time objects are often too granular or complex for simple millisecond offsets.
10
+ #
11
+ # This class provides a millisecond-precision timestamp for event measurement.
12
+ #
13
+ # Use it to track event timing, calculate elapsed time, or trigger debouncing.
14
+ #
15
+ # === Examples
16
+ #
17
+ # timestamp = Timestamp.now
18
+ # puts timestamp.milliseconds
19
+ #
20
+ # if timestamp.elapsed?(300)
21
+ # puts "More than 300ms have passed."
22
+ # end
23
+ class Timestamp < Data.define(:milliseconds)
24
+ # Returns a new Timestamp representing the current time.
25
+ #
26
+ # === Example
27
+ #
28
+ # Timestamp.now #=> #<struct Timestamp milliseconds=123456789>
29
+ def self.now
30
+ new(milliseconds: (Time.now.to_f * 1000).to_i)
31
+ end
32
+
33
+ # Checks if a duration has passed since this timestamp.
34
+ #
35
+ # [duration_ms] Integer duration in milliseconds.
36
+ #
37
+ # === Example
38
+ #
39
+ # timestamp = Timestamp.now
40
+ # sleep(0.5)
41
+ # timestamp.elapsed?(300) #=> true
42
+ def elapsed?(duration_ms)
43
+ Timestamp.now.milliseconds >= milliseconds + duration_ms
44
+ end
45
+
46
+ # Returns the current time in milliseconds.
47
+ #
48
+ # === Example
49
+ #
50
+ # Timestamp.current #=> 123456789
51
+ def self.current
52
+ now.milliseconds
53
+ end
54
+ end
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 0 │ │Type Time Description │
3
+ │ Unmodified: 0 │ │Key — — │
4
+ │ Modified: 0 │ │Mouse — — │
5
+ │Mouse: 0 │ │Resize — — │
6
+ │ Down: 0 │ │Paste — — │
7
+ │ Up: 0 │ │Focus XX:XX:XX #<RatatuiRuby::Event::FocusLost:0xXXXXXX│
8
+ │ Drag: 0 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::FocusLost:0xXXXXXX> │
12
+ │Resize: 0 │ │ │
13
+ │Paste: 0 │ │ │
14
+ │Focus: 1 │ │ │
15
+ │ Gained: 0 │ │ │
16
+ │ Lost: 1 │ │ │
17
+ │None: 0 │ │ │
18
+ │ │ │ │
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 0 │ │Type Time Description │
3
+ │ Unmodified: 0 │ │Key — — │
4
+ │ Modified: 0 │ │Mouse — — │
5
+ │Mouse: 0 │ │Resize — — │
6
+ │ Down: 0 │ │Paste — — │
7
+ │ Up: 0 │ │Focus XX:XX:XX #<RatatuiRuby::Event::FocusGained:0xXXXXXX│
8
+ │ Drag: 0 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::FocusLost:0xXXXXXX> │
12
+ │Resize: 0 │ │ │
13
+ │Paste: 0 │ │#<RatatuiRuby::Event::FocusGained:0xXXXXXX> │
14
+ │Focus: 2 │ │ │
15
+ │ Gained: 1 │ │ │
16
+ │ Lost: 1 │ │ │
17
+ │None: 0 │ │ │
18
+ │ │ │ │
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 0 │ │Type Time Description │
3
+ │ Unmodified: 0 │ │Key — — │
4
+ │ Modified: 0 │ │Mouse — — │
5
+ │Mouse: 0 │ │Resize XX:XX:XX #<RatatuiRuby::Event::Resize:0xXXXXXX│
6
+ │ Down: 0 │ │Paste — — │
7
+ │ Up: 0 │ │Focus — — │
8
+ │ Drag: 0 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::Resize:0xXXXXXX │
12
+ │Resize: 1 │ │@width=100, @height=24> │
13
+ │Paste: 0 │ │ │
14
+ │Focus: 0 │ │ │
15
+ │ Gained: 0 │ │ │
16
+ │ Lost: 0 │ │ │
17
+ │None: 0 │ │ │
18
+ │ │ │ │
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 1 │ │Type Time Description │
3
+ │ Unmodified: 1 │ │Key XX:XX:XX #<RatatuiRuby::Event::Key code="a" mod│
4
+ │ Modified: 0 │ │Mouse — — │
5
+ │Mouse: 0 │ │Resize — — │
6
+ │ Down: 0 │ │Paste — — │
7
+ │ Up: 0 │ │Focus — — │
8
+ │ Drag: 0 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::Key code="a" modifiers=[]> │
12
+ │Resize: 0 │ │ │
13
+ │Paste: 0 │ │ │
14
+ │Focus: 0 │ │ │
15
+ │ Gained: 0 │ │ │
16
+ │ Lost: 0 │ │ │
17
+ │None: 0 │ │ │
18
+ │ │ │ │
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 1 │ │Type Time Description │
3
+ │ Unmodified: 0 │ │Key XX:XX:XX #<RatatuiRuby::Event::Key code="x" mod│
4
+ │ Modified: 1 │ │Mouse — — │
5
+ │Mouse: 0 │ │Resize — — │
6
+ │ Down: 0 │ │Paste — — │
7
+ │ Up: 0 │ │Focus — — │
8
+ │ Drag: 0 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::Key code="x" modifiers=["ctrl"]> │
12
+ │Resize: 0 │ │ │
13
+ │Paste: 0 │ │ │
14
+ │Focus: 0 │ │ │
15
+ │ Gained: 0 │ │ │
16
+ │ Lost: 0 │ │ │
17
+ │None: 0 │ │ │
18
+ │ │ │ │
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 0 │ │Type Time Description │
3
+ │ Unmodified: 0 │ │Key — — │
4
+ │ Modified: 0 │ │Mouse XX:XX:XX #<RatatuiRuby::Event::Mouse:0xXXXXXX│
5
+ │Mouse: 1 │ │Resize — — │
6
+ │ Down: 1 │ │Paste — — │
7
+ │ Up: 0 │ │Focus — — │
8
+ │ Drag: 0 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::Mouse:0xXXXXXX │
12
+ │Resize: 0 │ │@kind="down", @x=40, @y=12, @button="left", │
13
+ │Paste: 0 │ │@modifiers=[]> │
14
+ │Focus: 0 │ │ │
15
+ │ Gained: 0 │ │ │
16
+ │ Lost: 0 │ │ │
17
+ │None: 0 │ │ │
18
+ │ │ │ │
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 0 │ │Type Time Description │
3
+ │ Unmodified: 0 │ │Key — — │
4
+ │ Modified: 0 │ │Mouse XX:XX:XX #<RatatuiRuby::Event::Mouse:0xXXXXXX│
5
+ │Mouse: 1 │ │Resize — — │
6
+ │ Down: 0 │ │Paste — — │
7
+ │ Up: 0 │ │Focus — — │
8
+ │ Drag: 1 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::Mouse:0xXXXXXX │
12
+ │Resize: 0 │ │@kind="drag", @x=25, @y=8, @button="left", @modifiers=[]>│
13
+ │Paste: 0 │ │ │
14
+ │Focus: 0 │ │ │
15
+ │ Gained: 0 │ │ │
16
+ │ Lost: 0 │ │ │
17
+ │None: 0 │ │ │
18
+ │ │ │ │
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 3 │ │Type Time Description │
3
+ │ Unmodified: 3 │ │Key XX:XX:XX #<RatatuiRuby::Event::Key code="c" mod│
4
+ │ Modified: 0 │ │Mouse XX:XX:XX #<RatatuiRuby::Event::Mouse:0xXXXXXX│
5
+ │Mouse: 1 │ │Resize — — │
6
+ │ Down: 1 │ │Paste — — │
7
+ │ Up: 0 │ │Focus — — │
8
+ │ Drag: 0 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::Key code="a" modifiers=[]> │
12
+ │Resize: 0 │ │ │
13
+ │Paste: 0 │ │#<RatatuiRuby::Event::Key code="b" modifiers=[]> │
14
+ │Focus: 0 │ │ │
15
+ │ Gained: 0 │ │#<RatatuiRuby::Event::Key code="c" modifiers=[]> │
16
+ │ Lost: 0 │ │ │
17
+ │None: 0 │ │#<RatatuiRuby::Event::Mouse:0xXXXXXX │
18
+ │ │ │@kind="down", @x=10, @y=5, @button="left", @modifiers=[]>│
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘
@@ -0,0 +1,24 @@
1
+ ┌Event Counts──────┐ ┌Live Display─────────────────────────────────────────────┐
2
+ │Key: 0 │ │Type Time Description │
3
+ │ Unmodified: 0 │ │Key — — │
4
+ │ Modified: 0 │ │Mouse — — │
5
+ │Mouse: 0 │ │Resize — — │
6
+ │ Down: 0 │ │Paste XX:XX:XX #<RatatuiRuby::Event::Paste:0xXXXXXX│
7
+ │ Up: 0 │ │Focus — — │
8
+ │ Drag: 0 │ │ │
9
+ │ Moved: 0 │ └─────────────────────────────────────────────────────────┘
10
+ │ Scroll_up: 0 │ ┌Event Log────────────────────────────────────────────────┐
11
+ │ Scroll_down: 0 │ │#<RatatuiRuby::Event::Paste:0xXXXXXX │
12
+ │Resize: 0 │ │@content="Hello World"> │
13
+ │Paste: 1 │ │ │
14
+ │Focus: 0 │ │ │
15
+ │ Gained: 0 │ │ │
16
+ │ Lost: 0 │ │ │
17
+ │None: 0 │ │ │
18
+ │ │ │ │
19
+ │ │ │ │
20
+ │ │ │ │
21
+ └──────────────────┘ └─────────────────────────────────────────────────────────┘
22
+ ┌Controls──────────────────────────────────────────────────────────────────────┐
23
+ │q: Quit Ctrl+C: Quit │
24
+ └──────────────────────────────────────────────────────────────────────────────┘