Class: Clack::Core::Prompt Abstract
- Inherits:
-
Object
- Object
- Clack::Core::Prompt
- Includes:
- Chrome
- Defined in:
- lib/clack/core/prompt.rb
Overview
Subclass and override #build_frame to implement a prompt.
Base class for all interactive prompts.
Implements a state machine with states: :initial, :active, :error, :warning, :submit, :cancel. Subclasses override #handle_input, #build_frame, and #build_final_frame to customize behavior and rendering.
The prompt loop:
- Renders the initial frame
- Reads keyboard input via KeyReader
- Handles input and transitions state
- Re-renders the frame
- Repeats until a terminal state (:submit or :cancel)
Direct Known Subclasses
Prompts::Autocomplete, Prompts::AutocompleteMultiselect, Prompts::Confirm, Prompts::Date, Prompts::GroupMultiselect, Prompts::MultilineText, Prompts::Multiselect, Prompts::Password, Prompts::Path, Prompts::Range, Prompts::Select, Prompts::SelectKey, Prompts::Text
Constant Summary collapse
- MIN_TERMINAL_WIDTH =
Minimum terminal width for clean rendering. Prompts warn (non-blocking) if the terminal is narrower.
40
Class Attribute Summary collapse
-
.active_prompts ⇒ Object
readonly
Returns the value of attribute active_prompts.
-
.resize_pending ⇒ Object
Returns the value of attribute resize_pending.
Instance Attribute Summary collapse
-
#error_message ⇒ String?
readonly
Validation error message, if any.
-
#state ⇒ Symbol
readonly
Current state (:initial, :active, :error, :warning, :submit, :cancel).
-
#value ⇒ Object
readonly
The current/final value.
-
#warning_message ⇒ String?
readonly
Validation warning message, if any.
Class Method Summary collapse
-
.flush_resize ⇒ Object
Notify all active prompts of a pending resize.
-
.register(prompt) ⇒ Object
Register a prompt instance for resize notifications.
-
.setup_signal_handler ⇒ Object
Set up SIGWINCH handler (called once on load).
-
.unregister(prompt) ⇒ Object
Unregister a prompt instance from resize notifications.
Instance Method Summary collapse
-
#initialize(message:, help: nil, validate: nil, transform: nil, with_guide: nil, show_instructions: nil, instructions: nil, input: $stdin, output: $stdout) ⇒ Prompt
constructor
A new instance of Prompt.
-
#request_redraw ⇒ Object
Request a full redraw on next render cycle.
-
#run ⇒ Object, Clack::CANCEL
Run the prompt interaction loop.
Constructor Details
#initialize(message:, help: nil, validate: nil, transform: nil, with_guide: nil, show_instructions: nil, instructions: nil, input: $stdin, output: $stdout) ⇒ Prompt
Returns a new instance of Prompt.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/clack/core/prompt.rb', line 99 def initialize(message:, help: nil, validate: nil, transform: nil, with_guide: nil, show_instructions: nil, instructions: nil, input: $stdin, output: $stdout) @message = @help = help setup_chrome(with_guide:, show_instructions:, instructions:) @validate = Validators.resolve(validate) @transform = Transformers.resolve(transform) @input = input @output = output @state = :initial @value = nil @error_message = nil @warning_message = nil @warning_confirmed = false @prev_frame = nil @needs_redraw = false end |
Class Attribute Details
.active_prompts ⇒ Object (readonly)
Returns the value of attribute active_prompts.
42 43 44 |
# File 'lib/clack/core/prompt.rb', line 42 def active_prompts @active_prompts end |
.resize_pending ⇒ Object
Returns the value of attribute resize_pending.
43 44 45 |
# File 'lib/clack/core/prompt.rb', line 43 def resize_pending @resize_pending end |
Instance Attribute Details
#error_message ⇒ String? (readonly)
Returns validation error message, if any.
81 82 83 |
# File 'lib/clack/core/prompt.rb', line 81 def @error_message end |
#state ⇒ Symbol (readonly)
Returns current state (:initial, :active, :error, :warning, :submit, :cancel).
77 78 79 |
# File 'lib/clack/core/prompt.rb', line 77 def state @state end |
#value ⇒ Object (readonly)
Returns the current/final value.
79 80 81 |
# File 'lib/clack/core/prompt.rb', line 79 def value @value end |
#warning_message ⇒ String? (readonly)
Returns validation warning message, if any.
83 84 85 |
# File 'lib/clack/core/prompt.rb', line 83 def @warning_message end |
Class Method Details
.flush_resize ⇒ Object
Notify all active prompts of a pending resize. Called from the render loop, not from the signal handler.
57 58 59 60 61 62 |
# File 'lib/clack/core/prompt.rb', line 57 def flush_resize return unless @resize_pending @resize_pending = false @active_prompts.each(&:request_redraw) end |
.register(prompt) ⇒ Object
Register a prompt instance for resize notifications
46 47 48 |
# File 'lib/clack/core/prompt.rb', line 46 def register(prompt) @active_prompts << prompt end |
.setup_signal_handler ⇒ Object
Set up SIGWINCH handler (called once on load). Signal handler only sets a flag -- no allocation or iteration.
66 67 68 69 70 71 72 73 |
# File 'lib/clack/core/prompt.rb', line 66 def setup_signal_handler return if Clack::Environment.windows? return unless Signal.list.key?("WINCH") Signal.trap("WINCH") do @resize_pending = true end end |
.unregister(prompt) ⇒ Object
Unregister a prompt instance from resize notifications.
51 52 53 |
# File 'lib/clack/core/prompt.rb', line 51 def unregister(prompt) @active_prompts.delete(prompt) end |
Instance Method Details
#request_redraw ⇒ Object
Request a full redraw on next render cycle. Called by SIGWINCH handler when terminal is resized.
120 121 122 |
# File 'lib/clack/core/prompt.rb', line 120 def request_redraw @needs_redraw = true end |
#run ⇒ Object, Clack::CANCEL
Run the prompt interaction loop.
Sets up the terminal, renders frames, and processes input until the user submits or cancels. Returns the final value or Clack::CANCEL.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/clack/core/prompt.rb', line 131 def run return run_ci_mode if CiMode.active?(@input) Prompt.register(self) warn_narrow_terminal terminal_setup = false begin setup_terminal terminal_setup = true render @state = :active loop do Prompt.flush_resize key = KeyReader.read(@input) dispatch_key(key) render break if terminal_state? end finalize (terminal_state? && @state == :cancel) ? CANCEL : @value rescue NotATerminalError # The first read failed, so the frame drawn above is orphaned: erase # it so the caller's error output is the only thing left on screen. finalize("") raise ensure Prompt.unregister(self) cleanup_terminal if terminal_setup end end |