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
|
@@ -1,229 +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 completion visualization with interactive attribute cycling.
|
|
12
|
-
#
|
|
13
|
-
# Long-running tasks create anxiety. Users need to know that the system is working and how much is left to do.
|
|
14
|
-
#
|
|
15
|
-
# This demo showcases the <tt>Gauge</tt> widget. It provides an interactive playground where you can cycle through different ratios, colors, and label templates in real-time.
|
|
16
|
-
#
|
|
17
|
-
# Use it to understand how to communicate progress and task status in your terminal interface.
|
|
18
|
-
#
|
|
19
|
-
# === Example
|
|
20
|
-
#
|
|
21
|
-
# Run the demo from the terminal:
|
|
22
|
-
#
|
|
23
|
-
# ruby examples/widget_gauge/app.rb
|
|
24
|
-
#
|
|
25
|
-
# rdoc-image:/doc/images/widget_gauge.png
|
|
26
|
-
class WidgetGauge
|
|
27
|
-
def initialize
|
|
28
|
-
@ratio = 0.65
|
|
29
|
-
@ratios = [0.0, 0.25, 0.5, 0.65, 0.8, 0.95, 1.0]
|
|
30
|
-
@ratio_index = 3
|
|
31
|
-
|
|
32
|
-
# Demonstrates both ratio (0.0-1.0) and percent (0-100) input modes
|
|
33
|
-
@input_modes = [:ratio, :percent]
|
|
34
|
-
@input_mode_index = 0
|
|
35
|
-
|
|
36
|
-
@gauge_colors = [
|
|
37
|
-
{ name: "Green", color: :green },
|
|
38
|
-
{ name: "Yellow", color: :yellow },
|
|
39
|
-
{ name: "Red", color: :red },
|
|
40
|
-
{ name: "Cyan", color: :cyan },
|
|
41
|
-
{ name: "Blue", color: :blue },
|
|
42
|
-
]
|
|
43
|
-
@gauge_color_index = 0
|
|
44
|
-
|
|
45
|
-
@bg_styles = nil # Initialized in run when @tui is available
|
|
46
|
-
@bg_style_index = 1
|
|
47
|
-
|
|
48
|
-
@use_unicode_options = [true, false]
|
|
49
|
-
@use_unicode_index = 0
|
|
50
|
-
|
|
51
|
-
@label_modes = [
|
|
52
|
-
{ name: "Percentage", template: -> (ratio) { "#{(ratio * 100).to_i}%" } },
|
|
53
|
-
{ name: "Ratio (decimal)", template: -> (ratio) { format("%.2f", ratio) } },
|
|
54
|
-
{ name: "Progress", template: -> (ratio) { "Progress: #{(ratio * 100).to_i}%" } },
|
|
55
|
-
{ name: "None", template: -> (_ratio) { nil } },
|
|
56
|
-
]
|
|
57
|
-
@label_mode_index = 0
|
|
58
|
-
@hotkey_style = nil # Initialized in run when @tui is available
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def run
|
|
62
|
-
RatatuiRuby.run do |tui|
|
|
63
|
-
@tui = tui
|
|
64
|
-
|
|
65
|
-
# Initialize styles using tui helpers
|
|
66
|
-
@bg_styles = [
|
|
67
|
-
{ name: "None", style: nil },
|
|
68
|
-
{ name: "Dark Gray BG", style: tui.style(fg: :dark_gray) },
|
|
69
|
-
{ name: "White on Black", style: tui.style(fg: :white, bg: :black) },
|
|
70
|
-
{ name: "Bold White", style: tui.style(fg: :white, modifiers: [:bold]) },
|
|
71
|
-
]
|
|
72
|
-
@hotkey_style = tui.style(modifiers: [:bold, :underlined])
|
|
73
|
-
|
|
74
|
-
loop do
|
|
75
|
-
render
|
|
76
|
-
break if handle_input == :quit
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
private def render
|
|
82
|
-
@ratio = @ratios[@ratio_index]
|
|
83
|
-
gauge_color = @gauge_colors[@gauge_color_index][:color]
|
|
84
|
-
bg_style = @bg_styles[@bg_style_index][:style]
|
|
85
|
-
use_unicode = @use_unicode_options[@use_unicode_index]
|
|
86
|
-
label_template = @label_modes[@label_mode_index][:template]
|
|
87
|
-
|
|
88
|
-
gauge_style = @tui.style(fg: gauge_color)
|
|
89
|
-
label = label_template.call(@ratio)
|
|
90
|
-
|
|
91
|
-
@tui.draw do |frame|
|
|
92
|
-
# Split into main content and control panel
|
|
93
|
-
main_area, controls_area = @tui.layout_split(
|
|
94
|
-
frame.area,
|
|
95
|
-
direction: :vertical,
|
|
96
|
-
constraints: [
|
|
97
|
-
@tui.constraint_fill(1),
|
|
98
|
-
@tui.constraint_length(6),
|
|
99
|
-
]
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
# Split main area into title, gauges, and spacer
|
|
103
|
-
title_area, gauge1_area, gauge2_area, gauge3_area, spacer_area = @tui.layout_split(
|
|
104
|
-
main_area,
|
|
105
|
-
direction: :vertical,
|
|
106
|
-
constraints: [
|
|
107
|
-
@tui.constraint_length(1),
|
|
108
|
-
@tui.constraint_fill(1),
|
|
109
|
-
@tui.constraint_fill(1),
|
|
110
|
-
@tui.constraint_fill(1),
|
|
111
|
-
@tui.constraint_length(1),
|
|
112
|
-
]
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
# Render title
|
|
116
|
-
title = @tui.paragraph(
|
|
117
|
-
text: "Gauge Widget",
|
|
118
|
-
style: @tui.style(modifiers: [:bold])
|
|
119
|
-
)
|
|
120
|
-
frame.render_widget(title, title_area)
|
|
121
|
-
|
|
122
|
-
# Gauge 1: Main interactive gauge
|
|
123
|
-
# Demonstrates both ratio (0.0-1.0) and percent (0-100) input modes
|
|
124
|
-
input_mode = @input_modes[@input_mode_index]
|
|
125
|
-
gauge_opts = if input_mode == :percent
|
|
126
|
-
{ percent: (@ratio * 100).to_i } # percent: accepts 0-100
|
|
127
|
-
else
|
|
128
|
-
{ ratio: @ratio } # ratio: accepts 0.0-1.0
|
|
129
|
-
end
|
|
130
|
-
gauge1 = @tui.gauge(
|
|
131
|
-
**gauge_opts,
|
|
132
|
-
label:,
|
|
133
|
-
style: bg_style,
|
|
134
|
-
gauge_style:,
|
|
135
|
-
use_unicode:,
|
|
136
|
-
block: @tui.block(title: "Interactive Gauge (#{input_mode}:)")
|
|
137
|
-
)
|
|
138
|
-
frame.render_widget(gauge1, gauge1_area)
|
|
139
|
-
|
|
140
|
-
# Gauge 2: Inverse ratio for comparison
|
|
141
|
-
gauge2 = @tui.gauge(
|
|
142
|
-
ratio: 1.0 - @ratio,
|
|
143
|
-
label: label_template.call(1.0 - @ratio),
|
|
144
|
-
style: bg_style,
|
|
145
|
-
gauge_style:,
|
|
146
|
-
use_unicode:,
|
|
147
|
-
block: @tui.block(title: "Inverse (1.0 - ratio)")
|
|
148
|
-
)
|
|
149
|
-
frame.render_widget(gauge2, gauge2_area)
|
|
150
|
-
|
|
151
|
-
# Gauge 3: Fixed at different stages
|
|
152
|
-
gauge3 = @tui.gauge(
|
|
153
|
-
ratio: [@ratio, 0.5].max,
|
|
154
|
-
label: "Min 50%",
|
|
155
|
-
style: @tui.style(fg: :dark_gray),
|
|
156
|
-
gauge_style: @tui.style(fg: :magenta),
|
|
157
|
-
use_unicode:,
|
|
158
|
-
block: @tui.block(title: "Min Threshold (Magenta)")
|
|
159
|
-
)
|
|
160
|
-
frame.render_widget(gauge3, gauge3_area)
|
|
161
|
-
|
|
162
|
-
# Render empty spacer
|
|
163
|
-
spacer = @tui.paragraph(text: "")
|
|
164
|
-
frame.render_widget(spacer, spacer_area)
|
|
165
|
-
|
|
166
|
-
# Bottom controls panel
|
|
167
|
-
controls = @tui.block(
|
|
168
|
-
title: "Controls",
|
|
169
|
-
borders: [:all],
|
|
170
|
-
children: [
|
|
171
|
-
@tui.paragraph(
|
|
172
|
-
text: [
|
|
173
|
-
# Navigation & General
|
|
174
|
-
@tui.text_line(spans: [
|
|
175
|
-
@tui.text_span(content: "←/→", style: @hotkey_style),
|
|
176
|
-
@tui.text_span(content: ": Adjust Ratio (#{format('%.2f', @ratio)}) "),
|
|
177
|
-
@tui.text_span(content: "q", style: @hotkey_style),
|
|
178
|
-
@tui.text_span(content: ": Quit"),
|
|
179
|
-
]),
|
|
180
|
-
# Styling
|
|
181
|
-
@tui.text_line(spans: [
|
|
182
|
-
@tui.text_span(content: "g", style: @hotkey_style),
|
|
183
|
-
@tui.text_span(content: ": Color (#{@gauge_colors[@gauge_color_index][:name]}) "),
|
|
184
|
-
@tui.text_span(content: "b", style: @hotkey_style),
|
|
185
|
-
@tui.text_span(content: ": Background (#{@bg_styles[@bg_style_index][:name]})"),
|
|
186
|
-
]),
|
|
187
|
-
# Options
|
|
188
|
-
@tui.text_line(spans: [
|
|
189
|
-
@tui.text_span(content: "u", style: @hotkey_style),
|
|
190
|
-
@tui.text_span(content: ": Unicode (#{use_unicode ? 'On' : 'Off'}) "),
|
|
191
|
-
@tui.text_span(content: "l", style: @hotkey_style),
|
|
192
|
-
@tui.text_span(content: ": Label (#{@label_modes[@label_mode_index][:name]}) "),
|
|
193
|
-
@tui.text_span(content: "i", style: @hotkey_style),
|
|
194
|
-
@tui.text_span(content: ": Input (#{@input_modes[@input_mode_index]}:)"),
|
|
195
|
-
]),
|
|
196
|
-
]
|
|
197
|
-
),
|
|
198
|
-
]
|
|
199
|
-
)
|
|
200
|
-
frame.render_widget(controls, controls_area)
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
private def handle_input
|
|
205
|
-
case @tui.poll_event
|
|
206
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
207
|
-
:quit
|
|
208
|
-
in type: :key, code: "right"
|
|
209
|
-
@ratio_index = (@ratio_index + 1) % @ratios.length
|
|
210
|
-
in type: :key, code: "left"
|
|
211
|
-
@ratio_index = (@ratio_index - 1) % @ratios.length
|
|
212
|
-
in type: :key, code: "g"
|
|
213
|
-
@gauge_color_index = (@gauge_color_index + 1) % @gauge_colors.length
|
|
214
|
-
in type: :key, code: "b"
|
|
215
|
-
@bg_style_index = (@bg_style_index + 1) % @bg_styles.length
|
|
216
|
-
in type: :key, code: "u"
|
|
217
|
-
@use_unicode_index = (@use_unicode_index + 1) % @use_unicode_options.length
|
|
218
|
-
in type: :key, code: "l"
|
|
219
|
-
@label_mode_index = (@label_mode_index + 1) % @label_modes.length
|
|
220
|
-
in type: :key, code: "i"
|
|
221
|
-
@input_mode_index = (@input_mode_index + 1) % @input_modes.length
|
|
222
|
-
else
|
|
223
|
-
# Ignore other events
|
|
224
|
-
nil
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
WidgetGauge.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Layout (Split, Grid) Example
|
|
7
|
-
|
|
8
|
-
[](app.rb)
|
|
9
|
-
|
|
10
|
-
Demonstrates dynamic geometry management with constraints and flex modes.
|
|
11
|
-
|
|
12
|
-
Terminal screens vary in size. Hardcoded layouts break. `Layout.split` manages space dynamically, ensuring your interface adapts to any window dimension.
|
|
13
|
-
|
|
14
|
-
## Features Demonstrated
|
|
15
|
-
|
|
16
|
-
- **Constraints**:
|
|
17
|
-
- `Fill(n)`: Takes available space proportional to `n`.
|
|
18
|
-
- `Length(n)`: Fixed number of cells.
|
|
19
|
-
- `Percentage(n)`: Percentage of the parent area.
|
|
20
|
-
- `Min(n)`: At least `n` cells.
|
|
21
|
-
- `Ratio(x, y)`: `x/y` of the parent area.
|
|
22
|
-
- **Flex Modes**: Controlling how extra space is distributed (`Start`, `End`, `Center`, `SpaceBetween`, etc.).
|
|
23
|
-
- **Direction**: Splitting Vertically vs Horizontally.
|
|
24
|
-
|
|
25
|
-
## Hotkeys
|
|
26
|
-
|
|
27
|
-
- **d**: Toggle Direction (`direction`)
|
|
28
|
-
- **f**: Cycle Flex Mode (`flex`)
|
|
29
|
-
- **c**: Cycle Constraint Set (`constraints`)
|
|
30
|
-
- **q**: Quit
|
|
31
|
-
|
|
32
|
-
## Usage
|
|
33
|
-
|
|
34
|
-
<!-- SPDX-SnippetBegin -->
|
|
35
|
-
<!--
|
|
36
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
37
|
-
SPDX-License-Identifier: MIT-0
|
|
38
|
-
-->
|
|
39
|
-
```bash
|
|
40
|
-
ruby examples/widget_layout_split/app.rb
|
|
41
|
-
```
|
|
42
|
-
<!-- SPDX-SnippetEnd -->
|
|
43
|
-
|
|
44
|
-
## Learning Outcomes
|
|
45
|
-
|
|
46
|
-
Use this example if you need to...
|
|
47
|
-
|
|
48
|
-
- Build responsive dashboards.
|
|
49
|
-
- Create 3-column layouts where the middle content fills remaining space.
|
|
50
|
-
- Center a modal dialog on the screen.
|
|
51
|
-
- Distribute buttons evenly across a control bar.
|
|
52
|
-
|
|
53
|
-
[Read the source code →](app.rb)
|
|
@@ -1,260 +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 dynamic geometry management with interactive cycling.
|
|
12
|
-
#
|
|
13
|
-
# Terminal screens vary in size. Hardcoded positions break when the window resizes. You need a way to organize space dynamically.
|
|
14
|
-
#
|
|
15
|
-
# This demo showcases the <tt>Layout.split</tt> mechanism. It provides an interactive playground where you can toggle directions, all seven flex modes, and various constraint types (Fill, Length, Percentage, Min, Ratio) in real-time.
|
|
16
|
-
#
|
|
17
|
-
# Use it to understand how to build responsive, fluid terminal interfaces that adapt to any window dimensions.
|
|
18
|
-
#
|
|
19
|
-
# === Example
|
|
20
|
-
#
|
|
21
|
-
# Run the demo from the terminal:
|
|
22
|
-
#
|
|
23
|
-
# ruby examples/widget_layout_split/app.rb
|
|
24
|
-
#
|
|
25
|
-
# rdoc-image:/doc/images/widget_layout_split.png
|
|
26
|
-
class WidgetLayoutSplit
|
|
27
|
-
DIRECTIONS = [
|
|
28
|
-
{ name: "Vertical", value: :vertical },
|
|
29
|
-
{ name: "Horizontal", value: :horizontal },
|
|
30
|
-
].freeze
|
|
31
|
-
|
|
32
|
-
FLEX_MODES = [
|
|
33
|
-
{ name: "Legacy", value: :legacy },
|
|
34
|
-
{ name: "Start", value: :start },
|
|
35
|
-
{ name: "Center", value: :center },
|
|
36
|
-
{ name: "End", value: :end },
|
|
37
|
-
{ name: "Space Between", value: :space_between },
|
|
38
|
-
{ name: "Space Around", value: :space_around },
|
|
39
|
-
{ name: "Space Evenly", value: :space_evenly },
|
|
40
|
-
].freeze
|
|
41
|
-
|
|
42
|
-
BLOCK_COLORS = %i[red green blue].freeze
|
|
43
|
-
|
|
44
|
-
def initialize
|
|
45
|
-
@direction_index = 0
|
|
46
|
-
@flex_index = 0
|
|
47
|
-
@constraint_index = 0
|
|
48
|
-
@hotkey_style = nil
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def run
|
|
52
|
-
RatatuiRuby.run do |tui|
|
|
53
|
-
@tui = tui
|
|
54
|
-
@hotkey_style = tui.style(modifiers: [:bold, :underlined])
|
|
55
|
-
@constraint_demos = build_constraint_demos
|
|
56
|
-
|
|
57
|
-
loop do
|
|
58
|
-
render
|
|
59
|
-
break if handle_input == :quit
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
private def build_constraint_demos
|
|
65
|
-
[
|
|
66
|
-
{
|
|
67
|
-
name: "Fill (1:2:1)",
|
|
68
|
-
constraints: -> (dir) {
|
|
69
|
-
[
|
|
70
|
-
@tui.constraint_fill(1),
|
|
71
|
-
@tui.constraint_fill(2),
|
|
72
|
-
@tui.constraint_fill(1),
|
|
73
|
-
]
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: "Length (10/15/10)",
|
|
78
|
-
constraints: -> (dir) {
|
|
79
|
-
[
|
|
80
|
-
@tui.constraint_length(10),
|
|
81
|
-
@tui.constraint_length(15),
|
|
82
|
-
@tui.constraint_length(10),
|
|
83
|
-
]
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
name: "Percentage (25/50/25)",
|
|
88
|
-
constraints: -> (dir) {
|
|
89
|
-
[
|
|
90
|
-
@tui.constraint_percentage(25),
|
|
91
|
-
@tui.constraint_percentage(50),
|
|
92
|
-
@tui.constraint_percentage(25),
|
|
93
|
-
]
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
name: "Min (5/10/5)",
|
|
98
|
-
constraints: -> (dir) {
|
|
99
|
-
[
|
|
100
|
-
@tui.constraint_min(5),
|
|
101
|
-
@tui.constraint_min(10),
|
|
102
|
-
@tui.constraint_min(5),
|
|
103
|
-
]
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: "Ratio (1:4, 2:4, 1:4)",
|
|
108
|
-
constraints: -> (dir) {
|
|
109
|
-
[
|
|
110
|
-
@tui.constraint_ratio(1, 4),
|
|
111
|
-
@tui.constraint_ratio(2, 4),
|
|
112
|
-
@tui.constraint_ratio(1, 4),
|
|
113
|
-
]
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: -> (dir) { (dir == :vertical) ? "Mixed (Len 3, Fill, Pct 25)" : "Mixed (Len 20, Fill, Pct 25)" },
|
|
118
|
-
constraints: -> (dir) {
|
|
119
|
-
fixed = (dir == :vertical) ? 3 : 20
|
|
120
|
-
[
|
|
121
|
-
@tui.constraint_length(fixed),
|
|
122
|
-
@tui.constraint_fill(1),
|
|
123
|
-
@tui.constraint_percentage(25),
|
|
124
|
-
]
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
name: "Batch (from_percentages)",
|
|
129
|
-
constraints: -> (_dir) {
|
|
130
|
-
RatatuiRuby::Layout::Constraint.from_percentages([25, 50, 25])
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
]
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
private def current_direction
|
|
137
|
-
DIRECTIONS[@direction_index][:value]
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
private def current_flex
|
|
141
|
-
FLEX_MODES[@flex_index][:value]
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
private def current_constraints
|
|
145
|
-
demo = @constraint_demos[@constraint_index]
|
|
146
|
-
demo[:constraints].call(current_direction)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
private def current_constraint_name
|
|
150
|
-
demo = @constraint_demos[@constraint_index]
|
|
151
|
-
name = demo[:name]
|
|
152
|
-
name.respond_to?(:call) ? name.call(current_direction) : name
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
private def render
|
|
156
|
-
@tui.draw do |frame|
|
|
157
|
-
# Split into main content and control panel
|
|
158
|
-
main_area, controls_area = @tui.layout_split(
|
|
159
|
-
frame.area,
|
|
160
|
-
direction: :vertical,
|
|
161
|
-
constraints: [
|
|
162
|
-
@tui.constraint_fill(1),
|
|
163
|
-
@tui.constraint_length(6),
|
|
164
|
-
]
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
render_demo_area(frame, main_area)
|
|
168
|
-
render_controls(frame, controls_area)
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
private def render_demo_area(frame, area)
|
|
173
|
-
# Split demo area into title and content
|
|
174
|
-
title_area, content_area = @tui.layout_split(
|
|
175
|
-
area,
|
|
176
|
-
direction: :vertical,
|
|
177
|
-
constraints: [
|
|
178
|
-
@tui.constraint_length(1),
|
|
179
|
-
@tui.constraint_fill(1),
|
|
180
|
-
]
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
# Render title
|
|
184
|
-
title = @tui.paragraph(
|
|
185
|
-
text: "Layout.split",
|
|
186
|
-
style: @tui.style(modifiers: [:bold])
|
|
187
|
-
)
|
|
188
|
-
frame.render_widget(title, title_area)
|
|
189
|
-
|
|
190
|
-
# Apply current layout settings to 3 colored blocks
|
|
191
|
-
block_areas = @tui.layout_split(
|
|
192
|
-
content_area,
|
|
193
|
-
direction: current_direction,
|
|
194
|
-
flex: current_flex,
|
|
195
|
-
constraints: current_constraints
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
block_areas.each_with_index do |block_area, i|
|
|
199
|
-
block = @tui.block(
|
|
200
|
-
title: "Block #{i + 1}",
|
|
201
|
-
borders: [:all],
|
|
202
|
-
border_style: @tui.style(fg: BLOCK_COLORS[i % BLOCK_COLORS.length])
|
|
203
|
-
)
|
|
204
|
-
frame.render_widget(block, block_area)
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
private def render_controls(frame, area)
|
|
209
|
-
# Demonstrate Constraint#call - show computed sizes for 100 units
|
|
210
|
-
constraints = current_constraints
|
|
211
|
-
applied = constraints.map { |c| c.(100) } # proc-like invocation
|
|
212
|
-
apply_str = "constraint.(100): #{applied.join(', ')}"
|
|
213
|
-
|
|
214
|
-
controls = @tui.block(
|
|
215
|
-
title: "Controls",
|
|
216
|
-
borders: [:all],
|
|
217
|
-
children: [
|
|
218
|
-
@tui.paragraph(
|
|
219
|
-
text: [
|
|
220
|
-
# Row 1: Direction and Flex
|
|
221
|
-
@tui.text_line(spans: [
|
|
222
|
-
@tui.text_span(content: "d", style: @hotkey_style),
|
|
223
|
-
@tui.text_span(content: ": Direction (#{DIRECTIONS[@direction_index][:name]}) "),
|
|
224
|
-
@tui.text_span(content: "f", style: @hotkey_style),
|
|
225
|
-
@tui.text_span(content: ": Flex (#{FLEX_MODES[@flex_index][:name]})"),
|
|
226
|
-
]),
|
|
227
|
-
@tui.text_line(spans: [
|
|
228
|
-
@tui.text_span(content: "c", style: @hotkey_style),
|
|
229
|
-
@tui.text_span(content: ": Constraints (#{current_constraint_name}) "),
|
|
230
|
-
@tui.text_span(content: "q", style: @hotkey_style),
|
|
231
|
-
@tui.text_span(content: ": Quit"),
|
|
232
|
-
]),
|
|
233
|
-
# Row 3: Apply demonstration
|
|
234
|
-
@tui.text_line(spans: [
|
|
235
|
-
@tui.text_span(content: apply_str, style: @tui.style(fg: :dark_gray)),
|
|
236
|
-
]),
|
|
237
|
-
]
|
|
238
|
-
),
|
|
239
|
-
]
|
|
240
|
-
)
|
|
241
|
-
frame.render_widget(controls, area)
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
private def handle_input
|
|
245
|
-
case @tui.poll_event
|
|
246
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
247
|
-
:quit
|
|
248
|
-
in type: :key, code: "d"
|
|
249
|
-
@direction_index = (@direction_index + 1) % DIRECTIONS.length
|
|
250
|
-
in type: :key, code: "f"
|
|
251
|
-
@flex_index = (@flex_index + 1) % FLEX_MODES.length
|
|
252
|
-
in type: :key, code: "c"
|
|
253
|
-
@constraint_index = (@constraint_index + 1) % @constraint_demos.length
|
|
254
|
-
else
|
|
255
|
-
nil
|
|
256
|
-
end
|
|
257
|
-
end
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
WidgetLayoutSplit.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# Line Gauge Widget Example
|
|
7
|
-
|
|
8
|
-
[](app.rb)
|
|
9
|
-
|
|
10
|
-
Demonstrates compact progress bars for constrained spaces.
|
|
11
|
-
|
|
12
|
-
Standard block gauges take up vertical space. Sometimes you only have one line to show status. The `LineGauge` provides a compact, high-density progress indicator.
|
|
13
|
-
|
|
14
|
-
## Features Demonstrated
|
|
15
|
-
|
|
16
|
-
- **Compact Rendering**: Visualizing progress in a single character height.
|
|
17
|
-
- **Custom Symbols**: Replacing the standard line with Blocks, Shades, Dashes, or ASCII characters.
|
|
18
|
-
- **Styling**: Independent styling for the filled (progress) and unfilled (track) portions.
|
|
19
|
-
|
|
20
|
-
## Hotkeys
|
|
21
|
-
|
|
22
|
-
- **Arrows (←/→)**: Adjust Ratio (`ratio`)
|
|
23
|
-
- **f**: Cycle Filled Symbol (`filled_symbol`)
|
|
24
|
-
- **u**: Cycle Unfilled Symbol (`unfilled_symbol`)
|
|
25
|
-
- **c**: Cycle Filled Color (`filled_style`)
|
|
26
|
-
- **x**: Cycle Unfilled Color (`unfilled_style`)
|
|
27
|
-
- **b**: Cycle Base Style (`style`)
|
|
28
|
-
- **q**: Cycle Quit
|
|
29
|
-
|
|
30
|
-
## Usage
|
|
31
|
-
|
|
32
|
-
<!-- SPDX-SnippetBegin -->
|
|
33
|
-
<!--
|
|
34
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
35
|
-
SPDX-License-Identifier: MIT-0
|
|
36
|
-
-->
|
|
37
|
-
```bash
|
|
38
|
-
ruby examples/widget_line_gauge/app.rb
|
|
39
|
-
```
|
|
40
|
-
<!-- SPDX-SnippetEnd -->
|
|
41
|
-
|
|
42
|
-
## Learning Outcomes
|
|
43
|
-
|
|
44
|
-
Use this example if you need to...
|
|
45
|
-
|
|
46
|
-
- Add a progress bar to a list item or table row.
|
|
47
|
-
- Create a status line at the bottom of the screen.
|
|
48
|
-
- Show multiple metrics (CPU, RAM, Net) in a compact list.
|
|
49
|
-
|
|
50
|
-
[Read the source code →](app.rb)
|