ratatui_ruby 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.builds/ruby-3.2.yml +1 -1
- data/.builds/ruby-3.3.yml +1 -1
- data/.builds/ruby-3.4.yml +1 -1
- data/.builds/ruby-4.0.0.yml +1 -1
- data/AGENTS.md +4 -4
- data/CHANGELOG.md +35 -0
- data/README.md +26 -1
- data/doc/application_architecture.md +16 -16
- data/doc/application_testing.md +1 -1
- data/doc/contributors/architectural_overhaul/chat_conversations.md +4952 -0
- data/doc/contributors/architectural_overhaul/implementation_plan.md +60 -0
- data/doc/contributors/architectural_overhaul/task.md +37 -0
- data/doc/contributors/design/ruby_frontend.md +277 -81
- data/doc/contributors/design/rust_backend.md +349 -55
- data/doc/contributors/developing_examples.md +5 -5
- data/doc/contributors/index.md +7 -5
- data/doc/contributors/v1.0.0_blockers.md +1729 -0
- data/doc/index.md +11 -6
- data/doc/interactive_design.md +2 -2
- data/doc/quickstart.md +66 -97
- data/doc/v0.7.0_migration.md +236 -0
- data/doc/why.md +93 -0
- data/examples/app_all_events/README.md +6 -4
- data/examples/app_all_events/app.rb +1 -1
- data/examples/app_all_events/model/app_model.rb +1 -1
- data/examples/app_all_events/model/msg.rb +1 -1
- data/examples/app_all_events/update.rb +1 -1
- data/examples/app_all_events/view/app_view.rb +1 -1
- data/examples/app_all_events/view/controls_view.rb +1 -1
- data/examples/app_all_events/view/counts_view.rb +1 -1
- data/examples/app_all_events/view/live_view.rb +1 -1
- data/examples/app_all_events/view/log_view.rb +1 -1
- data/examples/app_color_picker/README.md +7 -5
- data/examples/app_color_picker/app.rb +1 -1
- data/examples/app_login_form/README.md +2 -0
- data/examples/app_stateful_interaction/README.md +2 -0
- data/examples/app_stateful_interaction/app.rb +1 -1
- data/examples/verify_quickstart_dsl/README.md +4 -3
- data/examples/verify_quickstart_dsl/app.rb +1 -1
- data/examples/verify_quickstart_layout/README.md +1 -1
- data/examples/verify_quickstart_lifecycle/README.md +3 -3
- data/examples/verify_quickstart_lifecycle/app.rb +2 -2
- data/examples/verify_readme_usage/README.md +1 -1
- data/examples/widget_barchart_demo/README.md +2 -1
- data/examples/widget_block_demo/README.md +2 -0
- data/examples/widget_box_demo/README.md +3 -3
- data/examples/widget_calendar_demo/README.md +3 -3
- data/examples/widget_calendar_demo/app.rb +5 -1
- data/examples/widget_canvas_demo/README.md +3 -3
- data/examples/widget_cell_demo/README.md +3 -3
- data/examples/widget_center_demo/README.md +3 -3
- data/examples/widget_chart_demo/README.md +3 -3
- data/examples/widget_gauge_demo/README.md +3 -3
- data/examples/widget_layout_split/README.md +3 -3
- data/examples/widget_line_gauge_demo/README.md +3 -3
- data/examples/widget_list_demo/README.md +3 -3
- data/examples/widget_map_demo/README.md +3 -3
- data/examples/widget_map_demo/app.rb +2 -2
- data/examples/widget_overlay_demo/README.md +36 -0
- data/examples/widget_popup_demo/README.md +3 -3
- data/examples/widget_ratatui_logo_demo/README.md +3 -3
- data/examples/widget_ratatui_logo_demo/app.rb +1 -1
- data/examples/widget_ratatui_mascot_demo/README.md +3 -3
- data/examples/widget_rect/README.md +3 -3
- data/examples/widget_render/README.md +3 -3
- data/examples/widget_render/app.rb +3 -3
- data/examples/widget_rich_text/README.md +3 -3
- data/examples/widget_scroll_text/README.md +3 -3
- data/examples/widget_scrollbar_demo/README.md +3 -3
- data/examples/widget_sparkline_demo/README.md +3 -3
- data/examples/widget_style_colors/README.md +3 -3
- data/examples/widget_table_demo/README.md +3 -3
- data/examples/widget_table_demo/app.rb +19 -4
- data/examples/widget_tabs_demo/README.md +3 -3
- data/examples/widget_text_width/README.md +3 -3
- data/examples/widget_text_width/app.rb +8 -1
- data/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/ext/ratatui_ruby/src/frame.rs +6 -5
- data/ext/ratatui_ruby/src/lib.rs +3 -2
- data/ext/ratatui_ruby/src/rendering.rs +22 -21
- data/ext/ratatui_ruby/src/text.rs +12 -3
- data/ext/ratatui_ruby/src/widgets/canvas.rs +5 -5
- data/ext/ratatui_ruby/src/widgets/table.rs +81 -36
- data/lib/ratatui_ruby/buffer/cell.rb +168 -0
- data/lib/ratatui_ruby/buffer.rb +15 -0
- data/lib/ratatui_ruby/frame.rb +8 -8
- data/lib/ratatui_ruby/layout/constraint.rb +95 -0
- data/lib/ratatui_ruby/layout/layout.rb +106 -0
- data/lib/ratatui_ruby/layout/rect.rb +118 -0
- data/lib/ratatui_ruby/layout.rb +19 -0
- data/lib/ratatui_ruby/list_state.rb +2 -2
- data/lib/ratatui_ruby/schema/layout.rb +1 -1
- data/lib/ratatui_ruby/schema/row.rb +66 -0
- data/lib/ratatui_ruby/schema/table.rb +10 -10
- data/lib/ratatui_ruby/schema/text.rb +27 -2
- data/lib/ratatui_ruby/style/style.rb +81 -0
- data/lib/ratatui_ruby/style.rb +15 -0
- data/lib/ratatui_ruby/table_state.rb +1 -1
- data/lib/ratatui_ruby/test_helper/snapshot.rb +24 -0
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +1 -1
- data/lib/ratatui_ruby/tui/buffer_factories.rb +20 -0
- data/lib/ratatui_ruby/tui/canvas_factories.rb +44 -0
- data/lib/ratatui_ruby/tui/core.rb +38 -0
- data/lib/ratatui_ruby/tui/layout_factories.rb +74 -0
- data/lib/ratatui_ruby/tui/state_factories.rb +33 -0
- data/lib/ratatui_ruby/tui/style_factories.rb +20 -0
- data/lib/ratatui_ruby/tui/text_factories.rb +44 -0
- data/lib/ratatui_ruby/tui/widget_factories.rb +195 -0
- data/lib/ratatui_ruby/tui.rb +75 -0
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +47 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +25 -0
- data/lib/ratatui_ruby/widgets/bar_chart.rb +239 -0
- data/lib/ratatui_ruby/widgets/block.rb +192 -0
- data/lib/ratatui_ruby/widgets/calendar.rb +84 -0
- data/lib/ratatui_ruby/widgets/canvas.rb +231 -0
- data/lib/ratatui_ruby/widgets/cell.rb +47 -0
- data/lib/ratatui_ruby/widgets/center.rb +59 -0
- data/lib/ratatui_ruby/widgets/chart.rb +185 -0
- data/lib/ratatui_ruby/widgets/clear.rb +54 -0
- data/lib/ratatui_ruby/widgets/cursor.rb +42 -0
- data/lib/ratatui_ruby/widgets/gauge.rb +72 -0
- data/lib/ratatui_ruby/widgets/line_gauge.rb +80 -0
- data/lib/ratatui_ruby/widgets/list.rb +127 -0
- data/lib/ratatui_ruby/widgets/list_item.rb +43 -0
- data/lib/ratatui_ruby/widgets/overlay.rb +43 -0
- data/lib/ratatui_ruby/widgets/paragraph.rb +99 -0
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +31 -0
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +36 -0
- data/lib/ratatui_ruby/widgets/row.rb +68 -0
- data/lib/ratatui_ruby/widgets/scrollbar.rb +143 -0
- data/lib/ratatui_ruby/widgets/shape/label.rb +68 -0
- data/lib/ratatui_ruby/widgets/sparkline.rb +134 -0
- data/lib/ratatui_ruby/widgets/table.rb +141 -0
- data/lib/ratatui_ruby/widgets/tabs.rb +85 -0
- data/lib/ratatui_ruby/widgets.rb +40 -0
- data/lib/ratatui_ruby.rb +23 -39
- data/sig/examples/app_all_events/view.rbs +1 -1
- data/sig/examples/app_all_events/view_state.rbs +1 -1
- data/sig/ratatui_ruby/schema/row.rbs +22 -0
- data/sig/ratatui_ruby/schema/table.rbs +1 -1
- data/sig/ratatui_ruby/schema/text.rbs +1 -0
- data/sig/ratatui_ruby/session.rbs +29 -49
- data/sig/ratatui_ruby/tui/buffer_factories.rbs +10 -0
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +14 -0
- data/sig/ratatui_ruby/tui/core.rbs +14 -0
- data/sig/ratatui_ruby/tui/layout_factories.rbs +19 -0
- data/sig/ratatui_ruby/tui/state_factories.rbs +12 -0
- data/sig/ratatui_ruby/tui/style_factories.rbs +10 -0
- data/sig/ratatui_ruby/tui/text_factories.rbs +14 -0
- data/sig/ratatui_ruby/tui/widget_factories.rbs +39 -0
- data/sig/ratatui_ruby/tui.rbs +19 -0
- data/tasks/autodoc.rake +1 -35
- data/tasks/sourcehut.rake +4 -1
- metadata +62 -15
- data/doc/contributors/dwim_dx.md +0 -366
- data/doc/contributors/examples_audit/p1_high.md +0 -21
- data/doc/contributors/examples_audit/p2_moderate.md +0 -81
- data/doc/contributors/examples_audit.md +0 -41
- data/doc/images/app_analytics.png +0 -0
- data/doc/images/app_custom_widget.png +0 -0
- data/doc/images/app_mouse_events.png +0 -0
- data/doc/images/widget_table_flex.png +0 -0
- data/lib/ratatui_ruby/session/autodoc.rb +0 -482
- data/lib/ratatui_ruby/session.rb +0 -178
- data/tasks/autodoc/inventory.rb +0 -63
- data/tasks/autodoc/notice.rb +0 -26
- data/tasks/autodoc/rbs.rb +0 -38
- data/tasks/autodoc/rdoc.rb +0 -45
|
@@ -20,21 +20,21 @@ module RatatuiRuby
|
|
|
20
20
|
# Run the interactive demo from the terminal:
|
|
21
21
|
#
|
|
22
22
|
# ruby examples/widget_table_flex/app.rb
|
|
23
|
-
class Table < Data.define(:header, :rows, :widths, :
|
|
23
|
+
class Table < Data.define(:header, :rows, :widths, :row_highlight_style, :highlight_symbol, :highlight_spacing, :column_highlight_style, :cell_highlight_style, :selected_row, :selected_column, :offset, :block, :footer, :flex, :style, :column_spacing)
|
|
24
24
|
##
|
|
25
25
|
# :attr_reader: header
|
|
26
|
-
# Header row content (Array of Strings).
|
|
26
|
+
# Header row content (Array of Strings, Text::Spans, Text::Lines, or Paragraphs).
|
|
27
27
|
|
|
28
28
|
##
|
|
29
29
|
# :attr_reader: rows
|
|
30
|
-
# Data rows (Array of Arrays
|
|
30
|
+
# Data rows (Array of Arrays). Each cell can be String, Text::Span, Text::Line, Paragraph, or Cell.
|
|
31
31
|
|
|
32
32
|
##
|
|
33
33
|
# :attr_reader: widths
|
|
34
34
|
# Column width constraints (Array of Constraint).
|
|
35
35
|
|
|
36
36
|
##
|
|
37
|
-
# :attr_reader:
|
|
37
|
+
# :attr_reader: row_highlight_style
|
|
38
38
|
# Style for the selected row.
|
|
39
39
|
|
|
40
40
|
##
|
|
@@ -83,7 +83,7 @@ module RatatuiRuby
|
|
|
83
83
|
|
|
84
84
|
##
|
|
85
85
|
# :attr_reader: footer
|
|
86
|
-
# Footer row content (Array of Strings).
|
|
86
|
+
# Footer row content (Array of Strings, Text::Spans, Text::Lines, or Paragraphs).
|
|
87
87
|
|
|
88
88
|
##
|
|
89
89
|
# :attr_reader: flex
|
|
@@ -99,10 +99,10 @@ module RatatuiRuby
|
|
|
99
99
|
|
|
100
100
|
# Creates a new Table.
|
|
101
101
|
#
|
|
102
|
-
# [header] Array of strings
|
|
103
|
-
# [rows] 2D Array
|
|
102
|
+
# [header] Array of strings, Text::Spans, Text::Lines, or paragraphs.
|
|
103
|
+
# [rows] 2D Array where each cell is String, Text::Span, Text::Line, Paragraph, or Cell.
|
|
104
104
|
# [widths] Array of Constraints.
|
|
105
|
-
# [
|
|
105
|
+
# [row_highlight_style] Style object.
|
|
106
106
|
# [highlight_symbol] String.
|
|
107
107
|
# [highlight_spacing] Symbol (optional, default: <tt>:when_selected</tt>).
|
|
108
108
|
# [column_highlight_style] Style object.
|
|
@@ -115,12 +115,12 @@ module RatatuiRuby
|
|
|
115
115
|
# [flex] Symbol (optional, default: <tt>:legacy</tt>).
|
|
116
116
|
# [style] Style object or Hash (optional).
|
|
117
117
|
# [column_spacing] Integer (optional, default: 1).
|
|
118
|
-
def initialize(header: nil, rows: [], widths: [],
|
|
118
|
+
def initialize(header: nil, rows: [], widths: [], row_highlight_style: nil, highlight_symbol: "> ", highlight_spacing: :when_selected, column_highlight_style: nil, cell_highlight_style: nil, selected_row: nil, selected_column: nil, offset: nil, block: nil, footer: nil, flex: :legacy, style: nil, column_spacing: 1)
|
|
119
119
|
super(
|
|
120
120
|
header:,
|
|
121
121
|
rows:,
|
|
122
122
|
widths:,
|
|
123
|
-
|
|
123
|
+
row_highlight_style:,
|
|
124
124
|
highlight_symbol:,
|
|
125
125
|
highlight_spacing:,
|
|
126
126
|
column_highlight_style:,
|
|
@@ -94,7 +94,7 @@ module RatatuiRuby
|
|
|
94
94
|
# Text::Span.styled("kerrick", Style.new(fg: :blue))
|
|
95
95
|
# ]
|
|
96
96
|
# )
|
|
97
|
-
class Line < Data.define(:spans, :alignment)
|
|
97
|
+
class Line < Data.define(:spans, :alignment, :style)
|
|
98
98
|
##
|
|
99
99
|
# :attr_reader: spans
|
|
100
100
|
# Array of Span objects.
|
|
@@ -105,11 +105,18 @@ module RatatuiRuby
|
|
|
105
105
|
#
|
|
106
106
|
# <tt>:left</tt>, <tt>:center</tt>, or <tt>:right</tt>.
|
|
107
107
|
|
|
108
|
+
##
|
|
109
|
+
# :attr_reader: style
|
|
110
|
+
# Line-level style applied to all spans.
|
|
111
|
+
#
|
|
112
|
+
# A Style object that sets colors/modifiers for the entire line.
|
|
113
|
+
|
|
108
114
|
# Creates a new Line.
|
|
109
115
|
#
|
|
110
116
|
# [spans] Array of Span objects (or Strings).
|
|
111
117
|
# [alignment] Symbol (optional).
|
|
112
|
-
|
|
118
|
+
# [style] Style object (optional).
|
|
119
|
+
def initialize(spans: [], alignment: nil, style: nil)
|
|
113
120
|
super
|
|
114
121
|
end
|
|
115
122
|
|
|
@@ -119,6 +126,24 @@ module RatatuiRuby
|
|
|
119
126
|
def self.from_string(content, alignment: nil)
|
|
120
127
|
new(spans: [Span.new(content:, style: nil)], alignment:)
|
|
121
128
|
end
|
|
129
|
+
|
|
130
|
+
# Calculates the display width of this line in terminal cells.
|
|
131
|
+
#
|
|
132
|
+
# Sums the widths of all span contents using the same unicode-aware
|
|
133
|
+
# algorithm as Text.width. Useful for layout calculations.
|
|
134
|
+
#
|
|
135
|
+
# === Examples
|
|
136
|
+
#
|
|
137
|
+
# line = Text::Line.new(spans: [
|
|
138
|
+
# Text::Span.new(content: "Hello "),
|
|
139
|
+
# Text::Span.new(content: "世界")
|
|
140
|
+
# ])
|
|
141
|
+
# line.width # => 10 (6 ASCII + 4 CJK)
|
|
142
|
+
#
|
|
143
|
+
# Returns: Integer (number of terminal cells)
|
|
144
|
+
def width
|
|
145
|
+
RatatuiRuby::Text.width(spans.map { |s| s.content.to_s }.join)
|
|
146
|
+
end
|
|
122
147
|
end
|
|
123
148
|
|
|
124
149
|
##
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
module Style
|
|
8
|
+
# Defines colors and text modifiers.
|
|
9
|
+
#
|
|
10
|
+
# The terminal is traditionally monochrome, but efficient interfaces use color to convey meaning.
|
|
11
|
+
# Red for errors. Green for success. Bold for headers.
|
|
12
|
+
#
|
|
13
|
+
# This value object encapsulates those choices. It applies foreground and background colors. It adds effects like italics or blinking.
|
|
14
|
+
#
|
|
15
|
+
# Use it to theme your application or highlight critical data.
|
|
16
|
+
#
|
|
17
|
+
# === Examples
|
|
18
|
+
#
|
|
19
|
+
# # Standard colors
|
|
20
|
+
# Style::Style.new(fg: :red, bg: :white, modifiers: [:bold])
|
|
21
|
+
#
|
|
22
|
+
# # Hex colors
|
|
23
|
+
# Style::Style.new(fg: "#ff00ff")
|
|
24
|
+
#
|
|
25
|
+
# === Supported Colors
|
|
26
|
+
#
|
|
27
|
+
# ==== Integer
|
|
28
|
+
# Represents an indexed color from the Xterm 256-color palette (0-255).
|
|
29
|
+
# * <tt>0</tt>–<tt>15</tt>: Standard and bright ANSI colors.
|
|
30
|
+
# * <tt>16</tt>–<tt>231</tt>: {6x6x6 Color Cube}[https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit].
|
|
31
|
+
# * <tt>232</tt>–<tt>255</tt>: Grayscale ramp.
|
|
32
|
+
#
|
|
33
|
+
# ==== Symbol
|
|
34
|
+
# Represents a named color from the standard ANSI palette. Supported values:
|
|
35
|
+
# * <tt>:black</tt>, <tt>:red</tt>, <tt>:green</tt>, <tt>:yellow</tt>,
|
|
36
|
+
# <tt>:blue</tt>, <tt>:magenta</tt>, <tt>:cyan</tt>, <tt>:gray</tt>
|
|
37
|
+
# * <tt>:dark_gray</tt>, <tt>:light_red</tt>, <tt>:light_green</tt>,
|
|
38
|
+
# <tt>:light_yellow</tt>, <tt>:light_blue</tt>, <tt>:light_magenta</tt>,
|
|
39
|
+
# <tt>:light_cyan</tt>, <tt>:white</tt>
|
|
40
|
+
#
|
|
41
|
+
# ==== String
|
|
42
|
+
# Represents a specific RGB color using a Hex code (<tt>"#RRGGBB"</tt>).
|
|
43
|
+
# Requires a terminal emulator with "True Color" (24-bit color) support.
|
|
44
|
+
class Style < Data.define(:fg, :bg, :modifiers)
|
|
45
|
+
##
|
|
46
|
+
# :attr_reader: fg
|
|
47
|
+
# Foreground color.
|
|
48
|
+
#
|
|
49
|
+
# Symbol (<tt>:red</tt>), Hex String (<tt>"#ffffff"</tt>), or Integer (0-255).
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
# :attr_reader: bg
|
|
53
|
+
# Background color.
|
|
54
|
+
#
|
|
55
|
+
# Symbol (<tt>:black</tt>), Hex String (<tt>"#000000"</tt>), or Integer (0-255).
|
|
56
|
+
|
|
57
|
+
##
|
|
58
|
+
# :attr_reader: modifiers
|
|
59
|
+
# Text effects.
|
|
60
|
+
#
|
|
61
|
+
# Array of symbols: <tt>:bold</tt>, <tt>:dim</tt>, <tt>:italic</tt>, <tt>:underlined</tt>,
|
|
62
|
+
# <tt>:slow_blink</tt>, <tt>:rapid_blink</tt>, <tt>:reversed</tt>, <tt>:hidden</tt>, <tt>:crossed_out</tt>.
|
|
63
|
+
|
|
64
|
+
# Creates a new Style.
|
|
65
|
+
#
|
|
66
|
+
# [fg] Color (Symbol/String/Integer).
|
|
67
|
+
# [bg] Color (Symbol/String/Integer).
|
|
68
|
+
# [modifiers] Array of Symbols.
|
|
69
|
+
def initialize(fg: nil, bg: nil, modifiers: [])
|
|
70
|
+
super
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns an empty style.
|
|
74
|
+
#
|
|
75
|
+
# Use this as a baseline to prevent style inheritance issues or when no styling is required.
|
|
76
|
+
def self.default
|
|
77
|
+
new
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
# Styling primitives for colors and text effects.
|
|
8
|
+
#
|
|
9
|
+
# This module mirrors +ratatui::style+ and contains:
|
|
10
|
+
# - {Style} — Colors and modifiers
|
|
11
|
+
module Style
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
require_relative "style/style"
|
|
@@ -18,7 +18,7 @@ module RatatuiRuby
|
|
|
18
18
|
# @table_state.select_column(0) # Select first column
|
|
19
19
|
#
|
|
20
20
|
# RatatuiRuby.draw do |frame|
|
|
21
|
-
# table = RatatuiRuby::Table.new(rows: [...], widths: [...])
|
|
21
|
+
# table = RatatuiRuby::Widgets::Table.new(rows: [...], widths: [...])
|
|
22
22
|
# frame.render_stateful_widget(table, frame.area, @table_state)
|
|
23
23
|
# end
|
|
24
24
|
#
|
|
@@ -252,6 +252,30 @@ module RatatuiRuby
|
|
|
252
252
|
end
|
|
253
253
|
end
|
|
254
254
|
|
|
255
|
+
##
|
|
256
|
+
# Returns the current buffer content as an ANSI-encoded string.
|
|
257
|
+
#
|
|
258
|
+
# The rich snapshot assertion captures styled output. Sometimes you need the raw ANSI
|
|
259
|
+
# string for debugging, custom assertions, or programmatic inspection.
|
|
260
|
+
#
|
|
261
|
+
# This method renders the buffer with escape codes for colors and modifiers.
|
|
262
|
+
# You can `cat` the output to see exactly what the terminal would display.
|
|
263
|
+
#
|
|
264
|
+
# === Example
|
|
265
|
+
#
|
|
266
|
+
# with_test_terminal(80, 25) do
|
|
267
|
+
# RatatuiRuby.run do |tui|
|
|
268
|
+
# tui.draw tui.paragraph(text: "Hello", block: tui.block(title: "Test"))
|
|
269
|
+
# break
|
|
270
|
+
# end
|
|
271
|
+
# ansi_output = render_rich_buffer
|
|
272
|
+
# puts ansi_output # Shows styled output with escape codes
|
|
273
|
+
# end
|
|
274
|
+
#
|
|
275
|
+
def render_rich_buffer
|
|
276
|
+
_render_buffer_with_ansi
|
|
277
|
+
end
|
|
278
|
+
|
|
255
279
|
private def _render_buffer_with_ansi
|
|
256
280
|
RatatuiRuby.get_buffer_content # Ensure buffer is fresh if needed
|
|
257
281
|
|
|
@@ -86,7 +86,7 @@ module RatatuiRuby
|
|
|
86
86
|
#
|
|
87
87
|
# === Examples
|
|
88
88
|
#
|
|
89
|
-
# header = RatatuiRuby::Rect.new(x: 0, y: 0, width: 80, height: 1)
|
|
89
|
+
# header = RatatuiRuby::Layout::Rect.new(x: 0, y: 0, width: 80, height: 1)
|
|
90
90
|
# assert_area_style(header, bg: :blue, modifiers: [:bold])
|
|
91
91
|
#
|
|
92
92
|
# assert_area_style({ x: 0, y: 0, w: 10, h: 1 }, fg: :red)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
class TUI
|
|
8
|
+
# Buffer inspection factory methods for Session.
|
|
9
|
+
#
|
|
10
|
+
# Provides convenient access to Buffer::Cell for testing
|
|
11
|
+
# and buffer inspection purposes.
|
|
12
|
+
module BufferFactories
|
|
13
|
+
# Creates a Buffer::Cell (for testing).
|
|
14
|
+
# @return [Buffer::Cell]
|
|
15
|
+
def cell(...)
|
|
16
|
+
Buffer::Cell.new(...)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
class TUI
|
|
8
|
+
# Canvas shape factory methods for Session.
|
|
9
|
+
#
|
|
10
|
+
# Provides convenient access to Widgets::Shape::* classes
|
|
11
|
+
# for creating custom drawings on Canvas widgets.
|
|
12
|
+
module CanvasFactories
|
|
13
|
+
# Creates a map shape for Canvas.
|
|
14
|
+
# @return [Widgets::Shape::Map]
|
|
15
|
+
def shape_map(...)
|
|
16
|
+
Widgets::Shape::Map.new(...)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Creates a line shape for Canvas.
|
|
20
|
+
# @return [Widgets::Shape::Line]
|
|
21
|
+
def shape_line(...)
|
|
22
|
+
Widgets::Shape::Line.new(...)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Creates a point (single pixel) shape for Canvas.
|
|
26
|
+
# @return [Widgets::Shape::Point]
|
|
27
|
+
def shape_point(...)
|
|
28
|
+
Widgets::Shape::Point.new(...)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Creates a circle shape for Canvas.
|
|
32
|
+
# @return [Widgets::Shape::Circle]
|
|
33
|
+
def shape_circle(...)
|
|
34
|
+
Widgets::Shape::Circle.new(...)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Creates a rectangle shape for Canvas.
|
|
38
|
+
# @return [Widgets::Shape::Rectangle]
|
|
39
|
+
def shape_rectangle(...)
|
|
40
|
+
Widgets::Shape::Rectangle.new(...)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
class TUI
|
|
8
|
+
# Core terminal methods delegated to RatatuiRuby module.
|
|
9
|
+
#
|
|
10
|
+
# These are the fundamental operations for the render loop:
|
|
11
|
+
# drawing UI, polling events, and inspecting the buffer.
|
|
12
|
+
module Core
|
|
13
|
+
# Draws the given UI node tree to the terminal.
|
|
14
|
+
# @see RatatuiRuby.draw
|
|
15
|
+
def draw(tree = nil, &)
|
|
16
|
+
RatatuiRuby.draw(tree, &)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Checks for user input.
|
|
20
|
+
# @see RatatuiRuby.poll_event
|
|
21
|
+
def poll_event(timeout: 0.016)
|
|
22
|
+
RatatuiRuby.poll_event(timeout:)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Inspects the terminal buffer at specific coordinates.
|
|
26
|
+
# @see RatatuiRuby.get_cell_at
|
|
27
|
+
def get_cell_at(x, y)
|
|
28
|
+
RatatuiRuby.get_cell_at(x, y)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Creates a Draw::CellCmd for placing a cell at coordinates.
|
|
32
|
+
# @return [Draw::CellCmd]
|
|
33
|
+
def draw_cell(x, y, cell)
|
|
34
|
+
Draw.cell(x, y, cell)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
class TUI
|
|
8
|
+
# Layout factory methods for Session.
|
|
9
|
+
#
|
|
10
|
+
# Provides convenient access to Layout::Rect, Layout::Constraint,
|
|
11
|
+
# and Layout::Layout without fully qualifying the class names.
|
|
12
|
+
module LayoutFactories
|
|
13
|
+
# Creates a Layout::Rect.
|
|
14
|
+
# @return [Layout::Rect]
|
|
15
|
+
def rect(...)
|
|
16
|
+
Layout::Rect.new(...)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Creates a Layout::Constraint.
|
|
20
|
+
# @return [Layout::Constraint]
|
|
21
|
+
def constraint(...)
|
|
22
|
+
Layout::Constraint.new(...)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Creates a Layout::Constraint.length.
|
|
26
|
+
# @return [Layout::Constraint]
|
|
27
|
+
def constraint_length(n)
|
|
28
|
+
Layout::Constraint.length(n)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Creates a Layout::Constraint.percentage.
|
|
32
|
+
# @return [Layout::Constraint]
|
|
33
|
+
def constraint_percentage(n)
|
|
34
|
+
Layout::Constraint.percentage(n)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Creates a Layout::Constraint.min.
|
|
38
|
+
# @return [Layout::Constraint]
|
|
39
|
+
def constraint_min(n)
|
|
40
|
+
Layout::Constraint.min(n)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Creates a Layout::Constraint.max.
|
|
44
|
+
# @return [Layout::Constraint]
|
|
45
|
+
def constraint_max(n)
|
|
46
|
+
Layout::Constraint.max(n)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Creates a Layout::Constraint.fill.
|
|
50
|
+
# @return [Layout::Constraint]
|
|
51
|
+
def constraint_fill(n = 1)
|
|
52
|
+
Layout::Constraint.fill(n)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Creates a Layout::Constraint.ratio.
|
|
56
|
+
# @return [Layout::Constraint]
|
|
57
|
+
def constraint_ratio(numerator, denominator)
|
|
58
|
+
Layout::Constraint.ratio(numerator, denominator)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Creates a Layout::Layout.
|
|
62
|
+
# @return [Layout::Layout]
|
|
63
|
+
def layout(...)
|
|
64
|
+
Layout::Layout.new(...)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Splits an area using Layout::Layout.split.
|
|
68
|
+
# @return [Array<Layout::Rect>]
|
|
69
|
+
def layout_split(area, direction: :vertical, constraints:, flex: :legacy)
|
|
70
|
+
Layout::Layout.split(area, direction:, constraints:, flex:)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
class TUI
|
|
8
|
+
# State object factory methods for Session.
|
|
9
|
+
#
|
|
10
|
+
# Provides convenient access to stateful widget state objects
|
|
11
|
+
# (ListState, TableState, ScrollbarState) without fully
|
|
12
|
+
# qualifying the class names.
|
|
13
|
+
module StateFactories
|
|
14
|
+
# Creates a ListState.
|
|
15
|
+
# @return [ListState]
|
|
16
|
+
def list_state(...)
|
|
17
|
+
ListState.new(...)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Creates a TableState.
|
|
21
|
+
# @return [TableState]
|
|
22
|
+
def table_state(...)
|
|
23
|
+
TableState.new(...)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Creates a ScrollbarState.
|
|
27
|
+
# @return [ScrollbarState]
|
|
28
|
+
def scrollbar_state(...)
|
|
29
|
+
ScrollbarState.new(...)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
class TUI
|
|
8
|
+
# Style factory methods for Session.
|
|
9
|
+
#
|
|
10
|
+
# Provides convenient access to Style::Style without fully
|
|
11
|
+
# qualifying the class name.
|
|
12
|
+
module StyleFactories
|
|
13
|
+
# Creates a Style::Style.
|
|
14
|
+
# @return [Style::Style]
|
|
15
|
+
def style(...)
|
|
16
|
+
Style::Style.new(...)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
module RatatuiRuby
|
|
7
|
+
class TUI
|
|
8
|
+
# Text factory methods for Session.
|
|
9
|
+
#
|
|
10
|
+
# Provides convenient access to Text::Span and Text::Line
|
|
11
|
+
# without fully qualifying the class names.
|
|
12
|
+
module TextFactories
|
|
13
|
+
# Creates a Text::Span.
|
|
14
|
+
# @return [Text::Span]
|
|
15
|
+
def text_span(...)
|
|
16
|
+
Text::Span.new(...)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Creates a Text::Span (alias).
|
|
20
|
+
# @return [Text::Span]
|
|
21
|
+
def span(...)
|
|
22
|
+
Text::Span.new(...)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Creates a Text::Line.
|
|
26
|
+
# @return [Text::Line]
|
|
27
|
+
def text_line(...)
|
|
28
|
+
Text::Line.new(...)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Creates a Text::Line (alias).
|
|
32
|
+
# @return [Text::Line]
|
|
33
|
+
def line(...)
|
|
34
|
+
Text::Line.new(...)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Calculates the display width of a string.
|
|
38
|
+
# @return [Integer]
|
|
39
|
+
def text_width(string)
|
|
40
|
+
Text.width(string)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|