ratatui_ruby 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.builds/ruby-3.2.yml +54 -0
- data/.builds/ruby-3.3.yml +54 -0
- data/.builds/ruby-3.4.yml +54 -0
- data/.builds/ruby-4.0.0.yml +54 -0
- data/.pre-commit-config.yaml +16 -0
- data/.rubocop.yml +10 -0
- data/AGENTS.md +147 -0
- data/CHANGELOG.md +771 -0
- data/README.md +187 -0
- data/README.rdoc +302 -0
- data/Rakefile +11 -0
- data/Steepfile +50 -0
- data/doc/concepts/application_architecture.md +321 -0
- data/doc/concepts/application_testing.md +193 -0
- data/doc/concepts/async.md +190 -0
- data/doc/concepts/custom_widgets.md +247 -0
- data/doc/concepts/debugging.md +401 -0
- data/doc/concepts/event_handling.md +162 -0
- data/doc/concepts/interactive_design.md +146 -0
- data/doc/contributors/auditing/parity.md +239 -0
- data/doc/contributors/design/ruby_frontend.md +448 -0
- data/doc/contributors/design/rust_backend.md +434 -0
- data/doc/contributors/design.md +11 -0
- data/doc/contributors/developing_examples.md +400 -0
- data/doc/contributors/documentation_style.md +121 -0
- data/doc/contributors/index.md +21 -0
- data/doc/contributors/releasing.md +215 -0
- data/doc/contributors/todo/align/api_completeness_audit-finished.md +381 -0
- data/doc/contributors/todo/align/api_completeness_audit-unfinished.md +200 -0
- data/doc/contributors/todo/align/term.md +351 -0
- data/doc/contributors/todo/align/terminal.md +647 -0
- data/doc/contributors/todo/future_work.md +169 -0
- data/doc/contributors/upstream_requests/paragraph_span_rects.md +259 -0
- data/doc/contributors/upstream_requests/tab_rects.md +173 -0
- data/doc/contributors/upstream_requests/title_rects.md +132 -0
- data/doc/custom.css +22 -0
- data/doc/getting_started/quickstart.md +291 -0
- data/doc/getting_started/why.md +93 -0
- 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 +34 -0
- data/doc/troubleshooting/async.md +4 -0
- data/doc/troubleshooting/terminal_limitations.md +131 -0
- data/doc/troubleshooting/tui_output.md +197 -0
- data/examples/app_all_events/README.md +114 -0
- data/examples/app_all_events/app.rb +98 -0
- data/examples/app_all_events/model/app_model.rb +159 -0
- data/examples/app_all_events/model/event_color_cycle.rb +43 -0
- data/examples/app_all_events/model/event_entry.rb +94 -0
- data/examples/app_all_events/model/msg.rb +39 -0
- data/examples/app_all_events/model/timestamp.rb +56 -0
- data/examples/app_all_events/update.rb +75 -0
- data/examples/app_all_events/view/app_view.rb +80 -0
- data/examples/app_all_events/view/controls_view.rb +54 -0
- data/examples/app_all_events/view/counts_view.rb +61 -0
- data/examples/app_all_events/view/live_view.rb +72 -0
- data/examples/app_all_events/view/log_view.rb +57 -0
- data/examples/app_all_events/view.rb +9 -0
- data/examples/app_cli_rich_moments/README.md +81 -0
- data/examples/app_cli_rich_moments/app.rb +189 -0
- data/examples/app_color_picker/README.md +156 -0
- data/examples/app_color_picker/app.rb +76 -0
- data/examples/app_color_picker/clipboard.rb +86 -0
- data/examples/app_color_picker/color.rb +193 -0
- data/examples/app_color_picker/controls.rb +92 -0
- data/examples/app_color_picker/copy_dialog.rb +168 -0
- data/examples/app_color_picker/export_pane.rb +128 -0
- data/examples/app_color_picker/harmony.rb +58 -0
- data/examples/app_color_picker/input.rb +176 -0
- data/examples/app_color_picker/main_container.rb +180 -0
- data/examples/app_color_picker/palette.rb +111 -0
- data/examples/app_debugging_showcase/README.md +119 -0
- data/examples/app_debugging_showcase/app.rb +318 -0
- data/examples/app_external_editor/README.md +62 -0
- data/examples/app_external_editor/app.rb +344 -0
- data/examples/app_login_form/README.md +58 -0
- data/examples/app_login_form/app.rb +109 -0
- data/examples/app_stateful_interaction/README.md +35 -0
- data/examples/app_stateful_interaction/app.rb +328 -0
- data/examples/timeout_demo.rb +45 -0
- data/examples/verify_quickstart_dsl/README.md +55 -0
- data/examples/verify_quickstart_dsl/app.rb +49 -0
- data/examples/verify_quickstart_layout/README.md +77 -0
- data/examples/verify_quickstart_layout/app.rb +73 -0
- data/examples/verify_quickstart_lifecycle/README.md +68 -0
- data/examples/verify_quickstart_lifecycle/app.rb +62 -0
- data/examples/verify_readme_usage/README.md +49 -0
- data/examples/verify_readme_usage/app.rb +42 -0
- data/examples/verify_website_managed/README.md +48 -0
- data/examples/verify_website_managed/app.rb +36 -0
- data/examples/verify_website_menu/README.md +60 -0
- data/examples/verify_website_menu/app.rb +84 -0
- data/examples/verify_website_spinner/README.md +44 -0
- data/examples/verify_website_spinner/app.rb +34 -0
- data/examples/widget_barchart/README.md +58 -0
- data/examples/widget_barchart/app.rb +240 -0
- data/examples/widget_block/README.md +44 -0
- data/examples/widget_block/app.rb +258 -0
- data/examples/widget_box/README.md +54 -0
- data/examples/widget_box/app.rb +255 -0
- data/examples/widget_calendar/README.md +48 -0
- data/examples/widget_calendar/app.rb +115 -0
- data/examples/widget_canvas/README.md +31 -0
- data/examples/widget_canvas/app.rb +130 -0
- data/examples/widget_cell/README.md +45 -0
- data/examples/widget_cell/app.rb +112 -0
- data/examples/widget_center/README.md +33 -0
- data/examples/widget_center/app.rb +118 -0
- data/examples/widget_chart/README.md +50 -0
- data/examples/widget_chart/app.rb +220 -0
- data/examples/widget_gauge/README.md +50 -0
- data/examples/widget_gauge/app.rb +229 -0
- data/examples/widget_layout_split/README.md +53 -0
- data/examples/widget_layout_split/app.rb +260 -0
- data/examples/widget_line_gauge/README.md +50 -0
- data/examples/widget_line_gauge/app.rb +219 -0
- data/examples/widget_list/README.md +58 -0
- data/examples/widget_list/app.rb +382 -0
- data/examples/widget_map/README.md +48 -0
- data/examples/widget_map/app.rb +95 -0
- data/examples/widget_overlay/README.md +45 -0
- data/examples/widget_overlay/app.rb +250 -0
- data/examples/widget_popup/README.md +45 -0
- data/examples/widget_popup/app.rb +106 -0
- data/examples/widget_ratatui_logo/README.md +43 -0
- data/examples/widget_ratatui_logo/app.rb +104 -0
- data/examples/widget_ratatui_mascot/README.md +43 -0
- data/examples/widget_ratatui_mascot/app.rb +95 -0
- data/examples/widget_rect/README.md +53 -0
- data/examples/widget_rect/app.rb +222 -0
- data/examples/widget_render/README.md +46 -0
- data/examples/widget_render/app.rb +186 -0
- data/examples/widget_render/app.rbs +41 -0
- data/examples/widget_rich_text/README.md +44 -0
- data/examples/widget_rich_text/app.rb +193 -0
- data/examples/widget_scroll_text/README.md +46 -0
- data/examples/widget_scroll_text/app.rb +109 -0
- data/examples/widget_scrollbar/README.md +46 -0
- data/examples/widget_scrollbar/app.rb +155 -0
- data/examples/widget_sparkline/README.md +51 -0
- data/examples/widget_sparkline/app.rb +277 -0
- data/examples/widget_style_colors/README.md +43 -0
- data/examples/widget_style_colors/app.rb +83 -0
- data/examples/widget_table/README.md +57 -0
- data/examples/widget_table/app.rb +285 -0
- data/examples/widget_tabs/README.md +50 -0
- data/examples/widget_tabs/app.rb +183 -0
- data/examples/widget_text_width/README.md +44 -0
- data/examples/widget_text_width/app.rb +117 -0
- data/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/lib/ratatui_ruby/event/focus_gained.rb +50 -0
- data/lib/ratatui_ruby/event/focus_lost.rb +51 -0
- data/lib/ratatui_ruby/event/key/dwim.rb +301 -0
- data/lib/ratatui_ruby/event/key/modifier.rb +2 -0
- data/lib/ratatui_ruby/event/key.rb +9 -0
- data/lib/ratatui_ruby/event/mouse.rb +33 -0
- data/lib/ratatui_ruby/event/paste.rb +25 -0
- data/lib/ratatui_ruby/event/resize.rb +65 -0
- data/lib/ratatui_ruby/version.rb +1 -1
- data/migrate_to_buffer.rb +145 -0
- data/mise.toml +8 -0
- data/sig/ratatui_ruby/event.rbs +97 -0
- data/tasks/autodoc/examples.rb +87 -0
- data/tasks/autodoc/member.rb +58 -0
- data/tasks/autodoc/name.rb +21 -0
- data/tasks/autodoc.rake +21 -0
- data/tasks/bump/bump_workflow.rb +49 -0
- data/tasks/bump/cargo_lockfile.rb +21 -0
- data/tasks/bump/changelog.rb +104 -0
- data/tasks/bump/header.rb +32 -0
- data/tasks/bump/history.rb +32 -0
- data/tasks/bump/links.rb +69 -0
- data/tasks/bump/manifest.rb +33 -0
- data/tasks/bump/patch_release.rb +19 -0
- data/tasks/bump/release_branch.rb +17 -0
- data/tasks/bump/release_from_trunk.rb +49 -0
- data/tasks/bump/repository.rb +54 -0
- data/tasks/bump/ruby_gem.rb +29 -0
- data/tasks/bump/sem_ver.rb +44 -0
- data/tasks/bump/unreleased_section.rb +73 -0
- data/tasks/bump.rake +61 -0
- data/tasks/doc/documentation.rb +59 -0
- data/tasks/doc/link/file_url.rb +30 -0
- data/tasks/doc/link/relative_path.rb +61 -0
- data/tasks/doc/link/web_url.rb +55 -0
- data/tasks/doc/link.rb +52 -0
- data/tasks/doc/link_audit.rb +116 -0
- data/tasks/doc/problem.rb +40 -0
- data/tasks/doc/source_file.rb +93 -0
- data/tasks/doc.rake +905 -0
- data/tasks/example_viewer.html.erb +172 -0
- data/tasks/extension.rake +14 -0
- data/tasks/license/headers_md.rb +223 -0
- data/tasks/license/headers_rb.rb +210 -0
- data/tasks/license/license_utils.rb +130 -0
- data/tasks/license/snippets_md.rb +315 -0
- data/tasks/license/snippets_rdoc.rb +150 -0
- data/tasks/license.rake +91 -0
- data/tasks/lint.rake +170 -0
- data/tasks/rbs_predicates/predicate_catalog.rb +52 -0
- data/tasks/rbs_predicates/predicate_tests.rb +124 -0
- data/tasks/rbs_predicates/rbs_signature.rb +63 -0
- data/tasks/rbs_predicates.rake +31 -0
- data/tasks/rdoc_config.rb +29 -0
- data/tasks/resources/build.yml.erb +60 -0
- data/tasks/resources/index.html.erb +141 -0
- data/tasks/resources/rubies.yml +7 -0
- data/tasks/sourcehut.rake +122 -0
- data/tasks/steep.rake +11 -0
- data/tasks/terminal_preview/app_screenshot.rb +45 -0
- data/tasks/terminal_preview/crash_report.rb +54 -0
- data/tasks/terminal_preview/example_app.rb +27 -0
- data/tasks/terminal_preview/launcher_script.rb +48 -0
- data/tasks/terminal_preview/preview_collection.rb +60 -0
- data/tasks/terminal_preview/preview_timing.rb +24 -0
- data/tasks/terminal_preview/safety_confirmation.rb +58 -0
- data/tasks/terminal_preview/saved_screenshot.rb +56 -0
- data/tasks/terminal_preview/system_appearance.rb +13 -0
- data/tasks/terminal_preview/terminal_window.rb +138 -0
- data/tasks/terminal_preview/window_id.rb +16 -0
- data/tasks/terminal_preview.rake +30 -0
- data/tasks/test.rake +36 -0
- data/tasks/website/index_page.rb +30 -0
- data/tasks/website/version.rb +122 -0
- data/tasks/website/version_menu.rb +68 -0
- data/tasks/website/versioned_documentation.rb +83 -0
- data/tasks/website/website.rb +53 -0
- data/tasks/website.rake +28 -0
- metadata +256 -1
|
@@ -70,6 +70,56 @@ module RatatuiRuby
|
|
|
70
70
|
def ==(other)
|
|
71
71
|
other.is_a?(FocusGained)
|
|
72
72
|
end
|
|
73
|
+
|
|
74
|
+
# =========================================================================
|
|
75
|
+
# DWIM Predicates
|
|
76
|
+
# =========================================================================
|
|
77
|
+
|
|
78
|
+
# Returns true. The terminal window is now in focus.
|
|
79
|
+
#
|
|
80
|
+
# event.focus? # => true
|
|
81
|
+
def focus?
|
|
82
|
+
true
|
|
83
|
+
end
|
|
84
|
+
alias focused? focus?
|
|
85
|
+
|
|
86
|
+
# Returns true. The application gained focus.
|
|
87
|
+
#
|
|
88
|
+
# event.gained? # => true
|
|
89
|
+
def gained?
|
|
90
|
+
true
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Returns false. This is not a focus lost event.
|
|
94
|
+
#
|
|
95
|
+
# event.lost? # => false
|
|
96
|
+
def lost?
|
|
97
|
+
false
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Returns false. Blur is the opposite of focus gained.
|
|
101
|
+
#
|
|
102
|
+
# event.blur? # => false
|
|
103
|
+
def blur?
|
|
104
|
+
false
|
|
105
|
+
end
|
|
106
|
+
alias blurred? blur?
|
|
107
|
+
|
|
108
|
+
# Returns true. The application is active.
|
|
109
|
+
#
|
|
110
|
+
# event.active? # => true
|
|
111
|
+
def active?
|
|
112
|
+
true
|
|
113
|
+
end
|
|
114
|
+
alias foreground? active?
|
|
115
|
+
|
|
116
|
+
# Returns false. The application is not inactive.
|
|
117
|
+
#
|
|
118
|
+
# event.inactive? # => false
|
|
119
|
+
def inactive?
|
|
120
|
+
false
|
|
121
|
+
end
|
|
122
|
+
alias background? inactive?
|
|
73
123
|
end
|
|
74
124
|
end
|
|
75
125
|
end
|
|
@@ -71,6 +71,57 @@ module RatatuiRuby
|
|
|
71
71
|
def ==(other)
|
|
72
72
|
other.is_a?(FocusLost)
|
|
73
73
|
end
|
|
74
|
+
|
|
75
|
+
# =========================================================================
|
|
76
|
+
# DWIM Predicates
|
|
77
|
+
# =========================================================================
|
|
78
|
+
|
|
79
|
+
# Returns true. The terminal has lost focus (blur).
|
|
80
|
+
#
|
|
81
|
+
# event.blur? # => true
|
|
82
|
+
def blur?
|
|
83
|
+
true
|
|
84
|
+
end
|
|
85
|
+
alias blurred? blur?
|
|
86
|
+
|
|
87
|
+
# Returns true. The application lost focus.
|
|
88
|
+
#
|
|
89
|
+
# event.lost? # => true
|
|
90
|
+
def lost?
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
alias unfocused? lost?
|
|
94
|
+
|
|
95
|
+
# Returns false. This is not a focus gained event.
|
|
96
|
+
#
|
|
97
|
+
# event.focus? # => false
|
|
98
|
+
def focus?
|
|
99
|
+
false
|
|
100
|
+
end
|
|
101
|
+
alias focused? focus?
|
|
102
|
+
|
|
103
|
+
# Returns false. This is not a gained event.
|
|
104
|
+
#
|
|
105
|
+
# event.gained? # => false
|
|
106
|
+
def gained?
|
|
107
|
+
false
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Returns true. The application is inactive.
|
|
111
|
+
#
|
|
112
|
+
# event.inactive? # => true
|
|
113
|
+
def inactive?
|
|
114
|
+
true
|
|
115
|
+
end
|
|
116
|
+
alias background? inactive?
|
|
117
|
+
|
|
118
|
+
# Returns false. The application is not active.
|
|
119
|
+
#
|
|
120
|
+
# event.active? # => false
|
|
121
|
+
def active?
|
|
122
|
+
false
|
|
123
|
+
end
|
|
124
|
+
alias foreground? active?
|
|
74
125
|
end
|
|
75
126
|
end
|
|
76
127
|
end
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
8
|
+
module RatatuiRuby
|
|
9
|
+
class Event
|
|
10
|
+
class Key < Event
|
|
11
|
+
# DWIM predicates for common key patterns.
|
|
12
|
+
#
|
|
13
|
+
# These predicates anticipate what developers intuitively try. Space bars,
|
|
14
|
+
# character categories, Unix signals, and Vim-style navigation.
|
|
15
|
+
module Dwim
|
|
16
|
+
# Returns true if the key is a space character.
|
|
17
|
+
#
|
|
18
|
+
# event.space? # => true for " "
|
|
19
|
+
def space?
|
|
20
|
+
@code == " " && @modifiers.empty?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
alias spacebar? space?
|
|
24
|
+
|
|
25
|
+
# Returns true if the key is Enter. Alias for carriage return.
|
|
26
|
+
#
|
|
27
|
+
# event.cr? # => true for enter
|
|
28
|
+
def cr?
|
|
29
|
+
@code == "enter" && @modifiers.empty?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
alias carriagereturn? cr?
|
|
33
|
+
alias linefeed? cr?
|
|
34
|
+
alias newline? cr?
|
|
35
|
+
alias lf? cr?
|
|
36
|
+
|
|
37
|
+
# Returns true if the key is a single letter (a-z, A-Z).
|
|
38
|
+
#
|
|
39
|
+
# Event::Key.new(code: "a").letter? # => true
|
|
40
|
+
def letter?
|
|
41
|
+
@code.length == 1 && @code.match?(/\A[A-Za-z]\z/)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Returns true if the key is a digit (0-9).
|
|
45
|
+
#
|
|
46
|
+
# Event::Key.new(code: "5").digit? # => true
|
|
47
|
+
def digit?
|
|
48
|
+
@code.length == 1 && @code.match?(/\A[0-9]\z/)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns true if the key is alphanumeric.
|
|
52
|
+
#
|
|
53
|
+
# Event::Key.new(code: "a").alphanumeric? # => true
|
|
54
|
+
def alphanumeric?
|
|
55
|
+
letter? || digit?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns true if the key is punctuation.
|
|
59
|
+
#
|
|
60
|
+
# Event::Key.new(code: "@", modifiers: ["shift"]).punctuation? # => true
|
|
61
|
+
def punctuation?
|
|
62
|
+
return false unless @code.length == 1
|
|
63
|
+
!letter? && !digit? && !whitespace?
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Returns true if the key is whitespace (space, enter, tab).
|
|
67
|
+
#
|
|
68
|
+
# Event::Key.new(code: " ").whitespace? # => true
|
|
69
|
+
def whitespace?
|
|
70
|
+
@code == " " || @code == "enter" || @code == "tab"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns true for interrupt (Ctrl+C).
|
|
74
|
+
#
|
|
75
|
+
# event.interrupt? # => true for Ctrl+C
|
|
76
|
+
def interrupt?
|
|
77
|
+
@code == "c" && @modifiers == ["ctrl"]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Returns true for end-of-file (Ctrl+D).
|
|
81
|
+
#
|
|
82
|
+
# event.eof? # => true for Ctrl+D
|
|
83
|
+
def eof?
|
|
84
|
+
@code == "d" && @modifiers == ["ctrl"]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Returns true for cancel (Esc or Ctrl+C).
|
|
88
|
+
#
|
|
89
|
+
# event.cancel? # => true for Esc or Ctrl+C
|
|
90
|
+
def cancel?
|
|
91
|
+
(@code == "esc" && @modifiers.empty?) || interrupt?
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Returns true for SIGINT (Ctrl+C).
|
|
95
|
+
#
|
|
96
|
+
# event.sigint? # => true for Ctrl+C
|
|
97
|
+
def sigint?
|
|
98
|
+
interrupt?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
alias int? sigint?
|
|
102
|
+
|
|
103
|
+
# Returns true for SIGTSTP (Ctrl+Z) - suspend/stop.
|
|
104
|
+
#
|
|
105
|
+
# event.suspend? # => true for Ctrl+Z
|
|
106
|
+
def suspend?
|
|
107
|
+
@code == "z" && @modifiers == ["ctrl"]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
alias sigtstp? suspend?
|
|
111
|
+
alias tstp? suspend?
|
|
112
|
+
|
|
113
|
+
# Returns true for SIGQUIT (Ctrl+\).
|
|
114
|
+
#
|
|
115
|
+
# event.quit? # => true for Ctrl+\
|
|
116
|
+
def quit?
|
|
117
|
+
@code == "\\" && @modifiers == ["ctrl"]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
alias sigquit? quit?
|
|
121
|
+
|
|
122
|
+
NAVIGATION_KEYS = %w[up down left right home end page_up page_down].freeze # :nodoc:
|
|
123
|
+
|
|
124
|
+
# Returns true if key is a navigation key.
|
|
125
|
+
#
|
|
126
|
+
# Event::Key.new(code: "up").navigation? # => true
|
|
127
|
+
def navigation?
|
|
128
|
+
NAVIGATION_KEYS.include?(@code) && @modifiers.empty?
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
ARROW_KEYS = %w[up down left right].freeze # :nodoc:
|
|
132
|
+
|
|
133
|
+
# Returns true if key is an arrow key.
|
|
134
|
+
#
|
|
135
|
+
# Event::Key.new(code: "up").arrow? # => true
|
|
136
|
+
def arrow?
|
|
137
|
+
ARROW_KEYS.include?(@code) && @modifiers.empty?
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
VIM_MOVEMENT_KEYS = %w[h j k l w b g G].freeze # :nodoc:
|
|
141
|
+
|
|
142
|
+
# Returns true if key is a Vim movement key.
|
|
143
|
+
#
|
|
144
|
+
# Event::Key.new(code: "j").vim? # => true
|
|
145
|
+
def vim?
|
|
146
|
+
return true if VIM_MOVEMENT_KEYS.include?(@code) && @modifiers.empty?
|
|
147
|
+
@code == "G" && @modifiers == ["shift"]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Returns true for Vim left (h).
|
|
151
|
+
def vim_left?
|
|
152
|
+
@code == "h" && @modifiers.empty?
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Returns true for Vim down (j).
|
|
156
|
+
def vim_down?
|
|
157
|
+
@code == "j" && @modifiers.empty?
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Returns true for Vim up (k).
|
|
161
|
+
def vim_up?
|
|
162
|
+
@code == "k" && @modifiers.empty?
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Returns true for Vim right (l).
|
|
166
|
+
def vim_right?
|
|
167
|
+
@code == "l" && @modifiers.empty?
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Returns true for Vim word forward (w).
|
|
171
|
+
def vim_word_forward?
|
|
172
|
+
@code == "w" && @modifiers.empty?
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Returns true for Vim word backward (b).
|
|
176
|
+
def vim_word_backward?
|
|
177
|
+
@code == "b" && @modifiers.empty?
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Returns true for Vim go to top (gg pattern, here just g).
|
|
181
|
+
def vim_top?
|
|
182
|
+
@code == "g" && @modifiers.empty?
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Returns true for Vim go to bottom (G).
|
|
186
|
+
def vim_bottom?
|
|
187
|
+
@code == "G" && @modifiers == ["shift"]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Punctuation name predicates - generated at load time for performance.
|
|
191
|
+
# Maps intuitive names to their symbol characters.
|
|
192
|
+
# :nodoc:
|
|
193
|
+
PUNCTUATION_NAMES = {
|
|
194
|
+
# Navigation shortcuts (the original use case!)
|
|
195
|
+
tilde: "~",
|
|
196
|
+
slash: "/",
|
|
197
|
+
forwardslash: "/",
|
|
198
|
+
backslash: "\\",
|
|
199
|
+
|
|
200
|
+
# Common punctuation
|
|
201
|
+
comma: ",",
|
|
202
|
+
period: ".",
|
|
203
|
+
dot: ".",
|
|
204
|
+
colon: ":",
|
|
205
|
+
semicolon: ";",
|
|
206
|
+
|
|
207
|
+
# Question and exclamation
|
|
208
|
+
question: "?",
|
|
209
|
+
questionmark: "?",
|
|
210
|
+
exclamation: "!",
|
|
211
|
+
exclamationmark: "!",
|
|
212
|
+
exclamationpoint: "!",
|
|
213
|
+
bang: "!",
|
|
214
|
+
|
|
215
|
+
# Programming symbols
|
|
216
|
+
at: "@",
|
|
217
|
+
atsign: "@",
|
|
218
|
+
hash: "#",
|
|
219
|
+
pound: "#",
|
|
220
|
+
numbersign: "#",
|
|
221
|
+
dollar: "$",
|
|
222
|
+
dollarsign: "$",
|
|
223
|
+
percent: "%",
|
|
224
|
+
caret: "^",
|
|
225
|
+
circumflex: "^",
|
|
226
|
+
ampersand: "&",
|
|
227
|
+
asterisk: "*",
|
|
228
|
+
star: "*",
|
|
229
|
+
|
|
230
|
+
# Arithmetic and comparison
|
|
231
|
+
underscore: "_",
|
|
232
|
+
hyphen: "-",
|
|
233
|
+
dash: "-",
|
|
234
|
+
minus: "-",
|
|
235
|
+
plus: "+",
|
|
236
|
+
equals: "=",
|
|
237
|
+
equalsign: "=",
|
|
238
|
+
pipe: "|",
|
|
239
|
+
bar: "|",
|
|
240
|
+
lessthan: "<",
|
|
241
|
+
lt: "<",
|
|
242
|
+
greaterthan: ">",
|
|
243
|
+
gt: ">",
|
|
244
|
+
|
|
245
|
+
# Brackets and parens
|
|
246
|
+
lparen: "(",
|
|
247
|
+
leftparen: "(",
|
|
248
|
+
openparen: "(",
|
|
249
|
+
leftparenthesis: "(",
|
|
250
|
+
openparenthesis: "(",
|
|
251
|
+
rparen: ")",
|
|
252
|
+
rightparen: ")",
|
|
253
|
+
closeparen: ")",
|
|
254
|
+
rightparenthesis: ")",
|
|
255
|
+
closeparenthesis: ")",
|
|
256
|
+
lbracket: "[",
|
|
257
|
+
leftbracket: "[",
|
|
258
|
+
openbracket: "[",
|
|
259
|
+
leftsquarebracket: "[",
|
|
260
|
+
opensquarebracket: "[",
|
|
261
|
+
rbracket: "]",
|
|
262
|
+
rightbracket: "]",
|
|
263
|
+
closebracket: "]",
|
|
264
|
+
rightsquarebracket: "]",
|
|
265
|
+
closesquarebracket: "]",
|
|
266
|
+
lbrace: "{",
|
|
267
|
+
leftbrace: "{",
|
|
268
|
+
openbrace: "{",
|
|
269
|
+
leftcurlybrace: "{",
|
|
270
|
+
opencurlybrace: "{",
|
|
271
|
+
rbrace: "}",
|
|
272
|
+
rightbrace: "}",
|
|
273
|
+
closebrace: "}",
|
|
274
|
+
rightcurlybrace: "}",
|
|
275
|
+
closecurlybrace: "}",
|
|
276
|
+
|
|
277
|
+
# Quotes
|
|
278
|
+
backtick: "`",
|
|
279
|
+
grave: "`",
|
|
280
|
+
singlequote: "'",
|
|
281
|
+
apostrophe: "'",
|
|
282
|
+
doublequote: "\"",
|
|
283
|
+
}.freeze
|
|
284
|
+
|
|
285
|
+
# Generate predicate methods at load time (faster than method_missing)
|
|
286
|
+
PUNCTUATION_NAMES.each do |name, char|
|
|
287
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
288
|
+
def #{name}?
|
|
289
|
+
@code == #{char.inspect}
|
|
290
|
+
end
|
|
291
|
+
RUBY
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# quote? matches both single and double quotes
|
|
295
|
+
def quote?
|
|
296
|
+
@code == "'" || @code == "\""
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#++
|
|
7
7
|
|
|
8
8
|
require_relative "key/character"
|
|
9
|
+
require_relative "key/dwim"
|
|
9
10
|
require_relative "key/media"
|
|
10
11
|
require_relative "key/modifier"
|
|
11
12
|
require_relative "key/navigation"
|
|
@@ -88,6 +89,7 @@ module RatatuiRuby
|
|
|
88
89
|
# These keys will not work in Terminal.app, iTerm2, or GNOME Terminal.
|
|
89
90
|
class Key < Event
|
|
90
91
|
include Character
|
|
92
|
+
include Dwim
|
|
91
93
|
include Media
|
|
92
94
|
include Modifier
|
|
93
95
|
include Navigation
|
|
@@ -435,6 +437,13 @@ module RatatuiRuby
|
|
|
435
437
|
normalized_code = @code.delete("_")
|
|
436
438
|
return true if normalized_predicate == normalized_code && @modifiers.empty?
|
|
437
439
|
|
|
440
|
+
# DWIM: Underscore variants delegate to existing methods
|
|
441
|
+
# space_bar? → spacebar? → space?, sig_int? → sigint?
|
|
442
|
+
normalized_method = :"#{normalized_predicate}?"
|
|
443
|
+
if normalized_method != name && respond_to?(normalized_method)
|
|
444
|
+
return public_send(normalized_method)
|
|
445
|
+
end
|
|
446
|
+
|
|
438
447
|
false
|
|
439
448
|
else
|
|
440
449
|
super
|
|
@@ -253,6 +253,39 @@ module RatatuiRuby
|
|
|
253
253
|
else false
|
|
254
254
|
end
|
|
255
255
|
end
|
|
256
|
+
|
|
257
|
+
alias wheel_up? scroll_up?
|
|
258
|
+
alias wheel_down? scroll_down?
|
|
259
|
+
|
|
260
|
+
# Returns true for any scroll event.
|
|
261
|
+
#
|
|
262
|
+
# event.scroll? # => true for scroll_up or scroll_down
|
|
263
|
+
def scroll?
|
|
264
|
+
scroll_up? || scroll_down?
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
alias primary? left?
|
|
268
|
+
alias secondary? right?
|
|
269
|
+
alias context_menu? right?
|
|
270
|
+
alias aux? middle?
|
|
271
|
+
alias auxiliary? aux?
|
|
272
|
+
|
|
273
|
+
# Returns true for mouse movement without button press.
|
|
274
|
+
#
|
|
275
|
+
# event.moved? # => true for moved (no button)
|
|
276
|
+
def moved?
|
|
277
|
+
@kind == "moved"
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
alias hover? moved?
|
|
281
|
+
alias hovering? moved?
|
|
282
|
+
alias move? moved?
|
|
283
|
+
alias dragging? drag?
|
|
284
|
+
|
|
285
|
+
alias release? up?
|
|
286
|
+
alias released? up?
|
|
287
|
+
alias press? down?
|
|
288
|
+
alias pressed? down?
|
|
256
289
|
end
|
|
257
290
|
end
|
|
258
291
|
end
|
|
@@ -67,6 +67,9 @@ module RatatuiRuby
|
|
|
67
67
|
def paste?
|
|
68
68
|
true
|
|
69
69
|
end
|
|
70
|
+
alias clipboard? paste?
|
|
71
|
+
alias pasteboard? paste?
|
|
72
|
+
alias pasted? paste?
|
|
70
73
|
|
|
71
74
|
# Creates a new Paste event.
|
|
72
75
|
#
|
|
@@ -100,6 +103,28 @@ module RatatuiRuby
|
|
|
100
103
|
return false unless other.is_a?(Paste)
|
|
101
104
|
content == other.content
|
|
102
105
|
end
|
|
106
|
+
|
|
107
|
+
# Returns true if the pasted content is empty.
|
|
108
|
+
def empty?
|
|
109
|
+
@content.empty?
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns true if the pasted content is empty or whitespace-only.
|
|
113
|
+
def blank?
|
|
114
|
+
@content.strip.empty?
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Returns true if the pasted content spans multiple lines.
|
|
118
|
+
def multiline?
|
|
119
|
+
@content.include?("\n")
|
|
120
|
+
end
|
|
121
|
+
alias multi_line? multiline?
|
|
122
|
+
|
|
123
|
+
# Returns true if the pasted content is a single line.
|
|
124
|
+
def single_line?
|
|
125
|
+
!multiline?
|
|
126
|
+
end
|
|
127
|
+
alias singleline? single_line?
|
|
103
128
|
end
|
|
104
129
|
end
|
|
105
130
|
end
|
|
@@ -151,6 +151,71 @@ module RatatuiRuby
|
|
|
151
151
|
else false
|
|
152
152
|
end
|
|
153
153
|
end
|
|
154
|
+
|
|
155
|
+
# Returns true. Unix <tt>SIGWINCH</tt> triggers terminal resize.
|
|
156
|
+
#
|
|
157
|
+
# event.sigwinch? # => true
|
|
158
|
+
def sigwinch?
|
|
159
|
+
true
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
alias winch? sigwinch?
|
|
163
|
+
alias sig_winch? sigwinch?
|
|
164
|
+
|
|
165
|
+
alias terminal_resize? resize?
|
|
166
|
+
alias window_resize? resize?
|
|
167
|
+
alias window_change? resize?
|
|
168
|
+
alias viewport_resize? resize?
|
|
169
|
+
alias viewport_change? resize?
|
|
170
|
+
alias size_change? resize?
|
|
171
|
+
alias resized? resize?
|
|
172
|
+
|
|
173
|
+
VT100_WIDTH = 80 # :nodoc:
|
|
174
|
+
VT100_HEIGHT = 24 # :nodoc:
|
|
175
|
+
|
|
176
|
+
# Returns true if width exceeds height.
|
|
177
|
+
#
|
|
178
|
+
# Event::Resize.new(width: 120, height: 24).landscape? # => true
|
|
179
|
+
def landscape?
|
|
180
|
+
@width > @height
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Returns true if height exceeds or equals width.
|
|
184
|
+
#
|
|
185
|
+
# Event::Resize.new(width: 40, height: 80).portrait? # => true
|
|
186
|
+
def portrait?
|
|
187
|
+
@height >= @width
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Returns true if dimensions are exactly 80x24.
|
|
191
|
+
#
|
|
192
|
+
# Event::Resize.new(width: 80, height: 24).vt100? # => true
|
|
193
|
+
def vt100?
|
|
194
|
+
@width == VT100_WIDTH && @height == VT100_HEIGHT
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Returns true if both dimensions meet or exceed 80x24.
|
|
198
|
+
#
|
|
199
|
+
# Event::Resize.new(width: 120, height: 40).at_least_vt100? # => true
|
|
200
|
+
def at_least_vt100?
|
|
201
|
+
@width >= VT100_WIDTH && @height >= VT100_HEIGHT
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Returns true if both dimensions exceed 80x24.
|
|
205
|
+
#
|
|
206
|
+
# Event::Resize.new(width: 81, height: 25).over_vt100? # => true
|
|
207
|
+
def over_vt100?
|
|
208
|
+
@width > VT100_WIDTH && @height > VT100_HEIGHT
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Returns true if either dimension falls below VT100 standard.
|
|
212
|
+
#
|
|
213
|
+
# Event::Resize.new(width: 60, height: 24).cramped? # => true
|
|
214
|
+
def cramped?
|
|
215
|
+
@width < VT100_WIDTH || @height < VT100_HEIGHT
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
alias constrained? cramped?
|
|
154
219
|
end
|
|
155
220
|
end
|
|
156
221
|
end
|
data/lib/ratatui_ruby/version.rb
CHANGED