Back to Projects
TUIX v0.1Alpha

Last Updated: 2026-05-20

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:

PlatformModuleMethod
Windowsmsvcrtmsvcrt.getch() for non-blocking key reads. Arrow keys are detected via two-byte sequences (0xE0 prefix).
macOS / Linuxtermios, tty, selectSets 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

KeyWindows CodeUnix SequenceReturn Value
Arrow Up0xE0 + 'H'\x1b[A'up'
Arrow Down0xE0 + 'P'\x1b[B'down'
Arrow Right0xE0 + 'M'\x1b[C'right'
Arrow Left0xE0 + '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.

Dual StateBoth InputHandler and RenderEngine maintain their own selected_row / selected_index fields. The InputHandler is the source of truth and passes values to the RenderEngine on each refresh.

Current Limitations

  • Only arrow keys and Enter are supported
  • Only choice component type has input handling
  • No multi-component focus management
FuturePlanned: additional key bindings (Escape, Tab, etc.), multi-component focus and tab order, and input handling for text_input components.