ratatui_ruby 0.9.1 → 0.10.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 +2 -1
- data/CHANGELOG.md +98 -0
- data/REUSE.toml +5 -0
- data/Rakefile +1 -1
- data/Steepfile +49 -0
- data/doc/concepts/debugging.md +401 -0
- data/doc/getting_started/quickstart.md +8 -3
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_color_picker.png +0 -0
- data/doc/images/app_debugging_showcase.gif +0 -0
- data/doc/images/app_debugging_showcase.png +0 -0
- data/doc/images/app_login_form.png +0 -0
- data/doc/images/app_stateful_interaction.png +0 -0
- data/doc/images/verify_quickstart_dsl.png +0 -0
- data/doc/images/verify_quickstart_layout.png +0 -0
- data/doc/images/verify_quickstart_lifecycle.png +0 -0
- data/doc/images/verify_readme_usage.png +0 -0
- data/doc/images/widget_barchart.png +0 -0
- data/doc/images/widget_block.png +0 -0
- data/doc/images/widget_box.png +0 -0
- data/doc/images/widget_calendar.png +0 -0
- data/doc/images/widget_canvas.png +0 -0
- data/doc/images/widget_cell.png +0 -0
- data/doc/images/widget_center.png +0 -0
- data/doc/images/widget_chart.png +0 -0
- data/doc/images/widget_gauge.png +0 -0
- data/doc/images/widget_layout_split.png +0 -0
- data/doc/images/widget_line_gauge.png +0 -0
- data/doc/images/widget_list.png +0 -0
- data/doc/images/widget_map.png +0 -0
- data/doc/images/widget_overlay.png +0 -0
- data/doc/images/widget_popup.png +0 -0
- data/doc/images/widget_ratatui_logo.png +0 -0
- data/doc/images/widget_ratatui_mascot.png +0 -0
- data/doc/images/widget_rect.png +0 -0
- data/doc/images/widget_render.png +0 -0
- data/doc/images/widget_rich_text.png +0 -0
- data/doc/images/widget_scroll_text.png +0 -0
- data/doc/images/widget_scrollbar.png +0 -0
- data/doc/images/widget_sparkline.png +0 -0
- data/doc/images/widget_style_colors.png +0 -0
- data/doc/images/widget_table.png +0 -0
- data/doc/images/widget_tabs.png +0 -0
- data/doc/images/widget_text_width.png +0 -0
- data/doc/troubleshooting/async.md +4 -0
- data/examples/app_debugging_showcase/README.md +119 -0
- data/examples/app_debugging_showcase/app.rb +318 -0
- data/examples/widget_canvas/app.rb +19 -14
- data/examples/widget_gauge/app.rb +18 -3
- data/examples/widget_layout_split/app.rb +10 -4
- data/examples/widget_list/app.rb +22 -6
- data/examples/widget_rect/app.rb +7 -6
- data/examples/widget_rich_text/app.rb +62 -37
- data/examples/widget_style_colors/app.rb +26 -47
- data/examples/widget_table/app.rb +28 -5
- data/examples/widget_text_width/app.rb +6 -4
- data/ext/ratatui_ruby/Cargo.lock +48 -1
- data/ext/ratatui_ruby/Cargo.toml +6 -2
- 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 +15 -14
- data/ext/ratatui_ruby/src/lib.rs +56 -0
- data/ext/ratatui_ruby/src/rendering.rs +3 -1
- data/ext/ratatui_ruby/src/style.rs +48 -21
- data/ext/ratatui_ruby/src/terminal.rs +40 -9
- data/ext/ratatui_ruby/src/text.rs +21 -9
- data/ext/ratatui_ruby/src/widgets/chart.rs +2 -1
- data/ext/ratatui_ruby/src/widgets/layout.rs +90 -2
- data/ext/ratatui_ruby/src/widgets/list.rs +6 -5
- data/ext/ratatui_ruby/src/widgets/overlay.rs +2 -1
- data/ext/ratatui_ruby/src/widgets/table.rs +7 -6
- data/ext/ratatui_ruby/src/widgets/table_state.rs +55 -0
- data/ext/ratatui_ruby/src/widgets/tabs.rs +3 -2
- data/lib/ratatui_ruby/buffer/cell.rb +25 -15
- data/lib/ratatui_ruby/buffer.rb +134 -2
- data/lib/ratatui_ruby/cell.rb +13 -5
- data/lib/ratatui_ruby/debug.rb +215 -0
- data/lib/ratatui_ruby/event/key.rb +3 -2
- data/lib/ratatui_ruby/event.rb +1 -1
- data/lib/ratatui_ruby/layout/constraint.rb +49 -0
- data/lib/ratatui_ruby/layout/layout.rb +119 -13
- data/lib/ratatui_ruby/layout/position.rb +55 -0
- data/lib/ratatui_ruby/layout/rect.rb +188 -0
- data/lib/ratatui_ruby/layout/size.rb +55 -0
- data/lib/ratatui_ruby/layout.rb +4 -0
- data/lib/ratatui_ruby/style/color.rb +149 -0
- data/lib/ratatui_ruby/style/style.rb +51 -4
- data/lib/ratatui_ruby/style.rb +2 -0
- data/lib/ratatui_ruby/symbols.rb +435 -0
- data/lib/ratatui_ruby/synthetic_events.rb +1 -1
- data/lib/ratatui_ruby/table_state.rb +51 -0
- data/lib/ratatui_ruby/terminal_lifecycle.rb +2 -1
- data/lib/ratatui_ruby/test_helper/event_injection.rb +6 -1
- data/lib/ratatui_ruby/test_helper.rb +9 -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/canvas_factories.rb +103 -0
- data/lib/ratatui_ruby/tui/core.rb +13 -2
- data/lib/ratatui_ruby/tui/layout_factories.rb +50 -3
- data/lib/ratatui_ruby/tui/state_factories.rb +42 -0
- data/lib/ratatui_ruby/tui/text_factories.rb +40 -0
- data/lib/ratatui_ruby/tui/widget_factories.rb +135 -60
- data/lib/ratatui_ruby/tui.rb +22 -1
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -0
- data/lib/ratatui_ruby/widgets/bar_chart.rb +30 -20
- data/lib/ratatui_ruby/widgets/block.rb +14 -6
- data/lib/ratatui_ruby/widgets/calendar.rb +2 -0
- data/lib/ratatui_ruby/widgets/canvas.rb +56 -0
- data/lib/ratatui_ruby/widgets/cell.rb +2 -0
- data/lib/ratatui_ruby/widgets/center.rb +2 -0
- data/lib/ratatui_ruby/widgets/chart.rb +6 -0
- data/lib/ratatui_ruby/widgets/clear.rb +2 -0
- data/lib/ratatui_ruby/widgets/coerceable_widget.rb +77 -0
- data/lib/ratatui_ruby/widgets/cursor.rb +2 -0
- data/lib/ratatui_ruby/widgets/gauge.rb +61 -3
- data/lib/ratatui_ruby/widgets/line_gauge.rb +66 -4
- data/lib/ratatui_ruby/widgets/list.rb +87 -3
- data/lib/ratatui_ruby/widgets/list_item.rb +2 -0
- data/lib/ratatui_ruby/widgets/overlay.rb +2 -0
- data/lib/ratatui_ruby/widgets/paragraph.rb +4 -0
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +2 -0
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +2 -0
- data/lib/ratatui_ruby/widgets/row.rb +45 -0
- data/lib/ratatui_ruby/widgets/scrollbar.rb +2 -0
- data/lib/ratatui_ruby/widgets/shape/label.rb +2 -0
- data/lib/ratatui_ruby/widgets/sparkline.rb +21 -13
- data/lib/ratatui_ruby/widgets/table.rb +13 -3
- data/lib/ratatui_ruby/widgets/tabs.rb +6 -4
- data/lib/ratatui_ruby/widgets.rb +1 -0
- data/lib/ratatui_ruby.rb +40 -9
- data/sig/examples/app_all_events/model/app_model.rbs +23 -0
- data/sig/examples/app_all_events/model/event_entry.rbs +15 -8
- data/sig/examples/app_all_events/model/timestamp.rbs +1 -1
- data/sig/examples/app_all_events/view.rbs +1 -1
- data/sig/examples/app_stateful_interaction/app.rbs +5 -5
- data/sig/examples/widget_block_demo/app.rbs +6 -6
- data/sig/manifest.yaml +5 -0
- data/sig/patches/data.rbs +26 -0
- data/sig/patches/debugger__.rbs +8 -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 +68 -8
- data/sig/ratatui_ruby/frame.rbs +4 -4
- data/sig/ratatui_ruby/interfaces.rbs +25 -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/output_guard.rbs +23 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +83 -4
- data/sig/ratatui_ruby/rect.rbs +17 -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 +21 -0
- data/sig/ratatui_ruby/table_state.rbs +6 -0
- data/sig/ratatui_ruby/terminal_lifecycle.rbs +31 -0
- data/sig/ratatui_ruby/test_helper/event_injection.rbs +2 -2
- data/sig/ratatui_ruby/test_helper/snapshot.rbs +22 -3
- data/sig/ratatui_ruby/test_helper/style_assertions.rbs +8 -1
- data/sig/ratatui_ruby/test_helper/test_doubles.rbs +7 -3
- 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 +1 -1
- data/sig/ratatui_ruby/tui/canvas_factories.rbs +23 -5
- data/sig/ratatui_ruby/tui/core.rbs +2 -2
- data/sig/ratatui_ruby/tui/layout_factories.rbs +16 -2
- data/sig/ratatui_ruby/tui/state_factories.rbs +8 -3
- data/sig/ratatui_ruby/tui/style_factories.rbs +3 -1
- data/sig/ratatui_ruby/tui/text_factories.rbs +7 -4
- data/sig/ratatui_ruby/tui/widget_factories.rbs +123 -30
- 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/{schema/list_item.rbs → widgets.rbs} +4 -4
- data/tasks/steep.rake +11 -0
- metadata +80 -63
- data/doc/contributors/v1.0.0_blockers.md +0 -870
- data/doc/troubleshooting/debugging.md +0 -101
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +0 -47
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +0 -25
- data/lib/ratatui_ruby/schema/bar_chart.rb +0 -287
- data/lib/ratatui_ruby/schema/block.rb +0 -198
- data/lib/ratatui_ruby/schema/calendar.rb +0 -84
- data/lib/ratatui_ruby/schema/canvas.rb +0 -239
- data/lib/ratatui_ruby/schema/center.rb +0 -67
- data/lib/ratatui_ruby/schema/chart.rb +0 -159
- data/lib/ratatui_ruby/schema/clear.rb +0 -62
- data/lib/ratatui_ruby/schema/constraint.rb +0 -151
- data/lib/ratatui_ruby/schema/cursor.rb +0 -50
- data/lib/ratatui_ruby/schema/gauge.rb +0 -72
- data/lib/ratatui_ruby/schema/layout.rb +0 -122
- data/lib/ratatui_ruby/schema/line_gauge.rb +0 -80
- data/lib/ratatui_ruby/schema/list.rb +0 -135
- data/lib/ratatui_ruby/schema/list_item.rb +0 -51
- data/lib/ratatui_ruby/schema/overlay.rb +0 -51
- data/lib/ratatui_ruby/schema/paragraph.rb +0 -107
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +0 -31
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +0 -36
- data/lib/ratatui_ruby/schema/rect.rb +0 -174
- data/lib/ratatui_ruby/schema/row.rb +0 -76
- data/lib/ratatui_ruby/schema/scrollbar.rb +0 -143
- data/lib/ratatui_ruby/schema/shape/label.rb +0 -76
- data/lib/ratatui_ruby/schema/sparkline.rb +0 -142
- data/lib/ratatui_ruby/schema/style.rb +0 -97
- data/lib/ratatui_ruby/schema/table.rb +0 -141
- data/lib/ratatui_ruby/schema/tabs.rb +0 -85
- data/lib/ratatui_ruby/schema/text.rb +0 -217
- data/sig/examples/app_all_events/model/events.rbs +0 -15
- data/sig/examples/app_all_events/view_state.rbs +0 -21
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +0 -22
- data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +0 -19
- data/sig/ratatui_ruby/schema/bar_chart.rbs +0 -38
- data/sig/ratatui_ruby/schema/block.rbs +0 -18
- data/sig/ratatui_ruby/schema/calendar.rbs +0 -23
- data/sig/ratatui_ruby/schema/canvas.rbs +0 -81
- data/sig/ratatui_ruby/schema/center.rbs +0 -17
- data/sig/ratatui_ruby/schema/chart.rbs +0 -39
- data/sig/ratatui_ruby/schema/constraint.rbs +0 -30
- data/sig/ratatui_ruby/schema/cursor.rbs +0 -16
- data/sig/ratatui_ruby/schema/draw.rbs +0 -33
- data/sig/ratatui_ruby/schema/gauge.rbs +0 -23
- data/sig/ratatui_ruby/schema/layout.rbs +0 -27
- data/sig/ratatui_ruby/schema/line_gauge.rbs +0 -24
- data/sig/ratatui_ruby/schema/list.rbs +0 -28
- data/sig/ratatui_ruby/schema/overlay.rbs +0 -15
- data/sig/ratatui_ruby/schema/paragraph.rbs +0 -20
- data/sig/ratatui_ruby/schema/ratatui_logo.rbs +0 -14
- data/sig/ratatui_ruby/schema/ratatui_mascot.rbs +0 -17
- data/sig/ratatui_ruby/schema/rect.rbs +0 -48
- data/sig/ratatui_ruby/schema/row.rbs +0 -28
- data/sig/ratatui_ruby/schema/scrollbar.rbs +0 -42
- data/sig/ratatui_ruby/schema/sparkline.rbs +0 -22
- data/sig/ratatui_ruby/schema/style.rbs +0 -19
- data/sig/ratatui_ruby/schema/table.rbs +0 -32
- data/sig/ratatui_ruby/schema/tabs.rbs +0 -21
- data/sig/ratatui_ruby/schema/text.rbs +0 -31
- /data/lib/ratatui_ruby/{schema/draw.rb → draw.rb} +0 -0
|
@@ -0,0 +1,435 @@
|
|
|
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
|
+
# Symbol constants from Ratatui's symbols module.
|
|
10
|
+
#
|
|
11
|
+
# Ratatui provides various character sets for rendering UI elements.
|
|
12
|
+
# Hardcoding these characters is error-prone and makes code less readable.
|
|
13
|
+
#
|
|
14
|
+
# This module exposes those constants for Ruby apps to use directly.
|
|
15
|
+
# Use them for gradients, fills, or custom widget styling.
|
|
16
|
+
module Symbols
|
|
17
|
+
# Shade characters for creating gradient or density effects.
|
|
18
|
+
#
|
|
19
|
+
# Terminal UIs often need to show density levels or create visual gradients.
|
|
20
|
+
# Memorizing Unicode block characters is tedious and error-prone.
|
|
21
|
+
#
|
|
22
|
+
# These constants provide named access to the standard shade characters.
|
|
23
|
+
# Use them to fill areas with varying visual densities.
|
|
24
|
+
#
|
|
25
|
+
# === Examples
|
|
26
|
+
#
|
|
27
|
+
#--
|
|
28
|
+
# SPDX-SnippetBegin
|
|
29
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
30
|
+
# SPDX-License-Identifier: MIT-0
|
|
31
|
+
#++
|
|
32
|
+
# # Create a density gradient
|
|
33
|
+
# gradient = [Shade::EMPTY, Shade::LIGHT, Shade::MEDIUM, Shade::DARK, Shade::FULL]
|
|
34
|
+
#
|
|
35
|
+
# # Use in a progress indicator
|
|
36
|
+
# filled = Shade::FULL * progress
|
|
37
|
+
# empty = Shade::LIGHT * (total - progress)
|
|
38
|
+
#--
|
|
39
|
+
# SPDX-SnippetEnd
|
|
40
|
+
#++
|
|
41
|
+
module Shade
|
|
42
|
+
# Empty space - 0% density.
|
|
43
|
+
EMPTY = " "
|
|
44
|
+
|
|
45
|
+
# Light shading - approximately 25% density.
|
|
46
|
+
LIGHT = "░"
|
|
47
|
+
|
|
48
|
+
# Medium shading - approximately 50% density.
|
|
49
|
+
MEDIUM = "▒"
|
|
50
|
+
|
|
51
|
+
# Dark shading - approximately 75% density.
|
|
52
|
+
DARK = "▓"
|
|
53
|
+
|
|
54
|
+
# Full block - 100% density.
|
|
55
|
+
FULL = "█"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Box-drawing characters for borders and lines.
|
|
59
|
+
#
|
|
60
|
+
# Terminal UIs need consistent box-drawing characters for borders and dividers.
|
|
61
|
+
# Memorizing Unicode box-drawing characters is tedious and error-prone.
|
|
62
|
+
#
|
|
63
|
+
# This module exposes both individual characters and predefined sets.
|
|
64
|
+
# Use the sets with widgets that accept a line_set parameter, or use
|
|
65
|
+
# individual characters for custom drawing.
|
|
66
|
+
#
|
|
67
|
+
# === Examples
|
|
68
|
+
#
|
|
69
|
+
#--
|
|
70
|
+
# SPDX-SnippetBegin
|
|
71
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
72
|
+
# SPDX-License-Identifier: MIT-0
|
|
73
|
+
#++
|
|
74
|
+
# # Use a predefined set for drawing boxes
|
|
75
|
+
# line_set = Symbols::Line::ROUNDED
|
|
76
|
+
#
|
|
77
|
+
# # Draw a simple frame
|
|
78
|
+
# top = "#{line_set[:top_left]}#{line_set[:horizontal] * 10}#{line_set[:top_right]}"
|
|
79
|
+
# mid = "#{line_set[:vertical]}#{' ' * 10}#{line_set[:vertical]}"
|
|
80
|
+
# bot = "#{line_set[:bottom_left]}#{line_set[:horizontal] * 10}#{line_set[:bottom_right]}"
|
|
81
|
+
#
|
|
82
|
+
# # Use individual characters for custom drawing
|
|
83
|
+
# corner = Symbols::Line::ROUNDED_TOP_LEFT # => "╭"
|
|
84
|
+
#--
|
|
85
|
+
# SPDX-SnippetEnd
|
|
86
|
+
#++
|
|
87
|
+
module Line
|
|
88
|
+
# Standard vertical line.
|
|
89
|
+
VERTICAL = "│"
|
|
90
|
+
# Double vertical line.
|
|
91
|
+
DOUBLE_VERTICAL = "║"
|
|
92
|
+
# Thick (heavy) vertical line.
|
|
93
|
+
THICK_VERTICAL = "┃"
|
|
94
|
+
|
|
95
|
+
# Standard horizontal line.
|
|
96
|
+
HORIZONTAL = "─"
|
|
97
|
+
# Double horizontal line.
|
|
98
|
+
DOUBLE_HORIZONTAL = "═"
|
|
99
|
+
# Thick (heavy) horizontal line.
|
|
100
|
+
THICK_HORIZONTAL = "━"
|
|
101
|
+
|
|
102
|
+
# Standard top-right corner.
|
|
103
|
+
TOP_RIGHT = "┐"
|
|
104
|
+
# Rounded top-right corner.
|
|
105
|
+
ROUNDED_TOP_RIGHT = "╮"
|
|
106
|
+
# Double top-right corner.
|
|
107
|
+
DOUBLE_TOP_RIGHT = "╗"
|
|
108
|
+
# Thick top-right corner.
|
|
109
|
+
THICK_TOP_RIGHT = "┓"
|
|
110
|
+
|
|
111
|
+
# Standard top-left corner.
|
|
112
|
+
TOP_LEFT = "┌"
|
|
113
|
+
# Rounded top-left corner.
|
|
114
|
+
ROUNDED_TOP_LEFT = "╭"
|
|
115
|
+
# Double top-left corner.
|
|
116
|
+
DOUBLE_TOP_LEFT = "╔"
|
|
117
|
+
# Thick top-left corner.
|
|
118
|
+
THICK_TOP_LEFT = "┏"
|
|
119
|
+
|
|
120
|
+
# Standard bottom-right corner.
|
|
121
|
+
BOTTOM_RIGHT = "┘"
|
|
122
|
+
# Rounded bottom-right corner.
|
|
123
|
+
ROUNDED_BOTTOM_RIGHT = "╯"
|
|
124
|
+
# Double bottom-right corner.
|
|
125
|
+
DOUBLE_BOTTOM_RIGHT = "╝"
|
|
126
|
+
# Thick bottom-right corner.
|
|
127
|
+
THICK_BOTTOM_RIGHT = "┛"
|
|
128
|
+
|
|
129
|
+
# Standard bottom-left corner.
|
|
130
|
+
BOTTOM_LEFT = "└"
|
|
131
|
+
# Rounded bottom-left corner.
|
|
132
|
+
ROUNDED_BOTTOM_LEFT = "╰"
|
|
133
|
+
# Double bottom-left corner.
|
|
134
|
+
DOUBLE_BOTTOM_LEFT = "╚"
|
|
135
|
+
# Thick bottom-left corner.
|
|
136
|
+
THICK_BOTTOM_LEFT = "┗"
|
|
137
|
+
|
|
138
|
+
# Standard T-junction pointing left.
|
|
139
|
+
VERTICAL_LEFT = "┤"
|
|
140
|
+
# Double T-junction pointing left.
|
|
141
|
+
DOUBLE_VERTICAL_LEFT = "╣"
|
|
142
|
+
# Thick T-junction pointing left.
|
|
143
|
+
THICK_VERTICAL_LEFT = "┫"
|
|
144
|
+
|
|
145
|
+
# Standard T-junction pointing right.
|
|
146
|
+
VERTICAL_RIGHT = "├"
|
|
147
|
+
# Double T-junction pointing right.
|
|
148
|
+
DOUBLE_VERTICAL_RIGHT = "╠"
|
|
149
|
+
# Thick T-junction pointing right.
|
|
150
|
+
THICK_VERTICAL_RIGHT = "┣"
|
|
151
|
+
|
|
152
|
+
# Standard T-junction pointing down.
|
|
153
|
+
HORIZONTAL_DOWN = "┬"
|
|
154
|
+
# Double T-junction pointing down.
|
|
155
|
+
DOUBLE_HORIZONTAL_DOWN = "╦"
|
|
156
|
+
# Thick T-junction pointing down.
|
|
157
|
+
THICK_HORIZONTAL_DOWN = "┳"
|
|
158
|
+
|
|
159
|
+
# Standard T-junction pointing up.
|
|
160
|
+
HORIZONTAL_UP = "┴"
|
|
161
|
+
# Double T-junction pointing up.
|
|
162
|
+
DOUBLE_HORIZONTAL_UP = "╩"
|
|
163
|
+
# Thick T-junction pointing up.
|
|
164
|
+
THICK_HORIZONTAL_UP = "┻"
|
|
165
|
+
|
|
166
|
+
# Standard cross (4-way intersection).
|
|
167
|
+
CROSS = "┼"
|
|
168
|
+
# Double cross (4-way intersection).
|
|
169
|
+
DOUBLE_CROSS = "╬"
|
|
170
|
+
# Thick cross (4-way intersection).
|
|
171
|
+
THICK_CROSS = "╋"
|
|
172
|
+
|
|
173
|
+
# Standard box-drawing set with straight corners.
|
|
174
|
+
NORMAL = {
|
|
175
|
+
vertical: VERTICAL,
|
|
176
|
+
horizontal: HORIZONTAL,
|
|
177
|
+
top_right: TOP_RIGHT,
|
|
178
|
+
top_left: TOP_LEFT,
|
|
179
|
+
bottom_right: BOTTOM_RIGHT,
|
|
180
|
+
bottom_left: BOTTOM_LEFT,
|
|
181
|
+
vertical_left: VERTICAL_LEFT,
|
|
182
|
+
vertical_right: VERTICAL_RIGHT,
|
|
183
|
+
horizontal_down: HORIZONTAL_DOWN,
|
|
184
|
+
horizontal_up: HORIZONTAL_UP,
|
|
185
|
+
cross: CROSS,
|
|
186
|
+
}.freeze
|
|
187
|
+
|
|
188
|
+
# Box-drawing set with rounded corners.
|
|
189
|
+
ROUNDED = {
|
|
190
|
+
vertical: VERTICAL,
|
|
191
|
+
horizontal: HORIZONTAL,
|
|
192
|
+
top_right: ROUNDED_TOP_RIGHT,
|
|
193
|
+
top_left: ROUNDED_TOP_LEFT,
|
|
194
|
+
bottom_right: ROUNDED_BOTTOM_RIGHT,
|
|
195
|
+
bottom_left: ROUNDED_BOTTOM_LEFT,
|
|
196
|
+
vertical_left: VERTICAL_LEFT,
|
|
197
|
+
vertical_right: VERTICAL_RIGHT,
|
|
198
|
+
horizontal_down: HORIZONTAL_DOWN,
|
|
199
|
+
horizontal_up: HORIZONTAL_UP,
|
|
200
|
+
cross: CROSS,
|
|
201
|
+
}.freeze
|
|
202
|
+
|
|
203
|
+
# Double-line box-drawing set.
|
|
204
|
+
DOUBLE = {
|
|
205
|
+
vertical: DOUBLE_VERTICAL,
|
|
206
|
+
horizontal: DOUBLE_HORIZONTAL,
|
|
207
|
+
top_right: DOUBLE_TOP_RIGHT,
|
|
208
|
+
top_left: DOUBLE_TOP_LEFT,
|
|
209
|
+
bottom_right: DOUBLE_BOTTOM_RIGHT,
|
|
210
|
+
bottom_left: DOUBLE_BOTTOM_LEFT,
|
|
211
|
+
vertical_left: DOUBLE_VERTICAL_LEFT,
|
|
212
|
+
vertical_right: DOUBLE_VERTICAL_RIGHT,
|
|
213
|
+
horizontal_down: DOUBLE_HORIZONTAL_DOWN,
|
|
214
|
+
horizontal_up: DOUBLE_HORIZONTAL_UP,
|
|
215
|
+
cross: DOUBLE_CROSS,
|
|
216
|
+
}.freeze
|
|
217
|
+
|
|
218
|
+
# Thick (heavy) box-drawing set.
|
|
219
|
+
THICK = {
|
|
220
|
+
vertical: THICK_VERTICAL,
|
|
221
|
+
horizontal: THICK_HORIZONTAL,
|
|
222
|
+
top_right: THICK_TOP_RIGHT,
|
|
223
|
+
top_left: THICK_TOP_LEFT,
|
|
224
|
+
bottom_right: THICK_BOTTOM_RIGHT,
|
|
225
|
+
bottom_left: THICK_BOTTOM_LEFT,
|
|
226
|
+
vertical_left: THICK_VERTICAL_LEFT,
|
|
227
|
+
vertical_right: THICK_VERTICAL_RIGHT,
|
|
228
|
+
horizontal_down: THICK_HORIZONTAL_DOWN,
|
|
229
|
+
horizontal_up: THICK_HORIZONTAL_UP,
|
|
230
|
+
cross: THICK_CROSS,
|
|
231
|
+
}.freeze
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Vertical bar characters for sparklines and bar charts.
|
|
235
|
+
#
|
|
236
|
+
# Sparklines and vertical bar charts need characters that show partial fill.
|
|
237
|
+
# Memorizing Unicode lower block characters is tedious and error-prone.
|
|
238
|
+
#
|
|
239
|
+
# This module exposes both individual characters and predefined sets.
|
|
240
|
+
# Use the sets with Sparkline widget, or use individual characters for
|
|
241
|
+
# custom visualizations.
|
|
242
|
+
#
|
|
243
|
+
# === Examples
|
|
244
|
+
#
|
|
245
|
+
#--
|
|
246
|
+
# SPDX-SnippetBegin
|
|
247
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
248
|
+
# SPDX-License-Identifier: MIT-0
|
|
249
|
+
#++
|
|
250
|
+
# # Use NINE_LEVELS for high-resolution sparklines (default)
|
|
251
|
+
# sparkline = tui.sparkline(data: [1, 2, 3], bar_set: Symbols::Bar::NINE_LEVELS)
|
|
252
|
+
#
|
|
253
|
+
# # Use THREE_LEVELS for simpler rendering
|
|
254
|
+
# sparkline = tui.sparkline(data: [1, 2, 3], bar_set: Symbols::Bar::THREE_LEVELS)
|
|
255
|
+
#--
|
|
256
|
+
# SPDX-SnippetEnd
|
|
257
|
+
#++
|
|
258
|
+
module Bar
|
|
259
|
+
# Full height bar (8/8).
|
|
260
|
+
FULL = "█"
|
|
261
|
+
# 7/8 height bar.
|
|
262
|
+
SEVEN_EIGHTHS = "▇"
|
|
263
|
+
# 3/4 height bar (6/8).
|
|
264
|
+
THREE_QUARTERS = "▆"
|
|
265
|
+
# 5/8 height bar.
|
|
266
|
+
FIVE_EIGHTHS = "▅"
|
|
267
|
+
# Half height bar (4/8).
|
|
268
|
+
HALF = "▄"
|
|
269
|
+
# 3/8 height bar.
|
|
270
|
+
THREE_EIGHTHS = "▃"
|
|
271
|
+
# 1/4 height bar (2/8).
|
|
272
|
+
ONE_QUARTER = "▂"
|
|
273
|
+
# 1/8 height bar.
|
|
274
|
+
ONE_EIGHTH = "▁"
|
|
275
|
+
|
|
276
|
+
# High-resolution bar set with 9 distinct levels.
|
|
277
|
+
NINE_LEVELS = {
|
|
278
|
+
full: FULL,
|
|
279
|
+
seven_eighths: SEVEN_EIGHTHS,
|
|
280
|
+
three_quarters: THREE_QUARTERS,
|
|
281
|
+
five_eighths: FIVE_EIGHTHS,
|
|
282
|
+
half: HALF,
|
|
283
|
+
three_eighths: THREE_EIGHTHS,
|
|
284
|
+
one_quarter: ONE_QUARTER,
|
|
285
|
+
one_eighth: ONE_EIGHTH,
|
|
286
|
+
empty: " ",
|
|
287
|
+
}.freeze
|
|
288
|
+
|
|
289
|
+
# Low-resolution bar set with 3 levels (full, half, empty).
|
|
290
|
+
THREE_LEVELS = {
|
|
291
|
+
full: FULL,
|
|
292
|
+
seven_eighths: FULL, # collapsed to full
|
|
293
|
+
three_quarters: HALF, # collapsed to half
|
|
294
|
+
five_eighths: HALF, # collapsed to half
|
|
295
|
+
half: HALF,
|
|
296
|
+
three_eighths: HALF, # collapsed to half
|
|
297
|
+
one_quarter: HALF, # collapsed to half
|
|
298
|
+
one_eighth: " ", # collapsed to empty
|
|
299
|
+
empty: " ",
|
|
300
|
+
}.freeze
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Horizontal block characters for gauges and progress indicators.
|
|
304
|
+
#
|
|
305
|
+
# Progress bars and gauges need characters that show partial fill from left to right.
|
|
306
|
+
# Memorizing Unicode left block characters is tedious and error-prone.
|
|
307
|
+
#
|
|
308
|
+
# This module exposes both individual characters and predefined sets.
|
|
309
|
+
# Use the sets with Gauge widget, or use individual characters for
|
|
310
|
+
# custom progress indicators.
|
|
311
|
+
#
|
|
312
|
+
# Note: Block uses LEFT block characters (fill from left) while Bar uses
|
|
313
|
+
# LOWER block characters (fill from bottom). They look similar but are different.
|
|
314
|
+
#
|
|
315
|
+
# === Examples
|
|
316
|
+
#
|
|
317
|
+
#--
|
|
318
|
+
# SPDX-SnippetBegin
|
|
319
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
320
|
+
# SPDX-License-Identifier: MIT-0
|
|
321
|
+
#++
|
|
322
|
+
# # Use NINE_LEVELS for high-resolution gauges (default)
|
|
323
|
+
# gauge = tui.gauge(percent: 50, block_set: Symbols::Block::NINE_LEVELS)
|
|
324
|
+
#
|
|
325
|
+
# # Use THREE_LEVELS for simpler rendering
|
|
326
|
+
# gauge = tui.gauge(percent: 50, block_set: Symbols::Block::THREE_LEVELS)
|
|
327
|
+
#--
|
|
328
|
+
# SPDX-SnippetEnd
|
|
329
|
+
#++
|
|
330
|
+
module Block
|
|
331
|
+
# Full width block (8/8).
|
|
332
|
+
FULL = "█"
|
|
333
|
+
# 7/8 width block.
|
|
334
|
+
SEVEN_EIGHTHS = "▉"
|
|
335
|
+
# 3/4 width block (6/8).
|
|
336
|
+
THREE_QUARTERS = "▊"
|
|
337
|
+
# 5/8 width block.
|
|
338
|
+
FIVE_EIGHTHS = "▋"
|
|
339
|
+
# Half width block (4/8).
|
|
340
|
+
HALF = "▌"
|
|
341
|
+
# 3/8 width block.
|
|
342
|
+
THREE_EIGHTHS = "▍"
|
|
343
|
+
# 1/4 width block (2/8).
|
|
344
|
+
ONE_QUARTER = "▎"
|
|
345
|
+
# 1/8 width block.
|
|
346
|
+
ONE_EIGHTH = "▏"
|
|
347
|
+
|
|
348
|
+
# High-resolution block set with 9 distinct levels.
|
|
349
|
+
NINE_LEVELS = {
|
|
350
|
+
full: FULL,
|
|
351
|
+
seven_eighths: SEVEN_EIGHTHS,
|
|
352
|
+
three_quarters: THREE_QUARTERS,
|
|
353
|
+
five_eighths: FIVE_EIGHTHS,
|
|
354
|
+
half: HALF,
|
|
355
|
+
three_eighths: THREE_EIGHTHS,
|
|
356
|
+
one_quarter: ONE_QUARTER,
|
|
357
|
+
one_eighth: ONE_EIGHTH,
|
|
358
|
+
empty: " ",
|
|
359
|
+
}.freeze
|
|
360
|
+
|
|
361
|
+
# Low-resolution block set with 3 levels (full, half, empty).
|
|
362
|
+
THREE_LEVELS = {
|
|
363
|
+
full: FULL,
|
|
364
|
+
seven_eighths: FULL, # collapsed to full
|
|
365
|
+
three_quarters: HALF, # collapsed to half
|
|
366
|
+
five_eighths: HALF, # collapsed to half
|
|
367
|
+
half: HALF,
|
|
368
|
+
three_eighths: HALF, # collapsed to half
|
|
369
|
+
one_quarter: HALF, # collapsed to half
|
|
370
|
+
one_eighth: " ", # collapsed to empty
|
|
371
|
+
empty: " ",
|
|
372
|
+
}.freeze
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# Scrollbar symbol sets for the Scrollbar widget.
|
|
376
|
+
#
|
|
377
|
+
# Scrollbars need consistent visual elements: a track, a thumb, and arrow indicators.
|
|
378
|
+
# Memorizing Unicode scroll characters is tedious and error-prone.
|
|
379
|
+
#
|
|
380
|
+
# This module exposes predefined sets with different visual styles.
|
|
381
|
+
# Use them with the Scrollbar widget to customize its appearance.
|
|
382
|
+
#
|
|
383
|
+
# Note: Uses <tt>begin_char</tt> and <tt>end_char</tt> instead of Rust's
|
|
384
|
+
# <tt>begin</tt>/<tt>end</tt> to avoid Ruby reserved word conflicts.
|
|
385
|
+
#
|
|
386
|
+
# === Examples
|
|
387
|
+
#
|
|
388
|
+
#--
|
|
389
|
+
# SPDX-SnippetBegin
|
|
390
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
391
|
+
# SPDX-License-Identifier: MIT-0
|
|
392
|
+
#++
|
|
393
|
+
# # Use DOUBLE_VERTICAL for bold vertical scrollbars (default)
|
|
394
|
+
# scrollbar = tui.scrollbar(symbols: Symbols::Scrollbar::DOUBLE_VERTICAL)
|
|
395
|
+
#
|
|
396
|
+
# # Use VERTICAL for lighter appearance
|
|
397
|
+
# scrollbar = tui.scrollbar(symbols: Symbols::Scrollbar::VERTICAL)
|
|
398
|
+
#--
|
|
399
|
+
# SPDX-SnippetEnd
|
|
400
|
+
#++
|
|
401
|
+
module Scrollbar
|
|
402
|
+
# Double-line vertical scrollbar with triangle arrows.
|
|
403
|
+
DOUBLE_VERTICAL = {
|
|
404
|
+
track: Line::DOUBLE_VERTICAL,
|
|
405
|
+
thumb: Block::FULL,
|
|
406
|
+
begin_char: "▲",
|
|
407
|
+
end_char: "▼",
|
|
408
|
+
}.freeze
|
|
409
|
+
|
|
410
|
+
# Double-line horizontal scrollbar with triangle arrows.
|
|
411
|
+
DOUBLE_HORIZONTAL = {
|
|
412
|
+
track: Line::DOUBLE_HORIZONTAL,
|
|
413
|
+
thumb: Block::FULL,
|
|
414
|
+
begin_char: "◄",
|
|
415
|
+
end_char: "►",
|
|
416
|
+
}.freeze
|
|
417
|
+
|
|
418
|
+
# Single-line vertical scrollbar with arrow characters.
|
|
419
|
+
VERTICAL = {
|
|
420
|
+
track: Line::VERTICAL,
|
|
421
|
+
thumb: Block::FULL,
|
|
422
|
+
begin_char: "↑",
|
|
423
|
+
end_char: "↓",
|
|
424
|
+
}.freeze
|
|
425
|
+
|
|
426
|
+
# Single-line horizontal scrollbar with arrow characters.
|
|
427
|
+
HORIZONTAL = {
|
|
428
|
+
track: Line::HORIZONTAL,
|
|
429
|
+
thumb: Block::FULL,
|
|
430
|
+
begin_char: "←",
|
|
431
|
+
end_char: "→",
|
|
432
|
+
}.freeze
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
end
|
|
@@ -96,5 +96,56 @@ module RatatuiRuby
|
|
|
96
96
|
# Scrolls up by +n+ rows.
|
|
97
97
|
#
|
|
98
98
|
# (Native method implemented in Rust)
|
|
99
|
+
|
|
100
|
+
##
|
|
101
|
+
# :method: selected_cell
|
|
102
|
+
# :call-seq: selected_cell() -> Array or nil
|
|
103
|
+
#
|
|
104
|
+
# Returns the currently selected cell as <tt>[row, column]</tt>.
|
|
105
|
+
# Returns +nil+ if either row or column is not selected.
|
|
106
|
+
#
|
|
107
|
+
# (Native method implemented in Rust)
|
|
108
|
+
|
|
109
|
+
##
|
|
110
|
+
# :method: select_next_column
|
|
111
|
+
# :call-seq: select_next_column() -> nil
|
|
112
|
+
#
|
|
113
|
+
# Selects the next column, or column 0 if none selected.
|
|
114
|
+
#
|
|
115
|
+
# (Native method implemented in Rust)
|
|
116
|
+
|
|
117
|
+
##
|
|
118
|
+
# :method: select_previous_column
|
|
119
|
+
# :call-seq: select_previous_column() -> nil
|
|
120
|
+
#
|
|
121
|
+
# Selects the previous column. Saturates at 0.
|
|
122
|
+
#
|
|
123
|
+
# (Native method implemented in Rust)
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
# :method: select_first_column
|
|
127
|
+
# :call-seq: select_first_column() -> nil
|
|
128
|
+
#
|
|
129
|
+
# Selects column 0.
|
|
130
|
+
#
|
|
131
|
+
# (Native method implemented in Rust)
|
|
132
|
+
|
|
133
|
+
##
|
|
134
|
+
# :method: select_last_column
|
|
135
|
+
# :call-seq: select_last_column() -> nil
|
|
136
|
+
#
|
|
137
|
+
# Selects the last column. The index is clamped during rendering.
|
|
138
|
+
#
|
|
139
|
+
# (Native method implemented in Rust)
|
|
140
|
+
|
|
141
|
+
##
|
|
142
|
+
# :singleton-method: with_selected_cell
|
|
143
|
+
# :call-seq: with_selected_cell(cell) -> TableState
|
|
144
|
+
#
|
|
145
|
+
# Creates a new TableState with both row and column selected.
|
|
146
|
+
#
|
|
147
|
+
# [cell] <tt>[row, column]</tt> array, or +nil+.
|
|
148
|
+
#
|
|
149
|
+
# (Native method implemented in Rust)
|
|
99
150
|
end
|
|
100
151
|
end
|
|
@@ -90,7 +90,7 @@ module RatatuiRuby
|
|
|
90
90
|
##
|
|
91
91
|
# Restores the terminal to its original state.
|
|
92
92
|
# Leaves alternate screen and disables raw mode.
|
|
93
|
-
# Also flushes any deferred warnings that were queued during the session.
|
|
93
|
+
# Also flushes any deferred warnings and panic info that were queued during the session.
|
|
94
94
|
#
|
|
95
95
|
# In headless mode ({headless!}), this method is a silent no-op since
|
|
96
96
|
# no terminal was ever initialized.
|
|
@@ -103,6 +103,7 @@ module RatatuiRuby
|
|
|
103
103
|
ensure
|
|
104
104
|
@tui_session_active = false
|
|
105
105
|
flush_warnings
|
|
106
|
+
flush_panic_info
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
##
|
|
@@ -64,7 +64,7 @@ module RatatuiRuby
|
|
|
64
64
|
# [event] A <tt>RatatuiRuby::Event</tt> object.
|
|
65
65
|
def inject_event(event)
|
|
66
66
|
unless @_ratatui_test_terminal_active
|
|
67
|
-
raise "Events must be injected inside a `with_test_terminal` block. " \
|
|
67
|
+
raise RatatuiRuby::Error::Invariant, "Events must be injected inside a `with_test_terminal` block. " \
|
|
68
68
|
"Calling this method outside the block causes a race condition where the event " \
|
|
69
69
|
"is flushed before the application starts."
|
|
70
70
|
end
|
|
@@ -209,6 +209,11 @@ module RatatuiRuby
|
|
|
209
209
|
# pending async operations to complete before processing the next event.
|
|
210
210
|
# This enables deterministic testing of async behavior.
|
|
211
211
|
#
|
|
212
|
+
# *Important*: Sync waits for commands to _complete_. Do not use it
|
|
213
|
+
# with long-running commands that wait indefinitely (e.g., for
|
|
214
|
+
# cancellation). Those commands will block forever, causing a timeout.
|
|
215
|
+
# For cancellation tests, dispatch the cancel command without Sync.
|
|
216
|
+
#
|
|
212
217
|
# === Example
|
|
213
218
|
#
|
|
214
219
|
#--
|
|
@@ -92,6 +92,15 @@ module RatatuiRuby
|
|
|
92
92
|
# SPDX-SnippetEnd
|
|
93
93
|
#++
|
|
94
94
|
module TestHelper
|
|
95
|
+
##
|
|
96
|
+
# Auto-enables debug mode when TestHelper is included.
|
|
97
|
+
#
|
|
98
|
+
# This ensures Rust backtraces are available in tests.
|
|
99
|
+
# Skips remote debugging since tests don't need it.
|
|
100
|
+
def self.included(base)
|
|
101
|
+
RatatuiRuby::Debug.enable!(source: :test)
|
|
102
|
+
end
|
|
103
|
+
|
|
95
104
|
include Terminal
|
|
96
105
|
include Snapshot
|
|
97
106
|
include EventInjection
|