Class: Rubino::UI::Composer::InputLine
- Inherits:
-
Object
- Object
- Rubino::UI::Composer::InputLine
- Defined in:
- lib/rubino/ui/composer/input_line.rb
Overview
The editable input line: the text buffer and the cursor, plus the pure editing operations over them. NO terminal I/O, NO rendering, NO locking —the composer owns the render mutex and calls these under it, then redraws. Extracted from BottomComposer so the cursor/codepoint math lives in one small, directly-unit-testable place instead of the god class.
All indices are CODEPOINT offsets into text (0..length). Mutators clamp to the buffer and never raise on out-of-range input.
Instance Attribute Summary collapse
-
#cursor ⇒ Object
readonly
Returns the value of attribute cursor.
-
#text ⇒ Object
readonly
Returns the value of attribute text.
Instance Method Summary collapse
-
#clear ⇒ Object
Clear the whole line (Ctrl+U on this single-line composer — see the BottomComposer note on why this kills the whole line, not just to BOL).
-
#delete_back ⇒ Object
Remove the single char BEFORE the cursor (Backspace).
-
#delete_forward ⇒ Object
Remove the char AT the cursor (Delete / Ctrl+D).
-
#delete_span(start, len) ⇒ Object
Remove
lenchars starting at codepointstartand park the cursor atstart— used to delete a whole “[Pasted text #N …]” placeholder token in one keystroke (the span is computed by the caller from the store). - #empty? ⇒ Boolean
-
#initialize(text: +"",, cursor: 0) ⇒ InputLine
constructor
A new instance of InputLine.
-
#insert(str) ⇒ Object
Insert
strat the cursor and advance past it. -
#kill_to_end ⇒ Object
Delete from the cursor to the end of the line (Ctrl+K).
- #length ⇒ Object
-
#move_by(delta) ⇒ Object
Move the cursor by
deltacodepoints, clamped. -
#move_to(index) ⇒ Object
Move the cursor to an absolute codepoint index, clamped.
-
#replace(str) ⇒ Object
Replace the whole line and park the cursor at its end (history recall, draft restore).
-
#take ⇒ Object
Return the current text and reset to an empty line (submit).
-
#word_left ⇒ Object
Word-jump LEFT: skip whitespace immediately left, then the word, landing at the start of the previous word.
-
#word_right ⇒ Object
Word-jump RIGHT: skip the current word then trailing whitespace, landing at the start of the next word.
Constructor Details
#initialize(text: +"",, cursor: 0) ⇒ InputLine
Returns a new instance of InputLine.
17 18 19 20 |
# File 'lib/rubino/ui/composer/input_line.rb', line 17 def initialize(text: +"", cursor: 0) @text = text.to_s.dup @cursor = cursor.clamp(0, @text.length) end |
Instance Attribute Details
#cursor ⇒ Object (readonly)
Returns the value of attribute cursor.
15 16 17 |
# File 'lib/rubino/ui/composer/input_line.rb', line 15 def cursor @cursor end |
#text ⇒ Object (readonly)
Returns the value of attribute text.
15 16 17 |
# File 'lib/rubino/ui/composer/input_line.rb', line 15 def text @text end |
Instance Method Details
#clear ⇒ Object
Clear the whole line (Ctrl+U on this single-line composer — see the BottomComposer note on why this kills the whole line, not just to BOL).
74 75 76 77 78 |
# File 'lib/rubino/ui/composer/input_line.rb', line 74 def clear @text = +"" @cursor = 0 self end |
#delete_back ⇒ Object
Remove the single char BEFORE the cursor (Backspace). No-op at col 0.
35 36 37 38 39 40 41 42 43 |
# File 'lib/rubino/ui/composer/input_line.rb', line 35 def delete_back return self unless @cursor.positive? chars = @text.chars chars.delete_at(@cursor - 1) @text = chars.join @cursor -= 1 self end |
#delete_forward ⇒ Object
Remove the char AT the cursor (Delete / Ctrl+D). No-op at end.
46 47 48 49 50 51 52 53 |
# File 'lib/rubino/ui/composer/input_line.rb', line 46 def delete_forward chars = @text.chars if @cursor < chars.length chars.delete_at(@cursor) @text = chars.join end self end |
#delete_span(start, len) ⇒ Object
Remove len chars starting at codepoint start and park the cursor at start — used to delete a whole “[Pasted text #N …]” placeholder token in one keystroke (the span is computed by the caller from the store).
58 59 60 61 62 63 64 |
# File 'lib/rubino/ui/composer/input_line.rb', line 58 def delete_span(start, len) chars = @text.chars chars.slice!(start, len) @text = chars.join @cursor = start self end |
#empty? ⇒ Boolean
23 |
# File 'lib/rubino/ui/composer/input_line.rb', line 23 def empty? = @text.empty? |
#insert(str) ⇒ Object
Insert str at the cursor and advance past it.
26 27 28 29 30 31 32 |
# File 'lib/rubino/ui/composer/input_line.rb', line 26 def insert(str) chars = @text.chars chars.insert(@cursor, *str.to_s.chars) @text = chars.join @cursor += str.to_s.chars.length self end |
#kill_to_end ⇒ Object
Delete from the cursor to the end of the line (Ctrl+K).
67 68 69 70 |
# File 'lib/rubino/ui/composer/input_line.rb', line 67 def kill_to_end @text = @text.chars.first(@cursor).join self end |
#length ⇒ Object
22 |
# File 'lib/rubino/ui/composer/input_line.rb', line 22 def length = @text.length |
#move_by(delta) ⇒ Object
Move the cursor by delta codepoints, clamped.
89 90 91 92 |
# File 'lib/rubino/ui/composer/input_line.rb', line 89 def move_by(delta) @cursor = (@cursor + delta).clamp(0, @text.length) self end |
#move_to(index) ⇒ Object
Move the cursor to an absolute codepoint index, clamped.
95 96 97 98 |
# File 'lib/rubino/ui/composer/input_line.rb', line 95 def move_to(index) @cursor = index.to_i.clamp(0, @text.length) self end |
#replace(str) ⇒ Object
Replace the whole line and park the cursor at its end (history recall, draft restore).
82 83 84 85 86 |
# File 'lib/rubino/ui/composer/input_line.rb', line 82 def replace(str) @text = str.to_s.dup @cursor = @text.length self end |
#take ⇒ Object
Return the current text and reset to an empty line (submit).
123 124 125 126 127 |
# File 'lib/rubino/ui/composer/input_line.rb', line 123 def take taken = @text clear taken end |
#word_left ⇒ Object
Word-jump LEFT: skip whitespace immediately left, then the word, landing at the start of the previous word.
102 103 104 105 106 107 108 109 |
# File 'lib/rubino/ui/composer/input_line.rb', line 102 def word_left chars = @text.chars i = @cursor i -= 1 while i.positive? && chars[i - 1] =~ /\s/ i -= 1 while i.positive? && chars[i - 1] !~ /\s/ @cursor = i self end |
#word_right ⇒ Object
Word-jump RIGHT: skip the current word then trailing whitespace, landing at the start of the next word.
113 114 115 116 117 118 119 120 |
# File 'lib/rubino/ui/composer/input_line.rb', line 113 def word_right chars = @text.chars i = @cursor i += 1 while i < chars.length && chars[i] !~ /\s/ i += 1 while i < chars.length && chars[i] =~ /\s/ @cursor = i self end |