ratatui_ruby 1.1.0 → 1.1.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 -255
- 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 -147
- data/CHANGELOG.md +0 -736
- data/README.md +0 -187
- data/README.rdoc +0 -302
- data/Rakefile +0 -11
- data/Steepfile +0 -50
- 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 -448
- data/doc/contributors/design/rust_backend.md +0 -434
- 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/releasing.md +0 -215
- data/doc/contributors/todo/align/api_completeness_audit-finished.md +0 -381
- data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +0 -200
- data/doc/contributors/todo/align/term.md +0 -351
- data/doc/contributors/todo/align/terminal.md +0 -647
- data/doc/contributors/todo/future_work.md +0 -169
- data/doc/contributors/upstream_requests/paragraph_span_rects.md +0 -259
- 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_external_editor.gif +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 -34
- 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_external_editor/README.md +0 -62
- data/examples/app_external_editor/app.rb +0 -344
- 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 -382
- 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 -285
- 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/bump_workflow.rb +0 -49
- data/tasks/bump/cargo_lockfile.rb +0 -21
- data/tasks/bump/changelog.rb +0 -104
- 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/patch_release.rb +0 -19
- data/tasks/bump/release_branch.rb +0 -17
- data/tasks/bump/release_from_trunk.rb +0 -49
- data/tasks/bump/repository.rb +0 -54
- data/tasks/bump/ruby_gem.rb +0 -29
- data/tasks/bump/sem_ver.rb +0 -44
- data/tasks/bump/unreleased_section.rb +0 -73
- data/tasks/bump.rake +0 -61
- data/tasks/doc/documentation.rb +0 -59
- data/tasks/doc/link/file_url.rb +0 -30
- data/tasks/doc/link/relative_path.rb +0 -61
- data/tasks/doc/link/web_url.rb +0 -55
- data/tasks/doc/link.rb +0 -52
- data/tasks/doc/link_audit.rb +0 -116
- data/tasks/doc/problem.rb +0 -40
- data/tasks/doc/source_file.rb +0 -93
- data/tasks/doc.rake +0 -905
- 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/rbs_predicates/predicate_catalog.rb +0 -52
- data/tasks/rbs_predicates/predicate_tests.rb +0 -124
- data/tasks/rbs_predicates/rbs_signature.rb +0 -63
- data/tasks/rbs_predicates.rake +0 -31
- 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 -36
- data/tasks/website/index_page.rb +0 -30
- data/tasks/website/version.rb +0 -122
- 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,318 +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
|
-
|
|
10
|
-
require "ratatui_ruby"
|
|
11
|
-
|
|
12
|
-
##
|
|
13
|
-
# Interactive demonstration of RatatuiRuby debugging features.
|
|
14
|
-
#
|
|
15
|
-
# This example lets you trigger each debugging feature with a hotkey to verify
|
|
16
|
-
# your setup works before encountering a real bug.
|
|
17
|
-
#
|
|
18
|
-
# == Hotkeys
|
|
19
|
-
#
|
|
20
|
-
# [d] Enable debug_mode! — Shows the debug socket path for remote attachment
|
|
21
|
-
# [p] Trigger test_panic! — Deliberately crashes to verify Rust backtrace visibility
|
|
22
|
-
# [t] Cause TypeError — Passes wrong type to widget factory to show Rust stack frames
|
|
23
|
-
# [b] Show backtrace status — Displays current debug configuration
|
|
24
|
-
# [q] Quit
|
|
25
|
-
#
|
|
26
|
-
# == Usage
|
|
27
|
-
#
|
|
28
|
-
# # Normal mode (no backtraces):
|
|
29
|
-
# ruby examples/verify_debugging_usage/app.rb
|
|
30
|
-
#
|
|
31
|
-
# # With Rust backtraces only:
|
|
32
|
-
# RUST_BACKTRACE=1 ruby examples/verify_debugging_usage/app.rb
|
|
33
|
-
#
|
|
34
|
-
# # Full debug mode (stops at startup for debugger attachment):
|
|
35
|
-
# RR_DEBUG=1 ruby examples/verify_debugging_usage/app.rb
|
|
36
|
-
#
|
|
37
|
-
# == Remote Debugging
|
|
38
|
-
#
|
|
39
|
-
# When you press [d] to enable debug_mode!, the app continues running but
|
|
40
|
-
# prints a socket path. From another terminal:
|
|
41
|
-
#
|
|
42
|
-
# rdbg --attach
|
|
43
|
-
#
|
|
44
|
-
# This gives you a full debugger REPL while the TUI keeps running.
|
|
45
|
-
class VerifyDebuggingUsage
|
|
46
|
-
def initialize
|
|
47
|
-
@status_message = "Press a key to test debugging features"
|
|
48
|
-
@show_debug_info = false
|
|
49
|
-
@quit = false
|
|
50
|
-
|
|
51
|
-
# If debug mode was enabled via RR_DEBUG=1 at startup, capture the socket path
|
|
52
|
-
if RatatuiRuby::Debug.enabled?
|
|
53
|
-
@socket_path = begin
|
|
54
|
-
::DEBUGGER__.create_unix_domain_socket_name
|
|
55
|
-
rescue NameError
|
|
56
|
-
nil
|
|
57
|
-
end
|
|
58
|
-
@show_debug_info = true
|
|
59
|
-
@status_message = "RR_DEBUG=1 detected — debug mode active"
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def run
|
|
64
|
-
RatatuiRuby.run do |tui|
|
|
65
|
-
@tui = tui
|
|
66
|
-
@loop_count = 0
|
|
67
|
-
|
|
68
|
-
loop do
|
|
69
|
-
@loop_count += 1
|
|
70
|
-
|
|
71
|
-
# 🎯 Breakpoint every 250 loops. Try: p @status_message
|
|
72
|
-
if RatatuiRuby::Debug.enabled? && (@loop_count % 250).zero?
|
|
73
|
-
you_found_me = "🎉 You found me! Loop ##{@loop_count}"
|
|
74
|
-
# rubocop:disable Lint/Debugger
|
|
75
|
-
debugger
|
|
76
|
-
# rubocop:enable Lint/Debugger
|
|
77
|
-
_ = you_found_me # Suppress unused variable warning
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
render
|
|
81
|
-
break if @quit || handle_input == :quit
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
private def render
|
|
87
|
-
@tui.draw do |frame|
|
|
88
|
-
constraints = [
|
|
89
|
-
@tui.constraint_length(3), # Status
|
|
90
|
-
@tui.constraint_length(5), # Config
|
|
91
|
-
@tui.constraint_length(6), # Actions
|
|
92
|
-
]
|
|
93
|
-
|
|
94
|
-
if @show_debug_info
|
|
95
|
-
constraints << @tui.constraint_length(6) # Debug info
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
constraints << @tui.constraint_fill(1) # Spacer
|
|
99
|
-
constraints << @tui.constraint_length(3) # Help
|
|
100
|
-
|
|
101
|
-
chunks = @tui.layout_split(frame.area, direction: :vertical, constraints:)
|
|
102
|
-
|
|
103
|
-
idx = 0
|
|
104
|
-
render_status(frame, chunks[idx])
|
|
105
|
-
idx += 1
|
|
106
|
-
render_config(frame, chunks[idx])
|
|
107
|
-
idx += 1
|
|
108
|
-
render_actions(frame, chunks[idx])
|
|
109
|
-
idx += 1
|
|
110
|
-
|
|
111
|
-
if @show_debug_info
|
|
112
|
-
render_debug_info(frame, chunks[idx])
|
|
113
|
-
idx += 1
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
# Skip spacer
|
|
117
|
-
idx += 1
|
|
118
|
-
render_help(frame, chunks[idx])
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
private def render_status(frame, area)
|
|
123
|
-
frame.render_widget(
|
|
124
|
-
@tui.paragraph(
|
|
125
|
-
text: @status_message,
|
|
126
|
-
alignment: :center,
|
|
127
|
-
block: @tui.block(
|
|
128
|
-
title: " Status ",
|
|
129
|
-
title_alignment: :center,
|
|
130
|
-
borders: [:all],
|
|
131
|
-
border_style: { fg: :yellow }
|
|
132
|
-
)
|
|
133
|
-
),
|
|
134
|
-
area
|
|
135
|
-
)
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
private def render_config(frame, area)
|
|
139
|
-
config_lines = [
|
|
140
|
-
"Rust Backtraces: #{flag(RatatuiRuby::Debug.rust_backtrace_enabled?)}",
|
|
141
|
-
"Full Debug Mode: #{flag(RatatuiRuby::Debug.enabled?)}",
|
|
142
|
-
"Remote Debugging: #{remote_mode_description}",
|
|
143
|
-
].join("\n")
|
|
144
|
-
|
|
145
|
-
frame.render_widget(
|
|
146
|
-
@tui.paragraph(
|
|
147
|
-
text: config_lines,
|
|
148
|
-
block: @tui.block(
|
|
149
|
-
title: " Current Debug Configuration ",
|
|
150
|
-
borders: [:all],
|
|
151
|
-
border_style: { fg: :cyan }
|
|
152
|
-
)
|
|
153
|
-
),
|
|
154
|
-
area
|
|
155
|
-
)
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
private def render_actions(frame, area)
|
|
159
|
-
actions_lines = [
|
|
160
|
-
"[d] Enable debug_mode! and show socket info",
|
|
161
|
-
"[p] Trigger test_panic! to verify backtrace visibility",
|
|
162
|
-
"[t] Cause TypeError (pass wrong type to widget)",
|
|
163
|
-
"[b] Refresh debug status",
|
|
164
|
-
].join("\n")
|
|
165
|
-
|
|
166
|
-
frame.render_widget(
|
|
167
|
-
@tui.paragraph(
|
|
168
|
-
text: actions_lines,
|
|
169
|
-
block: @tui.block(
|
|
170
|
-
title: " Available Actions ",
|
|
171
|
-
borders: [:all],
|
|
172
|
-
border_style: { fg: :green }
|
|
173
|
-
)
|
|
174
|
-
),
|
|
175
|
-
area
|
|
176
|
-
)
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
private def render_debug_info(frame, area)
|
|
180
|
-
socket_display = @socket_path || "(socket not available)"
|
|
181
|
-
info_lines = [
|
|
182
|
-
"Socket: #{socket_display}",
|
|
183
|
-
"Attach: rdbg --attach",
|
|
184
|
-
"Hint: type 'continue' if you see SIGURG",
|
|
185
|
-
]
|
|
186
|
-
|
|
187
|
-
frame.render_widget(
|
|
188
|
-
@tui.paragraph(
|
|
189
|
-
text: info_lines.join("\n"),
|
|
190
|
-
block: @tui.block(
|
|
191
|
-
title: " Remote Debugging ",
|
|
192
|
-
borders: [:all],
|
|
193
|
-
border_style: { fg: :magenta }
|
|
194
|
-
)
|
|
195
|
-
),
|
|
196
|
-
area
|
|
197
|
-
)
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
private def render_help(frame, area)
|
|
201
|
-
frame.render_widget(
|
|
202
|
-
@tui.paragraph(
|
|
203
|
-
text: "[d] debug_mode! [p] test_panic! [t] TypeError [b] status [q] quit",
|
|
204
|
-
alignment: :center,
|
|
205
|
-
block: @tui.block(
|
|
206
|
-
borders: [:all],
|
|
207
|
-
border_style: { fg: :dark_gray }
|
|
208
|
-
)
|
|
209
|
-
),
|
|
210
|
-
area
|
|
211
|
-
)
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
private def flag(value)
|
|
215
|
-
value ? "✓ enabled" : "✗ disabled"
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
private def remote_mode_description
|
|
219
|
-
case RatatuiRuby::Debug.remote_debugging_mode
|
|
220
|
-
when :open
|
|
221
|
-
attached = debugger_attached? ? " — ATTACHED" : " — waiting"
|
|
222
|
-
"✓ open#{attached}"
|
|
223
|
-
when :open_nonstop
|
|
224
|
-
attached = debugger_attached? ? " — ATTACHED" : ""
|
|
225
|
-
"✓ open_nonstop#{attached}"
|
|
226
|
-
else
|
|
227
|
-
"✗ not configured"
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
# ☣️ FRAGILE: This pokes at debug gem internals.
|
|
232
|
-
#
|
|
233
|
-
# Private instance variables can change between gem versions. This code
|
|
234
|
-
# may silently break. We accept that risk here because this showcase
|
|
235
|
-
# exists specifically to demonstrate debugger attachment status.
|
|
236
|
-
#
|
|
237
|
-
# For production apps, checking Debug.enabled? is sufficient — knowing
|
|
238
|
-
# whether a client has attached rarely matters.
|
|
239
|
-
private def debugger_attached?
|
|
240
|
-
return false unless defined?(::DEBUGGER__::SESSION)
|
|
241
|
-
|
|
242
|
-
ui = ::DEBUGGER__::SESSION.instance_variable_get(:@ui)
|
|
243
|
-
return false unless ui
|
|
244
|
-
|
|
245
|
-
# The @sock instance variable is set when a client connects
|
|
246
|
-
sock = ui.instance_variable_get(:@sock)
|
|
247
|
-
!sock.nil?
|
|
248
|
-
rescue
|
|
249
|
-
false
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
private def handle_input
|
|
253
|
-
case @tui.poll_event
|
|
254
|
-
in { type: :key, code: "q" } | { type: :key, code: "c", modifiers: ["ctrl"] }
|
|
255
|
-
:quit
|
|
256
|
-
|
|
257
|
-
in { type: :key, code: "d" }
|
|
258
|
-
enable_debug_mode!
|
|
259
|
-
|
|
260
|
-
in { type: :key, code: "p" }
|
|
261
|
-
trigger_test_panic!
|
|
262
|
-
|
|
263
|
-
in { type: :key, code: "t" }
|
|
264
|
-
trigger_type_error!
|
|
265
|
-
|
|
266
|
-
in { type: :key, code: "b" }
|
|
267
|
-
@status_message = "Debug status refreshed at #{Time.now.strftime('%H:%M:%S')}"
|
|
268
|
-
|
|
269
|
-
else
|
|
270
|
-
nil
|
|
271
|
-
end
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
private def enable_debug_mode!
|
|
275
|
-
if RatatuiRuby::Debug.enabled?
|
|
276
|
-
@status_message = "Debug mode already enabled!"
|
|
277
|
-
else
|
|
278
|
-
# debug_mode! returns the socket path and suppresses the debug gem's output
|
|
279
|
-
@socket_path = RatatuiRuby.debug_mode!
|
|
280
|
-
@status_message = "debug_mode! enabled"
|
|
281
|
-
@show_debug_info = true
|
|
282
|
-
end
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
private def trigger_test_panic!
|
|
286
|
-
if RatatuiRuby::Debug.rust_backtrace_enabled?
|
|
287
|
-
@status_message = "Triggering test_panic! — check stderr for backtrace..."
|
|
288
|
-
else
|
|
289
|
-
@status_message = "Triggering test_panic! — backtrace hidden (set RUST_BACKTRACE=1)"
|
|
290
|
-
end
|
|
291
|
-
render # Show the message before crashing
|
|
292
|
-
|
|
293
|
-
# Give a moment for the render to complete
|
|
294
|
-
sleep 0.1
|
|
295
|
-
|
|
296
|
-
# This will crash the app with a Rust panic. If RUST_BACKTRACE=1 or
|
|
297
|
-
# debug mode is enabled, you'll see the full Rust stack trace after
|
|
298
|
-
# the terminal is restored.
|
|
299
|
-
RatatuiRuby::Debug.test_panic!
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
private def trigger_type_error!
|
|
303
|
-
if RatatuiRuby::Debug.rust_backtrace_enabled?
|
|
304
|
-
@status_message = "Triggering TypeError — check stderr for error message..."
|
|
305
|
-
else
|
|
306
|
-
@status_message = "Triggering TypeError — set RUST_BACKTRACE=1 for stack trace"
|
|
307
|
-
end
|
|
308
|
-
render # Show the message before crashing
|
|
309
|
-
sleep 0.1
|
|
310
|
-
|
|
311
|
-
# Bypass the factory's DWIM coercion to trigger a real Rust TypeError.
|
|
312
|
-
# Uses Widgets::Table.new directly with invalid rows type.
|
|
313
|
-
bad_table = RatatuiRuby::Widgets::Table.new(rows: 42, widths: [])
|
|
314
|
-
@tui.draw { |f| f.render_widget(bad_table, f.area) }
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
VerifyDebuggingUsage.new.run if __FILE__ == $PROGRAM_NAME
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
-
SPDX-License-Identifier: CC-BY-SA-4.0
|
|
4
|
-
-->
|
|
5
|
-
|
|
6
|
-
# External Editor Example
|
|
7
|
-
|
|
8
|
-
[](app.rb)
|
|
9
|
-
|
|
10
|
-
Demonstrates temporarily exiting the TUI to invoke an external editor, then seamlessly re-entering—like editing a commit message in lazygit or tig.
|
|
11
|
-
|
|
12
|
-
Most applications use `RatatuiRuby.run { }` which handles terminal setup and teardown automatically. But some workflows require **repeatedly leaving and re-entering raw mode** during a single session. This example shows the low-level lifecycle API that makes this possible.
|
|
13
|
-
|
|
14
|
-
## Features Demonstrated
|
|
15
|
-
|
|
16
|
-
- **Full Lifecycle Control**: Using `init_terminal` and `restore_terminal` directly instead of the `run` block.
|
|
17
|
-
- **External Process Invocation**: Safely restoring the terminal before spawning an interactive subprocess.
|
|
18
|
-
- **Session Re-entry**: Returning to the TUI after the external process exits, with state preserved.
|
|
19
|
-
- **Split-Pane Layout**: Dynamically splitting the display when scratch content exists.
|
|
20
|
-
- **Focus-Aware Scrolling**: Keyboard scrolling affects the focused pane; mouse scroll affects the hovered pane.
|
|
21
|
-
- **Wrapped Line Clamping**: Scroll limits based on wrapped (not raw) line count using `paragraph.line_count`.
|
|
22
|
-
- **Mouse Hit Testing**: Using `area.contains?(x, y)` to detect which pane is hovered.
|
|
23
|
-
|
|
24
|
-
## Hotkeys
|
|
25
|
-
|
|
26
|
-
| Key | Action |
|
|
27
|
-
|-----|--------|
|
|
28
|
-
| `↑`/`↓` or `j`/`k` | Scroll one line |
|
|
29
|
-
| `PgUp`/`PgDn` | Scroll one page |
|
|
30
|
-
| `Home`/`End` | Jump to top/bottom |
|
|
31
|
-
| Mouse wheel | Scroll hovered pane |
|
|
32
|
-
| `Tab` or `←`/`→` or `h`/`l` | Switch focus between panes |
|
|
33
|
-
| `e` | Edit this README.md in `$EDITOR` |
|
|
34
|
-
| `s` | Edit scratch file; saved content appears in split pane |
|
|
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/app_external_editor/app.rb
|
|
46
|
-
```
|
|
47
|
-
<!-- SPDX-SnippetEnd -->
|
|
48
|
-
|
|
49
|
-
Press `e` to edit this README. Press `s` to open a scratch file—when you save content, it appears beside the README in a split view.
|
|
50
|
-
|
|
51
|
-
## Learning Outcomes
|
|
52
|
-
|
|
53
|
-
Use this example if you need to...
|
|
54
|
-
|
|
55
|
-
- Implement commit message editing (like lazygit, tig, or git rebase -i).
|
|
56
|
-
- Spawn an external config editor from a TUI settings menu.
|
|
57
|
-
- Build a workflow that alternates between TUI and external tools.
|
|
58
|
-
- Create a split-pane layout with focus-aware scrolling.
|
|
59
|
-
- Calculate wrapped line counts for proper scroll clamping.
|
|
60
|
-
- Implement mouse hit testing for pane-specific interactions.
|
|
61
|
-
|
|
62
|
-
[Read the source code →](app.rb)
|