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,219 +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 compact status visualization with interactive attribute cycling.
|
|
12
|
-
#
|
|
13
|
-
# Screen space is precious. Standard block gauges are bulky and consume multiple rows.
|
|
14
|
-
#
|
|
15
|
-
# This demo showcases the <tt>LineGauge</tt> widget. It provides an interactive playground where you can cycle through different ratios, symbols, and styling for both filled and unfilled portions in real-time.
|
|
16
|
-
#
|
|
17
|
-
# Use it to understand how to provide status feedback in constrained layouts without consuming vertical space.
|
|
18
|
-
#
|
|
19
|
-
# === Example
|
|
20
|
-
#
|
|
21
|
-
# Run the demo from the terminal:
|
|
22
|
-
#
|
|
23
|
-
# ruby examples/widget_line_gauge/app.rb
|
|
24
|
-
#
|
|
25
|
-
# rdoc-image:/doc/images/widget_line_gauge.png
|
|
26
|
-
class WidgetLineGauge
|
|
27
|
-
def initialize
|
|
28
|
-
@ratio = 0.5
|
|
29
|
-
@ratios = [0.2, 0.35, 0.5, 0.65, 0.8, 0.95]
|
|
30
|
-
@ratio_index = 2
|
|
31
|
-
|
|
32
|
-
@filled_symbols = [
|
|
33
|
-
{ name: "█ (Block)", symbol: "█" },
|
|
34
|
-
{ name: "▓ (Dark Shade)", symbol: "▓" },
|
|
35
|
-
{ name: "▒ (Medium Shade)", symbol: "▒" },
|
|
36
|
-
{ name: "= (Equals)", symbol: "=" },
|
|
37
|
-
{ name: "# (Hash)", symbol: "#" },
|
|
38
|
-
]
|
|
39
|
-
@filled_symbol_index = 0
|
|
40
|
-
|
|
41
|
-
@unfilled_symbols = [
|
|
42
|
-
{ name: "░ (Light Shade)", symbol: "░" },
|
|
43
|
-
{ name: "· (Dot)", symbol: "·" },
|
|
44
|
-
{ name: "- (Dash)", symbol: "-" },
|
|
45
|
-
{ name: "~ (Tilde)", symbol: "~" },
|
|
46
|
-
]
|
|
47
|
-
@unfilled_symbol_index = 0
|
|
48
|
-
|
|
49
|
-
@filled_colors = [
|
|
50
|
-
{ name: "Red", color: :red },
|
|
51
|
-
{ name: "Yellow", color: :yellow },
|
|
52
|
-
{ name: "Green", color: :green },
|
|
53
|
-
{ name: "Cyan", color: :cyan },
|
|
54
|
-
{ name: "Blue", color: :blue },
|
|
55
|
-
]
|
|
56
|
-
@filled_color_index = 2
|
|
57
|
-
|
|
58
|
-
@unfilled_colors = [
|
|
59
|
-
{ name: "Default", color: nil },
|
|
60
|
-
{ name: "Dark Gray", color: :dark_gray },
|
|
61
|
-
{ name: "Gray", color: :gray },
|
|
62
|
-
]
|
|
63
|
-
@unfilled_color_index = 1
|
|
64
|
-
|
|
65
|
-
@base_styles = nil # Initialized in run when @tui is available
|
|
66
|
-
@base_style_index = 0
|
|
67
|
-
@hotkey_style = nil # Initialized in run when @tui is available
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def run
|
|
71
|
-
RatatuiRuby.run do |tui|
|
|
72
|
-
@tui = tui
|
|
73
|
-
|
|
74
|
-
# Initialize styles using tui helpers
|
|
75
|
-
@base_styles = [
|
|
76
|
-
{ name: "None", style: nil },
|
|
77
|
-
{ name: "Bold White", style: tui.style(fg: :white, modifiers: [:bold]) },
|
|
78
|
-
{ name: "White on Blue", style: tui.style(fg: :white, bg: :blue) },
|
|
79
|
-
{ name: "Italic Cyan", style: tui.style(fg: :cyan, modifiers: [:italic]) },
|
|
80
|
-
]
|
|
81
|
-
@hotkey_style = tui.style(modifiers: [:bold, :underlined])
|
|
82
|
-
|
|
83
|
-
loop do
|
|
84
|
-
render
|
|
85
|
-
break if handle_input == :quit
|
|
86
|
-
sleep 0.05
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
private def render
|
|
92
|
-
@ratio = @ratios[@ratio_index]
|
|
93
|
-
|
|
94
|
-
filled_color = @filled_colors[@filled_color_index][:color]
|
|
95
|
-
unfilled_color = @unfilled_colors[@unfilled_color_index][:color]
|
|
96
|
-
|
|
97
|
-
filled_style = filled_color ? @tui.style(fg: filled_color) : @tui.style(fg: :white)
|
|
98
|
-
unfilled_style = unfilled_color ? @tui.style(fg: unfilled_color) : @tui.style(fg: :dark_gray)
|
|
99
|
-
|
|
100
|
-
@tui.draw do |frame|
|
|
101
|
-
# Split into main content and control panel
|
|
102
|
-
main_area, controls_area = @tui.layout_split(
|
|
103
|
-
frame.area,
|
|
104
|
-
direction: :vertical,
|
|
105
|
-
constraints: [
|
|
106
|
-
@tui.constraint_fill(1),
|
|
107
|
-
@tui.constraint_length(5),
|
|
108
|
-
]
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
# Split main area into title, gauges, and spacer
|
|
112
|
-
title_area, gauge1_area, gauge2_area, spacer_area = @tui.layout_split(
|
|
113
|
-
main_area,
|
|
114
|
-
direction: :vertical,
|
|
115
|
-
constraints: [
|
|
116
|
-
@tui.constraint_length(1),
|
|
117
|
-
@tui.constraint_length(4),
|
|
118
|
-
@tui.constraint_length(4),
|
|
119
|
-
@tui.constraint_fill(1),
|
|
120
|
-
]
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
# Render title
|
|
124
|
-
title = @tui.paragraph(text: "LineGauge Widget - Cycle attributes with hotkeys")
|
|
125
|
-
frame.render_widget(title, title_area)
|
|
126
|
-
|
|
127
|
-
# Example 1: Static gauge showing all features
|
|
128
|
-
gauge1 = @tui.line_gauge(
|
|
129
|
-
ratio: @ratio,
|
|
130
|
-
label: "#{(@ratio * 100).to_i}%",
|
|
131
|
-
style: @base_styles[@base_style_index][:style],
|
|
132
|
-
filled_style:,
|
|
133
|
-
unfilled_style:,
|
|
134
|
-
filled_symbol: @filled_symbols[@filled_symbol_index][:symbol],
|
|
135
|
-
unfilled_symbol: @unfilled_symbols[@unfilled_symbol_index][:symbol],
|
|
136
|
-
block: @tui.block(title: "Interactive Gauge")
|
|
137
|
-
)
|
|
138
|
-
frame.render_widget(gauge1, gauge1_area)
|
|
139
|
-
|
|
140
|
-
# Example 2: Inverted colors for contrast demonstration
|
|
141
|
-
gauge2 = @tui.line_gauge(
|
|
142
|
-
ratio: 1.0 - @ratio,
|
|
143
|
-
label: "#{((1.0 - @ratio) * 100).to_i}%",
|
|
144
|
-
filled_style: @tui.style(fg: :black, bg: :yellow),
|
|
145
|
-
unfilled_style: @tui.style(fg: :white, bg: :dark_gray),
|
|
146
|
-
filled_symbol: @filled_symbols[@filled_symbol_index][:symbol],
|
|
147
|
-
unfilled_symbol: @unfilled_symbols[@unfilled_symbol_index][:symbol],
|
|
148
|
-
block: @tui.block(title: "Inverse (100% - ratio)")
|
|
149
|
-
)
|
|
150
|
-
frame.render_widget(gauge2, gauge2_area)
|
|
151
|
-
|
|
152
|
-
# Render empty spacer
|
|
153
|
-
spacer = @tui.paragraph(text: "")
|
|
154
|
-
frame.render_widget(spacer, spacer_area)
|
|
155
|
-
|
|
156
|
-
# Bottom control panel
|
|
157
|
-
controls = @tui.block(
|
|
158
|
-
title: "Controls",
|
|
159
|
-
borders: [:all],
|
|
160
|
-
children: [
|
|
161
|
-
@tui.paragraph(
|
|
162
|
-
text: [
|
|
163
|
-
# Line 1: General
|
|
164
|
-
@tui.text_line(spans: [
|
|
165
|
-
@tui.text_span(content: "←/→", style: @hotkey_style),
|
|
166
|
-
@tui.text_span(content: ": Ratio (#{(@ratio * 100).to_i}%) "),
|
|
167
|
-
@tui.text_span(content: "b", style: @hotkey_style),
|
|
168
|
-
@tui.text_span(content: ": Base Style (#{@base_styles[@base_style_index][:name]}) "),
|
|
169
|
-
@tui.text_span(content: "q", style: @hotkey_style),
|
|
170
|
-
@tui.text_span(content: ": Quit"),
|
|
171
|
-
]),
|
|
172
|
-
# Line 2: Filled
|
|
173
|
-
@tui.text_line(spans: [
|
|
174
|
-
@tui.text_span(content: "f", style: @hotkey_style),
|
|
175
|
-
@tui.text_span(content: ": Filled Symbol (#{@filled_symbols[@filled_symbol_index][:name]}) "),
|
|
176
|
-
@tui.text_span(content: "c", style: @hotkey_style),
|
|
177
|
-
@tui.text_span(content: ": Filled Color (#{@filled_colors[@filled_color_index][:name]})"),
|
|
178
|
-
]),
|
|
179
|
-
# Line 3: Unfilled
|
|
180
|
-
@tui.text_line(spans: [
|
|
181
|
-
@tui.text_span(content: "u", style: @hotkey_style),
|
|
182
|
-
@tui.text_span(content: ": Unfilled Symbol (#{@unfilled_symbols[@unfilled_symbol_index][:name]}) "),
|
|
183
|
-
@tui.text_span(content: "x", style: @hotkey_style),
|
|
184
|
-
@tui.text_span(content: ": Unfilled Color (#{@unfilled_colors[@unfilled_color_index][:name]})"),
|
|
185
|
-
]),
|
|
186
|
-
]
|
|
187
|
-
),
|
|
188
|
-
]
|
|
189
|
-
)
|
|
190
|
-
frame.render_widget(controls, controls_area)
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
private def handle_input
|
|
195
|
-
case @tui.poll_event
|
|
196
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
197
|
-
:quit
|
|
198
|
-
in type: :key, code: "right"
|
|
199
|
-
@ratio_index = (@ratio_index + 1) % @ratios.length
|
|
200
|
-
in type: :key, code: "left"
|
|
201
|
-
@ratio_index = (@ratio_index - 1) % @ratios.length
|
|
202
|
-
in type: :key, code: "b"
|
|
203
|
-
@base_style_index = (@base_style_index + 1) % @base_styles.length
|
|
204
|
-
in type: :key, code: "f"
|
|
205
|
-
@filled_symbol_index = (@filled_symbol_index + 1) % @filled_symbols.length
|
|
206
|
-
in type: :key, code: "c"
|
|
207
|
-
@filled_color_index = (@filled_color_index + 1) % @filled_colors.length
|
|
208
|
-
in type: :key, code: "u"
|
|
209
|
-
@unfilled_symbol_index = (@unfilled_symbol_index + 1) % @unfilled_symbols.length
|
|
210
|
-
in type: :key, code: "x"
|
|
211
|
-
@unfilled_color_index = (@unfilled_color_index + 1) % @unfilled_colors.length
|
|
212
|
-
else
|
|
213
|
-
# Ignore other events
|
|
214
|
-
nil
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
WidgetLineGauge.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# List (ListItem) Example
|
|
7
|
-
|
|
8
|
-
[](app.rb)
|
|
9
|
-
|
|
10
|
-
Demonstrates a selectable list with extensive configuration options.
|
|
11
|
-
|
|
12
|
-
Lists are the workhorse of terminal interfaces. Managing selection state, scrolling windows, and highlight styles logic is complex. The `List` widget handles all of this.
|
|
13
|
-
|
|
14
|
-
## Features Demonstrated
|
|
15
|
-
|
|
16
|
-
- **Scrolling**: Automatically handles lists larger than the view area.
|
|
17
|
-
- **Selection**: Maintains selected index and supports "no selection" state.
|
|
18
|
-
- **Highlighting**: Custom styles and symbols (e.g., `>>`) for the selected item.
|
|
19
|
-
- **Offset Modes**: Manual control over the scroll offset vs automatic "scroll to selection" behavior.
|
|
20
|
-
- **Scroll Padding**: Keeping a margin of items visible above/below the selection.
|
|
21
|
-
|
|
22
|
-
## Hotkeys
|
|
23
|
-
|
|
24
|
-
- **i**: Cycle Item Data (`items`)
|
|
25
|
-
- **Arrow Keys (↑/↓)**: Navigate (`selected_index`)
|
|
26
|
-
- **x**: Toggle Selection (`selected_index`)
|
|
27
|
-
- **h**: Cycle Highlight Style (`highlight_style`)
|
|
28
|
-
- **y**: Cycle Highlight Symbol (`highlight_symbol`)
|
|
29
|
-
- **d**: Toggle Direction (`direction`)
|
|
30
|
-
- **s**: Cycle Highlight Spacing (`highlight_spacing`)
|
|
31
|
-
- **p**: Cycle Scroll Padding (`scroll_padding`)
|
|
32
|
-
- **b**: Cycle Base Style (`style`)
|
|
33
|
-
- **r**: Toggle Repeat Highlight Symbol (`repeat_highlight_symbol`)
|
|
34
|
-
- **o**: Cycle Offset Mode (`offset`)
|
|
35
|
-
- **q**: Quit
|
|
36
|
-
|
|
37
|
-
## Usage
|
|
38
|
-
|
|
39
|
-
<!-- SPDX-SnippetBegin -->
|
|
40
|
-
<!--
|
|
41
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
42
|
-
SPDX-License-Identifier: MIT-0
|
|
43
|
-
-->
|
|
44
|
-
```bash
|
|
45
|
-
ruby examples/widget_list/app.rb
|
|
46
|
-
```
|
|
47
|
-
<!-- SPDX-SnippetEnd -->
|
|
48
|
-
|
|
49
|
-
## Learning Outcomes
|
|
50
|
-
|
|
51
|
-
Use this example if you need to...
|
|
52
|
-
|
|
53
|
-
- Create a file explorer.
|
|
54
|
-
- Build a navigation menu.
|
|
55
|
-
- Display a log where users can scroll back to read history.
|
|
56
|
-
- Implement "infinite select" behaviors.
|
|
57
|
-
|
|
58
|
-
[Read the source code →](app.rb)
|
data/examples/widget_list/app.rb
DELETED
|
@@ -1,384 +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
|
-
require "faker" # Use Faker for large, realistic datasets
|
|
11
|
-
|
|
12
|
-
# Demonstrates a selectable list of items with interactive attribute cycling.
|
|
13
|
-
#
|
|
14
|
-
# Users need to browse and select from collections of data. Lists are fundamental to terminal interfaces, but managing selection state, scrolling, and styling can be complex.
|
|
15
|
-
#
|
|
16
|
-
# This demo showcases the <tt>List</tt> widget. It provides an interactive playground where you can cycle through different configurations, styles, and behaviors in real-time.
|
|
17
|
-
#
|
|
18
|
-
# Use it to understand how to implement menus, file browsers, or any selectable collection of items.
|
|
19
|
-
#
|
|
20
|
-
# === Examples
|
|
21
|
-
#
|
|
22
|
-
# Run the demo from the terminal:
|
|
23
|
-
#
|
|
24
|
-
# ruby examples/widget_list/app.rb
|
|
25
|
-
#
|
|
26
|
-
# rdoc-image:/doc/images/widget_list.png
|
|
27
|
-
class WidgetList
|
|
28
|
-
# Initializes the demo with example data and default configuration.
|
|
29
|
-
def initialize
|
|
30
|
-
Faker::Config.random = Random.new(12345)
|
|
31
|
-
@selected_index = 6 # Start at C# to avoid highlighting the rich text examples
|
|
32
|
-
@tui_for_setup = nil
|
|
33
|
-
|
|
34
|
-
@item_sets = [
|
|
35
|
-
{
|
|
36
|
-
name: "Programming",
|
|
37
|
-
items: [
|
|
38
|
-
:ruby_styled, # Will be replaced with rich text in run()
|
|
39
|
-
:rust_styled, # Will be replaced with rich text in run()
|
|
40
|
-
:python_styled, # Will be replaced with rich text in run()
|
|
41
|
-
:javascript_styled, # Will be replaced with rich text in run()
|
|
42
|
-
"Go",
|
|
43
|
-
"C++",
|
|
44
|
-
"C#",
|
|
45
|
-
"Java",
|
|
46
|
-
"Kotlin",
|
|
47
|
-
"Swift",
|
|
48
|
-
"Objective-C",
|
|
49
|
-
"PHP",
|
|
50
|
-
"TypeScript",
|
|
51
|
-
"Perl",
|
|
52
|
-
"Lua",
|
|
53
|
-
"R",
|
|
54
|
-
"Scala",
|
|
55
|
-
"Haskell",
|
|
56
|
-
"Elixir",
|
|
57
|
-
"Clojure",
|
|
58
|
-
"Groovy",
|
|
59
|
-
"Closure",
|
|
60
|
-
"VB.NET",
|
|
61
|
-
"F#",
|
|
62
|
-
"Erlang",
|
|
63
|
-
"Lisp",
|
|
64
|
-
"Scheme",
|
|
65
|
-
"Prolog",
|
|
66
|
-
"Fortran",
|
|
67
|
-
"COBOL",
|
|
68
|
-
"Pascal",
|
|
69
|
-
"Delphi",
|
|
70
|
-
"Ada",
|
|
71
|
-
"Bash",
|
|
72
|
-
"Sh",
|
|
73
|
-
"Tcl",
|
|
74
|
-
"Awk",
|
|
75
|
-
"sed",
|
|
76
|
-
"Vim Script",
|
|
77
|
-
"PowerShell",
|
|
78
|
-
"Batch",
|
|
79
|
-
"Assembly",
|
|
80
|
-
"Wasm",
|
|
81
|
-
"WebAssembly",
|
|
82
|
-
"Julia",
|
|
83
|
-
"Matlab",
|
|
84
|
-
"Octave",
|
|
85
|
-
"BASIC",
|
|
86
|
-
],
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: "Large List",
|
|
90
|
-
items: (1..200).map { |i| "Item #{i}" },
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
name: "Colors",
|
|
94
|
-
items: begin
|
|
95
|
-
Faker::Color.unique.clear
|
|
96
|
-
Array.new(100) { Faker::Color.color_name }
|
|
97
|
-
end,
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
name: "Fruits",
|
|
101
|
-
items: begin
|
|
102
|
-
Faker::Food.unique.clear
|
|
103
|
-
Array.new(100) { Faker::Food.fruits }
|
|
104
|
-
end,
|
|
105
|
-
},
|
|
106
|
-
]
|
|
107
|
-
@item_set_index = 0
|
|
108
|
-
|
|
109
|
-
@highlight_symbol_names = [">> ", "▶ ", "→ ", "• ", "★ "]
|
|
110
|
-
@highlight_symbol_index = 0
|
|
111
|
-
|
|
112
|
-
@direction_configs = [
|
|
113
|
-
{ name: "Top to Bottom", direction: :top_to_bottom },
|
|
114
|
-
{ name: "Bottom to Top", direction: :bottom_to_top },
|
|
115
|
-
]
|
|
116
|
-
@direction_index = 0
|
|
117
|
-
|
|
118
|
-
@highlight_spacing_configs = [
|
|
119
|
-
{ name: "When Selected", spacing: :when_selected },
|
|
120
|
-
{ name: "Always", spacing: :always },
|
|
121
|
-
{ name: "Never", spacing: :never },
|
|
122
|
-
]
|
|
123
|
-
@highlight_spacing_index = 1
|
|
124
|
-
|
|
125
|
-
@repeat_modes = [
|
|
126
|
-
{ name: "Off", repeat: false },
|
|
127
|
-
{ name: "On", repeat: true },
|
|
128
|
-
]
|
|
129
|
-
@repeat_index = 0
|
|
130
|
-
|
|
131
|
-
@scroll_padding_configs = [
|
|
132
|
-
{ name: "None", padding: nil },
|
|
133
|
-
{ name: "1 item", padding: 1 },
|
|
134
|
-
{ name: "2 items", padding: 2 },
|
|
135
|
-
]
|
|
136
|
-
@scroll_padding_index = 1
|
|
137
|
-
|
|
138
|
-
# Offset mode configurations to demonstrate offset + selection interaction
|
|
139
|
-
@offset_modes = [
|
|
140
|
-
{ name: "Auto (No Offset)", offset: nil, allow_selection: true },
|
|
141
|
-
{ name: "Offset Only", offset: 10, allow_selection: false },
|
|
142
|
-
{ name: "Selection + Offset (Conflict)", offset: 0, allow_selection: true },
|
|
143
|
-
]
|
|
144
|
-
@offset_mode_index = 0
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# Runs the demo application.
|
|
148
|
-
#
|
|
149
|
-
# This method enters the terminal alternate screen, starts the main loop, and handles cleanup on exit.
|
|
150
|
-
def run
|
|
151
|
-
RatatuiRuby.run do |tui|
|
|
152
|
-
@tui = tui
|
|
153
|
-
|
|
154
|
-
# Create rich text for "Ruby" - each letter with a different red style
|
|
155
|
-
ruby_line = @tui.text_line(spans: [
|
|
156
|
-
@tui.text_span(content: "R", style: @tui.style(fg: :red, modifiers: [:underlined])),
|
|
157
|
-
@tui.text_span(content: "u", style: @tui.style(fg: :light_red, modifiers: [:bold])),
|
|
158
|
-
@tui.text_span(content: "b", style: @tui.style(fg: :red, modifiers: [:italic])),
|
|
159
|
-
@tui.text_span(content: "y", style: @tui.style(fg: :light_red, modifiers: [:reversed])),
|
|
160
|
-
])
|
|
161
|
-
|
|
162
|
-
# Create rich text for "Rust" - single styled Span
|
|
163
|
-
rust_span = @tui.text_span(
|
|
164
|
-
content: "Rust",
|
|
165
|
-
style: @tui.style(fg: :magenta, modifiers: [:bold, :underlined])
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
# Create ListItem for "Python" - demonstrates content + row background
|
|
169
|
-
python_item = @tui.list_item(
|
|
170
|
-
content: @tui.text_span(content: "Python", style: @tui.style(fg: :yellow)),
|
|
171
|
-
style: @tui.style(bg: :dark_gray)
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
# Create ListItem for "JavaScript" - demonstrates styled text with row background
|
|
175
|
-
javascript_item = @tui.list_item(
|
|
176
|
-
content: @tui.text_line(spans: [
|
|
177
|
-
@tui.text_span(content: "Java", style: @tui.style(fg: :yellow, modifiers: [:bold])),
|
|
178
|
-
@tui.text_span(content: "Script", style: @tui.style(fg: :light_yellow, modifiers: [:italic])),
|
|
179
|
-
]),
|
|
180
|
-
style: @tui.style(bg: :blue)
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
# Replace the styled placeholders
|
|
184
|
-
@item_sets[0][:items][0] = ruby_line
|
|
185
|
-
@item_sets[0][:items][1] = rust_span
|
|
186
|
-
@item_sets[0][:items][2] = python_item
|
|
187
|
-
@item_sets[0][:items][3] = javascript_item
|
|
188
|
-
|
|
189
|
-
# Initialize styles that require @tui
|
|
190
|
-
@highlight_styles = [
|
|
191
|
-
{ name: "Blue on White Bold", style: @tui.style(fg: :blue, bg: :white, modifiers: [:bold]) },
|
|
192
|
-
{ name: "Blue Bold", style: @tui.style(fg: :blue, modifiers: [:bold]) },
|
|
193
|
-
{ name: "Yellow on Black", style: @tui.style(fg: :yellow, bg: :black) },
|
|
194
|
-
{ name: "Green Italic", style: @tui.style(fg: :green, modifiers: [:italic]) },
|
|
195
|
-
{ name: "White Reversed", style: @tui.style(fg: :white, modifiers: [:reversed]) },
|
|
196
|
-
{ name: "Cyan Bold", style: @tui.style(fg: :cyan, modifiers: [:bold]) },
|
|
197
|
-
]
|
|
198
|
-
@highlight_style_index = 0
|
|
199
|
-
|
|
200
|
-
@base_styles = [
|
|
201
|
-
{ name: "None", style: nil },
|
|
202
|
-
{ name: "Dark Gray", style: @tui.style(fg: :dark_gray) },
|
|
203
|
-
{ name: "White on Black", style: @tui.style(fg: :white, bg: :black) },
|
|
204
|
-
]
|
|
205
|
-
@base_style_index = 0
|
|
206
|
-
|
|
207
|
-
@hotkey_style = @tui.style(modifiers: [:bold, :underlined])
|
|
208
|
-
|
|
209
|
-
loop do
|
|
210
|
-
render
|
|
211
|
-
break if handle_input == :quit
|
|
212
|
-
|
|
213
|
-
sleep 0.05
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
# :nodoc:
|
|
219
|
-
private def render
|
|
220
|
-
items = @item_sets[@item_set_index][:items]
|
|
221
|
-
direction_config = @direction_configs[@direction_index]
|
|
222
|
-
spacing_config = @highlight_spacing_configs[@highlight_spacing_index]
|
|
223
|
-
repeat_config = @repeat_modes[@repeat_index]
|
|
224
|
-
highlight_style_config = @highlight_styles[@highlight_style_index]
|
|
225
|
-
highlight_symbol = @highlight_symbol_names[@highlight_symbol_index]
|
|
226
|
-
base_style_config = @base_styles[@base_style_index]
|
|
227
|
-
scroll_padding_config = @scroll_padding_configs[@scroll_padding_index]
|
|
228
|
-
offset_mode_config = @offset_modes[@offset_mode_index]
|
|
229
|
-
|
|
230
|
-
# Determine selection/offset based on mode
|
|
231
|
-
effective_selection = offset_mode_config[:allow_selection] ? @selected_index : nil
|
|
232
|
-
effective_offset = offset_mode_config[:offset]
|
|
233
|
-
|
|
234
|
-
@tui.draw do |frame|
|
|
235
|
-
# Split into main content and control panel
|
|
236
|
-
main_area, control_area = @tui.layout_split(
|
|
237
|
-
frame.area,
|
|
238
|
-
direction: :vertical,
|
|
239
|
-
constraints: [
|
|
240
|
-
@tui.constraint_fill(1),
|
|
241
|
-
@tui.constraint_length(8),
|
|
242
|
-
]
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
# Split main content into title and list
|
|
246
|
-
title_area, list_area = @tui.layout_split(
|
|
247
|
-
main_area,
|
|
248
|
-
direction: :vertical,
|
|
249
|
-
constraints: [
|
|
250
|
-
@tui.constraint_length(1),
|
|
251
|
-
@tui.constraint_fill(1),
|
|
252
|
-
]
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
# Render title
|
|
256
|
-
title = @tui.paragraph(text: "List Widget - Interactive Attribute Cycling")
|
|
257
|
-
frame.render_widget(title, title_area)
|
|
258
|
-
|
|
259
|
-
# Build list first to demonstrate query methods:
|
|
260
|
-
# - List#len (with #length, #size aliases)
|
|
261
|
-
# - List#selection (alias for #selected_index)
|
|
262
|
-
# - List#selected_item (returns item at selection, or nil)
|
|
263
|
-
base_list = @tui.list(
|
|
264
|
-
items:,
|
|
265
|
-
selected_index: effective_selection,
|
|
266
|
-
offset: effective_offset,
|
|
267
|
-
style: base_style_config[:style],
|
|
268
|
-
highlight_style: highlight_style_config[:style],
|
|
269
|
-
highlight_symbol:,
|
|
270
|
-
repeat_highlight_symbol: repeat_config[:repeat],
|
|
271
|
-
highlight_spacing: spacing_config[:spacing],
|
|
272
|
-
direction: direction_config[:direction],
|
|
273
|
-
scroll_padding: scroll_padding_config[:padding]
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
# Demonstrate query methods: len, selected_index, selected_item
|
|
277
|
-
item_count = base_list.len
|
|
278
|
-
current_index = base_list.selected_index # Explicit name - returns index
|
|
279
|
-
current_item = base_list.selected_item # Explicit name - returns item
|
|
280
|
-
|
|
281
|
-
# Format the selected item for display (handle rich text objects)
|
|
282
|
-
item_preview = case current_item
|
|
283
|
-
when nil then "none"
|
|
284
|
-
when String then (current_item.length > 12) ? "#{current_item[0..11]}…" : current_item
|
|
285
|
-
else current_item.class.name.split("::").last # Show type for rich text
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
list = base_list.with(
|
|
289
|
-
block: @tui.block(
|
|
290
|
-
title: "#{@item_sets[@item_set_index][:name]} (len: #{item_count}) | index: #{current_index.inspect} → #{item_preview}",
|
|
291
|
-
borders: [:all]
|
|
292
|
-
)
|
|
293
|
-
)
|
|
294
|
-
frame.render_widget(list, list_area)
|
|
295
|
-
|
|
296
|
-
# Render control panel
|
|
297
|
-
control_panel = @tui.block(
|
|
298
|
-
title: "Controls",
|
|
299
|
-
borders: [:all],
|
|
300
|
-
children: [
|
|
301
|
-
@tui.paragraph(
|
|
302
|
-
text: [
|
|
303
|
-
@tui.text_line(spans: [
|
|
304
|
-
@tui.text_span(content: "i", style: @hotkey_style),
|
|
305
|
-
@tui.text_span(content: ": Items "),
|
|
306
|
-
@tui.text_span(content: "↑/↓", style: @hotkey_style),
|
|
307
|
-
@tui.text_span(content: ": Navigate "),
|
|
308
|
-
@tui.text_span(content: "x", style: @hotkey_style),
|
|
309
|
-
@tui.text_span(content: ": Select "),
|
|
310
|
-
@tui.text_span(content: "h", style: @hotkey_style),
|
|
311
|
-
@tui.text_span(content: ": Highlight (#{highlight_style_config[:name]})"),
|
|
312
|
-
]),
|
|
313
|
-
@tui.text_line(spans: [
|
|
314
|
-
@tui.text_span(content: "y", style: @hotkey_style),
|
|
315
|
-
@tui.text_span(content: ": Symbol (#{highlight_symbol}) "),
|
|
316
|
-
@tui.text_span(content: "d", style: @hotkey_style),
|
|
317
|
-
@tui.text_span(content: ": Direction (#{direction_config[:name]})"),
|
|
318
|
-
]),
|
|
319
|
-
@tui.text_line(spans: [
|
|
320
|
-
@tui.text_span(content: "s", style: @hotkey_style),
|
|
321
|
-
@tui.text_span(content: ": Spacing (#{spacing_config[:name]}) "),
|
|
322
|
-
@tui.text_span(content: "p", style: @hotkey_style),
|
|
323
|
-
@tui.text_span(content: ": Scroll Padding (#{scroll_padding_config[:name]})"),
|
|
324
|
-
]),
|
|
325
|
-
@tui.text_line(spans: [
|
|
326
|
-
@tui.text_span(content: "b", style: @hotkey_style),
|
|
327
|
-
@tui.text_span(content: ": Base (#{base_style_config[:name]}) "),
|
|
328
|
-
@tui.text_span(content: "r", style: @hotkey_style),
|
|
329
|
-
@tui.text_span(content: ": Repeat (#{repeat_config[:name]})"),
|
|
330
|
-
]),
|
|
331
|
-
@tui.text_line(spans: [
|
|
332
|
-
@tui.text_span(content: "o", style: @hotkey_style),
|
|
333
|
-
@tui.text_span(content: ": Offset Mode (#{offset_mode_config[:name]}) "),
|
|
334
|
-
@tui.text_span(content: "q", style: @hotkey_style),
|
|
335
|
-
@tui.text_span(content: ": Quit"),
|
|
336
|
-
]),
|
|
337
|
-
]
|
|
338
|
-
),
|
|
339
|
-
]
|
|
340
|
-
)
|
|
341
|
-
frame.render_widget(control_panel, control_area)
|
|
342
|
-
end
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
# :nodoc:
|
|
346
|
-
private def handle_input
|
|
347
|
-
case @tui.poll_event
|
|
348
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
349
|
-
:quit
|
|
350
|
-
in type: :key, code: "i"
|
|
351
|
-
@item_set_index = (@item_set_index + 1) % @item_sets.size
|
|
352
|
-
@selected_index = nil
|
|
353
|
-
in type: :key, code: "up"
|
|
354
|
-
items = @item_sets[@item_set_index][:items]
|
|
355
|
-
@selected_index = (@selected_index || 0) - 1
|
|
356
|
-
@selected_index = items.size - 1 if @selected_index.negative?
|
|
357
|
-
in type: :key, code: "down"
|
|
358
|
-
items = @item_sets[@item_set_index][:items]
|
|
359
|
-
@selected_index = ((@selected_index || -1) + 1) % items.size
|
|
360
|
-
in type: :key, code: "x"
|
|
361
|
-
@selected_index = @selected_index.nil? ? 0 : nil
|
|
362
|
-
in type: :key, code: "h"
|
|
363
|
-
@highlight_style_index = (@highlight_style_index + 1) % @highlight_styles.size
|
|
364
|
-
in type: :key, code: "y"
|
|
365
|
-
@highlight_symbol_index = (@highlight_symbol_index + 1) % @highlight_symbol_names.size
|
|
366
|
-
in type: :key, code: "d"
|
|
367
|
-
@direction_index = (@direction_index + 1) % @direction_configs.size
|
|
368
|
-
in type: :key, code: "s"
|
|
369
|
-
@highlight_spacing_index = (@highlight_spacing_index + 1) % @highlight_spacing_configs.size
|
|
370
|
-
in type: :key, code: "b"
|
|
371
|
-
@base_style_index = (@base_style_index + 1) % @base_styles.size
|
|
372
|
-
in type: :key, code: "r"
|
|
373
|
-
@repeat_index = (@repeat_index + 1) % @repeat_modes.size
|
|
374
|
-
in type: :key, code: "p"
|
|
375
|
-
@scroll_padding_index = (@scroll_padding_index + 1) % @scroll_padding_configs.size
|
|
376
|
-
in type: :key, code: "o"
|
|
377
|
-
@offset_mode_index = (@offset_mode_index + 1) % @offset_modes.size
|
|
378
|
-
else
|
|
379
|
-
nil
|
|
380
|
-
end
|
|
381
|
-
end
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
WidgetList.new.run if __FILE__ == $PROGRAM_NAME
|