Class: Kward::PromptInterface::ComposerState
- Inherits:
-
Object
- Object
- Kward::PromptInterface::ComposerState
- Defined in:
- lib/kward/prompt_interface/composer_state.rb
Overview
Mutable text, cursor, history, and overlay state for the composer.
Instance Attribute Summary collapse
-
#attachments ⇒ Array<Hash>
readonly
Pending image/file attachments submitted with the next turn.
-
#cursor ⇒ Integer
Cursor offset into
input. -
#history ⇒ Array<String>
readonly
Submitted input history.
-
#history_draft ⇒ String?
Draft restored after leaving history navigation.
-
#history_index ⇒ Integer?
Active history index while navigating history.
-
#history_search_draft ⇒ String?
Draft restored after canceling history search.
-
#history_search_index ⇒ Integer
Active selection index while searching history.
-
#history_search_query ⇒ String?
Query typed while searching history.
-
#input ⇒ String
Editable text currently shown in the composer.
-
#kill_buffer ⇒ String
Most recently killed text available for yank.
-
#prefill_input ⇒ String?
Text queued for the next composer prompt.
Instance Method Summary collapse
- #accept_history_search ⇒ Object
-
#add_attachment(attachment) ⇒ Object
Adds one attachment unless its source is already pending.
-
#add_history(value) ⇒ Object
Stores a submitted input unless it is blank or duplicates the previous entry.
- #cancel_history_search ⇒ Object
-
#clear_attachments ⇒ Object
Removes all pending attachments without changing text input.
-
#cursor_logical_position ⇒ Object
Returns
[row, column]for cursor placement in multi-line input. -
#delete_at_cursor ⇒ Object
Deletes one character at the cursor without moving it.
-
#delete_before_cursor ⇒ Object
Deletes one character before the cursor.
-
#delete_word_after_cursor ⇒ Object
Kills the word after the cursor into
kill_buffer. -
#delete_word_before_cursor ⇒ Object
Kills the word before the cursor into
kill_buffer. - #fuzzy_history_match?(value, query) ⇒ Boolean
- #history_search_active? ⇒ Boolean
- #history_search_matches ⇒ Object
-
#initialize ⇒ ComposerState
constructor
A new instance of ComposerState.
-
#insert_string(string) ⇒ Object
Inserts text at the cursor and advances by the inserted length.
-
#kill_line_after_cursor ⇒ Object
Kills all text after the cursor into
kill_buffer. -
#kill_line_before_cursor ⇒ Object
Kills all text before the cursor into
kill_buffer. -
#kill_range(start_index, end_index) ⇒ Object
Removes a range, stores it in
kill_buffer, and moves the cursor to the start. -
#load_history(values) ⇒ Object
Replaces the in-memory history list with persisted entries.
-
#move_cursor_left ⇒ Object
Moves the cursor one character left when possible.
-
#move_cursor_right ⇒ Object
Moves the cursor one character right when possible.
-
#move_to_end_of_line ⇒ Object
Moves the cursor to the end of the input buffer.
-
#move_to_next_word ⇒ Object
Moves the cursor to the next word boundary.
-
#move_to_previous_word ⇒ Object
Moves the cursor to the previous word boundary.
-
#move_to_start_of_line ⇒ Object
Moves the cursor to the beginning of the input buffer.
-
#recall_next_history ⇒ Object
Replaces input with the next history entry or restores the saved draft.
-
#recall_previous_history ⇒ Object
Replaces input with the previous history entry, preserving the draft first.
-
#remove_last_attachment ⇒ Object
Removes the most recently added attachment.
-
#replace_input(value) ⇒ Object
Replaces the full input buffer and places the cursor at the end.
-
#reset_history_navigation ⇒ Object
Leaves history navigation and clears the saved draft/index state.
- #reset_history_search ⇒ Object
- #select_next_history_search_match ⇒ Object
- #select_previous_history_search_match ⇒ Object
- #selected_history_search_match ⇒ Object
- #start_history_search ⇒ Object
- #update_history_search_query(value) ⇒ Object
-
#yank_kill_buffer ⇒ Object
Inserts the last killed text at the cursor.
Constructor Details
#initialize ⇒ ComposerState
Returns a new instance of ComposerState.
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 32 def initialize @input = +"" @cursor = 0 @attachments = [] @kill_buffer = "" @history = [] @history_index = nil @history_draft = nil @prefill_input = nil @history_search_query = nil @history_search_draft = nil @history_search_index = 0 end |
Instance Attribute Details
#attachments ⇒ Array<Hash> (readonly)
Returns pending image/file attachments submitted with the next turn.
28 29 30 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 28 def @attachments end |
#cursor ⇒ Integer
Returns cursor offset into input.
12 13 14 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 12 def cursor @cursor end |
#history ⇒ Array<String> (readonly)
Returns submitted input history.
30 31 32 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 30 def history @history end |
#history_draft ⇒ String?
Returns draft restored after leaving history navigation.
18 19 20 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 18 def history_draft @history_draft end |
#history_index ⇒ Integer?
Returns active history index while navigating history.
16 17 18 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 16 def history_index @history_index end |
#history_search_draft ⇒ String?
Returns draft restored after canceling history search.
24 25 26 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 24 def history_search_draft @history_search_draft end |
#history_search_index ⇒ Integer
Returns active selection index while searching history.
26 27 28 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 26 def history_search_index @history_search_index end |
#history_search_query ⇒ String?
Returns query typed while searching history.
22 23 24 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 22 def history_search_query @history_search_query end |
#input ⇒ String
Returns editable text currently shown in the composer.
10 11 12 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 10 def input @input end |
#kill_buffer ⇒ String
Returns most recently killed text available for yank.
14 15 16 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 14 def kill_buffer @kill_buffer end |
#prefill_input ⇒ String?
Returns text queued for the next composer prompt.
20 21 22 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 20 def prefill_input @prefill_input end |
Instance Method Details
#accept_history_search ⇒ Object
260 261 262 263 264 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 260 def accept_history_search match = selected_history_search_match replace_input(match) if match reset_history_search end |
#add_attachment(attachment) ⇒ Object
Adds one attachment unless its source is already pending.
52 53 54 55 56 57 58 59 60 61 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 52 def () return false unless .respond_to?(:key?) source = [:source_text] || ["source_text"] || [:original_path] || ["original_path"] return false if source.to_s.empty? return false if @attachments.any? { |item| (item[:source_text] || item["source_text"]).to_s == source.to_s } @attachments << true end |
#add_history(value) ⇒ Object
Stores a submitted input unless it is blank or duplicates the previous entry.
181 182 183 184 185 186 187 188 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 181 def add_history(value) stripped = value.to_s.strip return false if stripped.empty? return false if @history.last == value @history << value true end |
#cancel_history_search ⇒ Object
266 267 268 269 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 266 def cancel_history_search replace_input(@history_search_draft.to_s) reset_history_search end |
#clear_attachments ⇒ Object
Removes all pending attachments without changing text input.
47 48 49 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 47 def @attachments.clear end |
#cursor_logical_position ⇒ Object
Returns [row, column] for cursor placement in multi-line input.
168 169 170 171 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 168 def cursor_logical_position before_cursor = @input[0...@cursor] [before_cursor.count("\n"), (before_cursor.split("\n", -1).last || "").length] end |
#delete_at_cursor ⇒ Object
Deletes one character at the cursor without moving it.
89 90 91 92 93 94 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 89 def delete_at_cursor return false unless @cursor < @input.length @input = @input[0...@cursor] + @input[(@cursor + 1)..] true end |
#delete_before_cursor ⇒ Object
Deletes one character before the cursor.
80 81 82 83 84 85 86 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 80 def delete_before_cursor return false if @cursor.zero? @input = @input[0...(@cursor - 1)] + @input[@cursor..] @cursor -= 1 true end |
#delete_word_after_cursor ⇒ Object
Kills the word after the cursor into kill_buffer.
132 133 134 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 132 def delete_word_after_cursor kill_range(@cursor, TextBoundary.next_word_boundary(@input, @cursor)) end |
#delete_word_before_cursor ⇒ Object
Kills the word before the cursor into kill_buffer.
127 128 129 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 127 def delete_word_before_cursor kill_range(TextBoundary.previous_word_boundary(@input, @cursor), @cursor) end |
#fuzzy_history_match?(value, query) ⇒ Boolean
277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 277 def fuzzy_history_match?(value, query) query.chars.all? do |char| index = value.index(char) if index value = value[(index + 1)..].to_s true else false end end end |
#history_search_active? ⇒ Boolean
225 226 227 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 225 def history_search_active? !@history_search_query.nil? end |
#history_search_matches ⇒ Object
235 236 237 238 239 240 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 235 def history_search_matches query = @history_search_query.to_s.downcase return @history.reverse if query.empty? @history.reverse.select { |value| fuzzy_history_match?(value.downcase, query) } end |
#insert_string(string) ⇒ Object
Inserts text at the cursor and advances by the inserted length.
72 73 74 75 76 77 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 72 def insert_string(string) return if string.empty? @input = @input[0...@cursor] + string + @input[@cursor..] @cursor += string.length end |
#kill_line_after_cursor ⇒ Object
Kills all text after the cursor into kill_buffer.
142 143 144 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 142 def kill_line_after_cursor kill_range(@cursor, @input.length) end |
#kill_line_before_cursor ⇒ Object
Kills all text before the cursor into kill_buffer.
137 138 139 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 137 def kill_line_before_cursor kill_range(0, @cursor) end |
#kill_range(start_index, end_index) ⇒ Object
Removes a range, stores it in kill_buffer, and moves the cursor to the start.
147 148 149 150 151 152 153 154 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 147 def kill_range(start_index, end_index) return false if start_index == end_index @kill_buffer = @input[start_index...end_index].to_s @input = @input[0...start_index].to_s + @input[end_index..].to_s @cursor = start_index true end |
#load_history(values) ⇒ Object
Replaces the in-memory history list with persisted entries.
174 175 176 177 178 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 174 def load_history(values) @history = Array(values).map(&:to_s).reject { |value| value.strip.empty? } reset_history_search end |
#move_cursor_left ⇒ Object
Moves the cursor one character left when possible.
97 98 99 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 97 def move_cursor_left @cursor -= 1 if @cursor.positive? end |
#move_cursor_right ⇒ Object
Moves the cursor one character right when possible.
102 103 104 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 102 def move_cursor_right @cursor += 1 if @cursor < @input.length end |
#move_to_end_of_line ⇒ Object
Moves the cursor to the end of the input buffer.
112 113 114 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 112 def move_to_end_of_line @cursor = @input.length end |
#move_to_next_word ⇒ Object
Moves the cursor to the next word boundary.
122 123 124 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 122 def move_to_next_word @cursor = TextBoundary.next_word_boundary(@input, @cursor) end |
#move_to_previous_word ⇒ Object
Moves the cursor to the previous word boundary.
117 118 119 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 117 def move_to_previous_word @cursor = TextBoundary.previous_word_boundary(@input, @cursor) end |
#move_to_start_of_line ⇒ Object
Moves the cursor to the beginning of the input buffer.
107 108 109 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 107 def move_to_start_of_line @cursor = 0 end |
#recall_next_history ⇒ Object
Replaces input with the next history entry or restores the saved draft.
200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 200 def recall_next_history return if @history_index.nil? if @history_index < @history.length - 1 @history_index += 1 replace_input(@history[@history_index]) else replace_input(@history_draft || "") end end |
#recall_previous_history ⇒ Object
Replaces input with the previous history entry, preserving the draft first.
191 192 193 194 195 196 197 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 191 def recall_previous_history return if @history.empty? @history_draft = @input if @history_index.nil? @history_index = @history_index.nil? ? @history.length - 1 : [@history_index - 1, 0].max replace_input(@history[@history_index]) end |
#remove_last_attachment ⇒ Object
Removes the most recently added attachment.
64 65 66 67 68 69 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 64 def return false if @attachments.empty? @attachments.pop true end |
#replace_input(value) ⇒ Object
Replaces the full input buffer and places the cursor at the end.
162 163 164 165 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 162 def replace_input(value) @input = value.to_s @cursor = @input.length end |
#reset_history_navigation ⇒ Object
Leaves history navigation and clears the saved draft/index state.
213 214 215 216 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 213 def @history_index = nil @history_draft = nil end |
#reset_history_search ⇒ Object
271 272 273 274 275 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 271 def reset_history_search @history_search_query = nil @history_search_draft = nil @history_search_index = 0 end |
#select_next_history_search_match ⇒ Object
253 254 255 256 257 258 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 253 def select_next_history_search_match matches = history_search_matches return if matches.empty? @history_search_index = [@history_search_index + 1, matches.length - 1].min end |
#select_previous_history_search_match ⇒ Object
249 250 251 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 249 def select_previous_history_search_match @history_search_index = [@history_search_index - 1, 0].max end |
#selected_history_search_match ⇒ Object
242 243 244 245 246 247 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 242 def selected_history_search_match matches = history_search_matches return nil if matches.empty? matches[[@history_search_index, matches.length - 1].min] end |
#start_history_search ⇒ Object
218 219 220 221 222 223 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 218 def start_history_search @history_search_draft = @input if @history_search_query.nil? @history_search_query = @input.to_s @history_search_index = 0 replace_input(@history_search_query) end |
#update_history_search_query(value) ⇒ Object
229 230 231 232 233 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 229 def update_history_search_query(value) @history_search_query = value.to_s @history_search_index = 0 replace_input(@history_search_query) end |
#yank_kill_buffer ⇒ Object
Inserts the last killed text at the cursor.
157 158 159 |
# File 'lib/kward/prompt_interface/composer_state.rb', line 157 def yank_kill_buffer insert_string(@kill_buffer.to_s) unless @kill_buffer.to_s.empty? end |