read static method

KeyEvent read()

Reads the next key event from stdin.

Expects stdin to be in raw mode. For ESC-based sequences, briefly peeks ahead to differentiate a lone ESC from arrow keys or other CSI sequences.

Implementation

static KeyEvent read() {
  final terminal = TerminalContext.current;
  final byte = _readByte(terminal);

  // Enter
  if (byte == 10 || byte == 13) return const KeyEvent(KeyEventType.enter);

  // Ctrl+C
  if (byte == 3) return const KeyEvent(KeyEventType.ctrlC);

  // Ctrl+R
  if (byte == 18) return const KeyEvent(KeyEventType.ctrlR);

  // Ctrl+D
  if (byte == 4) return const KeyEvent(KeyEventType.ctrlD);

  // Ctrl+E
  if (byte == 5) return const KeyEvent(KeyEventType.ctrlE);

  // Tab
  if (byte == 9) return const KeyEvent(KeyEventType.tab);

  // Generic Ctrl+[A-Z]
  if (byte >= 1 && byte <= 26) {
    final char = String.fromCharCode(byte + 96);
    return KeyEvent(KeyEventType.ctrlGeneric, char);
  }

  // Space
  if (byte == 32) return const KeyEvent(KeyEventType.space);

  // Slash
  if (byte == 47) return const KeyEvent(KeyEventType.slash);

  // Backspace
  if (byte == 127 || byte == 8) return const KeyEvent(KeyEventType.backspace);

  // ESC or Arrow Sequences
  if (byte == 27) {
    // Wait briefly to see if this is an escape sequence
    sleep(const Duration(milliseconds: 30));
    final next1 = TerminalControl.tryReadNextByte();
    final next2 = TerminalControl.tryReadNextByte();

    if (next1 == 91 && next2 != null) {
      switch (next2) {
        case 65:
          return const KeyEvent(KeyEventType.arrowUp);
        case 66:
          return const KeyEvent(KeyEventType.arrowDown);
        case 67:
          return const KeyEvent(KeyEventType.arrowRight);
        case 68:
          return const KeyEvent(KeyEventType.arrowLeft);
      }
    }

    // No following bytes → real ESC key
    return const KeyEvent(KeyEventType.esc);
  }

  // Printable char
  final ch = _readUtf8Character(terminal, byte);
  if (ch != null && _isPrintableCharacter(ch)) {
    return KeyEvent(KeyEventType.char, ch);
  }

  return const KeyEvent(KeyEventType.unknown);
}