ratatui_ruby 0.7.1 → 0.7.3

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 (311) 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 +12 -4
  7. data/CHANGELOG.md +49 -0
  8. data/README.md +7 -7
  9. data/Rakefile +1 -1
  10. data/doc/{application_architecture.md → concepts/application_architecture.md} +30 -0
  11. data/doc/{application_testing.md → concepts/application_testing.md} +4 -2
  12. data/doc/{event_handling.md → concepts/event_handling.md} +1 -1
  13. data/doc/contributors/auditing/parity.md +233 -0
  14. data/doc/contributors/developing_examples.md +10 -10
  15. data/doc/contributors/upstream_requests/tab_rects.md +173 -0
  16. data/doc/contributors/upstream_requests/title_rects.md +132 -0
  17. data/doc/contributors/v1.0.0_blockers.md +54 -747
  18. data/doc/{quickstart.md → getting_started/quickstart.md} +26 -26
  19. data/doc/{why.md → getting_started/why.md} +1 -1
  20. data/doc/index.md +23 -9
  21. data/doc/{terminal_limitations.md → troubleshooting/terminal_limitations.md} +33 -0
  22. data/doc/troubleshooting/tui_output.md +76 -0
  23. data/examples/app_all_events/README.md +1 -0
  24. data/examples/app_all_events/app.rb +2 -0
  25. data/examples/app_all_events/model/app_model.rb +2 -0
  26. data/examples/app_all_events/model/event_color_cycle.rb +2 -0
  27. data/examples/app_all_events/model/event_entry.rb +2 -0
  28. data/examples/app_all_events/model/msg.rb +2 -0
  29. data/examples/app_all_events/model/timestamp.rb +2 -0
  30. data/examples/app_all_events/update.rb +2 -0
  31. data/examples/app_all_events/view/app_view.rb +2 -0
  32. data/examples/app_all_events/view/controls_view.rb +2 -0
  33. data/examples/app_all_events/view/counts_view.rb +2 -0
  34. data/examples/app_all_events/view/live_view.rb +2 -0
  35. data/examples/app_all_events/view/log_view.rb +2 -0
  36. data/examples/app_all_events/view.rb +2 -0
  37. data/examples/app_color_picker/README.md +2 -0
  38. data/examples/app_color_picker/app.rb +2 -0
  39. data/examples/app_color_picker/clipboard.rb +2 -0
  40. data/examples/app_color_picker/color.rb +2 -0
  41. data/examples/app_color_picker/controls.rb +2 -0
  42. data/examples/app_color_picker/copy_dialog.rb +2 -0
  43. data/examples/app_color_picker/export_pane.rb +2 -0
  44. data/examples/app_color_picker/harmony.rb +2 -0
  45. data/examples/app_color_picker/input.rb +2 -0
  46. data/examples/app_color_picker/main_container.rb +2 -0
  47. data/examples/app_color_picker/palette.rb +2 -0
  48. data/examples/app_login_form/README.md +3 -0
  49. data/examples/app_login_form/app.rb +2 -0
  50. data/examples/app_stateful_interaction/README.md +2 -0
  51. data/examples/app_stateful_interaction/app.rb +2 -0
  52. data/examples/timeout_demo.rb +2 -0
  53. data/examples/verify_quickstart_dsl/README.md +2 -2
  54. data/examples/verify_quickstart_dsl/app.rb +2 -0
  55. data/examples/verify_quickstart_layout/README.md +2 -2
  56. data/examples/verify_quickstart_layout/app.rb +2 -0
  57. data/examples/verify_quickstart_lifecycle/README.md +2 -2
  58. data/examples/verify_quickstart_lifecycle/app.rb +2 -0
  59. data/examples/verify_readme_usage/app.rb +2 -0
  60. data/examples/{widget_barchart_demo → widget_barchart}/README.md +5 -3
  61. data/examples/{widget_barchart_demo → widget_barchart}/app.rb +7 -5
  62. data/examples/{widget_block_demo → widget_block}/README.md +5 -3
  63. data/examples/{widget_block_demo → widget_block}/app.rb +6 -4
  64. data/examples/{widget_box_demo → widget_box}/README.md +7 -4
  65. data/examples/{widget_box_demo → widget_box}/app.rb +7 -5
  66. data/examples/{widget_calendar_demo → widget_calendar}/README.md +6 -3
  67. data/examples/{widget_calendar_demo → widget_calendar}/app.rb +6 -4
  68. data/examples/{widget_canvas_demo → widget_canvas}/README.md +2 -2
  69. data/examples/{widget_canvas_demo → widget_canvas}/app.rb +6 -4
  70. data/examples/{widget_cell_demo → widget_cell}/README.md +6 -3
  71. data/examples/{widget_cell_demo → widget_cell}/app.rb +7 -5
  72. data/examples/{widget_center_demo → widget_center}/README.md +2 -2
  73. data/examples/{widget_center_demo → widget_center}/app.rb +6 -4
  74. data/examples/{widget_chart_demo → widget_chart}/README.md +7 -4
  75. data/examples/{widget_chart_demo → widget_chart}/app.rb +7 -5
  76. data/examples/{widget_gauge_demo → widget_gauge}/README.md +6 -3
  77. data/examples/{widget_gauge_demo → widget_gauge}/app.rb +7 -5
  78. data/examples/widget_layout_split/README.md +5 -2
  79. data/examples/widget_layout_split/app.rb +3 -1
  80. data/examples/{widget_line_gauge_demo → widget_line_gauge}/README.md +6 -3
  81. data/examples/{widget_line_gauge_demo → widget_line_gauge}/app.rb +7 -5
  82. data/examples/{widget_list_demo → widget_list}/README.md +7 -4
  83. data/examples/{widget_list_demo → widget_list}/app.rb +7 -5
  84. data/examples/{widget_map_demo → widget_map}/README.md +7 -4
  85. data/examples/{widget_map_demo → widget_map}/app.rb +4 -2
  86. data/examples/{widget_overlay_demo → widget_overlay}/README.md +6 -3
  87. data/examples/{widget_overlay_demo → widget_overlay}/app.rb +5 -3
  88. data/examples/{widget_popup_demo → widget_popup}/README.md +7 -4
  89. data/examples/{widget_popup_demo → widget_popup}/app.rb +6 -4
  90. data/examples/{widget_ratatui_logo_demo → widget_ratatui_logo}/README.md +6 -3
  91. data/examples/{widget_ratatui_logo_demo → widget_ratatui_logo}/app.rb +8 -6
  92. data/examples/{widget_ratatui_mascot_demo → widget_ratatui_mascot}/README.md +6 -3
  93. data/examples/{widget_ratatui_mascot_demo → widget_ratatui_mascot}/app.rb +6 -4
  94. data/examples/widget_rect/README.md +5 -2
  95. data/examples/widget_rect/app.rb +2 -0
  96. data/examples/widget_render/README.md +4 -1
  97. data/examples/widget_render/app.rb +2 -0
  98. data/examples/widget_rich_text/README.md +4 -1
  99. data/examples/widget_rich_text/app.rb +2 -0
  100. data/examples/widget_scroll_text/README.md +4 -1
  101. data/examples/widget_scroll_text/app.rb +3 -1
  102. data/examples/{widget_scrollbar_demo → widget_scrollbar}/README.md +7 -4
  103. data/examples/{widget_scrollbar_demo → widget_scrollbar}/app.rb +6 -4
  104. data/examples/{widget_sparkline_demo → widget_sparkline}/README.md +6 -3
  105. data/examples/{widget_sparkline_demo → widget_sparkline}/app.rb +7 -5
  106. data/examples/widget_style_colors/README.md +4 -1
  107. data/examples/widget_style_colors/app.rb +2 -0
  108. data/examples/{widget_table_demo → widget_table}/README.md +7 -4
  109. data/examples/{widget_table_demo → widget_table}/app.rb +4 -2
  110. data/examples/{widget_tabs_demo → widget_tabs}/README.md +6 -3
  111. data/examples/{widget_tabs_demo → widget_tabs}/app.rb +7 -5
  112. data/examples/widget_text_width/README.md +5 -2
  113. data/examples/widget_text_width/app.rb +2 -0
  114. data/exe/.gitkeep +0 -0
  115. data/ext/ratatui_ruby/Cargo.lock +1 -1
  116. data/ext/ratatui_ruby/Cargo.toml +1 -1
  117. data/ext/ratatui_ruby/extconf.rb +2 -0
  118. data/ext/ratatui_ruby/src/lib.rs +2 -2
  119. data/ext/ratatui_ruby/src/rendering.rs +9 -0
  120. data/ext/ratatui_ruby/src/style.rs +22 -2
  121. data/ext/ratatui_ruby/src/text.rs +26 -0
  122. data/ext/ratatui_ruby/src/widgets/barchart.rs +8 -6
  123. data/ext/ratatui_ruby/src/widgets/chart.rs +31 -4
  124. data/ext/ratatui_ruby/src/widgets/table.rs +13 -5
  125. data/ext/ratatui_ruby/src/widgets/tabs.rs +49 -9
  126. data/lib/ratatui_ruby/buffer/cell.rb +2 -0
  127. data/lib/ratatui_ruby/buffer.rb +2 -0
  128. data/lib/ratatui_ruby/cell.rb +2 -0
  129. data/lib/ratatui_ruby/event/focus_gained.rb +2 -0
  130. data/lib/ratatui_ruby/event/focus_lost.rb +2 -0
  131. data/lib/ratatui_ruby/event/key/character.rb +2 -0
  132. data/lib/ratatui_ruby/event/key/media.rb +2 -0
  133. data/lib/ratatui_ruby/event/key/modifier.rb +2 -0
  134. data/lib/ratatui_ruby/event/key/navigation.rb +2 -0
  135. data/lib/ratatui_ruby/event/key/system.rb +2 -0
  136. data/lib/ratatui_ruby/event/key.rb +2 -0
  137. data/lib/ratatui_ruby/event/mouse.rb +2 -0
  138. data/lib/ratatui_ruby/event/none.rb +2 -0
  139. data/lib/ratatui_ruby/event/paste.rb +2 -0
  140. data/lib/ratatui_ruby/event/resize.rb +2 -0
  141. data/lib/ratatui_ruby/event.rb +2 -0
  142. data/lib/ratatui_ruby/frame.rb +2 -0
  143. data/lib/ratatui_ruby/layout/constraint.rb +2 -0
  144. data/lib/ratatui_ruby/layout/layout.rb +2 -0
  145. data/lib/ratatui_ruby/layout/rect.rb +2 -0
  146. data/lib/ratatui_ruby/layout.rb +2 -0
  147. data/lib/ratatui_ruby/list_state.rb +2 -0
  148. data/lib/ratatui_ruby/schema/bar_chart/bar.rb +2 -0
  149. data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +2 -0
  150. data/lib/ratatui_ruby/schema/bar_chart.rb +4 -2
  151. data/lib/ratatui_ruby/schema/block.rb +4 -2
  152. data/lib/ratatui_ruby/schema/calendar.rb +4 -2
  153. data/lib/ratatui_ruby/schema/canvas.rb +2 -0
  154. data/lib/ratatui_ruby/schema/center.rb +2 -0
  155. data/lib/ratatui_ruby/schema/chart.rb +4 -2
  156. data/lib/ratatui_ruby/schema/clear.rb +2 -0
  157. data/lib/ratatui_ruby/schema/constraint.rb +2 -0
  158. data/lib/ratatui_ruby/schema/cursor.rb +2 -0
  159. data/lib/ratatui_ruby/schema/draw.rb +2 -0
  160. data/lib/ratatui_ruby/schema/gauge.rb +4 -2
  161. data/lib/ratatui_ruby/schema/layout.rb +2 -0
  162. data/lib/ratatui_ruby/schema/line_gauge.rb +4 -2
  163. data/lib/ratatui_ruby/schema/list.rb +3 -1
  164. data/lib/ratatui_ruby/schema/list_item.rb +2 -0
  165. data/lib/ratatui_ruby/schema/overlay.rb +2 -0
  166. data/lib/ratatui_ruby/schema/paragraph.rb +2 -0
  167. data/lib/ratatui_ruby/schema/ratatui_logo.rb +4 -2
  168. data/lib/ratatui_ruby/schema/ratatui_mascot.rb +4 -2
  169. data/lib/ratatui_ruby/schema/rect.rb +2 -0
  170. data/lib/ratatui_ruby/schema/row.rb +2 -0
  171. data/lib/ratatui_ruby/schema/scrollbar.rb +4 -2
  172. data/lib/ratatui_ruby/schema/shape/label.rb +2 -0
  173. data/lib/ratatui_ruby/schema/sparkline.rb +4 -2
  174. data/lib/ratatui_ruby/schema/style.rb +2 -0
  175. data/lib/ratatui_ruby/schema/table.rb +2 -0
  176. data/lib/ratatui_ruby/schema/tabs.rb +4 -2
  177. data/lib/ratatui_ruby/schema/text.rb +2 -0
  178. data/lib/ratatui_ruby/scrollbar_state.rb +2 -0
  179. data/lib/ratatui_ruby/style/style.rb +3 -0
  180. data/lib/ratatui_ruby/style.rb +2 -0
  181. data/lib/ratatui_ruby/table_state.rb +2 -0
  182. data/lib/ratatui_ruby/test_helper/event_injection.rb +2 -0
  183. data/lib/ratatui_ruby/test_helper/snapshot.rb +62 -21
  184. data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.ansi +24 -0
  185. data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.txt +24 -0
  186. data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.ansi +5 -0
  187. data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.txt +5 -0
  188. data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.ansi +24 -0
  189. data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.txt +24 -0
  190. data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.ansi +12 -0
  191. data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.txt +12 -0
  192. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.ansi +12 -0
  193. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.txt +12 -0
  194. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.ansi +12 -0
  195. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.txt +12 -0
  196. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.ansi +12 -0
  197. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.txt +12 -0
  198. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.ansi +12 -0
  199. data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.txt +12 -0
  200. data/lib/ratatui_ruby/test_helper/snapshots/my_snapshot.txt +1 -0
  201. data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.ansi +10 -0
  202. data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.txt +10 -0
  203. data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.ansi +10 -0
  204. data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.txt +10 -0
  205. data/lib/ratatui_ruby/test_helper/style_assertions.rb +2 -0
  206. data/lib/ratatui_ruby/test_helper/terminal.rb +5 -0
  207. data/lib/ratatui_ruby/test_helper/test_doubles.rb +2 -0
  208. data/lib/ratatui_ruby/test_helper.rb +6 -4
  209. data/lib/ratatui_ruby/tui/buffer_factories.rb +2 -0
  210. data/lib/ratatui_ruby/tui/canvas_factories.rb +2 -0
  211. data/lib/ratatui_ruby/tui/core.rb +2 -0
  212. data/lib/ratatui_ruby/tui/layout_factories.rb +2 -0
  213. data/lib/ratatui_ruby/tui/state_factories.rb +2 -0
  214. data/lib/ratatui_ruby/tui/style_factories.rb +2 -0
  215. data/lib/ratatui_ruby/tui/text_factories.rb +2 -0
  216. data/lib/ratatui_ruby/tui/widget_factories.rb +2 -0
  217. data/lib/ratatui_ruby/tui.rb +2 -0
  218. data/lib/ratatui_ruby/version.rb +3 -1
  219. data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -0
  220. data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -0
  221. data/lib/ratatui_ruby/widgets/bar_chart.rb +7 -4
  222. data/lib/ratatui_ruby/widgets/block.rb +46 -2
  223. data/lib/ratatui_ruby/widgets/calendar.rb +4 -2
  224. data/lib/ratatui_ruby/widgets/canvas.rb +2 -0
  225. data/lib/ratatui_ruby/widgets/cell.rb +2 -0
  226. data/lib/ratatui_ruby/widgets/center.rb +2 -0
  227. data/lib/ratatui_ruby/widgets/chart.rb +13 -6
  228. data/lib/ratatui_ruby/widgets/clear.rb +2 -0
  229. data/lib/ratatui_ruby/widgets/cursor.rb +2 -0
  230. data/lib/ratatui_ruby/widgets/gauge.rb +4 -2
  231. data/lib/ratatui_ruby/widgets/line_gauge.rb +4 -2
  232. data/lib/ratatui_ruby/widgets/list.rb +3 -1
  233. data/lib/ratatui_ruby/widgets/list_item.rb +2 -0
  234. data/lib/ratatui_ruby/widgets/overlay.rb +2 -0
  235. data/lib/ratatui_ruby/widgets/paragraph.rb +2 -0
  236. data/lib/ratatui_ruby/widgets/ratatui_logo.rb +4 -2
  237. data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +4 -2
  238. data/lib/ratatui_ruby/widgets/row.rb +2 -0
  239. data/lib/ratatui_ruby/widgets/scrollbar.rb +4 -2
  240. data/lib/ratatui_ruby/widgets/shape/label.rb +2 -0
  241. data/lib/ratatui_ruby/widgets/sparkline.rb +7 -4
  242. data/lib/ratatui_ruby/widgets/table.rb +2 -0
  243. data/lib/ratatui_ruby/widgets/tabs.rb +12 -8
  244. data/lib/ratatui_ruby/widgets.rb +2 -0
  245. data/lib/ratatui_ruby.rb +130 -9
  246. data/tasks/autodoc/examples.rb +2 -0
  247. data/tasks/autodoc/member.rb +2 -0
  248. data/tasks/autodoc/name.rb +2 -0
  249. data/tasks/autodoc.rake +2 -0
  250. data/tasks/bump/cargo_lockfile.rb +2 -0
  251. data/tasks/bump/changelog.rb +2 -0
  252. data/tasks/bump/header.rb +2 -0
  253. data/tasks/bump/history.rb +2 -0
  254. data/tasks/bump/links.rb +2 -0
  255. data/tasks/bump/manifest.rb +2 -0
  256. data/tasks/bump/ruby_gem.rb +2 -0
  257. data/tasks/bump/sem_ver.rb +2 -0
  258. data/tasks/bump/unreleased_section.rb +2 -0
  259. data/tasks/bump.rake +2 -0
  260. data/tasks/doc.rake +268 -0
  261. data/tasks/extension.rake +2 -0
  262. data/tasks/lint.rake +115 -0
  263. data/tasks/rdoc_config.rb +18 -4
  264. data/tasks/sourcehut.rake +2 -0
  265. data/tasks/terminal_preview/app_screenshot.rb +2 -0
  266. data/tasks/terminal_preview/crash_report.rb +2 -0
  267. data/tasks/terminal_preview/example_app.rb +2 -0
  268. data/tasks/terminal_preview/launcher_script.rb +2 -0
  269. data/tasks/terminal_preview/preview_collection.rb +2 -0
  270. data/tasks/terminal_preview/preview_timing.rb +2 -0
  271. data/tasks/terminal_preview/safety_confirmation.rb +2 -0
  272. data/tasks/terminal_preview/saved_screenshot.rb +2 -0
  273. data/tasks/terminal_preview/system_appearance.rb +2 -0
  274. data/tasks/terminal_preview/terminal_window.rb +2 -0
  275. data/tasks/terminal_preview/window_id.rb +2 -0
  276. data/tasks/terminal_preview.rake +2 -0
  277. data/tasks/test.rake +2 -0
  278. data/tasks/website/index_page.rb +2 -0
  279. data/tasks/website/version.rb +12 -2
  280. data/tasks/website/version_menu.rb +2 -0
  281. data/tasks/website/versioned_documentation.rb +2 -0
  282. data/tasks/website/website.rb +2 -0
  283. data/tasks/website.rake +2 -0
  284. metadata +97 -75
  285. data/doc/contributors/architectural_overhaul/chat_conversations.md +0 -4952
  286. data/doc/contributors/architectural_overhaul/implementation_plan.md +0 -60
  287. data/doc/contributors/architectural_overhaul/task.md +0 -37
  288. /data/doc/{async.md → concepts/async.md} +0 -0
  289. /data/doc/{interactive_design.md → concepts/interactive_design.md} +0 -0
  290. /data/doc/images/{widget_barchart_demo.png → widget_barchart.png} +0 -0
  291. /data/doc/images/{widget_block_demo.png → widget_block.png} +0 -0
  292. /data/doc/images/{widget_box_demo.png → widget_box.png} +0 -0
  293. /data/doc/images/{widget_calendar_demo.png → widget_calendar.png} +0 -0
  294. /data/doc/images/{widget_canvas_demo.png → widget_canvas.png} +0 -0
  295. /data/doc/images/{widget_cell_demo.png → widget_cell.png} +0 -0
  296. /data/doc/images/{widget_center_demo.png → widget_center.png} +0 -0
  297. /data/doc/images/{widget_chart_demo.png → widget_chart.png} +0 -0
  298. /data/doc/images/{widget_gauge_demo.png → widget_gauge.png} +0 -0
  299. /data/doc/images/{widget_line_gauge_demo.png → widget_line_gauge.png} +0 -0
  300. /data/doc/images/{widget_list_demo.png → widget_list.png} +0 -0
  301. /data/doc/images/{widget_map_demo.png → widget_map.png} +0 -0
  302. /data/doc/images/{widget_overlay_demo.png → widget_overlay.png} +0 -0
  303. /data/doc/images/{widget_popup_demo.png → widget_popup.png} +0 -0
  304. /data/doc/images/{widget_ratatui_logo_demo.png → widget_ratatui_logo.png} +0 -0
  305. /data/doc/images/{widget_ratatui_mascot_demo.png → widget_ratatui_mascot.png} +0 -0
  306. /data/doc/images/{widget_scrollbar_demo.png → widget_scrollbar.png} +0 -0
  307. /data/doc/images/{widget_sparkline_demo.png → widget_sparkline.png} +0 -0
  308. /data/doc/images/{widget_table_demo.png → widget_table.png} +0 -0
  309. /data/doc/images/{widget_tabs_demo.png → widget_tabs.png} +0 -0
  310. /data/doc/{v0.7.0_migration.md → migration/v0_7_0.md} +0 -0
  311. /data/doc/{debugging.md → troubleshooting/debugging.md} +0 -0
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
9
  require "bundler/setup"
@@ -18,7 +20,7 @@ PROCESSES = [
18
20
  { pid: 6789, name: "node", cpu: 18.9 },
19
21
  ].freeze
20
22
 
21
- class WidgetTableDemo
23
+ class WidgetTable
22
24
  attr_reader :selected_index, :selected_col, :current_style_index, :column_spacing, :highlight_spacing, :column_highlight_style, :cell_highlight_style
23
25
 
24
26
  HIGHLIGHT_SPACINGS = [
@@ -250,5 +252,5 @@ class WidgetTableDemo
250
252
  end
251
253
 
252
254
  if __FILE__ == $0
253
- WidgetTableDemo.new.run
255
+ WidgetTable.new.run
254
256
  end
@@ -5,7 +5,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0
5
5
 
6
6
  # Tabs Widget Example
7
7
 
8
- [![widget_tabs_demo](../../doc/images/widget_tabs_demo.png)](app.rb)
8
+ [![widget_tabs](../../doc/images/widget_tabs.png)](app.rb)
9
9
 
10
10
  Demonstrates view segregation with interactive navigation.
11
11
 
@@ -30,12 +30,15 @@ Screen real estate is limited. You cannot show everything at once. Tabs segregat
30
30
  ## Usage
31
31
 
32
32
  ```bash
33
- ruby examples/widget_tabs_demo/app.rb
33
+ ruby examples/widget_tabs/app.rb
34
34
  ```
35
35
 
36
36
  ## Learning Outcomes
37
37
 
38
38
  Use this example if you need to...
39
+
39
40
  - Build a multi-pane dashboard.
40
41
  - Create a "Settings" screen with different categories.
41
- - Implement a "wizard" interface with steps.
42
+ - Implement a "wizard" interface with steps.
43
+
44
+ [Read the source code →](app.rb)
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
9
  require "ratatui_ruby"
@@ -19,10 +21,10 @@ require "faker"
19
21
  #
20
22
  # Run the demo from the terminal:
21
23
  #
22
- # ruby examples/widget_tabs_demo/app.rb
24
+ # ruby examples/widget_tabs/app.rb
23
25
  #
24
- # rdoc-image:/doc/images/widget_tabs_demo.png
25
- class WidgetTabsDemo
26
+ # rdoc-image:/doc/images/widget_tabs.png
27
+ class WidgetTabs
26
28
  def initialize
27
29
  @selected_tab = 0
28
30
  @tabs = ["Revenue", "Traffic", "Errors", "Quarterly"]
@@ -93,7 +95,7 @@ class WidgetTabsDemo
93
95
  tabs = @tui.tabs(
94
96
  titles: @tabs,
95
97
  selected_index: @selected_tab,
96
- block: @tui.block(title: "Tabs Demo", borders: [:all]),
98
+ block: @tui.block(title: "Tabs", borders: [:all]),
97
99
  divider: @dividers[@divider_index],
98
100
  highlight_style: @highlight_styles[@highlight_style_index][:style],
99
101
  style: @base_styles[@base_style_index][:style],
@@ -178,4 +180,4 @@ class WidgetTabsDemo
178
180
  end
179
181
  end
180
182
 
181
- WidgetTabsDemo.new.run if __FILE__ == $0
183
+ WidgetTabs.new.run if __FILE__ == $0
@@ -3,7 +3,7 @@ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
3
  SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
 
6
- # Text Width Calculator
6
+ # Text Width (Unicode Width) Calculator
7
7
 
8
8
  [![widget_text_width](../../doc/images/widget_text_width.png)](app.rb)
9
9
 
@@ -30,6 +30,9 @@ ruby examples/widget_text_width/app.rb
30
30
  ## Learning Outcomes
31
31
 
32
32
  Use this example if you need to...
33
+
33
34
  - Align text correctly in columns.
34
35
  - Truncate strings that are too long for a widget.
35
- - Build your own custom layout engine.
36
+ - Build your own custom layout engine.
37
+
38
+ [Read the source code →](app.rb)
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
7
9
  require "ratatui_ruby"
data/exe/.gitkeep CHANGED
File without changes
@@ -1012,7 +1012,7 @@ dependencies = [
1012
1012
 
1013
1013
  [[package]]
1014
1014
  name = "ratatui_ruby"
1015
- version = "0.7.1"
1015
+ version = "0.7.3"
1016
1016
  dependencies = [
1017
1017
  "bumpalo",
1018
1018
  "lazy_static",
@@ -3,7 +3,7 @@
3
3
 
4
4
  [package]
5
5
  name = "ratatui_ruby"
6
- version = "0.7.1"
6
+ version = "0.7.3"
7
7
  edition = "2021"
8
8
 
9
9
  [lib]
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  require "mkmf"
7
9
  require "rb_sys/mkmf"
@@ -121,7 +121,7 @@ fn init() -> Result<(), Error> {
121
121
  let m = ruby.define_module("RatatuiRuby")?;
122
122
 
123
123
  m.define_module_function("_init_terminal", function!(init_terminal, 2))?;
124
- m.define_module_function("restore_terminal", function!(restore_terminal, 0))?;
124
+ m.define_module_function("_restore_terminal", function!(restore_terminal, 0))?;
125
125
  m.define_module_function("_draw", function!(draw, -1))?;
126
126
 
127
127
  // Register Frame class
@@ -147,7 +147,7 @@ fn init() -> Result<(), Error> {
147
147
 
148
148
  // Test backend helpers
149
149
  m.define_module_function(
150
- "init_test_terminal",
150
+ "_init_test_terminal",
151
151
  function!(terminal::init_test_terminal, 2),
152
152
  )?;
153
153
  m.define_module_function(
@@ -60,6 +60,15 @@ pub fn render_node(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Err
60
60
  "RatatuiRuby::Widgets::RatatuiMascot" => {
61
61
  widgets::ratatui_mascot::render_ratatui_mascot(frame, area, node)?;
62
62
  }
63
+ // Text primitives can also be rendered directly as widgets
64
+ "RatatuiRuby::Text::Line" => {
65
+ let line = crate::text::parse_line(node)?;
66
+ frame.render_widget(line, area);
67
+ }
68
+ "RatatuiRuby::Text::Span" => {
69
+ let span = crate::text::parse_span(node)?;
70
+ frame.render_widget(span, area);
71
+ }
63
72
  _ => {}
64
73
  }
65
74
  Ok(())
@@ -171,8 +171,28 @@ pub fn parse_border_set<'a>(
171
171
 
172
172
  pub fn parse_bar_set<'a>(set_val: Value, bump: &'a Bump) -> Result<symbols::bar::Set<'a>, Error> {
173
173
  let ruby = magnus::Ruby::get().unwrap();
174
- let hash = magnus::RHash::from_value(set_val)
175
- .ok_or_else(|| Error::new(ruby.exception_type_error(), "expected hash for bar_set"))?;
174
+
175
+ // Check if set_val is a symbol shortcut
176
+ if let Ok(sym) = magnus::Symbol::from_value(set_val)
177
+ .ok_or::<Error>(Error::new(ruby.exception_type_error(), ""))
178
+ {
179
+ let sym_str = sym.name().unwrap_or_default();
180
+ return match sym_str.as_ref() {
181
+ "nine_levels" => Ok(symbols::bar::NINE_LEVELS),
182
+ "three_levels" => Ok(symbols::bar::THREE_LEVELS),
183
+ _ => Err(Error::new(
184
+ ruby.exception_arg_error(),
185
+ format!("unknown bar_set symbol: :{sym_str}"),
186
+ )),
187
+ };
188
+ }
189
+
190
+ let hash = magnus::RHash::from_value(set_val).ok_or_else(|| {
191
+ Error::new(
192
+ ruby.exception_type_error(),
193
+ "expected symbol or hash for bar_set",
194
+ )
195
+ })?;
176
196
 
177
197
  let get_char = |key: &str| -> Result<Option<&'a str>, Error> {
178
198
  let mut val: Value = hash
@@ -133,6 +133,8 @@ pub fn parse_line(value: Value) -> Result<Line<'static>, Error> {
133
133
  let spans_val: Value = value.funcall("spans", ())?;
134
134
  // v0.7.0: Extract style from the Ruby Line
135
135
  let style_val: Value = value.funcall("style", ())?;
136
+ // Extract alignment from the Ruby Line
137
+ let alignment_val: Value = value.funcall("alignment", ())?;
136
138
 
137
139
  if spans_val.is_nil() {
138
140
  return Ok(Line::from(""));
@@ -177,6 +179,30 @@ pub fn parse_line(value: Value) -> Result<Line<'static>, Error> {
177
179
  line = line.style(parse_style(style_val)?);
178
180
  }
179
181
 
182
+ // Apply alignment if present
183
+ if !alignment_val.is_nil() {
184
+ if let Ok(alignment_sym) = magnus::Symbol::try_convert(alignment_val) {
185
+ let alignment_str = alignment_sym.name().map_err(|e| {
186
+ Error::new(
187
+ ruby.exception_type_error(),
188
+ format!("Invalid alignment symbol: {e}"),
189
+ )
190
+ })?;
191
+ let alignment = match alignment_str.as_ref() {
192
+ "left" => ratatui::layout::Alignment::Left,
193
+ "center" => ratatui::layout::Alignment::Center,
194
+ "right" => ratatui::layout::Alignment::Right,
195
+ _ => {
196
+ return Err(Error::new(
197
+ ruby.exception_arg_error(),
198
+ format!("Invalid alignment: {alignment_str}. Valid values: :left, :center, :right"),
199
+ ));
200
+ }
201
+ };
202
+ line = line.alignment(alignment);
203
+ }
204
+ }
205
+
180
206
  Ok(line)
181
207
  }
182
208
 
@@ -48,12 +48,14 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
48
48
  let group_obj: Value = array.entry(index)?;
49
49
 
50
50
  let label_val: Value = group_obj.funcall("label", ())?;
51
- let label_str: String = if label_val.is_nil() {
52
- String::new()
51
+ let group_label: Line = if label_val.is_nil() {
52
+ Line::from("")
53
+ } else if let Ok(line) = parse_line(label_val) {
54
+ line
53
55
  } else {
54
- label_val.funcall("to_s", ())?
56
+ let label_str: String = label_val.funcall("to_s", ())?;
57
+ Line::from(label_str)
55
58
  };
56
- let label_ref = bump.alloc_str(&label_str) as &str;
57
59
 
58
60
  let bars_array: RArray = group_obj.funcall("bars", ())?;
59
61
  let mut bars: Vec<Bar> = Vec::new();
@@ -110,8 +112,8 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
110
112
  }
111
113
 
112
114
  let mut group = BarGroup::new(bars);
113
- if !label_ref.is_empty() {
114
- group = group.label(Line::from(label_ref));
115
+ if !group_label.spans.is_empty() {
116
+ group = group.label(group_label);
115
117
  }
116
118
  bar_chart = bar_chart.data(group);
117
119
  }
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: AGPL-3.0-or-later
3
3
 
4
4
  use crate::style::{parse_block, parse_style};
5
+ use crate::text::parse_line;
5
6
  use bumpalo::Bump;
6
7
  use magnus::{prelude::*, Error, Symbol, Value};
7
8
  use ratatui::{
@@ -12,6 +13,7 @@ use ratatui::{
12
13
  Frame,
13
14
  };
14
15
 
16
+ #[allow(clippy::too_many_lines)]
15
17
  pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
16
18
  let bump = Bump::new();
17
19
  let ruby = magnus::Ruby::get().unwrap();
@@ -59,7 +61,13 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
59
61
  let index = isize::try_from(i)
60
62
  .map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
61
63
  let ds_val: Value = datasets_val.entry(index)?;
62
- let name: String = ds_val.funcall("name", ())?;
64
+ let name_val: Value = ds_val.funcall("name", ())?;
65
+ let name = if let Ok(line) = parse_line(name_val) {
66
+ line
67
+ } else {
68
+ let name_str: String = name_val.funcall("to_s", ())?;
69
+ ratatui::text::Line::from(name_str)
70
+ };
63
71
  let marker_sym: Symbol = ds_val.funcall("marker", ())?;
64
72
  let graph_type_sym: Symbol = ds_val.funcall("graph_type", ())?;
65
73
 
@@ -67,6 +75,7 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
67
75
  "braille" => symbols::Marker::Braille,
68
76
  "block" => symbols::Marker::Block,
69
77
  "bar" => symbols::Marker::Bar,
78
+ "half_block" => symbols::Marker::HalfBlock,
70
79
  _ => symbols::Marker::Dot,
71
80
  };
72
81
 
@@ -107,8 +116,12 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
107
116
  let pos_sym: Symbol = legend_position_val.funcall("to_sym", ())?;
108
117
  let pos = match pos_sym.to_string().as_str() {
109
118
  "top_left" => LegendPosition::TopLeft,
119
+ "top" => LegendPosition::Top,
110
120
  "bottom_left" => LegendPosition::BottomLeft,
121
+ "bottom" => LegendPosition::Bottom,
111
122
  "bottom_right" => LegendPosition::BottomRight,
123
+ "left" => LegendPosition::Left,
124
+ "right" => LegendPosition::Right,
112
125
  _ => LegendPosition::TopRight,
113
126
  };
114
127
  chart = chart.legend_position(Some(pos));
@@ -132,7 +145,15 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
132
145
 
133
146
  fn parse_axis(axis_val: Value) -> Result<Axis<'static>, Error> {
134
147
  let ruby = magnus::Ruby::get().unwrap();
135
- let title: String = axis_val.funcall("title", ())?;
148
+ let title_val: Value = axis_val.funcall("title", ())?;
149
+ let title = if title_val.is_nil() {
150
+ ratatui::text::Line::from("")
151
+ } else if let Ok(line) = parse_line(title_val) {
152
+ line
153
+ } else {
154
+ let title_str: String = title_val.funcall("to_s", ())?;
155
+ ratatui::text::Line::from(title_str)
156
+ };
136
157
  let bounds_val: magnus::RArray = axis_val.funcall("bounds", ())?;
137
158
  let labels_val: magnus::RArray = axis_val.funcall("labels", ())?;
138
159
  let style_val: Value = axis_val.funcall("style", ())?;
@@ -144,8 +165,14 @@ fn parse_axis(axis_val: Value) -> Result<Axis<'static>, Error> {
144
165
  for i in 0..labels_val.len() {
145
166
  let index = isize::try_from(i)
146
167
  .map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
147
- let label: String = labels_val.entry(index)?;
148
- labels.push(Span::from(label));
168
+ let entry_val: Value = labels_val.entry(index)?;
169
+ let label = if let Ok(line) = parse_line(entry_val) {
170
+ line
171
+ } else {
172
+ let label_str: String = entry_val.funcall("to_s", ())?;
173
+ ratatui::text::Line::from(label_str)
174
+ };
175
+ labels.push(label);
149
176
  }
150
177
 
151
178
  let mut axis = Axis::default().title(title).bounds(bounds).labels(labels);
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: AGPL-3.0-or-later
3
3
 
4
4
  use crate::style::{parse_block, parse_style};
5
- use crate::text::{parse_line, parse_span};
5
+ use crate::text::{parse_line, parse_span, parse_text};
6
6
  use crate::widgets::table_state::RubyTableState;
7
7
  use bumpalo::Bump;
8
8
  use magnus::{prelude::*, Error, Symbol, TryConvert, Value};
@@ -87,8 +87,12 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
87
87
  }
88
88
 
89
89
  if !highlight_symbol_val.is_nil() {
90
- let symbol: String = highlight_symbol_val.funcall("to_s", ())?;
91
- table = table.highlight_symbol(symbol);
90
+ if let Ok(text) = parse_text(highlight_symbol_val) {
91
+ table = table.highlight_symbol(ratatui::text::Text::from(text));
92
+ } else {
93
+ let symbol: String = highlight_symbol_val.funcall("to_s", ())?;
94
+ table = table.highlight_symbol(symbol);
95
+ }
92
96
  }
93
97
 
94
98
  let style_val: Value = node.funcall("style", ())?;
@@ -207,8 +211,12 @@ pub fn render_stateful(
207
211
  table = table.cell_highlight_style(parse_style(cell_highlight_style_val)?);
208
212
  }
209
213
  if !highlight_symbol_val.is_nil() {
210
- let symbol: String = highlight_symbol_val.funcall("to_s", ())?;
211
- table = table.highlight_symbol(symbol);
214
+ if let Ok(text) = parse_text(highlight_symbol_val) {
215
+ table = table.highlight_symbol(ratatui::text::Text::from(text));
216
+ } else {
217
+ let symbol: String = highlight_symbol_val.funcall("to_s", ())?;
218
+ table = table.highlight_symbol(symbol);
219
+ }
212
220
  }
213
221
  if !style_val.is_nil() {
214
222
  table = table.style(parse_style(style_val)?);
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: AGPL-3.0-or-later
3
3
 
4
4
  use crate::style::parse_block;
5
+ use crate::text::{parse_line, parse_span};
5
6
  use bumpalo::Bump;
6
7
  use magnus::{prelude::*, Error, Value};
7
8
  use ratatui::{layout::Rect, text::Line, widgets::Tabs, Frame};
@@ -13,7 +14,39 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
13
14
  Ok(())
14
15
  }
15
16
 
16
- use crate::text::parse_line;
17
+ /// Parses padding value with duck-typing support:
18
+ /// - Integer: generates that many spaces
19
+ /// - Line: uses styled Line directly
20
+ /// - Span: wraps in Line
21
+ /// - String or `to_s` responder: converts to Line
22
+ fn parse_padding(val: Value) -> Result<Line<'static>, Error> {
23
+ // Handle nil or zero
24
+ if val.is_nil() {
25
+ return Ok(Line::from(""));
26
+ }
27
+
28
+ // Try as Integer first (most common case)
29
+ if let Ok(n) = usize::try_convert(val) {
30
+ if n == 0 {
31
+ return Ok(Line::from(""));
32
+ }
33
+ return Ok(Line::from(" ".repeat(n)));
34
+ }
35
+
36
+ // Try to parse as Line
37
+ if let Ok(line) = parse_line(val) {
38
+ return Ok(line);
39
+ }
40
+
41
+ // Try to parse as Span (wrap in Line)
42
+ if let Ok(span) = parse_span(val) {
43
+ return Ok(Line::from(vec![span]));
44
+ }
45
+
46
+ // Fallback: call to_s and convert to Line
47
+ let s: String = val.funcall("to_s", ())?;
48
+ Ok(Line::from(s))
49
+ }
17
50
 
18
51
  fn create_tabs(node: Value, bump: &Bump) -> Result<Tabs<'_>, Error> {
19
52
  let ruby = magnus::Ruby::get().unwrap();
@@ -22,8 +55,8 @@ fn create_tabs(node: Value, bump: &Bump) -> Result<Tabs<'_>, Error> {
22
55
  let block_val: Value = node.funcall("block", ())?;
23
56
  let divider_val: Value = node.funcall("divider", ())?;
24
57
  let highlight_style_val: Value = node.funcall("highlight_style", ())?;
25
- let padding_left: usize = node.funcall("padding_left", ())?;
26
- let padding_right: usize = node.funcall("padding_right", ())?;
58
+ let padding_left_val: Value = node.funcall("padding_left", ())?;
59
+ let padding_right_val: Value = node.funcall("padding_right", ())?;
27
60
 
28
61
  let titles_array = magnus::RArray::from_value(titles_val)
29
62
  .ok_or_else(|| Error::new(ruby.exception_type_error(), "expected array for titles"))?;
@@ -44,8 +77,12 @@ fn create_tabs(node: Value, bump: &Bump) -> Result<Tabs<'_>, Error> {
44
77
  let mut tabs = Tabs::new(titles).select(selected_index);
45
78
 
46
79
  if !divider_val.is_nil() {
47
- let divider: String = divider_val.funcall("to_s", ())?;
48
- tabs = tabs.divider(divider);
80
+ if let Ok(span) = parse_span(divider_val) {
81
+ tabs = tabs.divider(span);
82
+ } else {
83
+ let divider: String = divider_val.funcall("to_s", ())?;
84
+ tabs = tabs.divider(divider);
85
+ }
49
86
  }
50
87
 
51
88
  if !highlight_style_val.is_nil() {
@@ -62,10 +99,11 @@ fn create_tabs(node: Value, bump: &Bump) -> Result<Tabs<'_>, Error> {
62
99
  tabs = tabs.block(parse_block(block_val, bump)?);
63
100
  }
64
101
 
65
- if padding_left > 0 || padding_right > 0 {
66
- let left_str = " ".repeat(padding_left);
67
- let right_str = " ".repeat(padding_right);
68
- tabs = tabs.padding(left_str, right_str);
102
+ // Handle duck-typed padding: Integer (spaces), String, Line, or anything with to_s
103
+ let left_padding = parse_padding(padding_left_val)?;
104
+ let right_padding = parse_padding(padding_right_val)?;
105
+ if !left_padding.spans.is_empty() || !right_padding.spans.is_empty() {
106
+ tabs = tabs.padding(left_padding, right_padding);
69
107
  }
70
108
 
71
109
  Ok(tabs)
@@ -101,6 +139,8 @@ pub fn width(node: Value) -> Result<usize, Error> {
101
139
  if titles_count > 1 {
102
140
  let divider_width = if divider_val.is_nil() {
103
141
  1 // Default divider is "|"
142
+ } else if let Ok(span) = parse_span(divider_val) {
143
+ span.width()
104
144
  } else {
105
145
  let d: String = divider_val.funcall("to_s", ())?;
106
146
  ratatui::text::Span::raw(d).width()
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  module Buffer
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  # Buffer primitives for terminal cell inspection.
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  # Represents a single cell in the terminal buffer.
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  require_relative "key/character"
7
9
  require_relative "key/media"
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #--
3
4
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
5
7
 
6
8
  module RatatuiRuby
7
9
  class Event