Class: Chamomile::EscapeParser

Inherits:
Object
  • Object
show all
Defined in:
lib/chamomile/escape_parser.rb

Overview

State-machine parser for ANSI escape sequences, CSI params, SGR mouse, and bracketed paste.

Constant Summary collapse

GROUND =

States

:ground
ESC_SEEN =
:esc_seen
CSI_ENTRY =
:csi_entry
SS3 =
:ss3
PASTE =
:paste
MODIFIER_MAP =

CSI modifier mapping (xterm-style: param 2=Shift, 3=Alt, 4=Shift+Alt, 5=Ctrl, etc.)

{
  2 => [:shift],
  3 => [:alt],
  4 => %i[shift alt],
  5 => [:ctrl],
  6 => %i[ctrl shift],
  7 => %i[ctrl alt],
  8 => %i[ctrl shift alt],
}.freeze
PASTE_START =
"\e[200~"
PASTE_END =
"\e[201~"
MAX_PASTE_SIZE =

Maximum paste buffer size (1MB) to prevent memory exhaustion

1_048_576

Instance Method Summary collapse

Constructor Details

#initializeEscapeParser

Returns a new instance of EscapeParser.



30
31
32
33
34
# File 'lib/chamomile/escape_parser.rb', line 30

def initialize
  @state = GROUND
  @buf = +""
  @paste_buf = +""
end

Instance Method Details

#feed(bytes, &block) ⇒ Object

Feed raw bytes into the parser, yielding parsed messages.



37
38
39
# File 'lib/chamomile/escape_parser.rb', line 37

def feed(bytes, &block)
  bytes.each_char { |ch| process_char(ch, &block) }
end

#timeout! {|KeyEvent.new(key: :escape, mod: [])| ... } ⇒ Object

Call when IO.select times out — flushes ambiguous ESC as :escape key.

Yields:



42
43
44
45
46
47
48
# File 'lib/chamomile/escape_parser.rb', line 42

def timeout!
  return unless @state == ESC_SEEN

  @state = GROUND
  @buf.clear
  yield KeyEvent.new(key: :escape, mod: [])
end