Class: PWN::Plugins::REPL::AIConsole::Editor

Inherits:
Object
  • Object
show all
Defined in:
lib/pwn/plugins/repl/ai_console.rb

Overview

Unicode grapheme editing and request recall from shared Pry history.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize ⇒ Editor

Returns a new instance of Editor.



180
181
182
183
184
185
# File 'lib/pwn/plugins/repl/ai_console.rb', line 180

def initialize
  @text = +''
  @cursor = 0
  @history = []
  @index = 0
end

Instance Attribute Details

#cursor ⇒ Object (readonly)

Returns the value of attribute cursor.



178
179
180
# File 'lib/pwn/plugins/repl/ai_console.rb', line 178

def cursor
  @cursor
end

#search ⇒ Object (readonly)

Returns the value of attribute search.



178
179
180
# File 'lib/pwn/plugins/repl/ai_console.rb', line 178

def search
  @search
end

#text ⇒ Object (readonly)

Returns the value of attribute text.



178
179
180
# File 'lib/pwn/plugins/repl/ai_console.rb', line 178

def text
  @text
end

Instance Method Details

#edit(key) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/pwn/plugins/repl/ai_console.rb', line 208

def edit(key)
  chars = @text.scan(/\X/)
  case key
  when :left then @cursor = [@cursor - 1, 0].max
  when :right then @cursor = [@cursor + 1, chars.length].min
  when :home, "\u0001" then @cursor = 0
  when :end, "\u0005" then @cursor = chars.length
  when :delete then chars.delete_at(@cursor)
  when "\u007f", "\b"
    chars.delete_at(@cursor -= 1) if @cursor.positive?
  when "\u0015" then chars.clear
                     @cursor = 0
  end
  @text = chars.join
end

#finish_search(accept: false) ⇒ Object



245
246
247
248
249
250
251
# File 'lib/pwn/plugins/repl/ai_console.rb', line 245

def finish_search(accept: false)
  if accept && @search&.dig(:match)
    replace(@search[:match])
    @index = @history.length
  end
  @search = nil
end

#insert(text) ⇒ Object



196
197
198
199
200
201
# File 'lib/pwn/plugins/repl/ai_console.rb', line 196

def insert(text)
  chars = @text.scan(/\X/)
  prefix = chars.take(@cursor).join + text
  @text = prefix + chars.drop(@cursor).join
  @cursor = prefix.scan(/\X/).length
end

#place(text, cursor) ⇒ Object



253
254
255
256
# File 'lib/pwn/plugins/repl/ai_console.rb', line 253

def place(text, cursor)
  replace(text)
  @cursor = cursor.to_i.clamp(0, @text.scan(/\X/).length)
end

#preload(lines) ⇒ Object



187
188
189
190
191
192
193
194
# File 'lib/pwn/plugins/repl/ai_console.rb', line 187

def preload(lines)
  Array(lines).each do |line|
    next if line.to_s.strip.empty? || line.match?(%r{\A\s*/input(?:\s|\z)}) || @history.last == line

    @history << line.dup
  end
  @index = @history.length
end

#recall(direction) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/pwn/plugins/repl/ai_console.rb', line 224

def recall(direction)
  return if @history.empty?
  return if direction == :up && @index.zero?
  return if direction == :down && @index == @history.length

  @draft = [@text.dup, @cursor] if @index == @history.length
  @index += direction == :up ? -1 : 1
  if @index == @history.length
    @text, @cursor = @draft
    @text = @text.dup
  else
    replace(@history[@index])
  end
end

#replace(text) ⇒ Object



203
204
205
206
# File 'lib/pwn/plugins/repl/ai_console.rb', line 203

def replace(text)
  @text = text.dup
  @cursor = @text.scan(/\X/).length
end

#search_history(query = '', older: false) ⇒ Object



239
240
241
242
243
# File 'lib/pwn/plugins/repl/ai_console.rb', line 239

def search_history(query = '', older: false)
  start = older && @search ? @search[:index] : @history.length
  index = (start - 1).downto(0).find { |position| @history[position].include?(query) }
  @search = { query: query, index: index || start, match: index ? @history[index].dup : nil }
end

#submit ⇒ Object



258
259
260
261
262
263
264
# File 'lib/pwn/plugins/repl/ai_console.rb', line 258

def submit
  line = @text.dup
  @history << line.dup unless line.strip.empty? || @history.last == line || line.match?(%r{\A\s*/input(?:\s|\z)})
  @index = @history.length
  replace('')
  line
end