ratatui_ruby 1.0.0 → 1.0.1
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/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/lib/ratatui_ruby/version.rb +1 -1
- metadata +1 -232
- data/.builds/ruby-3.2.yml +0 -54
- data/.builds/ruby-3.3.yml +0 -54
- data/.builds/ruby-3.4.yml +0 -54
- data/.builds/ruby-4.0.0.yml +0 -54
- data/.pre-commit-config.yaml +0 -16
- data/.rubocop.yml +0 -10
- data/AGENTS.md +0 -146
- data/CHANGELOG.md +0 -710
- data/README.md +0 -187
- data/README.rdoc +0 -302
- data/Rakefile +0 -11
- data/Steepfile +0 -49
- data/doc/concepts/application_architecture.md +0 -321
- data/doc/concepts/application_testing.md +0 -193
- data/doc/concepts/async.md +0 -190
- data/doc/concepts/custom_widgets.md +0 -247
- data/doc/concepts/debugging.md +0 -401
- data/doc/concepts/event_handling.md +0 -162
- data/doc/concepts/interactive_design.md +0 -146
- data/doc/contributors/auditing/parity.md +0 -239
- data/doc/contributors/design/ruby_frontend.md +0 -420
- data/doc/contributors/design/rust_backend.md +0 -422
- data/doc/contributors/design.md +0 -11
- data/doc/contributors/developing_examples.md +0 -400
- data/doc/contributors/documentation_style.md +0 -121
- data/doc/contributors/index.md +0 -21
- data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -375
- data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -206
- data/doc/contributors/todo/align/terminal.md +0 -647
- data/doc/contributors/todo/future_work.md +0 -169
- data/doc/contributors/upstream_requests/tab_rects.md +0 -173
- data/doc/contributors/upstream_requests/title_rects.md +0 -132
- data/doc/custom.css +0 -22
- data/doc/getting_started/quickstart.md +0 -291
- data/doc/getting_started/why.md +0 -93
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_cli_rich_moments.gif +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/index.md +0 -39
- data/doc/troubleshooting/async.md +0 -4
- data/doc/troubleshooting/terminal_limitations.md +0 -131
- data/doc/troubleshooting/tui_output.md +0 -197
- data/examples/app_all_events/README.md +0 -114
- data/examples/app_all_events/app.rb +0 -98
- data/examples/app_all_events/model/app_model.rb +0 -159
- data/examples/app_all_events/model/event_color_cycle.rb +0 -43
- data/examples/app_all_events/model/event_entry.rb +0 -94
- data/examples/app_all_events/model/msg.rb +0 -39
- data/examples/app_all_events/model/timestamp.rb +0 -56
- data/examples/app_all_events/update.rb +0 -75
- data/examples/app_all_events/view/app_view.rb +0 -80
- data/examples/app_all_events/view/controls_view.rb +0 -54
- data/examples/app_all_events/view/counts_view.rb +0 -61
- data/examples/app_all_events/view/live_view.rb +0 -72
- data/examples/app_all_events/view/log_view.rb +0 -57
- data/examples/app_all_events/view.rb +0 -9
- data/examples/app_cli_rich_moments/README.md +0 -81
- data/examples/app_cli_rich_moments/app.rb +0 -189
- data/examples/app_color_picker/README.md +0 -156
- data/examples/app_color_picker/app.rb +0 -76
- data/examples/app_color_picker/clipboard.rb +0 -86
- data/examples/app_color_picker/color.rb +0 -193
- data/examples/app_color_picker/controls.rb +0 -92
- data/examples/app_color_picker/copy_dialog.rb +0 -168
- data/examples/app_color_picker/export_pane.rb +0 -128
- data/examples/app_color_picker/harmony.rb +0 -58
- data/examples/app_color_picker/input.rb +0 -176
- data/examples/app_color_picker/main_container.rb +0 -180
- data/examples/app_color_picker/palette.rb +0 -111
- data/examples/app_debugging_showcase/README.md +0 -119
- data/examples/app_debugging_showcase/app.rb +0 -318
- data/examples/app_login_form/README.md +0 -58
- data/examples/app_login_form/app.rb +0 -109
- data/examples/app_stateful_interaction/README.md +0 -35
- data/examples/app_stateful_interaction/app.rb +0 -328
- data/examples/timeout_demo.rb +0 -45
- data/examples/verify_quickstart_dsl/README.md +0 -55
- data/examples/verify_quickstart_dsl/app.rb +0 -49
- data/examples/verify_quickstart_layout/README.md +0 -77
- data/examples/verify_quickstart_layout/app.rb +0 -73
- data/examples/verify_quickstart_lifecycle/README.md +0 -68
- data/examples/verify_quickstart_lifecycle/app.rb +0 -62
- data/examples/verify_readme_usage/README.md +0 -49
- data/examples/verify_readme_usage/app.rb +0 -42
- data/examples/verify_website_managed/README.md +0 -48
- data/examples/verify_website_managed/app.rb +0 -36
- data/examples/verify_website_menu/README.md +0 -60
- data/examples/verify_website_menu/app.rb +0 -84
- data/examples/verify_website_spinner/README.md +0 -44
- data/examples/verify_website_spinner/app.rb +0 -34
- data/examples/widget_barchart/README.md +0 -58
- data/examples/widget_barchart/app.rb +0 -240
- data/examples/widget_block/README.md +0 -44
- data/examples/widget_block/app.rb +0 -258
- data/examples/widget_box/README.md +0 -54
- data/examples/widget_box/app.rb +0 -255
- data/examples/widget_calendar/README.md +0 -48
- data/examples/widget_calendar/app.rb +0 -115
- data/examples/widget_canvas/README.md +0 -31
- data/examples/widget_canvas/app.rb +0 -130
- data/examples/widget_cell/README.md +0 -45
- data/examples/widget_cell/app.rb +0 -112
- data/examples/widget_center/README.md +0 -33
- data/examples/widget_center/app.rb +0 -118
- data/examples/widget_chart/README.md +0 -50
- data/examples/widget_chart/app.rb +0 -220
- data/examples/widget_gauge/README.md +0 -50
- data/examples/widget_gauge/app.rb +0 -229
- data/examples/widget_layout_split/README.md +0 -53
- data/examples/widget_layout_split/app.rb +0 -260
- data/examples/widget_line_gauge/README.md +0 -50
- data/examples/widget_line_gauge/app.rb +0 -219
- data/examples/widget_list/README.md +0 -58
- data/examples/widget_list/app.rb +0 -384
- data/examples/widget_map/README.md +0 -48
- data/examples/widget_map/app.rb +0 -95
- data/examples/widget_overlay/README.md +0 -45
- data/examples/widget_overlay/app.rb +0 -250
- data/examples/widget_popup/README.md +0 -45
- data/examples/widget_popup/app.rb +0 -106
- data/examples/widget_ratatui_logo/README.md +0 -43
- data/examples/widget_ratatui_logo/app.rb +0 -104
- data/examples/widget_ratatui_mascot/README.md +0 -43
- data/examples/widget_ratatui_mascot/app.rb +0 -95
- data/examples/widget_rect/README.md +0 -53
- data/examples/widget_rect/app.rb +0 -222
- data/examples/widget_render/README.md +0 -46
- data/examples/widget_render/app.rb +0 -186
- data/examples/widget_render/app.rbs +0 -41
- data/examples/widget_rich_text/README.md +0 -44
- data/examples/widget_rich_text/app.rb +0 -193
- data/examples/widget_scroll_text/README.md +0 -46
- data/examples/widget_scroll_text/app.rb +0 -109
- data/examples/widget_scrollbar/README.md +0 -46
- data/examples/widget_scrollbar/app.rb +0 -155
- data/examples/widget_sparkline/README.md +0 -51
- data/examples/widget_sparkline/app.rb +0 -277
- data/examples/widget_style_colors/README.md +0 -43
- data/examples/widget_style_colors/app.rb +0 -83
- data/examples/widget_table/README.md +0 -57
- data/examples/widget_table/app.rb +0 -279
- data/examples/widget_tabs/README.md +0 -50
- data/examples/widget_tabs/app.rb +0 -183
- data/examples/widget_text_width/README.md +0 -44
- data/examples/widget_text_width/app.rb +0 -117
- data/migrate_to_buffer.rb +0 -145
- data/mise.toml +0 -8
- data/tasks/autodoc/examples.rb +0 -87
- data/tasks/autodoc/member.rb +0 -58
- data/tasks/autodoc/name.rb +0 -21
- data/tasks/autodoc.rake +0 -21
- data/tasks/bump/cargo_lockfile.rb +0 -21
- data/tasks/bump/changelog.rb +0 -47
- data/tasks/bump/header.rb +0 -32
- data/tasks/bump/history.rb +0 -32
- data/tasks/bump/links.rb +0 -69
- data/tasks/bump/manifest.rb +0 -33
- data/tasks/bump/ruby_gem.rb +0 -49
- data/tasks/bump/sem_ver.rb +0 -40
- data/tasks/bump/unreleased_section.rb +0 -56
- data/tasks/bump.rake +0 -51
- data/tasks/doc.rake +0 -887
- data/tasks/example_viewer.html.erb +0 -172
- data/tasks/extension.rake +0 -14
- data/tasks/license/headers_md.rb +0 -223
- data/tasks/license/headers_rb.rb +0 -210
- data/tasks/license/license_utils.rb +0 -130
- data/tasks/license/snippets_md.rb +0 -315
- data/tasks/license/snippets_rdoc.rb +0 -150
- data/tasks/license.rake +0 -91
- data/tasks/lint.rake +0 -170
- data/tasks/rdoc_config.rb +0 -29
- data/tasks/resources/build.yml.erb +0 -60
- data/tasks/resources/index.html.erb +0 -141
- data/tasks/resources/rubies.yml +0 -7
- data/tasks/sourcehut.rake +0 -110
- data/tasks/steep.rake +0 -11
- data/tasks/terminal_preview/app_screenshot.rb +0 -45
- data/tasks/terminal_preview/crash_report.rb +0 -54
- data/tasks/terminal_preview/example_app.rb +0 -27
- data/tasks/terminal_preview/launcher_script.rb +0 -48
- data/tasks/terminal_preview/preview_collection.rb +0 -60
- data/tasks/terminal_preview/preview_timing.rb +0 -24
- data/tasks/terminal_preview/safety_confirmation.rb +0 -58
- data/tasks/terminal_preview/saved_screenshot.rb +0 -56
- data/tasks/terminal_preview/system_appearance.rb +0 -13
- data/tasks/terminal_preview/terminal_window.rb +0 -138
- data/tasks/terminal_preview/window_id.rb +0 -16
- data/tasks/terminal_preview.rake +0 -30
- data/tasks/test.rake +0 -33
- data/tasks/website/index_page.rb +0 -30
- data/tasks/website/version.rb +0 -127
- data/tasks/website/version_menu.rb +0 -68
- data/tasks/website/versioned_documentation.rb +0 -83
- data/tasks/website/website.rb +0 -53
- data/tasks/website.rake +0 -28
data/examples/widget_box/app.rb
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: MIT-0
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
9
|
-
require "ratatui_ruby"
|
|
10
|
-
|
|
11
|
-
# Demonstrates visual container attributes with interactive cycling.
|
|
12
|
-
#
|
|
13
|
-
# Widgets often float in void. Without boundaries, interfaces become a chaotic mess of text. Users need structure to parse information.
|
|
14
|
-
#
|
|
15
|
-
# This demo showcases the <tt>Block</tt> widget. It provides an interactive playground where you can cycle through different border types, colors, and title alignments in real-time.
|
|
16
|
-
#
|
|
17
|
-
# Use it to understand how to define distinct areas and create visual hierarchy in your terminal interface.
|
|
18
|
-
#
|
|
19
|
-
# === Example
|
|
20
|
-
#
|
|
21
|
-
# Run the demo from the terminal:
|
|
22
|
-
#
|
|
23
|
-
# ruby examples/widget_box/app.rb
|
|
24
|
-
#
|
|
25
|
-
# rdoc-image:/doc/images/widget_box.png
|
|
26
|
-
class WidgetBox
|
|
27
|
-
def initialize
|
|
28
|
-
# Border Types (ratatui native styles)
|
|
29
|
-
@border_types = [
|
|
30
|
-
{ name: "Plain", type: :plain },
|
|
31
|
-
{ name: "Rounded", type: :rounded },
|
|
32
|
-
{ name: "Double", type: :double },
|
|
33
|
-
{ name: "Thick", type: :thick },
|
|
34
|
-
{ name: "Quadrant Inside", type: :quadrant_inside },
|
|
35
|
-
{ name: "Quadrant Outside", type: :quadrant_outside },
|
|
36
|
-
]
|
|
37
|
-
@border_type_index = 0
|
|
38
|
-
|
|
39
|
-
# Custom Border Sets
|
|
40
|
-
# NOTE: We define these ONCE in initialize for efficiency.
|
|
41
|
-
@border_sets = [
|
|
42
|
-
{ name: "None", set: nil },
|
|
43
|
-
{
|
|
44
|
-
name: "Digits (Short)",
|
|
45
|
-
set: {
|
|
46
|
-
tl: "1",
|
|
47
|
-
tr: "2",
|
|
48
|
-
bl: "3",
|
|
49
|
-
br: "4",
|
|
50
|
-
vl: "5",
|
|
51
|
-
vr: "6",
|
|
52
|
-
ht: "7",
|
|
53
|
-
hb: "8",
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: "Letters (Long)",
|
|
58
|
-
set: {
|
|
59
|
-
top_left: "A",
|
|
60
|
-
top_right: "B",
|
|
61
|
-
bottom_left: "C",
|
|
62
|
-
bottom_right: "D",
|
|
63
|
-
vertical_left: "E",
|
|
64
|
-
vertical_right: "F",
|
|
65
|
-
horizontal_top: "G",
|
|
66
|
-
horizontal_bottom: "H",
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
]
|
|
70
|
-
@border_set_index = 0
|
|
71
|
-
|
|
72
|
-
@colors = [
|
|
73
|
-
{ name: "Green", color: "green" },
|
|
74
|
-
{ name: "Red", color: "red" },
|
|
75
|
-
{ name: "Blue", color: "blue" },
|
|
76
|
-
{ name: "Yellow", color: "yellow" },
|
|
77
|
-
{ name: "Magenta", color: "magenta" },
|
|
78
|
-
]
|
|
79
|
-
@color_index = 0
|
|
80
|
-
|
|
81
|
-
@title_alignments = [
|
|
82
|
-
{ name: "Left", alignment: :left },
|
|
83
|
-
{ name: "Center", alignment: :center },
|
|
84
|
-
{ name: "Right", alignment: :right },
|
|
85
|
-
]
|
|
86
|
-
@title_alignment_index = 0
|
|
87
|
-
|
|
88
|
-
@styles = [
|
|
89
|
-
{ name: "Default", style: nil },
|
|
90
|
-
{ name: "Blue on White", style: { fg: "blue", bg: "white", modifiers: [:bold] } },
|
|
91
|
-
]
|
|
92
|
-
@style_index = 0
|
|
93
|
-
|
|
94
|
-
@title_styles = [
|
|
95
|
-
{ name: "Default", style: nil },
|
|
96
|
-
{ name: "Yellow Bold Underlined", style: { fg: "yellow", modifiers: [:bold, :underlined] } },
|
|
97
|
-
]
|
|
98
|
-
@title_style_index = 0
|
|
99
|
-
|
|
100
|
-
@border_styles = [
|
|
101
|
-
{ name: "Default (no border style)", style: nil },
|
|
102
|
-
{ name: "Bold Red", style: { fg: "red", modifiers: [:bold] } },
|
|
103
|
-
{ name: "Cyan Italic", style: { fg: "cyan", modifiers: [:italic] } },
|
|
104
|
-
{ name: "Magenta Dim", style: { fg: "magenta", modifiers: [:dim] } },
|
|
105
|
-
]
|
|
106
|
-
@border_style_index = 0
|
|
107
|
-
|
|
108
|
-
@hotkey_style = nil # Initialized in run when tui is available
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def run
|
|
112
|
-
RatatuiRuby.run do |tui|
|
|
113
|
-
@tui = tui
|
|
114
|
-
@hotkey_style = tui.style(modifiers: [:bold, :underlined])
|
|
115
|
-
|
|
116
|
-
loop do
|
|
117
|
-
render
|
|
118
|
-
break if handle_input == :quit
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
private def render
|
|
124
|
-
# Get current values
|
|
125
|
-
border_type_config = @border_types[@border_type_index]
|
|
126
|
-
border_set_config = @border_sets[@border_set_index]
|
|
127
|
-
|
|
128
|
-
color_config = @colors[@color_index]
|
|
129
|
-
title_alignment_config = @title_alignments[@title_alignment_index]
|
|
130
|
-
style_config = @styles[@style_index]
|
|
131
|
-
title_style_config = @title_styles[@title_style_index]
|
|
132
|
-
border_style_config = @border_styles[@border_style_index]
|
|
133
|
-
|
|
134
|
-
# 1. State/View
|
|
135
|
-
# Use border_style if explicitly set; otherwise, only apply color picker
|
|
136
|
-
# color when no content style is set (preserves original border_color behavior)
|
|
137
|
-
effective_border_style = if border_style_config[:style]
|
|
138
|
-
border_style_config[:style]
|
|
139
|
-
elsif style_config[:style].nil?
|
|
140
|
-
@tui.style(fg: color_config[:color])
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
# Show overridden status if border_set is active
|
|
144
|
-
type_display = border_type_config[:name]
|
|
145
|
-
if border_set_config[:set]
|
|
146
|
-
type_display += " (Overridden)"
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
block = @tui.block(
|
|
150
|
-
title: "Box",
|
|
151
|
-
title_alignment: title_alignment_config[:alignment],
|
|
152
|
-
title_style: title_style_config[:style],
|
|
153
|
-
borders: [:all],
|
|
154
|
-
border_style: effective_border_style,
|
|
155
|
-
border_type: border_type_config[:type],
|
|
156
|
-
border_set: border_set_config[:set],
|
|
157
|
-
style: style_config[:style]
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
# Main content
|
|
161
|
-
main_panel = @tui.paragraph(
|
|
162
|
-
text: "Arrow Keys: Change Color\n\nCurrent Color: #{color_config[:name]}",
|
|
163
|
-
block:,
|
|
164
|
-
fg: style_config[:style] ? nil : color_config[:color],
|
|
165
|
-
style: style_config[:style],
|
|
166
|
-
alignment: :center
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
# Bottom control panel
|
|
170
|
-
control_panel = @tui.block(
|
|
171
|
-
title: "Controls",
|
|
172
|
-
borders: [:all],
|
|
173
|
-
children: [
|
|
174
|
-
@tui.paragraph(
|
|
175
|
-
text: [
|
|
176
|
-
# Line 1: Main Controls
|
|
177
|
-
@tui.text_line(spans: [
|
|
178
|
-
@tui.text_span(content: "↑↓←→", style: @hotkey_style),
|
|
179
|
-
@tui.text_span(content: ": Color (#{color_config[:name]}) "),
|
|
180
|
-
@tui.text_span(content: "q", style: @hotkey_style),
|
|
181
|
-
@tui.text_span(content: ": Quit"),
|
|
182
|
-
]),
|
|
183
|
-
# Line 2: Borders
|
|
184
|
-
@tui.text_line(spans: [
|
|
185
|
-
@tui.text_span(content: "space", style: @hotkey_style),
|
|
186
|
-
@tui.text_span(content: ": Border Type (#{type_display}) "),
|
|
187
|
-
@tui.text_span(content: "c", style: @hotkey_style),
|
|
188
|
-
@tui.text_span(content: ": Border Set (#{border_set_config[:name]})"),
|
|
189
|
-
]),
|
|
190
|
-
# Line 3: Styles
|
|
191
|
-
@tui.text_line(spans: [
|
|
192
|
-
@tui.text_span(content: "s", style: @hotkey_style),
|
|
193
|
-
@tui.text_span(content: ": Style (#{style_config[:name]}) "),
|
|
194
|
-
@tui.text_span(content: "b", style: @hotkey_style),
|
|
195
|
-
@tui.text_span(content: ": Border Style (#{border_style_config[:name]})"),
|
|
196
|
-
]),
|
|
197
|
-
# Line 4: Title
|
|
198
|
-
@tui.text_line(spans: [
|
|
199
|
-
@tui.text_span(content: "enter", style: @hotkey_style),
|
|
200
|
-
@tui.text_span(content: ": Align Title (#{title_alignment_config[:name]}) "),
|
|
201
|
-
@tui.text_span(content: "t", style: @hotkey_style),
|
|
202
|
-
@tui.text_span(content: ": Title Style (#{title_style_config[:name]})"),
|
|
203
|
-
]),
|
|
204
|
-
]
|
|
205
|
-
),
|
|
206
|
-
]
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
# 2. Render with Frame API
|
|
210
|
-
@tui.draw do |frame|
|
|
211
|
-
main_rect, control_rect = @tui.layout_split(
|
|
212
|
-
frame.area,
|
|
213
|
-
direction: :vertical,
|
|
214
|
-
constraints: [
|
|
215
|
-
@tui.constraint_fill(1),
|
|
216
|
-
@tui.constraint_length(6),
|
|
217
|
-
]
|
|
218
|
-
)
|
|
219
|
-
frame.render_widget(main_panel, main_rect)
|
|
220
|
-
frame.render_widget(control_panel, control_rect)
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
private def handle_input
|
|
225
|
-
# 3. Events
|
|
226
|
-
case @tui.poll_event
|
|
227
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
228
|
-
:quit
|
|
229
|
-
in type: :key, code: "up"
|
|
230
|
-
@color_index = (@color_index - 1) % @colors.size
|
|
231
|
-
in type: :key, code: "down"
|
|
232
|
-
@color_index = (@color_index + 1) % @colors.size
|
|
233
|
-
in type: :key, code: "left"
|
|
234
|
-
@color_index = (@color_index - 1) % @colors.size
|
|
235
|
-
in type: :key, code: "right"
|
|
236
|
-
@color_index = (@color_index + 1) % @colors.size
|
|
237
|
-
in type: :key, code: " "
|
|
238
|
-
@border_type_index = (@border_type_index + 1) % @border_types.size
|
|
239
|
-
in type: :key, code: "c"
|
|
240
|
-
@border_set_index = (@border_set_index + 1) % @border_sets.size
|
|
241
|
-
in type: :key, code: "enter"
|
|
242
|
-
@title_alignment_index = (@title_alignment_index + 1) % @title_alignments.size
|
|
243
|
-
in type: :key, code: "s"
|
|
244
|
-
@style_index = (@style_index + 1) % @styles.size
|
|
245
|
-
in type: :key, code: "t"
|
|
246
|
-
@title_style_index = (@title_style_index + 1) % @title_styles.size
|
|
247
|
-
in type: :key, code: "b"
|
|
248
|
-
@border_style_index = (@border_style_index + 1) % @border_styles.size
|
|
249
|
-
else
|
|
250
|
-
nil
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
WidgetBox.new.run if __FILE__ == $0
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Calendar Widget Example
|
|
7
|
-
|
|
8
|
-
[](app.rb)
|
|
9
|
-
|
|
10
|
-
Demonstrates a monthly calendar with customizable headers and event highlighting.
|
|
11
|
-
|
|
12
|
-
Rendering dates in a grid involves complex calculations for leap years and weekday offsets. This widget handles that logic, letting you focus on displaying dates.
|
|
13
|
-
|
|
14
|
-
## Features Demonstrated
|
|
15
|
-
|
|
16
|
-
- **Headers**: Toggling the Month name and Weekday labels.
|
|
17
|
-
- **Surrounding Days**: displaying (or hiding/dimming) days from the previous and next months to fill the grid.
|
|
18
|
-
- **Event Styling**: applying specific styles to individual `Time` or `Date` objects to highlight events.
|
|
19
|
-
|
|
20
|
-
## Hotkeys
|
|
21
|
-
|
|
22
|
-
- **h**: Toggle Month Header (`show_month_header`)
|
|
23
|
-
- **w**: Toggle Weekday Labels (`show_weekdays_header`)
|
|
24
|
-
- **s**: Toggle Surrounding Days (`show_surrounding`)
|
|
25
|
-
- **e**: Toggle Example Events (`events`)
|
|
26
|
-
- **q**: Quit
|
|
27
|
-
|
|
28
|
-
## Usage
|
|
29
|
-
|
|
30
|
-
<!-- SPDX-SnippetBegin -->
|
|
31
|
-
<!--
|
|
32
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
33
|
-
SPDX-License-Identifier: MIT-0
|
|
34
|
-
-->
|
|
35
|
-
```bash
|
|
36
|
-
ruby examples/widget_calendar/app.rb
|
|
37
|
-
```
|
|
38
|
-
<!-- SPDX-SnippetEnd -->
|
|
39
|
-
|
|
40
|
-
## Learning Outcomes
|
|
41
|
-
|
|
42
|
-
Use this example if you need to...
|
|
43
|
-
|
|
44
|
-
- Display a date picker.
|
|
45
|
-
- Show a schedule or timeline view.
|
|
46
|
-
- Highlight specific dates (deadlines, holidays) on a calendar grid.
|
|
47
|
-
|
|
48
|
-
[Read the source code →](app.rb)
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: MIT-0
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
9
|
-
require "ratatui_ruby"
|
|
10
|
-
|
|
11
|
-
# Demonstrates monthly calendar attributes with interactive cycling.
|
|
12
|
-
#
|
|
13
|
-
# Dates are complex. Rendering them in a grid requires calculation of leap years, month lengths, and day-of-week offsets.
|
|
14
|
-
# Use this widget to skip the boilerplate.
|
|
15
|
-
#
|
|
16
|
-
# This demo showcases the <tt>Calendar</tt> widget. It provides an interactive playground where you can toggle headers, weekday labels, and event highlights in real-time.
|
|
17
|
-
#
|
|
18
|
-
# Use it to understand how to render time-based data grids efficiently.
|
|
19
|
-
#
|
|
20
|
-
# === Example
|
|
21
|
-
#
|
|
22
|
-
# Run the demo from the terminal:
|
|
23
|
-
#
|
|
24
|
-
# ruby examples/widget_calendar/app.rb
|
|
25
|
-
#
|
|
26
|
-
# rdoc-image:/doc/images/widget_calendar.png
|
|
27
|
-
class WidgetCalendar
|
|
28
|
-
def initialize(date: nil)
|
|
29
|
-
@date = date
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def run
|
|
33
|
-
RatatuiRuby.run do |tui|
|
|
34
|
-
show_header = true
|
|
35
|
-
show_weekdays = true
|
|
36
|
-
show_surrounding = false
|
|
37
|
-
show_events = true
|
|
38
|
-
hotkey_style = tui.style(modifiers: [:bold])
|
|
39
|
-
|
|
40
|
-
loop do
|
|
41
|
-
now = @date || Time.now
|
|
42
|
-
surrounding_style = show_surrounding ? tui.style(fg: "gray", modifiers: [:dim]) : nil
|
|
43
|
-
|
|
44
|
-
events_map = if show_events
|
|
45
|
-
{
|
|
46
|
-
now => tui.style(fg: "green", modifiers: [:bold]),
|
|
47
|
-
(now + (86400 * 2)) => tui.style(fg: "red", modifiers: [:underlined]),
|
|
48
|
-
(now - (86400 * 5)) => tui.style(fg: "blue", bg: "white"),
|
|
49
|
-
}
|
|
50
|
-
else
|
|
51
|
-
{}
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
calendar = tui.calendar(
|
|
55
|
-
year: now.year,
|
|
56
|
-
month: now.month,
|
|
57
|
-
events: events_map,
|
|
58
|
-
header_style: tui.style(fg: "yellow", modifiers: [:bold]),
|
|
59
|
-
show_month_header: show_header,
|
|
60
|
-
show_weekdays_header: show_weekdays,
|
|
61
|
-
show_surrounding: surrounding_style,
|
|
62
|
-
block: tui.block(borders: [:top, :left, :right])
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
controls = tui.paragraph(
|
|
66
|
-
text: [
|
|
67
|
-
tui.text_line(spans: [
|
|
68
|
-
tui.text_span(content: " h/w/s/e", style: hotkey_style),
|
|
69
|
-
tui.text_span(content: ": Toggle Header/Weekdays/Surrounding/Events "),
|
|
70
|
-
tui.text_span(content: "q", style: hotkey_style),
|
|
71
|
-
tui.text_span(content: ": Quit"),
|
|
72
|
-
]),
|
|
73
|
-
tui.text_line(spans: [
|
|
74
|
-
tui.text_span(content: " Events: ", style: hotkey_style),
|
|
75
|
-
tui.text_span(content: "Today (Green), +2d (Red), -5d (Blue) (#{show_events ? 'On' : 'Off'})"),
|
|
76
|
-
]),
|
|
77
|
-
],
|
|
78
|
-
block: tui.block(title: " Controls ", borders: [:all])
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
tui.draw do |frame|
|
|
82
|
-
calendar_area, controls_area = tui.layout_split(
|
|
83
|
-
frame.area,
|
|
84
|
-
direction: :vertical,
|
|
85
|
-
constraints: [
|
|
86
|
-
tui.constraint_min(0),
|
|
87
|
-
tui.constraint_length(4),
|
|
88
|
-
]
|
|
89
|
-
)
|
|
90
|
-
frame.render_widget(calendar, calendar_area)
|
|
91
|
-
frame.render_widget(controls, controls_area)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
case tui.poll_event
|
|
95
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
96
|
-
break
|
|
97
|
-
in type: :key, code: "h"
|
|
98
|
-
show_header = !show_header
|
|
99
|
-
in type: :key, code: "w"
|
|
100
|
-
show_weekdays = !show_weekdays
|
|
101
|
-
in type: :key, code: "s"
|
|
102
|
-
show_surrounding = !show_surrounding
|
|
103
|
-
in type: :key, code: "e"
|
|
104
|
-
show_events = !show_events
|
|
105
|
-
else
|
|
106
|
-
nil
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
sleep 0.05
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
WidgetCalendar.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
# Canvas (Circle, Line, Point, Rectangle) Example
|
|
6
|
-
|
|
7
|
-
[](app.rb)
|
|
8
|
-
|
|
9
|
-
<!--
|
|
10
|
-
SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
11
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
12
|
-
-->
|
|
13
|
-
|
|
14
|
-
This example demonstrates the `Canvas` widget, which provides a high-resolution drawing surface using Braille characters.
|
|
15
|
-
|
|
16
|
-
## Key Concepts
|
|
17
|
-
|
|
18
|
-
- **Shapes**: Supports `Point`, `Line`, `Rectangle`, `Circle`, and `Map`.
|
|
19
|
-
- **Coordinates**: Uses a float-based coordinate system independent of terminal cells.
|
|
20
|
-
- **Markers**: Can use Braille (high res) or block characters (lower res) for rendering.
|
|
21
|
-
|
|
22
|
-
## Controls
|
|
23
|
-
|
|
24
|
-
| Key | Action |
|
|
25
|
-
| --- | --- |
|
|
26
|
-
| `q` | Quit |
|
|
27
|
-
|
|
28
|
-
## Screenshot
|
|
29
|
-
## Source Code
|
|
30
|
-
|
|
31
|
-
- [app.rb](app.rb)
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: MIT-0
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
9
|
-
require "ratatui_ruby"
|
|
10
|
-
|
|
11
|
-
# Canvas Widget
|
|
12
|
-
# Demonstrates how to draw geometric shapes (Points, Lines, Rects, Circles)
|
|
13
|
-
# on a high-resolution canvas.
|
|
14
|
-
class WidgetCanvas
|
|
15
|
-
def initialize
|
|
16
|
-
@x_offset = 0.0
|
|
17
|
-
@y_offset = 0.0
|
|
18
|
-
@time = 0.0
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def run
|
|
22
|
-
RatatuiRuby.run do |tui|
|
|
23
|
-
@tui = tui
|
|
24
|
-
loop do
|
|
25
|
-
# Animate
|
|
26
|
-
@time += 0.1
|
|
27
|
-
@x_offset = Math.sin(@time) * 20.0
|
|
28
|
-
@y_offset = Math.cos(@time) * 20.0
|
|
29
|
-
|
|
30
|
-
render
|
|
31
|
-
break if handle_input == :quit
|
|
32
|
-
|
|
33
|
-
sleep 0.05
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
private def render
|
|
39
|
-
@tui.draw do |frame|
|
|
40
|
-
# Define shapes using terse aliases (circle, rectangle, point, map, label)
|
|
41
|
-
# These are shorter forms of shape_circle, shape_rectangle, etc.
|
|
42
|
-
shapes = []
|
|
43
|
-
|
|
44
|
-
# 1. Static Grid (Lines) - using shape_line (no terse alias for line)
|
|
45
|
-
(-100..100).step(20) do |i|
|
|
46
|
-
shapes << @tui.shape_line(x1: i.to_f, y1: -100.0, x2: i.to_f, y2: 100.0, color: :gray)
|
|
47
|
-
shapes << @tui.shape_line(x1: -100.0, y1: i.to_f, x2: 100.0, y2: i.to_f, color: :gray)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# 2. Moving Circle (The "Player") - using terse 'circle' alias
|
|
51
|
-
shapes << @tui.circle(
|
|
52
|
-
x: @x_offset,
|
|
53
|
-
y: @y_offset,
|
|
54
|
-
radius: 10.0,
|
|
55
|
-
color: :green
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
# 3. Static Rectangle (Target) - using shape_rectangle (no 'rectangle' alias
|
|
59
|
-
# to avoid confusion with Layout::Rect)
|
|
60
|
-
shapes << @tui.shape_rectangle(
|
|
61
|
-
x: 30.0,
|
|
62
|
-
y: 30.0,
|
|
63
|
-
width: 20.0,
|
|
64
|
-
height: 20.0,
|
|
65
|
-
color: :red
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
# 4. Points (Starfield) - using terse 'point' alias
|
|
69
|
-
# Deterministic "random" points
|
|
70
|
-
10.times do |i|
|
|
71
|
-
shapes << @tui.point(
|
|
72
|
-
x: ((i * 37) % 200) - 100.0,
|
|
73
|
-
y: ((i * 19) % 200) - 100.0
|
|
74
|
-
)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# 5. Connecting line from origin to player position
|
|
78
|
-
shapes << @tui.shape_line(x1: 0.0, y1: 0.0, x2: @x_offset, y2: @y_offset, color: :yellow)
|
|
79
|
-
|
|
80
|
-
canvas = @tui.canvas(
|
|
81
|
-
shapes:,
|
|
82
|
-
x_bounds: [-100.0, 100.0],
|
|
83
|
-
y_bounds: [-100.0, 100.0],
|
|
84
|
-
marker: :braille,
|
|
85
|
-
block: @tui.block(title: "Canvas", borders: [:all])
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
# Main area for canvas
|
|
89
|
-
layout = @tui.layout_split(
|
|
90
|
-
frame.area,
|
|
91
|
-
direction: :vertical,
|
|
92
|
-
constraints: [
|
|
93
|
-
@tui.constraint_fill(1),
|
|
94
|
-
@tui.constraint_length(2),
|
|
95
|
-
]
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
frame.render_widget(canvas, layout[0])
|
|
99
|
-
|
|
100
|
-
# Query: Canvas#get_point maps canvas coordinates to normalized [0.0, 1.0] grid
|
|
101
|
-
normalized = canvas.get_point(@x_offset, @y_offset)
|
|
102
|
-
norm_str = normalized ? format("[%.2f, %.2f]", normalized[0], normalized[1]) : "nil"
|
|
103
|
-
|
|
104
|
-
# Controls showing query method demonstration (single concise line)
|
|
105
|
-
controls = @tui.paragraph(
|
|
106
|
-
text: [
|
|
107
|
-
@tui.text_line(spans: [
|
|
108
|
-
@tui.text_span(content: "q", style: @tui.style(modifiers: [:bold, :underlined])),
|
|
109
|
-
@tui.text_span(content: ": Quit "),
|
|
110
|
-
@tui.text_span(content: "get_point → ", style: @tui.style(fg: :dark_gray)),
|
|
111
|
-
@tui.text_span(content: norm_str, style: @tui.style(fg: :cyan)),
|
|
112
|
-
]),
|
|
113
|
-
],
|
|
114
|
-
block: @tui.block(borders: [:top])
|
|
115
|
-
)
|
|
116
|
-
frame.render_widget(controls, layout[1])
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def handle_input
|
|
121
|
-
case @tui.poll_event
|
|
122
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
123
|
-
:quit
|
|
124
|
-
else
|
|
125
|
-
# Ignore other events
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
WidgetCanvas.new.run if __FILE__ == $0
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Cell Widget Example
|
|
7
|
-
|
|
8
|
-
[](app.rb)
|
|
9
|
-
|
|
10
|
-
Demonstrates using `Cell` objects for granular control over individual character grid units.
|
|
11
|
-
|
|
12
|
-
Sometimes you need to render specific characters with unique styles outside of standard widgets. The `Cell` primitive allows you to build custom widgets or inject styled content into Tables.
|
|
13
|
-
|
|
14
|
-
## Features Demonstrated
|
|
15
|
-
|
|
16
|
-
- **Custom Widgets**: A `CheckeredBackground` widget built by rendering `Cell`s in a loop.
|
|
17
|
-
- **Table Integration**: Mixing simple Strings and rich `Cell` objects in a Table row.
|
|
18
|
-
- **Overlays**: Using `RatatuiRuby::Overlay` to stack widgets on top of each other.
|
|
19
|
-
- **Modifiers**: Using `rapid_blink`, `bold`, and `dim` on individual cells.
|
|
20
|
-
|
|
21
|
-
## Hotkeys
|
|
22
|
-
|
|
23
|
-
- **q** / **Ctrl+c**: Quit
|
|
24
|
-
|
|
25
|
-
## Usage
|
|
26
|
-
|
|
27
|
-
<!-- SPDX-SnippetBegin -->
|
|
28
|
-
<!--
|
|
29
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
30
|
-
SPDX-License-Identifier: MIT-0
|
|
31
|
-
-->
|
|
32
|
-
```bash
|
|
33
|
-
ruby examples/widget_cell/app.rb
|
|
34
|
-
```
|
|
35
|
-
<!-- SPDX-SnippetEnd -->
|
|
36
|
-
|
|
37
|
-
## Learning Outcomes
|
|
38
|
-
|
|
39
|
-
Use this example if you need to...
|
|
40
|
-
|
|
41
|
-
- Create a custom widget (like a game board or specialized graph).
|
|
42
|
-
- Style specific cells in a Table (e.g., Green "OK", Red "FAIL").
|
|
43
|
-
- Understand how to position content precisely with `Cell`.
|
|
44
|
-
|
|
45
|
-
[Read the source code →](app.rb)
|