Class: SwarmCLI::V3::TextInput
- Inherits:
-
Object
- Object
- SwarmCLI::V3::TextInput
- Defined in:
- lib/swarm_cli/v3/text_input.rb
Overview
Pure data model for the input prompt line with cursor tracking.
Manages the prompt text, typing buffer, and cursor position with no I/O side effects. The Display coordinator calls #render and uses #cursor_position to place the terminal cursor.
Instance Attribute Summary collapse
-
#buffer ⇒ String
readonly
Current buffer contents.
-
#cursor ⇒ Integer
readonly
Cursor position in the buffer (0 = before first char).
-
#prompt_visible_length ⇒ Integer
readonly
Visible length of the prompt (without ANSI codes).
Instance Method Summary collapse
-
#backspace ⇒ void
Delete the character before the cursor.
-
#blank? ⇒ Boolean
Whether the buffer is empty or only whitespace.
-
#cursor_position(width) ⇒ Array(Integer, Integer)
Calculate cursor position as terminal row/column offsets from the start of the prompt, accounting for line wrapping.
-
#initialize(prompt_text: "you> ") ⇒ TextInput
constructor
A new instance of TextInput.
-
#move_down ⇒ void
Move cursor down one line (multiline only).
-
#move_left ⇒ void
Move cursor one position left.
-
#move_right ⇒ void
Move cursor one position right.
-
#move_up ⇒ void
Move cursor up one line (multiline only).
-
#multiline? ⇒ Boolean
Whether the buffer contains newlines.
-
#render ⇒ String
Render the full prompt line (prompt string + buffer).
-
#replace(text) ⇒ void
Replace the entire buffer and move cursor to end.
-
#submit ⇒ String
Return the buffer contents and clear it.
-
#type_char(char) ⇒ void
Insert a character at the cursor position.
-
#wrapped_lines(width) ⇒ Integer
Calculate extra lines from wrapping and explicit newlines.
Constructor Details
#initialize(prompt_text: "you> ") ⇒ TextInput
Returns a new instance of TextInput.
28 29 30 31 32 33 34 |
# File 'lib/swarm_cli/v3/text_input.rb', line 28 def initialize(prompt_text: "you> ") @prompt_text = prompt_text @prompt_str = ANSIColors.green(prompt_text) @prompt_visible_length = prompt_text.length @buffer = +"" @cursor = 0 end |
Instance Attribute Details
#buffer ⇒ String (readonly)
Returns current buffer contents.
19 20 21 |
# File 'lib/swarm_cli/v3/text_input.rb', line 19 def buffer @buffer end |
#cursor ⇒ Integer (readonly)
Returns cursor position in the buffer (0 = before first char).
22 23 24 |
# File 'lib/swarm_cli/v3/text_input.rb', line 22 def cursor @cursor end |
#prompt_visible_length ⇒ Integer (readonly)
Returns visible length of the prompt (without ANSI codes).
25 26 27 |
# File 'lib/swarm_cli/v3/text_input.rb', line 25 def prompt_visible_length @prompt_visible_length end |
Instance Method Details
#backspace ⇒ void
This method returns an undefined value.
Delete the character before the cursor.
48 49 50 51 52 53 |
# File 'lib/swarm_cli/v3/text_input.rb', line 48 def backspace return if @cursor.zero? @buffer.slice!(@cursor - 1) @cursor -= 1 end |
#blank? ⇒ Boolean
Whether the buffer is empty or only whitespace.
77 78 79 |
# File 'lib/swarm_cli/v3/text_input.rb', line 77 def blank? @buffer.strip.empty? end |
#cursor_position(width) ⇒ Array(Integer, Integer)
Calculate cursor position as terminal row/column offsets from the start of the prompt, accounting for line wrapping.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/swarm_cli/v3/text_input.rb', line 161 def cursor_position(width) return [0, @prompt_visible_length + @cursor] if width <= 0 text_before = @buffer[0, @cursor] || "" lines = text_before.split("\n", -1) row = 0 lines.each_with_index do |line, idx| visible = (idx.zero? ? @prompt_visible_length : 0) + line.length row += visible / width end row += lines.size - 1 if lines.size > 1 last_line = lines.last || "" last_prefix = lines.size <= 1 ? @prompt_visible_length : 0 col = (last_prefix + last_line.length) % width [row, col] end |
#move_down ⇒ void
This method returns an undefined value.
Move cursor down one line (multiline only).
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/swarm_cli/v3/text_input.rb', line 128 def move_down row, col = cursor_row_col lines = buffer_lines return if row >= lines.size - 1 target_line = lines[row + 1] # Calculate target column accounting for prompt on line 0 if row.zero? # Moving from line 0 (which has the prompt) to line 1 # Visual columns should align, so add prompt length target_col = col + @prompt_visible_length target_col = [target_col, target_line.length].min else # Moving between lines that don't have the prompt target_col = [col, target_line.length].min end @cursor = line_start_offset(row + 1) + target_col end |
#move_left ⇒ void
This method returns an undefined value.
Move cursor one position left.
91 92 93 |
# File 'lib/swarm_cli/v3/text_input.rb', line 91 def move_left @cursor -= 1 if @cursor > 0 end |
#move_right ⇒ void
This method returns an undefined value.
Move cursor one position right.
98 99 100 |
# File 'lib/swarm_cli/v3/text_input.rb', line 98 def move_right @cursor += 1 if @cursor < @buffer.length end |
#move_up ⇒ void
This method returns an undefined value.
Move cursor up one line (multiline only).
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/swarm_cli/v3/text_input.rb', line 105 def move_up row, col = cursor_row_col return if row.zero? target_line = buffer_lines[row - 1] # Calculate target column accounting for prompt on line 0 if row == 1 # Moving from line 1 to line 0 (which has the prompt) # Visual columns should align, so subtract prompt length target_col = [col - @prompt_visible_length, 0].max target_col = [target_col, target_line.length].min else # Moving between lines that don't have the prompt target_col = [col, target_line.length].min end @cursor = line_start_offset(row - 1) + target_col end |
#multiline? ⇒ Boolean
Whether the buffer contains newlines.
84 85 86 |
# File 'lib/swarm_cli/v3/text_input.rb', line 84 def multiline? @buffer.include?("\n") end |
#render ⇒ String
Render the full prompt line (prompt string + buffer).
152 153 154 |
# File 'lib/swarm_cli/v3/text_input.rb', line 152 def render "#{@prompt_str}#{@buffer}" end |
#replace(text) ⇒ void
This method returns an undefined value.
Replace the entire buffer and move cursor to end.
69 70 71 72 |
# File 'lib/swarm_cli/v3/text_input.rb', line 69 def replace(text) @buffer = +(text || "") @cursor = @buffer.length end |
#submit ⇒ String
Return the buffer contents and clear it.
58 59 60 61 62 63 |
# File 'lib/swarm_cli/v3/text_input.rb', line 58 def submit text = @buffer.dup @buffer = +"" @cursor = 0 text end |
#type_char(char) ⇒ void
This method returns an undefined value.
Insert a character at the cursor position.
40 41 42 43 |
# File 'lib/swarm_cli/v3/text_input.rb', line 40 def type_char(char) @buffer.insert(@cursor, char) @cursor += char.length end |
#wrapped_lines(width) ⇒ Integer
Calculate extra lines from wrapping and explicit newlines.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/swarm_cli/v3/text_input.rb', line 185 def wrapped_lines(width) return 0 if width <= 0 lines = buffer_lines total = 0 lines.each_with_index do |line, idx| visible = (idx.zero? ? @prompt_visible_length : 0) + line.length total += visible > 0 ? (visible - 1) / width : 0 end total += lines.size - 1 if lines.size > 1 total end |