ratatui_ruby 1.4.0-x86_64-linux
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.
- checksums.yaml +7 -0
- data/LICENSE +15 -0
- data/LICENSES/AGPL-3.0-or-later.txt +661 -0
- data/LICENSES/CC-BY-SA-4.0.txt +427 -0
- data/LICENSES/CC0-1.0.txt +121 -0
- data/LICENSES/LGPL-3.0-or-later.txt +304 -0
- data/LICENSES/MIT-0.txt +16 -0
- data/LICENSES/MIT.txt +21 -0
- data/REUSE.toml +42 -0
- data/exe/.gitkeep +0 -0
- data/ext/ratatui_ruby/.cargo/config.toml +13 -0
- data/ext/ratatui_ruby/.gitignore +4 -0
- data/ext/ratatui_ruby/Cargo.lock +1737 -0
- data/ext/ratatui_ruby/Cargo.toml +24 -0
- data/ext/ratatui_ruby/clippy.toml +7 -0
- data/ext/ratatui_ruby/extconf.rb +21 -0
- data/ext/ratatui_ruby/src/color.rs +82 -0
- data/ext/ratatui_ruby/src/errors.rs +28 -0
- data/ext/ratatui_ruby/src/events.rs +700 -0
- data/ext/ratatui_ruby/src/frame.rs +241 -0
- data/ext/ratatui_ruby/src/lib.rs +343 -0
- data/ext/ratatui_ruby/src/lib_header.rs +11 -0
- data/ext/ratatui_ruby/src/rendering.rs +158 -0
- data/ext/ratatui_ruby/src/string_width.rs +101 -0
- data/ext/ratatui_ruby/src/style.rs +469 -0
- data/ext/ratatui_ruby/src/terminal/capabilities.rs +46 -0
- data/ext/ratatui_ruby/src/terminal/init.rs +233 -0
- data/ext/ratatui_ruby/src/terminal/mod.rs +42 -0
- data/ext/ratatui_ruby/src/terminal/mutations.rs +158 -0
- data/ext/ratatui_ruby/src/terminal/queries.rs +231 -0
- data/ext/ratatui_ruby/src/terminal/query.rs +400 -0
- data/ext/ratatui_ruby/src/terminal/storage.rs +109 -0
- data/ext/ratatui_ruby/src/terminal/wrapper.rs +16 -0
- data/ext/ratatui_ruby/src/text.rs +225 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +169 -0
- data/ext/ratatui_ruby/src/widgets/block.rs +41 -0
- data/ext/ratatui_ruby/src/widgets/calendar.rs +84 -0
- data/ext/ratatui_ruby/src/widgets/canvas.rs +183 -0
- data/ext/ratatui_ruby/src/widgets/center.rs +79 -0
- data/ext/ratatui_ruby/src/widgets/chart.rs +222 -0
- data/ext/ratatui_ruby/src/widgets/clear.rs +39 -0
- data/ext/ratatui_ruby/src/widgets/cursor.rs +32 -0
- data/ext/ratatui_ruby/src/widgets/gauge.rs +65 -0
- data/ext/ratatui_ruby/src/widgets/layout.rs +379 -0
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +100 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +378 -0
- data/ext/ratatui_ruby/src/widgets/list_state.rs +173 -0
- data/ext/ratatui_ruby/src/widgets/mod.rs +26 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +24 -0
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +87 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +40 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +55 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +214 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar_state.rs +169 -0
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +127 -0
- data/ext/ratatui_ruby/src/widgets/table.rs +415 -0
- data/ext/ratatui_ruby/src/widgets/table_state.rs +203 -0
- data/ext/ratatui_ruby/src/widgets/tabs.rs +194 -0
- data/lib/ratatui_ruby/backend/window_size.rb +50 -0
- data/lib/ratatui_ruby/backend.rb +59 -0
- data/lib/ratatui_ruby/buffer/cell.rb +212 -0
- data/lib/ratatui_ruby/buffer.rb +149 -0
- data/lib/ratatui_ruby/cell.rb +208 -0
- data/lib/ratatui_ruby/debug.rb +215 -0
- data/lib/ratatui_ruby/draw.rb +63 -0
- data/lib/ratatui_ruby/event/focus_gained.rb +125 -0
- data/lib/ratatui_ruby/event/focus_lost.rb +127 -0
- data/lib/ratatui_ruby/event/key/character.rb +53 -0
- data/lib/ratatui_ruby/event/key/dwim.rb +301 -0
- data/lib/ratatui_ruby/event/key/media.rb +46 -0
- data/lib/ratatui_ruby/event/key/modifier.rb +107 -0
- data/lib/ratatui_ruby/event/key/navigation.rb +72 -0
- data/lib/ratatui_ruby/event/key/system.rb +47 -0
- data/lib/ratatui_ruby/event/key.rb +479 -0
- data/lib/ratatui_ruby/event/mouse.rb +291 -0
- data/lib/ratatui_ruby/event/none.rb +53 -0
- data/lib/ratatui_ruby/event/paste.rb +130 -0
- data/lib/ratatui_ruby/event/resize.rb +221 -0
- data/lib/ratatui_ruby/event/sync.rb +52 -0
- data/lib/ratatui_ruby/event.rb +163 -0
- data/lib/ratatui_ruby/frame.rb +257 -0
- data/lib/ratatui_ruby/labs/a11y.rb +182 -0
- data/lib/ratatui_ruby/labs/frame_a11y_capture.rb +50 -0
- data/lib/ratatui_ruby/labs.rb +47 -0
- data/lib/ratatui_ruby/layout/alignment.rb +91 -0
- data/lib/ratatui_ruby/layout/constraint.rb +337 -0
- data/lib/ratatui_ruby/layout/layout.rb +258 -0
- data/lib/ratatui_ruby/layout/position.rb +81 -0
- data/lib/ratatui_ruby/layout/rect.rb +733 -0
- data/lib/ratatui_ruby/layout/size.rb +62 -0
- data/lib/ratatui_ruby/layout.rb +29 -0
- data/lib/ratatui_ruby/list_state.rb +201 -0
- data/lib/ratatui_ruby/output_guard.rb +171 -0
- data/lib/ratatui_ruby/ratatui_ruby.so +0 -0
- data/lib/ratatui_ruby/scrollbar_state.rb +122 -0
- data/lib/ratatui_ruby/style/color.rb +149 -0
- data/lib/ratatui_ruby/style/style.rb +147 -0
- data/lib/ratatui_ruby/style.rb +19 -0
- data/lib/ratatui_ruby/symbols.rb +435 -0
- data/lib/ratatui_ruby/synthetic_events.rb +106 -0
- data/lib/ratatui_ruby/table_state.rb +251 -0
- data/lib/ratatui_ruby/terminal/capabilities.rb +316 -0
- data/lib/ratatui_ruby/terminal/viewport.rb +80 -0
- data/lib/ratatui_ruby/terminal.rb +66 -0
- data/lib/ratatui_ruby/terminal_lifecycle.rb +303 -0
- data/lib/ratatui_ruby/terminal_lifecycle.rb.bak +197 -0
- data/lib/ratatui_ruby/test_helper/event_injection.rb +241 -0
- data/lib/ratatui_ruby/test_helper/global_state.rb +111 -0
- data/lib/ratatui_ruby/test_helper/snapshot.rb +568 -0
- data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.ansi +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.txt +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.ansi +5 -0
- data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.txt +5 -0
- data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.ansi +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.txt +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/my_snapshot.txt +1 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.ansi +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.txt +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.ansi +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.txt +10 -0
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +449 -0
- data/lib/ratatui_ruby/test_helper/subprocess_timeout.rb +35 -0
- data/lib/ratatui_ruby/test_helper/terminal.rb +187 -0
- data/lib/ratatui_ruby/test_helper/test_doubles.rb +86 -0
- data/lib/ratatui_ruby/test_helper.rb +115 -0
- data/lib/ratatui_ruby/text/line.rb +245 -0
- data/lib/ratatui_ruby/text/span.rb +158 -0
- data/lib/ratatui_ruby/text.rb +99 -0
- data/lib/ratatui_ruby/tui/buffer_factories.rb +22 -0
- data/lib/ratatui_ruby/tui/canvas_factories.rb +149 -0
- data/lib/ratatui_ruby/tui/core.rb +67 -0
- data/lib/ratatui_ruby/tui/layout_factories.rb +153 -0
- data/lib/ratatui_ruby/tui/state_factories.rb +77 -0
- data/lib/ratatui_ruby/tui/style_factories.rb +22 -0
- data/lib/ratatui_ruby/tui/text_factories.rb +86 -0
- data/lib/ratatui_ruby/tui/widget_factories.rb +272 -0
- data/lib/ratatui_ruby/tui.rb +106 -0
- data/lib/ratatui_ruby/version.rb +12 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +51 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +29 -0
- data/lib/ratatui_ruby/widgets/bar_chart.rb +308 -0
- data/lib/ratatui_ruby/widgets/block.rb +266 -0
- data/lib/ratatui_ruby/widgets/calendar.rb +88 -0
- data/lib/ratatui_ruby/widgets/canvas.rb +297 -0
- data/lib/ratatui_ruby/widgets/cell.rb +59 -0
- data/lib/ratatui_ruby/widgets/center.rb +71 -0
- data/lib/ratatui_ruby/widgets/chart.rb +172 -0
- data/lib/ratatui_ruby/widgets/clear.rb +66 -0
- data/lib/ratatui_ruby/widgets/coerceable_widget.rb +77 -0
- data/lib/ratatui_ruby/widgets/cursor.rb +54 -0
- data/lib/ratatui_ruby/widgets/gauge.rb +146 -0
- data/lib/ratatui_ruby/widgets/line_gauge.rb +158 -0
- data/lib/ratatui_ruby/widgets/list.rb +252 -0
- data/lib/ratatui_ruby/widgets/list_item.rb +55 -0
- data/lib/ratatui_ruby/widgets/overlay.rb +55 -0
- data/lib/ratatui_ruby/widgets/paragraph.rb +113 -0
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +35 -0
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +40 -0
- data/lib/ratatui_ruby/widgets/row.rb +123 -0
- data/lib/ratatui_ruby/widgets/scrollbar.rb +147 -0
- data/lib/ratatui_ruby/widgets/shape/label.rb +80 -0
- data/lib/ratatui_ruby/widgets/sparkline.rb +153 -0
- data/lib/ratatui_ruby/widgets/table.rb +213 -0
- data/lib/ratatui_ruby/widgets/tabs.rb +91 -0
- data/lib/ratatui_ruby/widgets.rb +43 -0
- data/lib/ratatui_ruby.rb +555 -0
- data/sig/examples/app_all_events/app.rbs +11 -0
- data/sig/examples/app_all_events/model/app_model.rbs +23 -0
- data/sig/examples/app_all_events/model/event_entry.rbs +23 -0
- data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
- data/sig/examples/app_all_events/view/app_view.rbs +8 -0
- data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
- data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
- data/sig/examples/app_all_events/view/live_view.rbs +6 -0
- data/sig/examples/app_all_events/view/log_view.rbs +6 -0
- data/sig/examples/app_all_events/view.rbs +14 -0
- data/sig/examples/app_cli_rich_moments/app.rbs +12 -0
- data/sig/examples/app_color_picker/app.rbs +17 -0
- data/sig/examples/app_external_editor/app.rbs +12 -0
- data/sig/examples/app_login_form/app.rbs +11 -0
- data/sig/examples/app_stateful_interaction/app.rbs +39 -0
- data/sig/examples/verify_quickstart_dsl/app.rbs +17 -0
- data/sig/examples/verify_quickstart_lifecycle/app.rbs +17 -0
- data/sig/examples/verify_readme_usage/app.rbs +17 -0
- data/sig/examples/widget_block_demo/app.rbs +38 -0
- data/sig/examples/widget_box_demo/app.rbs +17 -0
- data/sig/examples/widget_calendar_demo/app.rbs +17 -0
- data/sig/examples/widget_cell_demo/app.rbs +17 -0
- data/sig/examples/widget_chart_demo/app.rbs +17 -0
- data/sig/examples/widget_gauge_demo/app.rbs +17 -0
- data/sig/examples/widget_layout_split/app.rbs +16 -0
- data/sig/examples/widget_line_gauge_demo/app.rbs +17 -0
- data/sig/examples/widget_list_demo/app.rbs +17 -0
- data/sig/examples/widget_map_demo/app.rbs +17 -0
- data/sig/examples/widget_popup_demo/app.rbs +17 -0
- data/sig/examples/widget_ratatui_logo_demo/app.rbs +17 -0
- data/sig/examples/widget_ratatui_mascot_demo/app.rbs +17 -0
- data/sig/examples/widget_rect/app.rbs +18 -0
- data/sig/examples/widget_render/app.rbs +16 -0
- data/sig/examples/widget_rich_text/app.rbs +17 -0
- data/sig/examples/widget_scroll_text/app.rbs +17 -0
- data/sig/examples/widget_scrollbar_demo/app.rbs +17 -0
- data/sig/examples/widget_sparkline_demo/app.rbs +16 -0
- data/sig/examples/widget_style_colors/app.rbs +20 -0
- data/sig/examples/widget_table_demo/app.rbs +17 -0
- data/sig/examples/widget_text_width/app.rbs +16 -0
- data/sig/generated/event_key_predicates.rbs +1348 -0
- data/sig/manifest.yaml +5 -0
- data/sig/patches/data.rbs +26 -0
- data/sig/patches/debugger__.rbs +8 -0
- data/sig/ratatui_ruby/backend/window_size.rbs +17 -0
- data/sig/ratatui_ruby/backend.rbs +12 -0
- data/sig/ratatui_ruby/buffer/cell.rbs +46 -0
- data/sig/ratatui_ruby/buffer.rbs +18 -0
- data/sig/ratatui_ruby/cell.rbs +44 -0
- data/sig/ratatui_ruby/clear.rbs +18 -0
- data/sig/ratatui_ruby/constraint.rbs +26 -0
- data/sig/ratatui_ruby/debug.rbs +45 -0
- data/sig/ratatui_ruby/draw.rbs +30 -0
- data/sig/ratatui_ruby/event.rbs +249 -0
- data/sig/ratatui_ruby/frame.rbs +23 -0
- data/sig/ratatui_ruby/interfaces.rbs +25 -0
- data/sig/ratatui_ruby/labs.rbs +90 -0
- data/sig/ratatui_ruby/layout/alignment.rbs +26 -0
- data/sig/ratatui_ruby/layout/constraint.rbs +39 -0
- data/sig/ratatui_ruby/layout/layout.rbs +45 -0
- data/sig/ratatui_ruby/layout/position.rbs +18 -0
- data/sig/ratatui_ruby/layout/rect.rbs +64 -0
- data/sig/ratatui_ruby/layout/size.rbs +18 -0
- data/sig/ratatui_ruby/list_state.rbs +23 -0
- data/sig/ratatui_ruby/output_guard.rbs +23 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +113 -0
- data/sig/ratatui_ruby/rect.rbs +17 -0
- data/sig/ratatui_ruby/scrollbar_state.rbs +24 -0
- data/sig/ratatui_ruby/session.rbs +93 -0
- data/sig/ratatui_ruby/style/color.rbs +22 -0
- data/sig/ratatui_ruby/style/style.rbs +29 -0
- data/sig/ratatui_ruby/symbols.rbs +141 -0
- data/sig/ratatui_ruby/synthetic_events.rbs +24 -0
- data/sig/ratatui_ruby/table_state.rbs +27 -0
- data/sig/ratatui_ruby/terminal/capabilities.rbs +38 -0
- data/sig/ratatui_ruby/terminal/viewport.rbs +33 -0
- data/sig/ratatui_ruby/terminal_lifecycle.rbs +39 -0
- data/sig/ratatui_ruby/test_helper/event_injection.rbs +22 -0
- data/sig/ratatui_ruby/test_helper/snapshot.rbs +37 -0
- data/sig/ratatui_ruby/test_helper/style_assertions.rbs +77 -0
- data/sig/ratatui_ruby/test_helper/terminal.rbs +20 -0
- data/sig/ratatui_ruby/test_helper/test_doubles.rbs +32 -0
- data/sig/ratatui_ruby/test_helper.rbs +18 -0
- data/sig/ratatui_ruby/text/line.rbs +27 -0
- data/sig/ratatui_ruby/text/span.rbs +23 -0
- data/sig/ratatui_ruby/text.rbs +12 -0
- data/sig/ratatui_ruby/tui/buffer_factories.rbs +16 -0
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +38 -0
- data/sig/ratatui_ruby/tui/core.rbs +23 -0
- data/sig/ratatui_ruby/tui/layout_factories.rbs +39 -0
- data/sig/ratatui_ruby/tui/state_factories.rbs +23 -0
- data/sig/ratatui_ruby/tui/style_factories.rbs +18 -0
- data/sig/ratatui_ruby/tui/text_factories.rbs +23 -0
- data/sig/ratatui_ruby/tui/widget_factories.rbs +138 -0
- data/sig/ratatui_ruby/tui.rbs +25 -0
- data/sig/ratatui_ruby/version.rbs +12 -0
- data/sig/ratatui_ruby/widgets/bar_chart.rbs +95 -0
- data/sig/ratatui_ruby/widgets/block.rbs +51 -0
- data/sig/ratatui_ruby/widgets/calendar.rbs +45 -0
- data/sig/ratatui_ruby/widgets/canvas.rbs +95 -0
- data/sig/ratatui_ruby/widgets/chart.rbs +91 -0
- data/sig/ratatui_ruby/widgets/coerceable_widget.rbs +26 -0
- data/sig/ratatui_ruby/widgets/gauge.rbs +44 -0
- data/sig/ratatui_ruby/widgets/line_gauge.rbs +48 -0
- data/sig/ratatui_ruby/widgets/list.rbs +63 -0
- data/sig/ratatui_ruby/widgets/misc.rbs +158 -0
- data/sig/ratatui_ruby/widgets/paragraph.rbs +45 -0
- data/sig/ratatui_ruby/widgets/row.rbs +43 -0
- data/sig/ratatui_ruby/widgets/scrollbar.rbs +53 -0
- data/sig/ratatui_ruby/widgets/shape/label.rbs +37 -0
- data/sig/ratatui_ruby/widgets/sparkline.rbs +45 -0
- data/sig/ratatui_ruby/widgets/table.rbs +78 -0
- data/sig/ratatui_ruby/widgets/tabs.rbs +44 -0
- data/sig/ratatui_ruby/widgets.rbs +16 -0
- data/vendor/goodcop/base.yml +1047 -0
- metadata +729 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
8
|
+
module RatatuiRuby
|
|
9
|
+
# Experimental lab features.
|
|
10
|
+
module Labs
|
|
11
|
+
@enabled_lab = nil #: Symbol?
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
# Returns whether the specified lab is enabled.
|
|
15
|
+
def enabled?(lab)
|
|
16
|
+
@enabled_lab == lab.to_sym.downcase
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Enables a lab programmatically.
|
|
20
|
+
def enable!(lab)
|
|
21
|
+
@enabled_lab = lab.to_sym.downcase
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Resets all labs (for testing only).
|
|
25
|
+
def reset!
|
|
26
|
+
@enabled_lab = nil
|
|
27
|
+
@warned = false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Emits experimental warning once per session.
|
|
31
|
+
def warn_once!(feature_name)
|
|
32
|
+
return if @warned
|
|
33
|
+
|
|
34
|
+
RatatuiRuby.warn_experimental_feature(feature_name)
|
|
35
|
+
@warned = true
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Auto-enable from environment variable
|
|
42
|
+
if (lab = ENV["RR_LABS"])
|
|
43
|
+
RatatuiRuby::Labs.enable!(lab)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
require_relative "labs/a11y"
|
|
47
|
+
require_relative "labs/frame_a11y_capture"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
8
|
+
module RatatuiRuby
|
|
9
|
+
module Layout
|
|
10
|
+
# Horizontal content alignment within a layout area.
|
|
11
|
+
#
|
|
12
|
+
# Use these constants for discoverability, or pass symbols directly
|
|
13
|
+
# (<tt>:left</tt>, <tt>:center</tt>, <tt>:right</tt>).
|
|
14
|
+
#
|
|
15
|
+
# Mirrors +ratatui::layout::HorizontalAlignment+ from upstream Ratatui.
|
|
16
|
+
#
|
|
17
|
+
# === Example
|
|
18
|
+
#
|
|
19
|
+
#--
|
|
20
|
+
# SPDX-SnippetBegin
|
|
21
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
22
|
+
# SPDX-License-Identifier: MIT-0
|
|
23
|
+
#++
|
|
24
|
+
# # Using constants (discoverable)
|
|
25
|
+
# paragraph = Paragraph.new(
|
|
26
|
+
# text: "Hello",
|
|
27
|
+
# alignment: HorizontalAlignment::CENTER
|
|
28
|
+
# )
|
|
29
|
+
#
|
|
30
|
+
# # Using symbols directly (idiomatic Ruby)
|
|
31
|
+
# paragraph = Paragraph.new(text: "Hello", alignment: :center)
|
|
32
|
+
#--
|
|
33
|
+
# SPDX-SnippetEnd
|
|
34
|
+
#++
|
|
35
|
+
module HorizontalAlignment
|
|
36
|
+
# Align content to the left edge.
|
|
37
|
+
LEFT = :left
|
|
38
|
+
|
|
39
|
+
# Align content to the center.
|
|
40
|
+
CENTER = :center
|
|
41
|
+
|
|
42
|
+
# Align content to the right edge.
|
|
43
|
+
RIGHT = :right
|
|
44
|
+
|
|
45
|
+
# All valid alignment values.
|
|
46
|
+
ALL = [LEFT, CENTER, RIGHT].freeze
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Vertical content alignment within a layout area.
|
|
50
|
+
#
|
|
51
|
+
# Use these constants for discoverability, or pass symbols directly
|
|
52
|
+
# (<tt>:top</tt>, <tt>:center</tt>, <tt>:bottom</tt>).
|
|
53
|
+
#
|
|
54
|
+
# Mirrors +ratatui::layout::VerticalAlignment+ from upstream Ratatui.
|
|
55
|
+
#
|
|
56
|
+
# === Example
|
|
57
|
+
#
|
|
58
|
+
#--
|
|
59
|
+
# SPDX-SnippetBegin
|
|
60
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
61
|
+
# SPDX-License-Identifier: MIT-0
|
|
62
|
+
#++
|
|
63
|
+
# # Using constants (discoverable)
|
|
64
|
+
# widget.vertical_alignment = VerticalAlignment::CENTER
|
|
65
|
+
#
|
|
66
|
+
# # Using symbols directly (idiomatic Ruby)
|
|
67
|
+
# widget.vertical_alignment = :center
|
|
68
|
+
#--
|
|
69
|
+
# SPDX-SnippetEnd
|
|
70
|
+
#++
|
|
71
|
+
module VerticalAlignment
|
|
72
|
+
# Align content to the top edge.
|
|
73
|
+
TOP = :top
|
|
74
|
+
|
|
75
|
+
# Align content to the center.
|
|
76
|
+
CENTER = :center
|
|
77
|
+
|
|
78
|
+
# Align content to the bottom edge.
|
|
79
|
+
BOTTOM = :bottom
|
|
80
|
+
|
|
81
|
+
# All valid alignment values.
|
|
82
|
+
ALL = [TOP, CENTER, BOTTOM].freeze
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Type alias for HorizontalAlignment.
|
|
86
|
+
#
|
|
87
|
+
# Provided for upstream API parity. In Ratatui, +Alignment+ was the
|
|
88
|
+
# original name before +HorizontalAlignment+ was introduced in v0.30.0.
|
|
89
|
+
Alignment = HorizontalAlignment
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
8
|
+
module RatatuiRuby
|
|
9
|
+
module Layout
|
|
10
|
+
# Defines the sizing rule for a layout section.
|
|
11
|
+
#
|
|
12
|
+
# Flexible layouts need rules. You can't just place widgets at absolute coordinates; they must adapt to changing terminal sizes.
|
|
13
|
+
#
|
|
14
|
+
# This class defines the rules of engagement. It tells the layout engine exactly how much space a section requires relative to others.
|
|
15
|
+
#
|
|
16
|
+
# Mix and match fixed lengths, percentages, ratios, and minimums. Build layouts that breathe.
|
|
17
|
+
#
|
|
18
|
+
# === Examples
|
|
19
|
+
#
|
|
20
|
+
#--
|
|
21
|
+
# SPDX-SnippetBegin
|
|
22
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
23
|
+
# SPDX-License-Identifier: MIT-0
|
|
24
|
+
#++
|
|
25
|
+
# Layout::Constraint.length(5) # Exactly 5 cells
|
|
26
|
+
# Layout::Constraint.percentage(50) # Half the available space
|
|
27
|
+
# Layout::Constraint.min(10) # At least 10 cells, maybe more
|
|
28
|
+
# Layout::Constraint.fill(1) # Fill remaining space (weight 1)
|
|
29
|
+
#--
|
|
30
|
+
# SPDX-SnippetEnd
|
|
31
|
+
#++
|
|
32
|
+
class Constraint < Data.define(:type, :value)
|
|
33
|
+
##
|
|
34
|
+
# :attr_reader: type
|
|
35
|
+
# The type of constraint.
|
|
36
|
+
#
|
|
37
|
+
# <tt>:length</tt>, <tt>:percentage</tt>, <tt>:min</tt>, <tt>:max</tt>, <tt>:fill</tt>, or <tt>:ratio</tt>.
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# :attr_reader: value
|
|
41
|
+
# The numeric value (or array for ratio) associated with the rule.
|
|
42
|
+
|
|
43
|
+
# Requests a fixed size.
|
|
44
|
+
#
|
|
45
|
+
#--
|
|
46
|
+
# SPDX-SnippetBegin
|
|
47
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
48
|
+
# SPDX-License-Identifier: MIT-0
|
|
49
|
+
#++
|
|
50
|
+
# Layout::Constraint.length(10) # 10 characters wide/high
|
|
51
|
+
#
|
|
52
|
+
#--
|
|
53
|
+
# SPDX-SnippetEnd
|
|
54
|
+
#++
|
|
55
|
+
# [v] Number of cells (Integer).
|
|
56
|
+
def self.length(v)
|
|
57
|
+
new(type: :length, value: Integer(v))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Requests a percentage of available space.
|
|
61
|
+
#
|
|
62
|
+
#--
|
|
63
|
+
# SPDX-SnippetBegin
|
|
64
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
65
|
+
# SPDX-License-Identifier: MIT-0
|
|
66
|
+
#++
|
|
67
|
+
# Layout::Constraint.percentage(25) # 25% of the area
|
|
68
|
+
#
|
|
69
|
+
#--
|
|
70
|
+
# SPDX-SnippetEnd
|
|
71
|
+
#++
|
|
72
|
+
# [v] Percentage 0-100 (Integer).
|
|
73
|
+
def self.percentage(v)
|
|
74
|
+
new(type: :percentage, value: Integer(v))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Enforces a minimum size.
|
|
78
|
+
#
|
|
79
|
+
#--
|
|
80
|
+
# SPDX-SnippetBegin
|
|
81
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
82
|
+
# SPDX-License-Identifier: MIT-0
|
|
83
|
+
#++
|
|
84
|
+
# Layout::Constraint.min(5) # At least 5 cells
|
|
85
|
+
#
|
|
86
|
+
#--
|
|
87
|
+
# SPDX-SnippetEnd
|
|
88
|
+
#++
|
|
89
|
+
# This section will grow if space permits, but never shrink below +v+.
|
|
90
|
+
#
|
|
91
|
+
# [v] Minimum cells (Integer).
|
|
92
|
+
def self.min(v)
|
|
93
|
+
new(type: :min, value: Integer(v))
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Enforces a maximum size.
|
|
97
|
+
#
|
|
98
|
+
#--
|
|
99
|
+
# SPDX-SnippetBegin
|
|
100
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
101
|
+
# SPDX-License-Identifier: MIT-0
|
|
102
|
+
#++
|
|
103
|
+
# Layout::Constraint.max(10) # At most 10 cells
|
|
104
|
+
#
|
|
105
|
+
#--
|
|
106
|
+
# SPDX-SnippetEnd
|
|
107
|
+
#++
|
|
108
|
+
# [v] Maximum cells (Integer).
|
|
109
|
+
def self.max(v)
|
|
110
|
+
new(type: :max, value: Integer(v))
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Fills remaining space proportionally.
|
|
114
|
+
#
|
|
115
|
+
#--
|
|
116
|
+
# SPDX-SnippetBegin
|
|
117
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
118
|
+
# SPDX-License-Identifier: MIT-0
|
|
119
|
+
#++
|
|
120
|
+
# Layout::Constraint.fill(1) # Equal share
|
|
121
|
+
# Layout::Constraint.fill(2) # Double share
|
|
122
|
+
#
|
|
123
|
+
#--
|
|
124
|
+
# SPDX-SnippetEnd
|
|
125
|
+
#++
|
|
126
|
+
# Fill constraints distribute any space left after satisfying strict rules.
|
|
127
|
+
# They behave like flex-grow. A fill(2) takes twice as much space as a fill(1).
|
|
128
|
+
#
|
|
129
|
+
# [v] Proportional weight (Integer, default: 1).
|
|
130
|
+
def self.fill(v = 1)
|
|
131
|
+
new(type: :fill, value: Integer(v))
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Requests a specific ratio of the total space.
|
|
135
|
+
#
|
|
136
|
+
#--
|
|
137
|
+
# SPDX-SnippetBegin
|
|
138
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
139
|
+
# SPDX-License-Identifier: MIT-0
|
|
140
|
+
#++
|
|
141
|
+
# Layout::Constraint.ratio(1, 3) # 1/3rd of the area
|
|
142
|
+
#
|
|
143
|
+
#--
|
|
144
|
+
# SPDX-SnippetEnd
|
|
145
|
+
#++
|
|
146
|
+
# [numerator] Top part of fraction (Integer).
|
|
147
|
+
# [denominator] Bottom part of fraction (Integer).
|
|
148
|
+
def self.ratio(numerator, denominator)
|
|
149
|
+
new(type: :ratio, value: [Integer(numerator), Integer(denominator)])
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Converts an array of lengths into an array of Length constraints.
|
|
153
|
+
#
|
|
154
|
+
# Complex layouts often use multiple fixed-size sections. Manually creating each constraint
|
|
155
|
+
# clutters the code.
|
|
156
|
+
#
|
|
157
|
+
# This method maps over the input, returning a constraint array in one call.
|
|
158
|
+
#
|
|
159
|
+
# === Example
|
|
160
|
+
#
|
|
161
|
+
#--
|
|
162
|
+
# SPDX-SnippetBegin
|
|
163
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
164
|
+
# SPDX-License-Identifier: MIT-0
|
|
165
|
+
#++
|
|
166
|
+
# Constraint.from_lengths([10, 20, 10])
|
|
167
|
+
# # => [Constraint.length(10), Constraint.length(20), Constraint.length(10)]
|
|
168
|
+
#
|
|
169
|
+
#--
|
|
170
|
+
# SPDX-SnippetEnd
|
|
171
|
+
#++
|
|
172
|
+
# [values] Enumerable of Integers.
|
|
173
|
+
def self.from_lengths(values)
|
|
174
|
+
values.map { |v| length(v) }
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Converts an array of percentages into an array of Percentage constraints.
|
|
178
|
+
#
|
|
179
|
+
# Percentage-based layouts distribute space proportionally. This method batches the creation.
|
|
180
|
+
#
|
|
181
|
+
# === Example
|
|
182
|
+
#
|
|
183
|
+
#--
|
|
184
|
+
# SPDX-SnippetBegin
|
|
185
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
186
|
+
# SPDX-License-Identifier: MIT-0
|
|
187
|
+
#++
|
|
188
|
+
# Constraint.from_percentages([25, 50, 25])
|
|
189
|
+
# # => [Constraint.percentage(25), Constraint.percentage(50), Constraint.percentage(25)]
|
|
190
|
+
#
|
|
191
|
+
#--
|
|
192
|
+
# SPDX-SnippetEnd
|
|
193
|
+
#++
|
|
194
|
+
# [values] Enumerable of Integers (0-100).
|
|
195
|
+
def self.from_percentages(values)
|
|
196
|
+
values.map { |v| percentage(v) }
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Converts an array of minimums into an array of Min constraints.
|
|
200
|
+
#
|
|
201
|
+
# Minimum constraints ensure sections never shrink below a threshold. Batch them here.
|
|
202
|
+
#
|
|
203
|
+
# === Example
|
|
204
|
+
#
|
|
205
|
+
#--
|
|
206
|
+
# SPDX-SnippetBegin
|
|
207
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
208
|
+
# SPDX-License-Identifier: MIT-0
|
|
209
|
+
#++
|
|
210
|
+
# Constraint.from_mins([5, 10, 5])
|
|
211
|
+
# # => [Constraint.min(5), Constraint.min(10), Constraint.min(5)]
|
|
212
|
+
#
|
|
213
|
+
#--
|
|
214
|
+
# SPDX-SnippetEnd
|
|
215
|
+
#++
|
|
216
|
+
# [values] Enumerable of Integers.
|
|
217
|
+
def self.from_mins(values)
|
|
218
|
+
values.map { |v| min(v) }
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Converts an array of maximums into an array of Max constraints.
|
|
222
|
+
#
|
|
223
|
+
# Maximum constraints cap section sizes. Batch them here.
|
|
224
|
+
#
|
|
225
|
+
# === Example
|
|
226
|
+
#
|
|
227
|
+
#--
|
|
228
|
+
# SPDX-SnippetBegin
|
|
229
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
230
|
+
# SPDX-License-Identifier: MIT-0
|
|
231
|
+
#++
|
|
232
|
+
# Constraint.from_maxes([20, 30, 40])
|
|
233
|
+
# # => [Constraint.max(20), Constraint.max(30), Constraint.max(40)]
|
|
234
|
+
#
|
|
235
|
+
#--
|
|
236
|
+
# SPDX-SnippetEnd
|
|
237
|
+
#++
|
|
238
|
+
# [values] Enumerable of Integers.
|
|
239
|
+
def self.from_maxes(values)
|
|
240
|
+
values.map { |v| max(v) }
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Converts an array of weights into an array of Fill constraints.
|
|
244
|
+
#
|
|
245
|
+
# Fill constraints distribute remaining space by weight. Batch them here.
|
|
246
|
+
#
|
|
247
|
+
# === Example
|
|
248
|
+
#
|
|
249
|
+
#--
|
|
250
|
+
# SPDX-SnippetBegin
|
|
251
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
252
|
+
# SPDX-License-Identifier: MIT-0
|
|
253
|
+
#++
|
|
254
|
+
# Constraint.from_fills([1, 2, 1])
|
|
255
|
+
# # => [Constraint.fill(1), Constraint.fill(2), Constraint.fill(1)]
|
|
256
|
+
#
|
|
257
|
+
#--
|
|
258
|
+
# SPDX-SnippetEnd
|
|
259
|
+
#++
|
|
260
|
+
# [values] Enumerable of Integers.
|
|
261
|
+
def self.from_fills(values)
|
|
262
|
+
values.map { |v| fill(v) }
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Converts an array of ratio pairs into an array of Ratio constraints.
|
|
266
|
+
#
|
|
267
|
+
# Ratio constraints define exact fractions of space. Batch them here.
|
|
268
|
+
#
|
|
269
|
+
# === Example
|
|
270
|
+
#
|
|
271
|
+
#--
|
|
272
|
+
# SPDX-SnippetBegin
|
|
273
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
274
|
+
# SPDX-License-Identifier: MIT-0
|
|
275
|
+
#++
|
|
276
|
+
# Constraint.from_ratios([[1, 4], [2, 4], [1, 4]])
|
|
277
|
+
# # => [Constraint.ratio(1, 4), Constraint.ratio(2, 4), Constraint.ratio(1, 4)]
|
|
278
|
+
#
|
|
279
|
+
#--
|
|
280
|
+
# SPDX-SnippetEnd
|
|
281
|
+
#++
|
|
282
|
+
# [pairs] Enumerable of <tt>[numerator, denominator]</tt> arrays.
|
|
283
|
+
def self.from_ratios(pairs)
|
|
284
|
+
pairs.map { |n, d| ratio(n, d) }
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Computes the size this constraint would produce given available space.
|
|
288
|
+
#
|
|
289
|
+
# Layout engines use constraints to compute actual dimensions.
|
|
290
|
+
# Calling apply lets you preview the result without rendering.
|
|
291
|
+
#
|
|
292
|
+
# === Example
|
|
293
|
+
#
|
|
294
|
+
#--
|
|
295
|
+
# SPDX-SnippetBegin
|
|
296
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
297
|
+
# SPDX-License-Identifier: MIT-0
|
|
298
|
+
#++
|
|
299
|
+
# Constraint.percentage(50).apply(100) # => 50
|
|
300
|
+
# Constraint.length(10).apply(100) # => 10
|
|
301
|
+
# Constraint.min(10).apply(5) # => 10
|
|
302
|
+
# Constraint.max(10).apply(15) # => 10
|
|
303
|
+
# Constraint.ratio(1, 4).apply(100) # => 25
|
|
304
|
+
#--
|
|
305
|
+
# SPDX-SnippetEnd
|
|
306
|
+
#++
|
|
307
|
+
#
|
|
308
|
+
# [length] Available space (Integer).
|
|
309
|
+
#
|
|
310
|
+
# Returns the computed size (Integer).
|
|
311
|
+
def apply(length)
|
|
312
|
+
length = Integer(length)
|
|
313
|
+
case type
|
|
314
|
+
when :length
|
|
315
|
+
value
|
|
316
|
+
when :percentage
|
|
317
|
+
(length * value) / 100
|
|
318
|
+
when :min
|
|
319
|
+
[value, length].max
|
|
320
|
+
when :max
|
|
321
|
+
[value, length].min
|
|
322
|
+
when :fill
|
|
323
|
+
length
|
|
324
|
+
when :ratio
|
|
325
|
+
numerator, denominator = value
|
|
326
|
+
denominator.zero? ? 0 : (length * numerator) / denominator
|
|
327
|
+
else
|
|
328
|
+
length
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# Ruby-idiomatic alias (TIMTOWTDI)
|
|
333
|
+
# Allows proc-like invocation: constraint.(100)
|
|
334
|
+
alias call apply
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
end
|