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,158 @@
|
|
|
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 Text
|
|
10
|
+
# A styled string fragment.
|
|
11
|
+
#
|
|
12
|
+
# Text is rarely uniform. You need to bold a keyword, colorize an error, or dim a timestamp.
|
|
13
|
+
#
|
|
14
|
+
# This class attaches style to content. It pairs a string with visual attributes.
|
|
15
|
+
#
|
|
16
|
+
# combine spans into a {Line} to create rich text.
|
|
17
|
+
#
|
|
18
|
+
# === Examples
|
|
19
|
+
#
|
|
20
|
+
# Text::Span.new(content: "Error", style: Style.new(fg: :red, modifiers: [:bold]))
|
|
21
|
+
class Span < Data.define(:content, :style)
|
|
22
|
+
##
|
|
23
|
+
# :attr_reader: content
|
|
24
|
+
# The text content.
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# :attr_reader: style
|
|
28
|
+
# The style to apply.
|
|
29
|
+
|
|
30
|
+
# Creates a new Span.
|
|
31
|
+
#
|
|
32
|
+
# [content] String.
|
|
33
|
+
# [style] Style object (optional).
|
|
34
|
+
def initialize(content:, style: nil)
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Concise helper for styling.
|
|
39
|
+
#
|
|
40
|
+
# === Example
|
|
41
|
+
#
|
|
42
|
+
# Text::Span.styled("Bold", Style::Style.new(modifiers: [:bold]))
|
|
43
|
+
def self.styled(content, style = nil)
|
|
44
|
+
new(content:, style:)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Returns the unicode display width of the content in terminal cells.
|
|
48
|
+
#
|
|
49
|
+
# CJK characters and emoji count as 2 cells. ASCII characters count as 1 cell.
|
|
50
|
+
# Use this to measure how much horizontal space a span will occupy.
|
|
51
|
+
#
|
|
52
|
+
# === Example
|
|
53
|
+
#
|
|
54
|
+
#--
|
|
55
|
+
# SPDX-SnippetBegin
|
|
56
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
57
|
+
# SPDX-License-Identifier: MIT-0
|
|
58
|
+
#++
|
|
59
|
+
# span = Text::Span.new(content: "Hello")
|
|
60
|
+
# span.width # => 5
|
|
61
|
+
#
|
|
62
|
+
# span = Text::Span.new(content: "你好") # Chinese characters
|
|
63
|
+
# span.width # => 4
|
|
64
|
+
#
|
|
65
|
+
#--
|
|
66
|
+
# SPDX-SnippetEnd
|
|
67
|
+
#++
|
|
68
|
+
# Returns: Integer.
|
|
69
|
+
def width
|
|
70
|
+
RatatuiRuby::Text.width(content.to_s)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Creates a span with the default style.
|
|
74
|
+
#
|
|
75
|
+
# Use this factory method when you want unstyled text. It mirrors the Ratatui API.
|
|
76
|
+
#
|
|
77
|
+
# === Example
|
|
78
|
+
#
|
|
79
|
+
#--
|
|
80
|
+
# SPDX-SnippetBegin
|
|
81
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
82
|
+
# SPDX-License-Identifier: MIT-0
|
|
83
|
+
#++
|
|
84
|
+
# span = Text::Span.raw("test content")
|
|
85
|
+
# span.content # => "test content"
|
|
86
|
+
# span.style # => nil
|
|
87
|
+
#
|
|
88
|
+
#--
|
|
89
|
+
# SPDX-SnippetEnd
|
|
90
|
+
#++
|
|
91
|
+
# [content] String.
|
|
92
|
+
#
|
|
93
|
+
# Returns: Span.
|
|
94
|
+
def self.raw(content)
|
|
95
|
+
new(content:)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Patches the style of the span, merging modifiers from the given style.
|
|
99
|
+
#
|
|
100
|
+
# Non-nil values from the patch style override the existing style. Use this when you want to
|
|
101
|
+
# layer styles without replacing the entire style. Colors in the patch take precedence over
|
|
102
|
+
# existing colors. Modifiers are combined.
|
|
103
|
+
#
|
|
104
|
+
# === Example
|
|
105
|
+
#
|
|
106
|
+
#--
|
|
107
|
+
# SPDX-SnippetBegin
|
|
108
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
109
|
+
# SPDX-License-Identifier: MIT-0
|
|
110
|
+
#++
|
|
111
|
+
# span = Text::Span.new(content: "test", style: Style::Style.new(fg: :green))
|
|
112
|
+
# patched = span.patch_style(Style::Style.new(bg: :yellow, modifiers: [:bold]))
|
|
113
|
+
# patched.style.fg # => :green (preserved)
|
|
114
|
+
# patched.style.bg # => :yellow (added)
|
|
115
|
+
#
|
|
116
|
+
#--
|
|
117
|
+
# SPDX-SnippetEnd
|
|
118
|
+
#++
|
|
119
|
+
# [patch] Style::Style to merge.
|
|
120
|
+
#
|
|
121
|
+
# Returns: Span.
|
|
122
|
+
def patch_style(patch)
|
|
123
|
+
return self if patch.nil?
|
|
124
|
+
return with(style: patch) if style.nil?
|
|
125
|
+
|
|
126
|
+
merged = Style::Style.new(
|
|
127
|
+
fg: patch.fg.nil? ? style.fg : patch.fg,
|
|
128
|
+
bg: patch.bg.nil? ? style.bg : patch.bg,
|
|
129
|
+
modifiers: patch.modifiers.empty? ? style.modifiers : (style.modifiers + patch.modifiers).uniq
|
|
130
|
+
)
|
|
131
|
+
with(style: merged)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Resets the style of the span.
|
|
135
|
+
#
|
|
136
|
+
# Returns a new span with no style applied. Use this to strip all styling.
|
|
137
|
+
#
|
|
138
|
+
# === Example
|
|
139
|
+
#
|
|
140
|
+
#--
|
|
141
|
+
# SPDX-SnippetBegin
|
|
142
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
143
|
+
# SPDX-License-Identifier: MIT-0
|
|
144
|
+
#++
|
|
145
|
+
# span = Text::Span.new(content: "styled", style: Style::Style.new(fg: :red))
|
|
146
|
+
# reset = span.reset_style
|
|
147
|
+
# reset.style # => nil
|
|
148
|
+
#
|
|
149
|
+
#--
|
|
150
|
+
# SPDX-SnippetEnd
|
|
151
|
+
#++
|
|
152
|
+
# Returns: Span.
|
|
153
|
+
def reset_style
|
|
154
|
+
with(style: nil)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
# Namespace for rich text components (Span, Line) and text utilities.
|
|
10
|
+
# Distinct from canvas shapes and other Line usages.
|
|
11
|
+
#
|
|
12
|
+
# == Text Measurement
|
|
13
|
+
#
|
|
14
|
+
# The Text module provides a utility method for calculating the display width
|
|
15
|
+
# of strings in terminal cells. This accounts for unicode complexity:
|
|
16
|
+
#
|
|
17
|
+
# - ASCII characters: 1 cell each
|
|
18
|
+
# - CJK (Chinese, Japanese, Korean) characters: 2 cells each (full-width)
|
|
19
|
+
# - Emoji: typically 2 cells each (varies by terminal)
|
|
20
|
+
# - Combining marks: 0 cells (zero-width)
|
|
21
|
+
#
|
|
22
|
+
# This is essential for layout calculations in TUI applications, where you need to know
|
|
23
|
+
# how much space a string will occupy on the screen, not just its byte or character length.
|
|
24
|
+
#
|
|
25
|
+
# === Use Cases
|
|
26
|
+
#
|
|
27
|
+
# - Auto-sizing widgets (Button, Badge) that fit their content
|
|
28
|
+
# - Calculating padding or centering for text alignment
|
|
29
|
+
# - Building responsive layouts that adapt to content width
|
|
30
|
+
# - Measuring text for scrolling or truncation logic
|
|
31
|
+
#
|
|
32
|
+
# === Examples
|
|
33
|
+
#
|
|
34
|
+
#--
|
|
35
|
+
# SPDX-SnippetBegin
|
|
36
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
37
|
+
# SPDX-License-Identifier: MIT-0
|
|
38
|
+
#++
|
|
39
|
+
# # Simple ASCII text
|
|
40
|
+
# RatatuiRuby::Text.width("Hello") # => 5
|
|
41
|
+
#
|
|
42
|
+
# # With emoji
|
|
43
|
+
# RatatuiRuby::Text.width("Hello 👍") # => 8 (5 + space + 2-width emoji)
|
|
44
|
+
#
|
|
45
|
+
# # With CJK characters
|
|
46
|
+
# RatatuiRuby::Text.width("你好") # => 4 (each CJK char is 2 cells)
|
|
47
|
+
#
|
|
48
|
+
# # Mixed content
|
|
49
|
+
# RatatuiRuby::Text.width("Hi 你好 👍") # => 11 (2 + space + 4 + space + 2)
|
|
50
|
+
#--
|
|
51
|
+
# SPDX-SnippetEnd
|
|
52
|
+
#++
|
|
53
|
+
module Text
|
|
54
|
+
##
|
|
55
|
+
# :method: width
|
|
56
|
+
# :call-seq: width(string) -> Integer
|
|
57
|
+
#
|
|
58
|
+
# Calculates the display width of a string in terminal cells.
|
|
59
|
+
#
|
|
60
|
+
# Layout demands precision. Terminals measure space in cells, not characters. An ASCII letter occupies one cell. A Chinese character occupies two. An emoji occupies two. Combining marks occupy zero.
|
|
61
|
+
#
|
|
62
|
+
# Measuring width manually is error-prone. You can count <tt>string.length</tt>, but that counts characters, not cells. A string with one emoji counts as 1 character but occupies 2 cells.
|
|
63
|
+
#
|
|
64
|
+
# This method returns the true display width. Use it to auto-size widgets, calculate padding, center text, or build responsive layouts.
|
|
65
|
+
#
|
|
66
|
+
# === Examples
|
|
67
|
+
#
|
|
68
|
+
#--
|
|
69
|
+
# SPDX-SnippetBegin
|
|
70
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
71
|
+
# SPDX-License-Identifier: MIT-0
|
|
72
|
+
#++
|
|
73
|
+
# RatatuiRuby::Text.width("Hello") # => 5 (5 ASCII chars × 1 cell)
|
|
74
|
+
#
|
|
75
|
+
# RatatuiRuby::Text.width("你好") # => 4 (2 CJK chars × 2 cells)
|
|
76
|
+
#
|
|
77
|
+
# RatatuiRuby::Text.width("Hello 👍") # => 8 (5 ASCII + 1 space + 1 emoji × 2)
|
|
78
|
+
#
|
|
79
|
+
# # In the Session DSL (easier)
|
|
80
|
+
# RatatuiRuby.run do |tui|
|
|
81
|
+
# width = tui.text_width("Hello 👍")
|
|
82
|
+
# end
|
|
83
|
+
#
|
|
84
|
+
#--
|
|
85
|
+
# SPDX-SnippetEnd
|
|
86
|
+
#++
|
|
87
|
+
# [string] String to measure (String or object convertible to String)
|
|
88
|
+
# Returns: Integer (number of terminal cells the string occupies)
|
|
89
|
+
# Raises: TypeError if the argument is not a String
|
|
90
|
+
#
|
|
91
|
+
# (Native method implemented in Rust)
|
|
92
|
+
def self.width(string)
|
|
93
|
+
RatatuiRuby._text_width(string)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
require_relative "text/span"
|
|
99
|
+
require_relative "text/line"
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
class TUI
|
|
10
|
+
# Buffer inspection factory methods for Session.
|
|
11
|
+
#
|
|
12
|
+
# Provides convenient access to Buffer::Cell for testing
|
|
13
|
+
# and buffer inspection purposes.
|
|
14
|
+
module BufferFactories
|
|
15
|
+
# Creates a Buffer::Cell (for testing).
|
|
16
|
+
# @return [Buffer::Cell]
|
|
17
|
+
def cell(...)
|
|
18
|
+
Buffer::Cell.new(...)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
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
|
+
class TUI
|
|
10
|
+
# Canvas shape factory methods for Session.
|
|
11
|
+
#
|
|
12
|
+
# Provides convenient access to Widgets::Shape::* classes
|
|
13
|
+
# for creating custom drawings on Canvas widgets.
|
|
14
|
+
module CanvasFactories
|
|
15
|
+
# Creates a map shape for Canvas.
|
|
16
|
+
# @return [Widgets::Shape::Map]
|
|
17
|
+
def shape_map(...)
|
|
18
|
+
Widgets::Shape::Map.new(...)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Creates a line shape for Canvas.
|
|
22
|
+
# @return [Widgets::Shape::Line]
|
|
23
|
+
def shape_line(...)
|
|
24
|
+
Widgets::Shape::Line.new(...)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Creates a point (single pixel) shape for Canvas.
|
|
28
|
+
# @return [Widgets::Shape::Point]
|
|
29
|
+
def shape_point(...)
|
|
30
|
+
Widgets::Shape::Point.new(...)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Creates a circle shape for Canvas.
|
|
34
|
+
# @return [Widgets::Shape::Circle]
|
|
35
|
+
def shape_circle(...)
|
|
36
|
+
Widgets::Shape::Circle.new(...)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Creates a rectangle shape for Canvas.
|
|
40
|
+
# @return [Widgets::Shape::Rectangle]
|
|
41
|
+
def shape_rectangle(...)
|
|
42
|
+
Widgets::Shape::Rectangle.new(...)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# =====================================
|
|
46
|
+
# Terse Shape Aliases (DWIM)
|
|
47
|
+
# =====================================
|
|
48
|
+
|
|
49
|
+
# Creates a circle shape (terse alias).
|
|
50
|
+
# @return [Widgets::Shape::Circle]
|
|
51
|
+
alias circle shape_circle
|
|
52
|
+
|
|
53
|
+
# Creates a point shape (terse alias).
|
|
54
|
+
# @return [Widgets::Shape::Point]
|
|
55
|
+
alias point shape_point
|
|
56
|
+
|
|
57
|
+
# NOTE: No terse 'rectangle' alias - would conflict with Layout::Rect concept.
|
|
58
|
+
# Use shape_rectangle() explicitly.
|
|
59
|
+
|
|
60
|
+
# Creates a map shape (terse alias).
|
|
61
|
+
# @return [Widgets::Shape::Map]
|
|
62
|
+
alias map shape_map
|
|
63
|
+
|
|
64
|
+
# Creates a label shape (terse alias).
|
|
65
|
+
#
|
|
66
|
+
# Note: shape_label is defined in WidgetFactories.
|
|
67
|
+
# @return [Widgets::Shape::Label]
|
|
68
|
+
def label(first = nil, **kwargs)
|
|
69
|
+
Widgets::Shape::Label.coerce_args(first, kwargs)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# =====================================
|
|
73
|
+
# Bidirectional Shape Aliases (*_shape)
|
|
74
|
+
# =====================================
|
|
75
|
+
|
|
76
|
+
# Creates a circle shape (bidirectional alias).
|
|
77
|
+
# @return [Widgets::Shape::Circle]
|
|
78
|
+
alias circle_shape shape_circle
|
|
79
|
+
|
|
80
|
+
# Creates a point shape (bidirectional alias).
|
|
81
|
+
# @return [Widgets::Shape::Point]
|
|
82
|
+
alias point_shape shape_point
|
|
83
|
+
|
|
84
|
+
# Creates a rectangle shape (bidirectional alias).
|
|
85
|
+
# Note: Terse 'rectangle' is intentionally excluded to avoid confusion with Layout::Rect,
|
|
86
|
+
# but 'rectangle_shape' is unambiguous.
|
|
87
|
+
# @return [Widgets::Shape::Rectangle]
|
|
88
|
+
alias rectangle_shape shape_rectangle
|
|
89
|
+
|
|
90
|
+
# Creates a map shape (bidirectional alias).
|
|
91
|
+
# @return [Widgets::Shape::Map]
|
|
92
|
+
alias map_shape shape_map
|
|
93
|
+
|
|
94
|
+
# Creates a label shape (bidirectional alias).
|
|
95
|
+
# @return [Widgets::Shape::Label]
|
|
96
|
+
alias label_shape label
|
|
97
|
+
|
|
98
|
+
# =====================================
|
|
99
|
+
# Shape Dispatcher (TIMTOWTDI)
|
|
100
|
+
# =====================================
|
|
101
|
+
|
|
102
|
+
# Creates a shape by type symbol.
|
|
103
|
+
#
|
|
104
|
+
# Hard-coding method names limits flexibility. Programmatic shape creation
|
|
105
|
+
# from user input or config files requires tedious case statements.
|
|
106
|
+
#
|
|
107
|
+
# This dispatcher routes shape creation through a single entry point.
|
|
108
|
+
# Pass the type as a symbol and the remaining parameters as kwargs.
|
|
109
|
+
#
|
|
110
|
+
# Use it for dynamic shape generation, config-driven UIs, or when you
|
|
111
|
+
# prefer explicit type specification over method names.
|
|
112
|
+
#
|
|
113
|
+
# Also available as: <tt>tui.circle</tt>, <tt>tui.shape_circle</tt>
|
|
114
|
+
#
|
|
115
|
+
# === Examples
|
|
116
|
+
#
|
|
117
|
+
#--
|
|
118
|
+
# SPDX-SnippetBegin
|
|
119
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
120
|
+
# SPDX-License-Identifier: MIT-0
|
|
121
|
+
#++
|
|
122
|
+
# # Direct dispatch
|
|
123
|
+
# tui.shape(:circle, x: 5.0, y: 5.0, radius: 2.5, color: :red)
|
|
124
|
+
#
|
|
125
|
+
# # Dynamic shape creation from config
|
|
126
|
+
# config = { type: :rectangle, x: 0.0, y: 0.0, width: 10.0, height: 10.0 }
|
|
127
|
+
# tui.shape(config[:type], **config.except(:type))
|
|
128
|
+
#--
|
|
129
|
+
# SPDX-SnippetEnd
|
|
130
|
+
#++
|
|
131
|
+
#
|
|
132
|
+
# @param type [Symbol] Shape type: :circle, :line, :point, :rectangle, :map, :label
|
|
133
|
+
# @return [Widgets::Shape::*]
|
|
134
|
+
def shape(type, **)
|
|
135
|
+
case type
|
|
136
|
+
when :circle then shape_circle(**)
|
|
137
|
+
when :line then shape_line(**)
|
|
138
|
+
when :point then shape_point(**)
|
|
139
|
+
when :rectangle then shape_rectangle(**)
|
|
140
|
+
when :map then shape_map(**)
|
|
141
|
+
when :label then label(**)
|
|
142
|
+
else
|
|
143
|
+
raise ArgumentError, "Unknown shape type: #{type.inspect}. " \
|
|
144
|
+
"Valid types: :circle, :line, :point, :rectangle, :map, :label"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
class TUI
|
|
10
|
+
# Core terminal methods delegated to RatatuiRuby module.
|
|
11
|
+
#
|
|
12
|
+
# These are the fundamental operations for the render loop:
|
|
13
|
+
# drawing UI, polling events, and inspecting the buffer.
|
|
14
|
+
module Core
|
|
15
|
+
# Draws the given UI node tree to the terminal.
|
|
16
|
+
# @see RatatuiRuby.draw
|
|
17
|
+
def draw(tree = nil, &block)
|
|
18
|
+
if tree && block
|
|
19
|
+
raise ArgumentError, "Cannot provide both a tree and a block to draw"
|
|
20
|
+
end
|
|
21
|
+
unless tree || block
|
|
22
|
+
raise ArgumentError, "Must provide either a tree or a block to draw"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if block
|
|
26
|
+
RatatuiRuby.draw(&block)
|
|
27
|
+
else
|
|
28
|
+
RatatuiRuby.draw(tree)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Checks for user input.
|
|
33
|
+
# @see RatatuiRuby.poll_event
|
|
34
|
+
def poll_event(timeout: 0.016)
|
|
35
|
+
RatatuiRuby.poll_event(timeout:)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Inspects the terminal buffer at specific coordinates.
|
|
39
|
+
# @see RatatuiRuby.get_cell_at
|
|
40
|
+
def get_cell_at(x, y)
|
|
41
|
+
RatatuiRuby.get_cell_at(x, y)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Creates a Draw::CellCmd for placing a cell at coordinates.
|
|
45
|
+
# @return [Draw::CellCmd]
|
|
46
|
+
def draw_cell(x, y, cell)
|
|
47
|
+
Draw.cell(x, y, cell)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Inserts content above an inline viewport.
|
|
51
|
+
# @see RatatuiRuby.insert_before
|
|
52
|
+
def insert_before(height, widget = nil, &)
|
|
53
|
+
RatatuiRuby.insert_before(height, widget, &)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Gets the Rect of the entire terminal, regardless of viewport
|
|
57
|
+
def terminal_area
|
|
58
|
+
RatatuiRuby.terminal_area
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Gets the Rect of the viewport
|
|
62
|
+
def viewport_area
|
|
63
|
+
RatatuiRuby.viewport_area
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
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
|
+
class TUI
|
|
10
|
+
# Layout factory methods for Session.
|
|
11
|
+
#
|
|
12
|
+
# Provides convenient access to Layout::Rect, Layout::Constraint,
|
|
13
|
+
# and Layout::Layout without fully qualifying the class names.
|
|
14
|
+
module LayoutFactories
|
|
15
|
+
# Creates a Layout::Rect.
|
|
16
|
+
# @return [Layout::Rect]
|
|
17
|
+
def rect(...)
|
|
18
|
+
Layout::Rect.new(...)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Creates a Layout::Constraint, with optional type-based dispatch.
|
|
22
|
+
#
|
|
23
|
+
# When called with a type symbol as the first argument, dispatches to
|
|
24
|
+
# the appropriate constraint factory (TIMTOWTDI pattern).
|
|
25
|
+
#
|
|
26
|
+
# Also available as: <tt>tui.percent(50)</tt>, <tt>tui.flex(1)</tt>
|
|
27
|
+
#
|
|
28
|
+
# === Examples
|
|
29
|
+
#
|
|
30
|
+
#--
|
|
31
|
+
# SPDX-SnippetBegin
|
|
32
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
33
|
+
# SPDX-License-Identifier: MIT-0
|
|
34
|
+
#++
|
|
35
|
+
# tui.constraint(:length, 10) # => Constraint.length(10)
|
|
36
|
+
# tui.constraint(:percentage, 50) # => Constraint.percentage(50)
|
|
37
|
+
# tui.constraint(:min, 5) # => Constraint.min(5)
|
|
38
|
+
# tui.constraint(:fill, 2) # => Constraint.fill(2)
|
|
39
|
+
# tui.constraint(:ratio, 1, 3) # => Constraint.ratio(1, 3)
|
|
40
|
+
#--
|
|
41
|
+
# SPDX-SnippetEnd
|
|
42
|
+
#++
|
|
43
|
+
# @return [Layout::Constraint]
|
|
44
|
+
def constraint(type_or_arg = nil, arg1 = nil, arg2 = nil, **)
|
|
45
|
+
# Type-based dispatch when first arg is a symbol
|
|
46
|
+
if type_or_arg.is_a?(Symbol)
|
|
47
|
+
case type_or_arg
|
|
48
|
+
when :length, :fixed
|
|
49
|
+
constraint_length(arg1 || raise(ArgumentError, "#{type_or_arg} requires a value"))
|
|
50
|
+
when :percentage, :percent
|
|
51
|
+
constraint_percentage(arg1 || raise(ArgumentError, "#{type_or_arg} requires a value"))
|
|
52
|
+
when :min
|
|
53
|
+
constraint_min(arg1 || raise(ArgumentError, "min requires a value"))
|
|
54
|
+
when :max
|
|
55
|
+
constraint_max(arg1 || raise(ArgumentError, "max requires a value"))
|
|
56
|
+
when :fill, :flex, :fr
|
|
57
|
+
constraint_fill(arg1 || 1)
|
|
58
|
+
when :ratio, :aspect
|
|
59
|
+
n = arg1 || raise(ArgumentError, "ratio requires numerator")
|
|
60
|
+
d = arg2 || raise(ArgumentError, "ratio requires denominator")
|
|
61
|
+
constraint_ratio(n, d)
|
|
62
|
+
else
|
|
63
|
+
# Use to_s since type_or_arg must be a Symbol here
|
|
64
|
+
raise ArgumentError, "Unknown constraint type: :#{type_or_arg}. " \
|
|
65
|
+
"Valid types: :length, :percentage, :min, :max, :fill, :ratio"
|
|
66
|
+
end
|
|
67
|
+
elsif type_or_arg.nil? && arg1.nil?
|
|
68
|
+
Layout::Constraint.new(**)
|
|
69
|
+
else
|
|
70
|
+
Layout::Constraint.new(type_or_arg, arg1, arg2, **)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Creates a Layout::Constraint.length.
|
|
75
|
+
# @return [Layout::Constraint]
|
|
76
|
+
def constraint_length(n)
|
|
77
|
+
Layout::Constraint.length(n)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Creates a Layout::Constraint.percentage.
|
|
81
|
+
# @return [Layout::Constraint]
|
|
82
|
+
def constraint_percentage(n)
|
|
83
|
+
Layout::Constraint.percentage(n)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Creates a Layout::Constraint.min.
|
|
87
|
+
# @return [Layout::Constraint]
|
|
88
|
+
def constraint_min(n)
|
|
89
|
+
Layout::Constraint.min(n)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Creates a Layout::Constraint.max.
|
|
93
|
+
# @return [Layout::Constraint]
|
|
94
|
+
def constraint_max(n)
|
|
95
|
+
Layout::Constraint.max(n)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Creates a Layout::Constraint.fill.
|
|
99
|
+
# @return [Layout::Constraint]
|
|
100
|
+
def constraint_fill(n = 1)
|
|
101
|
+
Layout::Constraint.fill(n)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Creates a Layout::Constraint.ratio.
|
|
105
|
+
# @return [Layout::Constraint]
|
|
106
|
+
def constraint_ratio(numerator, denominator)
|
|
107
|
+
Layout::Constraint.ratio(numerator, denominator)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Creates a Layout::Layout.
|
|
111
|
+
# @return [Layout::Layout]
|
|
112
|
+
def layout(...)
|
|
113
|
+
Layout::Layout.new(...)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Splits an area using Layout::Layout.split.
|
|
117
|
+
# @return [Array<Layout::Rect>]
|
|
118
|
+
def layout_split(area, direction: :vertical, constraints:, flex: :legacy)
|
|
119
|
+
Layout::Layout.split(area, direction:, constraints:, flex:)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Alias for {#layout_split} — shorter, more ergonomic.
|
|
123
|
+
# @return [Array<Layout::Rect>]
|
|
124
|
+
def split(area, direction: :vertical, constraints:, flex: :legacy)
|
|
125
|
+
layout_split(area, direction:, constraints:, flex:)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Alias for {#constraint_length} — CSS-inspired "fixed" sizing.
|
|
129
|
+
# @return [Layout::Constraint]
|
|
130
|
+
def fixed(n)
|
|
131
|
+
constraint_length(n)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Alias for {#constraint_percentage} — CSS-inspired percent sizing.
|
|
135
|
+
# @return [Layout::Constraint]
|
|
136
|
+
def percent(n)
|
|
137
|
+
constraint_percentage(n)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Alias for {#constraint_fill} — CSS Flexbox-inspired flexible sizing.
|
|
141
|
+
# @return [Layout::Constraint]
|
|
142
|
+
def flex(n = 1)
|
|
143
|
+
constraint_fill(n)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Alias for {#constraint_fill} — CSS Grid-inspired "fr" (fraction) unit.
|
|
147
|
+
# @return [Layout::Constraint]
|
|
148
|
+
def fr(n = 1)
|
|
149
|
+
constraint_fill(n)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|