Class: TUI::InputBuffer
- Inherits:
-
Object
- Object
- TUI::InputBuffer
- Defined in:
- lib/tui/input_buffer.rb
Overview
Manages editable text with cursor position tracking. Supports multiline input with newline insertion, cursor navigation across physical lines, and standard text editing operations.
Pure logic object with no rendering or framework dependencies.
Instance Attribute Summary collapse
-
#cursor_pos ⇒ Object
readonly
Returns the value of attribute cursor_pos.
-
#text ⇒ Object
readonly
Returns the value of attribute text.
Instance Method Summary collapse
-
#backspace ⇒ Boolean
Deletes the character before the cursor.
-
#clamp_cursor ⇒ void
Ensures cursor stays within valid bounds after external state changes.
-
#clear ⇒ void
Resets the buffer to empty state.
-
#consume ⇒ String
Returns stripped text and clears the buffer for message submission.
-
#cursor_location ⇒ Array(Integer, Integer)
- line_index, column
-
for current cursor position.
-
#delete ⇒ Boolean
Deletes the character at the cursor (forward delete).
-
#full? ⇒ Boolean
Whether the buffer has reached Settings.input_max_length.
-
#initialize ⇒ InputBuffer
constructor
A new instance of InputBuffer.
-
#insert(char) ⇒ Boolean
True if inserted, false if result would exceed Settings.input_max_length.
-
#line_start_positions ⇒ Array<Integer>
Maps each physical line to its starting offset within the text buffer.
-
#move_down ⇒ Boolean
Moves cursor down one physical line, preserving column position.
-
#move_end ⇒ Boolean
Moves cursor to the end of the current physical line.
-
#move_home ⇒ Boolean
Moves cursor to the start of the current physical line.
-
#move_left ⇒ Boolean
True if cursor moved.
-
#move_right ⇒ Boolean
True if cursor moved.
-
#move_up ⇒ Boolean
Moves cursor up one physical line, preserving column position.
-
#multiline? ⇒ Boolean
Whether the buffer contains any newline characters.
-
#newline ⇒ Boolean
True if a newline was inserted.
Constructor Details
#initialize ⇒ InputBuffer
Returns a new instance of InputBuffer.
14 15 16 17 |
# File 'lib/tui/input_buffer.rb', line 14 def initialize @text = "" @cursor_pos = 0 end |
Instance Attribute Details
#cursor_pos ⇒ Object (readonly)
Returns the value of attribute cursor_pos.
12 13 14 |
# File 'lib/tui/input_buffer.rb', line 12 def cursor_pos @cursor_pos end |
#text ⇒ Object (readonly)
Returns the value of attribute text.
12 13 14 |
# File 'lib/tui/input_buffer.rb', line 12 def text @text end |
Instance Method Details
#backspace ⇒ Boolean
Deletes the character before the cursor.
71 72 73 74 75 76 77 |
# File 'lib/tui/input_buffer.rb', line 71 def backspace return false if @cursor_pos == 0 @text = "#{@text[0...@cursor_pos - 1]}#{@text[@cursor_pos..]}" @cursor_pos -= 1 true end |
#clamp_cursor ⇒ void
This method returns an undefined value.
Ensures cursor stays within valid bounds after external state changes.
46 47 48 |
# File 'lib/tui/input_buffer.rb', line 46 def clamp_cursor @cursor_pos = @cursor_pos.clamp(0, @text.length) end |
#clear ⇒ void
This method returns an undefined value.
Resets the buffer to empty state.
21 22 23 24 |
# File 'lib/tui/input_buffer.rb', line 21 def clear @text = "" @cursor_pos = 0 end |
#consume ⇒ String
Returns stripped text and clears the buffer for message submission.
28 29 30 31 32 |
# File 'lib/tui/input_buffer.rb', line 28 def consume content = @text.strip clear content end |
#cursor_location ⇒ Array(Integer, Integer)
Returns [line_index, column] for current cursor position.
157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/tui/input_buffer.rb', line 157 def cursor_location return [0, 0] if @text.empty? lines = @text.split("\n", -1) pos = 0 lines.each_with_index do |line, index| len = line.length return [index, @cursor_pos - pos] if @cursor_pos <= pos + len pos += len + 1 end [lines.length - 1, lines.last.length] end |
#delete ⇒ Boolean
Deletes the character at the cursor (forward delete).
81 82 83 84 85 86 |
# File 'lib/tui/input_buffer.rb', line 81 def delete return false if @cursor_pos >= @text.length @text = "#{@text[0...@cursor_pos]}#{@text[@cursor_pos + 1..]}" true end |
#full? ⇒ Boolean
Returns whether the buffer has reached Settings.input_max_length.
40 41 42 |
# File 'lib/tui/input_buffer.rb', line 40 def full? @text.length >= Settings.input_max_length end |
#insert(char) ⇒ Boolean
Returns true if inserted, false if result would exceed Settings.input_max_length.
52 53 54 55 56 57 58 |
# File 'lib/tui/input_buffer.rb', line 52 def insert(char) return false if @text.length + char.length > Settings.input_max_length @text = "#{@text[0...@cursor_pos]}#{char}#{@text[@cursor_pos..]}" @cursor_pos += char.length true end |
#line_start_positions ⇒ Array<Integer>
Maps each physical line to its starting offset within the text buffer. Position after each newline marks the start of the next line.
173 174 175 176 177 178 179 |
# File 'lib/tui/input_buffer.rb', line 173 def line_start_positions positions = [0] @text.each_char.with_index do |char, offset| positions << (offset + 1) if char == "\n" end positions end |
#move_down ⇒ Boolean
Moves cursor down one physical line, preserving column position. Clamps column to the target line’s length when the next line is shorter.
145 146 147 148 149 150 151 152 153 154 |
# File 'lib/tui/input_buffer.rb', line 145 def move_down lines = @text.split("\n", -1) line_idx, col = cursor_location return false if line_idx >= lines.length - 1 next_idx = line_idx + 1 target_col = [col, lines[next_idx].length].min @cursor_pos = line_start_positions[next_idx] + target_col true end |
#move_end ⇒ Boolean
Moves cursor to the end of the current physical line.
119 120 121 122 123 124 125 126 |
# File 'lib/tui/input_buffer.rb', line 119 def move_end newline_pos = @text.index("\n", @cursor_pos) target = newline_pos || @text.length return false if @cursor_pos == target @cursor_pos = target true end |
#move_home ⇒ Boolean
Moves cursor to the start of the current physical line.
106 107 108 109 110 111 112 113 114 115 |
# File 'lib/tui/input_buffer.rb', line 106 def move_home return false if @cursor_pos == 0 last_newline = @text.rindex("\n", @cursor_pos - 1) target = last_newline ? last_newline + 1 : 0 return false if @cursor_pos == target @cursor_pos = target true end |
#move_left ⇒ Boolean
Returns true if cursor moved.
89 90 91 92 93 94 |
# File 'lib/tui/input_buffer.rb', line 89 def move_left return false if @cursor_pos == 0 @cursor_pos -= 1 true end |
#move_right ⇒ Boolean
Returns true if cursor moved.
97 98 99 100 101 102 |
# File 'lib/tui/input_buffer.rb', line 97 def move_right return false if @cursor_pos >= @text.length @cursor_pos += 1 true end |
#move_up ⇒ Boolean
Moves cursor up one physical line, preserving column position. Clamps column to the target line’s length when the previous line is shorter.
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/tui/input_buffer.rb', line 131 def move_up line_idx, col = cursor_location return false if line_idx == 0 lines = @text.split("\n", -1) prev_idx = line_idx - 1 target_col = [col, lines[prev_idx].length].min @cursor_pos = line_start_positions[prev_idx] + target_col true end |
#multiline? ⇒ Boolean
Returns whether the buffer contains any newline characters.
35 36 37 |
# File 'lib/tui/input_buffer.rb', line 35 def multiline? @text.include?("\n") end |
#newline ⇒ Boolean
Returns true if a newline was inserted.
61 62 63 64 65 66 67 |
# File 'lib/tui/input_buffer.rb', line 61 def newline return false if full? @text = "#{@text[0...@cursor_pos]}\n#{@text[@cursor_pos..]}" @cursor_pos += 1 true end |