parse method

List<KeyEvent> parse(
  1. String chunk
)

Implementation

List<KeyEvent> parse(String chunk) {
  final input = _pending + chunk;
  _pending = '';
  final events = <KeyEvent>[];
  final text = StringBuffer();
  void add(KeyEvent event) {
    if (text.isNotEmpty) {
      events.add(KeyEvent(Key.text, text.toString()));
      text.clear();
    }
    events.add(event);
  }

  var index = 0;
  while (index < input.length) {
    final paste = _paste;
    if (paste != null) {
      final end = input.indexOf(_pasteEnd, index);
      if (end < 0) {
        paste.write(input.substring(index));
        break;
      }
      paste.write(input.substring(index, end));
      add(KeyEvent(Key.paste, paste.toString()));
      _paste = null;
      index = end + _pasteEnd.length;
      continue;
    }

    final char = input[index];
    if (char == '\x1B') {
      final escape = _parseEscape(input, index);
      if (escape == null) {
        _pending = input.substring(index);
        break;
      }
      if (escape.event case final event?) {
        add(event);
      }
      index += escape.length;
      continue;
    }
    if (char == '\r' || char == '\n') {
      final length = char == '\r' && index + 1 < input.length && input[index + 1] == '\n' ? 2 : 1;
      // Without bracketed paste, pasted lines arrive in one read with text
      // after the line break; only a trailing break is the Enter key.
      final pastedBreak = input.substring(index + length).trim().isNotEmpty;
      add(KeyEvent(pastedBreak ? Key.newline : Key.enter));
      index += length;
      continue;
    }
    final control = _controlKeys[char];
    if (control != null) {
      add(KeyEvent(control));
    } else if (char.codeUnitAt(0) >= 0x20) {
      text.write(char);
    }
    index++;
  }
  if (text.isNotEmpty) {
    events.add(KeyEvent(Key.text, text.toString()));
  }
  return events;
}