Class: Kward::PromptInterface::ComposerState

Inherits:
Object
  • Object
show all
Defined in:
lib/kward/prompt_interface/composer_state.rb

Overview

Mutable text, cursor, history, and overlay state for the composer.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeComposerState

Returns a new instance of ComposerState.



24
25
26
27
28
29
30
31
32
33
# File 'lib/kward/prompt_interface/composer_state.rb', line 24

def initialize
  @input = +""
  @cursor = 0
  @attachments = []
  @kill_buffer = ""
  @history = []
  @history_index = nil
  @history_draft = nil
  @prefill_input = nil
end

Instance Attribute Details

#attachmentsArray<Hash> (readonly)

Returns pending image/file attachments submitted with the next turn.

Returns:

  • (Array<Hash>)

    pending image/file attachments submitted with the next turn



20
21
22
# File 'lib/kward/prompt_interface/composer_state.rb', line 20

def attachments
  @attachments
end

#cursorInteger

Returns cursor offset into input.

Returns:

  • (Integer)

    cursor offset into input



10
11
12
# File 'lib/kward/prompt_interface/composer_state.rb', line 10

def cursor
  @cursor
end

#historyArray<String> (readonly)

Returns submitted input history.

Returns:

  • (Array<String>)

    submitted input history



22
23
24
# File 'lib/kward/prompt_interface/composer_state.rb', line 22

def history
  @history
end

#history_draftString?

Returns draft restored after leaving history navigation.

Returns:

  • (String, nil)

    draft restored after leaving history navigation



16
17
18
# File 'lib/kward/prompt_interface/composer_state.rb', line 16

def history_draft
  @history_draft
end

#history_indexInteger?

Returns active history index while navigating history.

Returns:

  • (Integer, nil)

    active history index while navigating history



14
15
16
# File 'lib/kward/prompt_interface/composer_state.rb', line 14

def history_index
  @history_index
end

#inputString

Returns editable text currently shown in the composer.

Returns:

  • (String)

    editable text currently shown in the composer



8
9
10
# File 'lib/kward/prompt_interface/composer_state.rb', line 8

def input
  @input
end

#kill_bufferString

Returns most recently killed text available for yank.

Returns:

  • (String)

    most recently killed text available for yank



12
13
14
# File 'lib/kward/prompt_interface/composer_state.rb', line 12

def kill_buffer
  @kill_buffer
end

#prefill_inputString?

Returns text queued for the next composer prompt.

Returns:

  • (String, nil)

    text queued for the next composer prompt



18
19
20
# File 'lib/kward/prompt_interface/composer_state.rb', line 18

def prefill_input
  @prefill_input
end

Instance Method Details

#add_attachment(attachment) ⇒ Object

Adds one attachment unless its source is already pending.



41
42
43
44
45
46
47
48
49
50
# File 'lib/kward/prompt_interface/composer_state.rb', line 41

def add_attachment(attachment)
  return false unless attachment.respond_to?(:key?)

  source = attachment[:source_text] || attachment["source_text"] || attachment[:original_path] || attachment["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 << attachment
  true
end

#add_history(value) ⇒ Object

Stores a submitted input unless it is blank or duplicates the previous entry.



184
185
186
187
188
189
190
# File 'lib/kward/prompt_interface/composer_state.rb', line 184

def add_history(value)
  stripped = value.to_s.strip
  return if stripped.empty?
  return if @history.last == value

  @history << value
end

#clear_attachmentsObject

Removes all pending attachments without changing text input.



36
37
38
# File 'lib/kward/prompt_interface/composer_state.rb', line 36

def clear_attachments
  @attachments.clear
end

#cursor_logical_positionObject

Returns [row, column] for cursor placement in multi-line input.



178
179
180
181
# File 'lib/kward/prompt_interface/composer_state.rb', line 178

def cursor_logical_position
  before_cursor = @input[0...@cursor]
  [before_cursor.count("\n"), (before_cursor.split("\n", -1).last || "").length]
end

#delete_at_cursorObject

Deletes one character at the cursor without moving it.



78
79
80
81
82
83
# File 'lib/kward/prompt_interface/composer_state.rb', line 78

def delete_at_cursor
  return false unless @cursor < @input.length

  @input = @input[0...@cursor] + @input[(@cursor + 1)..]
  true
end

#delete_before_cursorObject

Deletes one character before the cursor.



69
70
71
72
73
74
75
# File 'lib/kward/prompt_interface/composer_state.rb', line 69

def delete_before_cursor
  return false if @cursor.zero?

  @input = @input[0...(@cursor - 1)] + @input[@cursor..]
  @cursor -= 1
  true
end

#delete_word_after_cursorObject

Kills the word after the cursor into kill_buffer.



121
122
123
# File 'lib/kward/prompt_interface/composer_state.rb', line 121

def delete_word_after_cursor
  kill_range(@cursor, next_word_boundary(@cursor))
end

#delete_word_before_cursorObject

Kills the word before the cursor into kill_buffer.



116
117
118
# File 'lib/kward/prompt_interface/composer_state.rb', line 116

def delete_word_before_cursor
  kill_range(previous_word_boundary(@cursor), @cursor)
end

#insert_string(string) ⇒ Object

Inserts text at the cursor and advances by the inserted length.



61
62
63
64
65
66
# File 'lib/kward/prompt_interface/composer_state.rb', line 61

def insert_string(string)
  return if string.empty?

  @input = @input[0...@cursor] + string + @input[@cursor..]
  @cursor += string.length
end

#kill_line_after_cursorObject

Kills all text after the cursor into kill_buffer.



131
132
133
# File 'lib/kward/prompt_interface/composer_state.rb', line 131

def kill_line_after_cursor
  kill_range(@cursor, @input.length)
end

#kill_line_before_cursorObject

Kills all text before the cursor into kill_buffer.



126
127
128
# File 'lib/kward/prompt_interface/composer_state.rb', line 126

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.



136
137
138
139
140
141
142
143
# File 'lib/kward/prompt_interface/composer_state.rb', line 136

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

#move_cursor_leftObject

Moves the cursor one character left when possible.



86
87
88
# File 'lib/kward/prompt_interface/composer_state.rb', line 86

def move_cursor_left
  @cursor -= 1 if @cursor.positive?
end

#move_cursor_rightObject

Moves the cursor one character right when possible.



91
92
93
# File 'lib/kward/prompt_interface/composer_state.rb', line 91

def move_cursor_right
  @cursor += 1 if @cursor < @input.length
end

#move_to_end_of_lineObject

Moves the cursor to the end of the input buffer.



101
102
103
# File 'lib/kward/prompt_interface/composer_state.rb', line 101

def move_to_end_of_line
  @cursor = @input.length
end

#move_to_next_wordObject

Moves the cursor to the next word boundary.



111
112
113
# File 'lib/kward/prompt_interface/composer_state.rb', line 111

def move_to_next_word
  @cursor = next_word_boundary(@cursor)
end

#move_to_previous_wordObject

Moves the cursor to the previous word boundary.



106
107
108
# File 'lib/kward/prompt_interface/composer_state.rb', line 106

def move_to_previous_word
  @cursor = previous_word_boundary(@cursor)
end

#move_to_start_of_lineObject

Moves the cursor to the beginning of the input buffer.



96
97
98
# File 'lib/kward/prompt_interface/composer_state.rb', line 96

def move_to_start_of_line
  @cursor = 0
end

#next_word_boundary(index) ⇒ Object

Finds the end offset of the word after index.



159
160
161
162
163
164
# File 'lib/kward/prompt_interface/composer_state.rb', line 159

def next_word_boundary(index)
  cursor = index
  cursor += 1 while cursor < @input.length && word_separator?(@input[cursor])
  cursor += 1 while cursor < @input.length && !word_separator?(@input[cursor])
  cursor
end

#previous_word_boundary(index) ⇒ Object

Finds the start offset of the word before index.



151
152
153
154
155
156
# File 'lib/kward/prompt_interface/composer_state.rb', line 151

def previous_word_boundary(index)
  cursor = index
  cursor -= 1 while cursor.positive? && word_separator?(@input[cursor - 1])
  cursor -= 1 while cursor.positive? && !word_separator?(@input[cursor - 1])
  cursor
end

#recall_next_historyObject

Replaces input with the next history entry or restores the saved draft.



202
203
204
205
206
207
208
209
210
211
212
# File 'lib/kward/prompt_interface/composer_state.rb', line 202

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 || "")
    reset_history_navigation
  end
end

#recall_previous_historyObject

Replaces input with the previous history entry, preserving the draft first.



193
194
195
196
197
198
199
# File 'lib/kward/prompt_interface/composer_state.rb', line 193

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_attachmentObject

Removes the most recently added attachment.



53
54
55
56
57
58
# File 'lib/kward/prompt_interface/composer_state.rb', line 53

def remove_last_attachment
  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.



172
173
174
175
# File 'lib/kward/prompt_interface/composer_state.rb', line 172

def replace_input(value)
  @input = value.to_s
  @cursor = @input.length
end

#reset_history_navigationObject

Leaves history navigation and clears the saved draft/index state.



215
216
217
218
# File 'lib/kward/prompt_interface/composer_state.rb', line 215

def reset_history_navigation
  @history_index = nil
  @history_draft = nil
end

#word_separator?(char) ⇒ Boolean

Treats whitespace as the only word separator for composer navigation.

Returns:

  • (Boolean)


167
168
169
# File 'lib/kward/prompt_interface/composer_state.rb', line 167

def word_separator?(char)
  char.to_s.match?(/\s/)
end

#yank_kill_bufferObject

Inserts the last killed text at the cursor.



146
147
148
# File 'lib/kward/prompt_interface/composer_state.rb', line 146

def yank_kill_buffer
  insert_string(@kill_buffer.to_s) unless @kill_buffer.to_s.empty?
end