ratatui_ruby 0.8.0 → 0.9.1

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 (355) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +2 -2
  3. data/.builds/ruby-3.3.yml +2 -2
  4. data/.builds/ruby-3.4.yml +2 -2
  5. data/.builds/ruby-4.0.0.yml +2 -2
  6. data/.pre-commit-config.yaml +1 -1
  7. data/AGENTS.md +3 -3
  8. data/CHANGELOG.md +77 -1
  9. data/LICENSES/LGPL-3.0-or-later.txt +304 -0
  10. data/LICENSES/MIT-0.txt +16 -0
  11. data/README.md +33 -5
  12. data/Rakefile +1 -1
  13. data/doc/concepts/application_architecture.md +44 -3
  14. data/doc/concepts/application_testing.md +43 -1
  15. data/doc/concepts/async.md +32 -2
  16. data/doc/concepts/custom_widgets.md +247 -0
  17. data/doc/concepts/event_handling.md +32 -3
  18. data/doc/concepts/interactive_design.md +32 -2
  19. data/doc/contributors/auditing/parity.md +7 -1
  20. data/doc/contributors/design/ruby_frontend.md +85 -1
  21. data/doc/contributors/design/rust_backend.md +67 -1
  22. data/doc/contributors/developing_examples.md +56 -2
  23. data/doc/contributors/documentation_style.md +20 -3
  24. data/doc/contributors/future_work.md +169 -0
  25. data/doc/contributors/index.md +1 -1
  26. data/doc/contributors/v1.0.0_blockers.md +19 -185
  27. data/doc/getting_started/quickstart.md +22 -4
  28. data/doc/getting_started/why.md +1 -1
  29. data/doc/index.md +2 -1
  30. data/doc/troubleshooting/debugging.md +32 -2
  31. data/doc/troubleshooting/terminal_limitations.md +8 -2
  32. data/doc/troubleshooting/tui_output.md +42 -0
  33. data/examples/app_all_events/README.md +14 -2
  34. data/examples/app_all_events/app.rb +1 -1
  35. data/examples/app_all_events/model/app_model.rb +1 -1
  36. data/examples/app_all_events/model/event_color_cycle.rb +1 -1
  37. data/examples/app_all_events/model/event_entry.rb +1 -1
  38. data/examples/app_all_events/model/msg.rb +1 -1
  39. data/examples/app_all_events/model/timestamp.rb +1 -1
  40. data/examples/app_all_events/update.rb +1 -1
  41. data/examples/app_all_events/view/app_view.rb +1 -1
  42. data/examples/app_all_events/view/controls_view.rb +1 -1
  43. data/examples/app_all_events/view/counts_view.rb +1 -1
  44. data/examples/app_all_events/view/live_view.rb +1 -1
  45. data/examples/app_all_events/view/log_view.rb +1 -1
  46. data/examples/app_all_events/view.rb +1 -1
  47. data/examples/app_color_picker/README.md +20 -2
  48. data/examples/app_color_picker/app.rb +1 -1
  49. data/examples/app_color_picker/clipboard.rb +1 -1
  50. data/examples/app_color_picker/color.rb +1 -1
  51. data/examples/app_color_picker/controls.rb +1 -1
  52. data/examples/app_color_picker/copy_dialog.rb +1 -1
  53. data/examples/app_color_picker/export_pane.rb +1 -1
  54. data/examples/app_color_picker/harmony.rb +1 -1
  55. data/examples/app_color_picker/input.rb +1 -1
  56. data/examples/app_color_picker/main_container.rb +1 -1
  57. data/examples/app_color_picker/palette.rb +1 -1
  58. data/examples/app_login_form/README.md +8 -2
  59. data/examples/app_login_form/app.rb +1 -1
  60. data/examples/app_stateful_interaction/README.md +2 -2
  61. data/examples/app_stateful_interaction/app.rb +71 -17
  62. data/examples/timeout_demo.rb +1 -1
  63. data/examples/verify_quickstart_dsl/README.md +6 -0
  64. data/examples/verify_quickstart_dsl/app.rb +3 -3
  65. data/examples/verify_quickstart_layout/README.md +6 -0
  66. data/examples/verify_quickstart_layout/app.rb +3 -3
  67. data/examples/verify_quickstart_lifecycle/README.md +6 -0
  68. data/examples/verify_quickstart_lifecycle/app.rb +3 -3
  69. data/examples/verify_readme_usage/README.md +6 -0
  70. data/examples/verify_readme_usage/app.rb +3 -3
  71. data/examples/widget_barchart/README.md +6 -0
  72. data/examples/widget_barchart/app.rb +2 -2
  73. data/examples/widget_block/README.md +7 -1
  74. data/examples/widget_block/app.rb +2 -2
  75. data/examples/widget_box/README.md +6 -0
  76. data/examples/widget_box/app.rb +9 -6
  77. data/examples/widget_calendar/README.md +6 -0
  78. data/examples/widget_calendar/app.rb +2 -2
  79. data/examples/widget_canvas/README.md +4 -0
  80. data/examples/widget_canvas/app.rb +2 -2
  81. data/examples/widget_cell/README.md +6 -0
  82. data/examples/widget_cell/app.rb +2 -3
  83. data/examples/widget_center/README.md +4 -0
  84. data/examples/widget_center/app.rb +2 -2
  85. data/examples/widget_chart/README.md +6 -0
  86. data/examples/widget_chart/app.rb +2 -2
  87. data/examples/widget_gauge/README.md +6 -0
  88. data/examples/widget_gauge/app.rb +2 -2
  89. data/examples/widget_layout_split/README.md +6 -0
  90. data/examples/widget_layout_split/app.rb +9 -3
  91. data/examples/widget_line_gauge/README.md +6 -0
  92. data/examples/widget_line_gauge/app.rb +2 -2
  93. data/examples/widget_list/README.md +6 -0
  94. data/examples/widget_list/app.rb +2 -2
  95. data/examples/widget_map/README.md +8 -2
  96. data/examples/widget_map/app.rb +2 -2
  97. data/examples/widget_overlay/README.md +7 -1
  98. data/examples/widget_overlay/app.rb +2 -2
  99. data/examples/widget_popup/README.md +6 -0
  100. data/examples/widget_popup/app.rb +2 -2
  101. data/examples/widget_ratatui_logo/README.md +6 -0
  102. data/examples/widget_ratatui_logo/app.rb +2 -3
  103. data/examples/widget_ratatui_mascot/README.md +6 -0
  104. data/examples/widget_ratatui_mascot/app.rb +2 -2
  105. data/examples/widget_rect/README.md +12 -0
  106. data/examples/widget_rect/app.rb +40 -26
  107. data/examples/widget_render/README.md +6 -0
  108. data/examples/widget_render/app.rb +2 -2
  109. data/examples/widget_render/app.rbs +41 -0
  110. data/examples/widget_rich_text/README.md +6 -0
  111. data/examples/widget_rich_text/app.rb +2 -2
  112. data/examples/widget_scroll_text/README.md +6 -0
  113. data/examples/widget_scroll_text/app.rb +2 -2
  114. data/examples/widget_scrollbar/README.md +6 -0
  115. data/examples/widget_scrollbar/app.rb +2 -2
  116. data/examples/widget_sparkline/README.md +6 -0
  117. data/examples/widget_sparkline/app.rb +2 -2
  118. data/examples/widget_style_colors/README.md +6 -0
  119. data/examples/widget_style_colors/app.rb +2 -2
  120. data/examples/widget_table/README.md +8 -2
  121. data/examples/widget_table/app.rb +2 -2
  122. data/examples/widget_tabs/README.md +6 -0
  123. data/examples/widget_tabs/app.rb +2 -2
  124. data/examples/widget_text_width/README.md +6 -0
  125. data/examples/widget_text_width/app.rb +4 -4
  126. data/ext/ratatui_ruby/Cargo.lock +1 -1
  127. data/ext/ratatui_ruby/Cargo.toml +1 -1
  128. data/ext/ratatui_ruby/extconf.rb +2 -2
  129. data/ext/ratatui_ruby/src/events.rs +1 -0
  130. data/ext/ratatui_ruby/src/rendering.rs +1 -1
  131. data/ext/ratatui_ruby/src/style.rs +0 -8
  132. data/ext/ratatui_ruby/src/widgets/chart.rs +0 -118
  133. data/ext/ratatui_ruby/src/widgets/list_state.rs +36 -0
  134. data/lib/ratatui_ruby/buffer/cell.rb +34 -2
  135. data/lib/ratatui_ruby/buffer.rb +2 -2
  136. data/lib/ratatui_ruby/cell.rb +34 -2
  137. data/lib/ratatui_ruby/event/focus_gained.rb +26 -2
  138. data/lib/ratatui_ruby/event/focus_lost.rb +26 -2
  139. data/lib/ratatui_ruby/event/key/character.rb +18 -2
  140. data/lib/ratatui_ruby/event/key/media.rb +2 -2
  141. data/lib/ratatui_ruby/event/key/modifier.rb +10 -2
  142. data/lib/ratatui_ruby/event/key/navigation.rb +2 -2
  143. data/lib/ratatui_ruby/event/key/system.rb +2 -2
  144. data/lib/ratatui_ruby/event/key.rb +114 -2
  145. data/lib/ratatui_ruby/event/mouse.rb +42 -2
  146. data/lib/ratatui_ruby/event/none.rb +10 -2
  147. data/lib/ratatui_ruby/event/paste.rb +34 -2
  148. data/lib/ratatui_ruby/event/resize.rb +34 -2
  149. data/lib/ratatui_ruby/event/sync.rb +52 -0
  150. data/lib/ratatui_ruby/event.rb +32 -2
  151. data/lib/ratatui_ruby/frame.rb +74 -2
  152. data/lib/ratatui_ruby/layout/constraint.rb +193 -2
  153. data/lib/ratatui_ruby/layout/layout.rb +47 -2
  154. data/lib/ratatui_ruby/layout/rect.rb +403 -2
  155. data/lib/ratatui_ruby/layout.rb +2 -2
  156. data/lib/ratatui_ruby/list_state.rb +113 -2
  157. data/lib/ratatui_ruby/output_guard.rb +26 -3
  158. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +2 -2
  159. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +2 -2
  160. data/lib/ratatui_ruby/schema/bar_chart.rb +50 -2
  161. data/lib/ratatui_ruby/schema/block.rb +21 -15
  162. data/lib/ratatui_ruby/schema/calendar.rb +2 -2
  163. data/lib/ratatui_ruby/schema/canvas.rb +10 -2
  164. data/lib/ratatui_ruby/schema/center.rb +10 -2
  165. data/lib/ratatui_ruby/schema/chart.rb +2 -28
  166. data/lib/ratatui_ruby/schema/clear.rb +10 -2
  167. data/lib/ratatui_ruby/schema/constraint.rb +58 -2
  168. data/lib/ratatui_ruby/schema/cursor.rb +10 -2
  169. data/lib/ratatui_ruby/schema/draw.rb +10 -2
  170. data/lib/ratatui_ruby/schema/gauge.rb +2 -2
  171. data/lib/ratatui_ruby/schema/layout.rb +18 -2
  172. data/lib/ratatui_ruby/schema/line_gauge.rb +2 -2
  173. data/lib/ratatui_ruby/schema/list.rb +10 -2
  174. data/lib/ratatui_ruby/schema/list_item.rb +10 -2
  175. data/lib/ratatui_ruby/schema/overlay.rb +10 -2
  176. data/lib/ratatui_ruby/schema/paragraph.rb +10 -2
  177. data/lib/ratatui_ruby/schema/ratatui_logo.rb +2 -2
  178. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +2 -2
  179. data/lib/ratatui_ruby/schema/rect.rb +58 -2
  180. data/lib/ratatui_ruby/schema/row.rb +10 -2
  181. data/lib/ratatui_ruby/schema/scrollbar.rb +2 -2
  182. data/lib/ratatui_ruby/schema/shape/label.rb +10 -2
  183. data/lib/ratatui_ruby/schema/sparkline.rb +10 -2
  184. data/lib/ratatui_ruby/schema/style.rb +18 -2
  185. data/lib/ratatui_ruby/schema/table.rb +2 -2
  186. data/lib/ratatui_ruby/schema/tabs.rb +2 -2
  187. data/lib/ratatui_ruby/schema/text.rb +34 -2
  188. data/lib/ratatui_ruby/scrollbar_state.rb +10 -2
  189. data/lib/ratatui_ruby/style/style.rb +18 -2
  190. data/lib/ratatui_ruby/style.rb +2 -2
  191. data/lib/ratatui_ruby/synthetic_events.rb +86 -0
  192. data/lib/ratatui_ruby/table_state.rb +10 -2
  193. data/lib/ratatui_ruby/terminal_lifecycle.rb +18 -3
  194. data/lib/ratatui_ruby/test_helper/event_injection.rb +62 -2
  195. data/lib/ratatui_ruby/test_helper/snapshot.rb +74 -9
  196. data/lib/ratatui_ruby/test_helper/style_assertions.rb +98 -2
  197. data/lib/ratatui_ruby/test_helper/terminal.rb +50 -2
  198. data/lib/ratatui_ruby/test_helper/test_doubles.rb +18 -2
  199. data/lib/ratatui_ruby/test_helper.rb +10 -2
  200. data/lib/ratatui_ruby/tui/buffer_factories.rb +2 -2
  201. data/lib/ratatui_ruby/tui/canvas_factories.rb +2 -2
  202. data/lib/ratatui_ruby/tui/core.rb +2 -2
  203. data/lib/ratatui_ruby/tui/layout_factories.rb +32 -2
  204. data/lib/ratatui_ruby/tui/state_factories.rb +2 -2
  205. data/lib/ratatui_ruby/tui/style_factories.rb +2 -2
  206. data/lib/ratatui_ruby/tui/text_factories.rb +2 -2
  207. data/lib/ratatui_ruby/tui/widget_factories.rb +2 -2
  208. data/lib/ratatui_ruby/tui.rb +11 -3
  209. data/lib/ratatui_ruby/version.rb +3 -3
  210. data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -2
  211. data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -2
  212. data/lib/ratatui_ruby/widgets/bar_chart.rb +58 -2
  213. data/lib/ratatui_ruby/widgets/block.rb +37 -15
  214. data/lib/ratatui_ruby/widgets/calendar.rb +2 -2
  215. data/lib/ratatui_ruby/widgets/canvas.rb +10 -2
  216. data/lib/ratatui_ruby/widgets/cell.rb +10 -2
  217. data/lib/ratatui_ruby/widgets/center.rb +10 -2
  218. data/lib/ratatui_ruby/widgets/chart.rb +2 -28
  219. data/lib/ratatui_ruby/widgets/clear.rb +10 -2
  220. data/lib/ratatui_ruby/widgets/cursor.rb +10 -2
  221. data/lib/ratatui_ruby/widgets/gauge.rb +16 -2
  222. data/lib/ratatui_ruby/widgets/line_gauge.rb +16 -2
  223. data/lib/ratatui_ruby/widgets/list.rb +41 -2
  224. data/lib/ratatui_ruby/widgets/list_item.rb +10 -2
  225. data/lib/ratatui_ruby/widgets/overlay.rb +10 -2
  226. data/lib/ratatui_ruby/widgets/paragraph.rb +10 -2
  227. data/lib/ratatui_ruby/widgets/ratatui_logo.rb +2 -2
  228. data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +2 -2
  229. data/lib/ratatui_ruby/widgets/row.rb +10 -2
  230. data/lib/ratatui_ruby/widgets/scrollbar.rb +2 -2
  231. data/lib/ratatui_ruby/widgets/shape/label.rb +10 -2
  232. data/lib/ratatui_ruby/widgets/sparkline.rb +10 -2
  233. data/lib/ratatui_ruby/widgets/table.rb +62 -2
  234. data/lib/ratatui_ruby/widgets/tabs.rb +2 -2
  235. data/lib/ratatui_ruby/widgets.rb +2 -2
  236. data/lib/ratatui_ruby.rb +101 -9
  237. data/sig/examples/app_all_events/view.rbs +7 -1
  238. data/sig/examples/app_all_events/view_state.rbs +7 -1
  239. data/sig/examples/app_color_picker/app.rbs +5 -0
  240. data/sig/examples/app_stateful_interaction/app.rbs +7 -1
  241. data/sig/examples/verify_quickstart_dsl/app.rbs +7 -1
  242. data/sig/examples/verify_quickstart_lifecycle/app.rbs +7 -1
  243. data/sig/examples/verify_readme_usage/app.rbs +7 -1
  244. data/sig/examples/widget_block_demo/app.rbs +6 -0
  245. data/sig/examples/widget_box_demo/app.rbs +7 -1
  246. data/sig/examples/widget_calendar_demo/app.rbs +7 -1
  247. data/sig/examples/widget_cell_demo/app.rbs +7 -1
  248. data/sig/examples/widget_chart_demo/app.rbs +7 -1
  249. data/sig/examples/widget_gauge_demo/app.rbs +7 -1
  250. data/sig/examples/widget_layout_split/app.rbs +7 -1
  251. data/sig/examples/widget_line_gauge_demo/app.rbs +7 -1
  252. data/sig/examples/widget_list_demo/app.rbs +5 -0
  253. data/sig/examples/widget_map_demo/app.rbs +7 -1
  254. data/sig/examples/widget_popup_demo/app.rbs +7 -1
  255. data/sig/examples/widget_ratatui_logo_demo/app.rbs +7 -1
  256. data/sig/examples/widget_ratatui_mascot_demo/app.rbs +7 -1
  257. data/sig/examples/widget_rect/app.rbs +7 -1
  258. data/sig/examples/widget_render/app.rbs +7 -1
  259. data/sig/examples/widget_rich_text/app.rbs +7 -1
  260. data/sig/examples/widget_scroll_text/app.rbs +7 -1
  261. data/sig/examples/widget_scrollbar_demo/app.rbs +7 -1
  262. data/sig/examples/widget_sparkline_demo/app.rbs +7 -1
  263. data/sig/examples/widget_style_colors/app.rbs +7 -1
  264. data/sig/examples/widget_table_demo/app.rbs +7 -1
  265. data/sig/examples/widget_text_width/app.rbs +7 -1
  266. data/sig/ratatui_ruby/event.rbs +7 -1
  267. data/sig/ratatui_ruby/frame.rbs +15 -3
  268. data/sig/ratatui_ruby/list_state.rbs +11 -1
  269. data/sig/ratatui_ruby/ratatui_ruby.rbs +8 -2
  270. data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +7 -1
  271. data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +6 -0
  272. data/sig/ratatui_ruby/schema/bar_chart.rbs +6 -0
  273. data/sig/ratatui_ruby/schema/block.rbs +7 -1
  274. data/sig/ratatui_ruby/schema/calendar.rbs +6 -0
  275. data/sig/ratatui_ruby/schema/canvas.rbs +6 -0
  276. data/sig/ratatui_ruby/schema/center.rbs +6 -0
  277. data/sig/ratatui_ruby/schema/chart.rbs +6 -9
  278. data/sig/ratatui_ruby/schema/constraint.rbs +14 -0
  279. data/sig/ratatui_ruby/schema/cursor.rbs +6 -0
  280. data/sig/ratatui_ruby/schema/draw.rbs +6 -0
  281. data/sig/ratatui_ruby/schema/gauge.rbs +9 -1
  282. data/sig/ratatui_ruby/schema/layout.rbs +6 -0
  283. data/sig/ratatui_ruby/schema/line_gauge.rbs +9 -1
  284. data/sig/ratatui_ruby/schema/list.rbs +9 -1
  285. data/sig/ratatui_ruby/schema/list_item.rbs +7 -1
  286. data/sig/ratatui_ruby/schema/overlay.rbs +6 -0
  287. data/sig/ratatui_ruby/schema/paragraph.rbs +6 -0
  288. data/sig/ratatui_ruby/schema/ratatui_logo.rbs +6 -0
  289. data/sig/ratatui_ruby/schema/ratatui_mascot.rbs +5 -0
  290. data/sig/ratatui_ruby/schema/rect.rbs +30 -0
  291. data/sig/ratatui_ruby/schema/row.rbs +7 -1
  292. data/sig/ratatui_ruby/schema/scrollbar.rbs +6 -0
  293. data/sig/ratatui_ruby/schema/sparkline.rbs +6 -0
  294. data/sig/ratatui_ruby/schema/style.rbs +7 -1
  295. data/sig/ratatui_ruby/schema/table.rbs +11 -1
  296. data/sig/ratatui_ruby/schema/tabs.rbs +6 -0
  297. data/sig/ratatui_ruby/schema/text.rbs +7 -1
  298. data/sig/ratatui_ruby/scrollbar_state.rbs +7 -1
  299. data/sig/ratatui_ruby/session.rbs +7 -1
  300. data/sig/ratatui_ruby/table_state.rbs +7 -1
  301. data/sig/ratatui_ruby/test_helper/event_injection.rbs +7 -1
  302. data/sig/ratatui_ruby/test_helper/snapshot.rbs +7 -1
  303. data/sig/ratatui_ruby/test_helper/style_assertions.rbs +7 -1
  304. data/sig/ratatui_ruby/test_helper/terminal.rbs +7 -1
  305. data/sig/ratatui_ruby/test_helper/test_doubles.rbs +7 -1
  306. data/sig/ratatui_ruby/test_helper.rbs +7 -1
  307. data/sig/ratatui_ruby/tui/buffer_factories.rbs +7 -1
  308. data/sig/ratatui_ruby/tui/canvas_factories.rbs +7 -1
  309. data/sig/ratatui_ruby/tui/core.rbs +7 -1
  310. data/sig/ratatui_ruby/tui/layout_factories.rbs +7 -1
  311. data/sig/ratatui_ruby/tui/state_factories.rbs +7 -1
  312. data/sig/ratatui_ruby/tui/style_factories.rbs +7 -1
  313. data/sig/ratatui_ruby/tui/text_factories.rbs +7 -1
  314. data/sig/ratatui_ruby/tui/widget_factories.rbs +7 -1
  315. data/sig/ratatui_ruby/tui.rbs +7 -1
  316. data/sig/ratatui_ruby/version.rbs +6 -0
  317. data/tasks/autodoc/examples.rb +1 -1
  318. data/tasks/autodoc/member.rb +1 -1
  319. data/tasks/autodoc/name.rb +1 -1
  320. data/tasks/bump/cargo_lockfile.rb +1 -1
  321. data/tasks/bump/changelog.rb +1 -1
  322. data/tasks/bump/header.rb +1 -1
  323. data/tasks/bump/history.rb +1 -1
  324. data/tasks/bump/links.rb +1 -1
  325. data/tasks/bump/manifest.rb +1 -1
  326. data/tasks/bump/ruby_gem.rb +1 -1
  327. data/tasks/bump/sem_ver.rb +1 -1
  328. data/tasks/bump/unreleased_section.rb +1 -1
  329. data/tasks/license/headers_md.rb +223 -0
  330. data/tasks/license/headers_rb.rb +210 -0
  331. data/tasks/license/license_utils.rb +130 -0
  332. data/tasks/license/snippets_md.rb +315 -0
  333. data/tasks/license/snippets_rdoc.rb +150 -0
  334. data/tasks/license.rake +91 -0
  335. data/tasks/rdoc_config.rb +1 -1
  336. data/tasks/resources/build.yml.erb +13 -7
  337. data/tasks/sourcehut.rake +3 -1
  338. data/tasks/terminal_preview/app_screenshot.rb +1 -1
  339. data/tasks/terminal_preview/crash_report.rb +1 -1
  340. data/tasks/terminal_preview/example_app.rb +1 -1
  341. data/tasks/terminal_preview/launcher_script.rb +1 -1
  342. data/tasks/terminal_preview/preview_collection.rb +1 -1
  343. data/tasks/terminal_preview/preview_timing.rb +1 -1
  344. data/tasks/terminal_preview/safety_confirmation.rb +1 -1
  345. data/tasks/terminal_preview/saved_screenshot.rb +1 -1
  346. data/tasks/terminal_preview/system_appearance.rb +1 -1
  347. data/tasks/terminal_preview/terminal_window.rb +1 -1
  348. data/tasks/terminal_preview/window_id.rb +1 -1
  349. data/tasks/website/index_page.rb +1 -1
  350. data/tasks/website/version.rb +1 -1
  351. data/tasks/website/version_menu.rb +1 -1
  352. data/tasks/website/versioned_documentation.rb +1 -1
  353. data/tasks/website/website.rb +1 -1
  354. metadata +15 -3
  355. data/doc/migration/v0_7_0.md +0 -236
@@ -78,6 +78,35 @@ impl RubyListState {
78
78
  self.inner.borrow_mut().scroll_up_by(amount);
79
79
  }
80
80
 
81
+ /// Selects the next item or the first one if no item is selected.
82
+ ///
83
+ /// Note: until the list is rendered, the number of items is not known, so the index
84
+ /// is set to 0 and will be corrected when the list is rendered.
85
+ pub fn select_next(&self) {
86
+ self.inner.borrow_mut().select_next();
87
+ }
88
+
89
+ /// Selects the previous item or the last one if no item is selected.
90
+ ///
91
+ /// Note: until the list is rendered, the number of items is not known, so the index
92
+ /// is set to `usize::MAX` and will be corrected when the list is rendered.
93
+ pub fn select_previous(&self) {
94
+ self.inner.borrow_mut().select_previous();
95
+ }
96
+
97
+ /// Selects the first item.
98
+ pub fn select_first(&self) {
99
+ self.inner.borrow_mut().select_first();
100
+ }
101
+
102
+ /// Selects the last item.
103
+ ///
104
+ /// Note: until the list is rendered, the number of items is not known, so the index
105
+ /// is set to `usize::MAX` and will be corrected when the list is rendered.
106
+ pub fn select_last(&self) {
107
+ self.inner.borrow_mut().select_last();
108
+ }
109
+
81
110
  /// Borrows the inner `ListState` mutably for rendering.
82
111
  ///
83
112
  /// # Safety
@@ -98,6 +127,13 @@ pub fn register(ruby: &Ruby, module: magnus::RModule) -> Result<(), Error> {
98
127
  class.define_method("offset", method!(RubyListState::offset, 0))?;
99
128
  class.define_method("scroll_down_by", method!(RubyListState::scroll_down_by, 1))?;
100
129
  class.define_method("scroll_up_by", method!(RubyListState::scroll_up_by, 1))?;
130
+ class.define_method("select_next", method!(RubyListState::select_next, 0))?;
131
+ class.define_method(
132
+ "select_previous",
133
+ method!(RubyListState::select_previous, 0),
134
+ )?;
135
+ class.define_method("select_first", method!(RubyListState::select_first, 0))?;
136
+ class.define_method("select_last", method!(RubyListState::select_last, 0))?;
101
137
  Ok(())
102
138
  }
103
139
 
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -18,11 +18,19 @@ module RatatuiRuby
18
18
  #
19
19
  # === Examples
20
20
  #
21
+ #--
22
+ # SPDX-SnippetBegin
23
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
24
+ # SPDX-License-Identifier: MIT-0
25
+ #++
21
26
  # cell = RatatuiRuby.get_cell_at(0, 0)
22
27
  # cell.char # => "H"
23
28
  # cell.fg # => :red
24
29
  # cell.bold? # => true
25
30
  #
31
+ #--
32
+ # SPDX-SnippetEnd
33
+ #++
26
34
  class Cell
27
35
  # The character displayed in the cell.
28
36
  #
@@ -45,8 +53,16 @@ module RatatuiRuby
45
53
  #
46
54
  # === Example
47
55
  #
56
+ #--
57
+ # SPDX-SnippetBegin
58
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
59
+ # SPDX-License-Identifier: MIT-0
60
+ #++
48
61
  # Buffer::Cell.empty # => #<RatatuiRuby::Buffer::Cell char=" ">
49
62
  #
63
+ #--
64
+ # SPDX-SnippetEnd
65
+ #++
50
66
  def self.empty
51
67
  new(symbol: " ", fg: nil, bg: nil, modifiers: [])
52
68
  end
@@ -55,8 +71,16 @@ module RatatuiRuby
55
71
  #
56
72
  # === Example
57
73
  #
74
+ #--
75
+ # SPDX-SnippetBegin
76
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
77
+ # SPDX-License-Identifier: MIT-0
78
+ #++
58
79
  # Buffer::Cell.default # => #<RatatuiRuby::Buffer::Cell char=" ">
59
80
  #
81
+ #--
82
+ # SPDX-SnippetEnd
83
+ #++
60
84
  def self.default
61
85
  empty
62
86
  end
@@ -67,8 +91,16 @@ module RatatuiRuby
67
91
  #
68
92
  # === Example
69
93
  #
94
+ #--
95
+ # SPDX-SnippetBegin
96
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
97
+ # SPDX-License-Identifier: MIT-0
98
+ #++
70
99
  # Buffer::Cell.symbol("X") # => #<RatatuiRuby::Buffer::Cell symbol="X">
71
100
  #
101
+ #--
102
+ # SPDX-SnippetEnd
103
+ #++
72
104
  def self.symbol(symbol)
73
105
  new(symbol:, fg: nil, bg: nil, modifiers: [])
74
106
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -17,11 +17,19 @@ module RatatuiRuby
17
17
  #
18
18
  # === Examples
19
19
  #
20
+ #--
21
+ # SPDX-SnippetBegin
22
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
23
+ # SPDX-License-Identifier: MIT-0
24
+ #++
20
25
  # cell = RatatuiRuby.get_cell_at(0, 0)
21
26
  # cell.char # => "H"
22
27
  # cell.fg # => :red
23
28
  # cell.bold? # => true
24
29
  #
30
+ #--
31
+ # SPDX-SnippetEnd
32
+ #++
25
33
  class Cell
26
34
  # The character displayed in the cell.
27
35
  #
@@ -44,8 +52,16 @@ module RatatuiRuby
44
52
  #
45
53
  # === Example
46
54
  #
55
+ #--
56
+ # SPDX-SnippetBegin
57
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
58
+ # SPDX-License-Identifier: MIT-0
59
+ #++
47
60
  # Cell.empty # => #<RatatuiRuby::Cell char=" ">
48
61
  #
62
+ #--
63
+ # SPDX-SnippetEnd
64
+ #++
49
65
  def self.empty
50
66
  new(symbol: " ", fg: nil, bg: nil, modifiers: [])
51
67
  end
@@ -54,8 +70,16 @@ module RatatuiRuby
54
70
  #
55
71
  # === Example
56
72
  #
73
+ #--
74
+ # SPDX-SnippetBegin
75
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
76
+ # SPDX-License-Identifier: MIT-0
77
+ #++
57
78
  # Cell.default # => #<RatatuiRuby::Cell char=" ">
58
79
  #
80
+ #--
81
+ # SPDX-SnippetEnd
82
+ #++
59
83
  def self.default
60
84
  empty
61
85
  end
@@ -66,8 +90,16 @@ module RatatuiRuby
66
90
  #
67
91
  # === Example
68
92
  #
93
+ #--
94
+ # SPDX-SnippetBegin
95
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
96
+ # SPDX-License-Identifier: MIT-0
97
+ #++
69
98
  # Cell.symbol("X") # => #<RatatuiRuby::Cell symbol="X">
70
99
  #
100
+ #--
101
+ # SPDX-SnippetEnd
102
+ #++
71
103
  def self.symbol(symbol)
72
104
  new(symbol:, fg: nil, bg: nil, modifiers: [])
73
105
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -19,24 +19,48 @@ module RatatuiRuby
19
19
  #
20
20
  # === Example
21
21
  #
22
+ #--
23
+ # SPDX-SnippetBegin
24
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
25
+ # SPDX-License-Identifier: MIT-0
26
+ #++
22
27
  # if event.focus_gained?
23
28
  # puts "Focus gained"
24
29
  # end
30
+ #--
31
+ # SPDX-SnippetEnd
32
+ #++
25
33
  class FocusGained < Event
26
34
  # Returns true for FocusGained events.
27
35
  #
36
+ #--
37
+ # SPDX-SnippetBegin
38
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
39
+ # SPDX-License-Identifier: MIT-0
40
+ #++
28
41
  # event.focus_gained? # => true
29
42
  # event.key? # => false
43
+ #--
44
+ # SPDX-SnippetEnd
45
+ #++
30
46
  def focus_gained?
31
47
  true
32
48
  end
33
49
 
34
50
  # Deconstructs the event for pattern matching.
35
51
  #
52
+ #--
53
+ # SPDX-SnippetBegin
54
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
55
+ # SPDX-License-Identifier: MIT-0
56
+ #++
36
57
  # case event
37
58
  # in type: :focus_gained
38
59
  # puts "Application gained focus"
39
60
  # end
61
+ #--
62
+ # SPDX-SnippetEnd
63
+ #++
40
64
  def deconstruct_keys(keys)
41
65
  { type: :focus_gained }
42
66
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -20,24 +20,48 @@ module RatatuiRuby
20
20
  #
21
21
  # === Example
22
22
  #
23
+ #--
24
+ # SPDX-SnippetBegin
25
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
26
+ # SPDX-License-Identifier: MIT-0
27
+ #++
23
28
  # if event.focus_lost?
24
29
  # puts "Focus lost"
25
30
  # end
31
+ #--
32
+ # SPDX-SnippetEnd
33
+ #++
26
34
  class FocusLost < Event
27
35
  # Returns true for FocusLost events.
28
36
  #
37
+ #--
38
+ # SPDX-SnippetBegin
39
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
40
+ # SPDX-License-Identifier: MIT-0
41
+ #++
29
42
  # event.focus_lost? # => true
30
43
  # event.key? # => false
44
+ #--
45
+ # SPDX-SnippetEnd
46
+ #++
31
47
  def focus_lost?
32
48
  true
33
49
  end
34
50
 
35
51
  # Deconstructs the event for pattern matching.
36
52
  #
53
+ #--
54
+ # SPDX-SnippetBegin
55
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
56
+ # SPDX-License-Identifier: MIT-0
57
+ #++
37
58
  # case event
38
59
  # in type: :focus_lost
39
60
  # puts "Application lost focus"
40
61
  # end
62
+ #--
63
+ # SPDX-SnippetEnd
64
+ #++
41
65
  def deconstruct_keys(keys)
42
66
  { type: :focus_lost }
43
67
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -12,9 +12,17 @@ module RatatuiRuby
12
12
  module Character
13
13
  # Returns true if the key represents a single printable character.
14
14
  #
15
+ #--
16
+ # SPDX-SnippetBegin
17
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
18
+ # SPDX-License-Identifier: MIT-0
19
+ #++
15
20
  # RatatuiRuby::Event::Key.new(code: "a").text? # => true
16
21
  # RatatuiRuby::Event::Key.new(code: "enter").text? # => false
17
22
  # RatatuiRuby::Event::Key.new(code: "space").text? # => false ("space" is not 1 char, " " is)
23
+ #--
24
+ # SPDX-SnippetEnd
25
+ #++
18
26
  def text?
19
27
  @code.length == 1
20
28
  end
@@ -24,10 +32,18 @@ module RatatuiRuby
24
32
  # [Printable Characters]
25
33
  # Returns the character itself (e.g., <tt>"a"</tt>, <tt>"1"</tt>, <tt>" "</tt>).
26
34
  # [Special Keys]
35
+ #--
36
+ # SPDX-SnippetBegin
37
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
38
+ # SPDX-License-Identifier: MIT-0
39
+ #++
27
40
  # Returns <tt>nil</tt> (e.g., <tt>"enter"</tt>, <tt>"up"</tt>, <tt>"f1"</tt>).
28
41
  #
29
42
  # RatatuiRuby::Event::Key.new(code: "a").char # => "a"
30
43
  # RatatuiRuby::Event::Key.new(code: "enter").char # => nil
44
+ #--
45
+ # SPDX-SnippetEnd
46
+ #++
31
47
  def char
32
48
  text? ? @code : nil
33
49
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -66,9 +66,17 @@ module RatatuiRuby
66
66
  #
67
67
  # === Example
68
68
  #
69
+ #--
70
+ # SPDX-SnippetBegin
71
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
72
+ # SPDX-License-Identifier: MIT-0
73
+ #++
69
74
  # if event.modifier?
70
75
  # # Handle solo modifier key press
71
76
  # end
77
+ #--
78
+ # SPDX-SnippetEnd
79
+ #++
72
80
  def modifier?
73
81
  @kind == :modifier
74
82
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  module RatatuiRuby
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
5
- # SPDX-License-Identifier: AGPL-3.0-or-later
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: LGPL-3.0-or-later
6
6
  #++
7
7
 
8
8
  require_relative "key/character"
@@ -27,21 +27,45 @@ module RatatuiRuby
27
27
  # === Examples
28
28
  #
29
29
  # Using predicates:
30
+ #--
31
+ # SPDX-SnippetBegin
32
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
33
+ # SPDX-License-Identifier: MIT-0
34
+ #++
30
35
  # if event.key? && event.ctrl? && event.code == "c"
31
36
  # exit
32
37
  # end
33
38
  #
39
+ #--
40
+ # SPDX-SnippetEnd
41
+ #++
34
42
  # Using symbol comparison:
43
+ #--
44
+ # SPDX-SnippetBegin
45
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
46
+ # SPDX-License-Identifier: MIT-0
47
+ #++
35
48
  # if event == :ctrl_c
36
49
  # exit
37
50
  # end
38
51
  #
52
+ #--
53
+ # SPDX-SnippetEnd
54
+ #++
39
55
  # Using pattern matching:
56
+ #--
57
+ # SPDX-SnippetBegin
58
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
59
+ # SPDX-License-Identifier: MIT-0
60
+ #++
40
61
  # case event
41
62
  # in type: :key, code: "c", modifiers: ["ctrl"]
42
63
  # exit
43
64
  # end
44
65
  #
66
+ #--
67
+ # SPDX-SnippetEnd
68
+ #++
45
69
  # === Terminal Compatibility
46
70
  #
47
71
  # Some key combinations never reach your application. Terminal emulators intercept them for
@@ -90,9 +114,17 @@ module RatatuiRuby
90
114
 
91
115
  # Returns true for Key events.
92
116
  #
117
+ #--
118
+ # SPDX-SnippetBegin
119
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
120
+ # SPDX-License-Identifier: MIT-0
121
+ #++
93
122
  # event.key? # => true
94
123
  # event.mouse? # => false
95
124
  # event.resize? # => false
125
+ #--
126
+ # SPDX-SnippetEnd
127
+ #++
96
128
  def key?
97
129
  true
98
130
  end
@@ -104,8 +136,16 @@ module RatatuiRuby
104
136
  # [modifiers]
105
137
  # List of modifiers (Array<String>).
106
138
  # [kind]
139
+ #--
140
+ # SPDX-SnippetBegin
141
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
142
+ # SPDX-License-Identifier: MIT-0
143
+ #++
107
144
  # The key category (Symbol). One of: <tt>:standard</tt>, <tt>:function</tt>,
108
145
  # <tt>:media</tt>, <tt>:modifier</tt>, <tt>:system</tt>. Defaults to <tt>:standard</tt>.
146
+ #--
147
+ # SPDX-SnippetEnd
148
+ #++
109
149
  def initialize(code:, modifiers: [], kind: :standard)
110
150
  @code = code.freeze
111
151
  @modifiers = modifiers.map(&:freeze).sort.freeze
@@ -141,8 +181,16 @@ module RatatuiRuby
141
181
  # [Standard]
142
182
  # <tt>:enter</tt>, <tt>:backspace</tt>, <tt>:tab</tt>, <tt>:back_tab</tt>, <tt>:esc</tt>, <tt>:null</tt>
143
183
  # [Navigation]
184
+ #--
185
+ # SPDX-SnippetBegin
186
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
187
+ # SPDX-License-Identifier: MIT-0
188
+ #++
144
189
  # <tt>:up</tt>, <tt>:down</tt>, <tt>:left</tt>, <tt>:right</tt>, <tt>:home</tt>, <tt>:end</tt>,
145
190
  # <tt>:page_up</tt>, <tt>:page_down</tt>, <tt>:insert</tt>, <tt>:delete</tt>
191
+ #--
192
+ # SPDX-SnippetEnd
193
+ #++
146
194
  # [Function Keys]
147
195
  # <tt>:f1</tt> through <tt>:f12</tt> (and beyond, e.g. <tt>:f24</tt>)
148
196
  # [Lock Keys]
@@ -150,17 +198,41 @@ module RatatuiRuby
150
198
  # [System Keys]
151
199
  # <tt>:print_screen</tt>, <tt>:pause</tt>, <tt>:menu</tt>, <tt>:keypad_begin</tt>
152
200
  # [Media Keys]
201
+ #--
202
+ # SPDX-SnippetBegin
203
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
204
+ # SPDX-License-Identifier: MIT-0
205
+ #++
153
206
  # <tt>:play</tt>, <tt>:media_pause</tt>, <tt>:play_pause</tt>, <tt>:reverse</tt>, <tt>:stop</tt>,
154
207
  # <tt>:fast_forward</tt>, <tt>:rewind</tt>, <tt>:track_next</tt>, <tt>:track_previous</tt>,
155
208
  # <tt>:record</tt>, <tt>:lower_volume</tt>, <tt>:raise_volume</tt>, <tt>:mute_volume</tt>
209
+ #--
210
+ # SPDX-SnippetEnd
211
+ #++
156
212
  # [Modifier Keys]
213
+ #--
214
+ # SPDX-SnippetBegin
215
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
216
+ # SPDX-License-Identifier: MIT-0
217
+ #++
157
218
  # <tt>:left_shift</tt>, <tt>:left_control</tt>, <tt>:left_alt</tt>, <tt>:left_super</tt>,
158
219
  # <tt>:left_hyper</tt>, <tt>:left_meta</tt>, <tt>:right_shift</tt>, <tt>:right_control</tt>,
159
220
  # <tt>:right_alt</tt>, <tt>:right_super</tt>, <tt>:right_hyper</tt>, <tt>:right_meta</tt>,
160
221
  # <tt>:iso_level3_shift</tt>, <tt>:iso_level5_shift</tt>
222
+ #--
223
+ # SPDX-SnippetEnd
224
+ #++
161
225
  # [Characters]
226
+ #--
227
+ # SPDX-SnippetBegin
228
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
229
+ # SPDX-License-Identifier: MIT-0
230
+ #++
162
231
  # <tt>:a</tt>, <tt>:b</tt>, <tt>:1</tt>, <tt>:space</tt>, etc.
163
232
  #
233
+ #--
234
+ # SPDX-SnippetEnd
235
+ #++
164
236
  # === Modifier Examples
165
237
  #
166
238
  # * <tt>:ctrl_c</tt>
@@ -183,8 +255,16 @@ module RatatuiRuby
183
255
  # [Special Keys]
184
256
  # Returns an empty string (e.g., <tt>"enter"</tt>, <tt>"up"</tt>, <tt>"f1"</tt> all return <tt>""</tt>).
185
257
  # [Modifiers]
258
+ #--
259
+ # SPDX-SnippetBegin
260
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
261
+ # SPDX-License-Identifier: MIT-0
262
+ #++
186
263
  # Returns the character if printable, ignoring modifiers unless they alter the character code itself.
187
264
  # Note that <tt>ctrl+c</tt> typically returns <tt>"c"</tt> as the code, so +to_s+ will return <tt>"c"</tt>.
265
+ #--
266
+ # SPDX-SnippetEnd
267
+ #++
188
268
  def to_s
189
269
  if text?
190
270
  @code
@@ -202,11 +282,19 @@ module RatatuiRuby
202
282
  #
203
283
  # Allows convenient checking for specific keys or key combinations:
204
284
  #
285
+ #--
286
+ # SPDX-SnippetBegin
287
+ # SPDX-FileCopyrightText: 2025 Kerrick Long
288
+ # SPDX-License-Identifier: MIT-0
289
+ #++
205
290
  # event.ctrl_c? # => true if Ctrl+C
206
291
  # event.enter? # => true if Enter
207
292
  # event.shift_up? # => true if Shift+Up
208
293
  # event.q? # => true if "q"
209
294
  #
295
+ #--
296
+ # SPDX-SnippetEnd
297
+ #++
210
298
  # The method name is converted to a symbol and compared against the event.
211
299
  # This works for any key code or modifier+key combination.
212
300
  #
@@ -214,18 +302,34 @@ module RatatuiRuby
214
302
  #
215
303
  # For convenience, generic predicates match both system and media variants:
216
304
  #
305
+ #--
306
+ # SPDX-SnippetBegin
307
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
308
+ # SPDX-License-Identifier: MIT-0
309
+ #++
217
310
  # event.pause? # => true for BOTH system "pause" AND "media_pause"
218
311
  # event.play? # => true for "media_play"
219
312
  # event.stop? # => true for "media_stop"
220
313
  #
314
+ #--
315
+ # SPDX-SnippetEnd
316
+ #++
221
317
  # This "Do What I Mean" behavior reduces boilerplate when you just want to
222
318
  # respond to a conceptual action (e.g., "pause the playback") regardless of
223
319
  # whether the user pressed a keyboard key or a media button.
224
320
  #
225
321
  # For strict matching, use the full predicate or compare the code directly:
226
322
  #
323
+ #--
324
+ # SPDX-SnippetBegin
325
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
326
+ # SPDX-License-Identifier: MIT-0
327
+ #++
227
328
  # event.media_pause? # => true ONLY for media pause
228
329
  # event.code == "pause" # => true ONLY for system pause
330
+ #--
331
+ # SPDX-SnippetEnd
332
+ #++
229
333
  def method_missing(name, *args, &block)
230
334
  if name.to_s.end_with?("?")
231
335
  key_name = name.to_s[0...-1]
@@ -259,12 +363,20 @@ module RatatuiRuby
259
363
 
260
364
  # Deconstructs the event for pattern matching.
261
365
  #
366
+ #--
367
+ # SPDX-SnippetBegin
368
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
369
+ # SPDX-License-Identifier: MIT-0
370
+ #++
262
371
  # case event
263
372
  # in type: :key, code: "c", modifiers: ["ctrl"]
264
373
  # puts "Ctrl+C pressed"
265
374
  # in type: :key, kind: :media
266
375
  # puts "Media key pressed"
267
376
  # end
377
+ #--
378
+ # SPDX-SnippetEnd
379
+ #++
268
380
  def deconstruct_keys(keys)
269
381
  { type: :key, code: @code, modifiers: @modifiers, kind: @kind }
270
382
  end