InputHandler
The InputHandler class manages keyboard input for interactive navigation. Accessible via engine.input, it provides cross-platform key detection and drives the selection state of choice components.
Platform Support
InputHandler automatically detects the platform and uses the appropriate input method:
| Platform | Module | Method |
|---|---|---|
| Windows | msvcrt | msvcrt.getch() for non-blocking key reads. Arrow keys are detected via two-byte sequences (0xE0 prefix). |
| macOS / Linux | termios, tty, select | Sets terminal to raw mode, uses select() with 0.1s timeout for non-blocking reads. Escape sequences (\x1b[A/B/C/D) map to arrow keys. |
get_key()
Low-level method that reads one key press. Returns a string ('up', 'down', 'left', 'right', 'enter') or None if no key was pressed. On Unix, terminal settings are saved and restored after each call.
Key Mappings
| Key | Windows Code | Unix Sequence | Return Value |
|---|---|---|---|
| Arrow Up | 0xE0 + 'H' | \x1b[A | 'up' |
| Arrow Down | 0xE0 + 'P' | \x1b[B | 'down' |
| Arrow Right | 0xE0 + 'M' | \x1b[C | 'right' |
| Arrow Left | 0xE0 + 'K' | \x1b[D | 'left' |
| Enter | \r or \n | \r or \n | 'enter' |
listen(choices)
The main input loop. Called automatically by RenderEngine._draw_choice() after rendering a choice component. Runs in a blocking while loop until Enter is pressed.
Navigation behavior:
- Up/Down arrows — move between rows (selected_index resets to 0)
- Left/Right arrows — move between buttons within the current row
- selected_row is clamped to [0, len(choices)-1]
- selected_index is clamped to [0, len(choices[selected_row])-1]
- Enter — clears the screen, prints the selected index, and exits the loop
After each arrow key press, listen() calls engine.render._refresh() to redraw the UI with the new selection. A 50ms sleep (time.sleep(0.05)) runs between key polls to prevent CPU spinning.
Selection State
The InputHandler maintains selected_row and selected_index attributes that track the current cursor position. These are passed to RenderEngine._refresh() and used by _draw_buttons() to highlight the active button.
Current Limitations
- Only arrow keys and Enter are supported
- Only choice component type has input handling
- No multi-component focus management