TermUI.Input.Selector (TermUI v1.0.0)

View Source

Selects the appropriate input handler based on the active backend mode.

This module bridges the gap between backend selection and input handling, providing a way to choose the correct input handler for the current terminal mode.

The runtime calls select/1 after it has selected a backend. select/0 is a standalone convenience that calls Backend.Selector.select/0; on a capable system that call may activate OTP's Raw shell, so do not use it as a read-only query. Use TermUI.Runtime.backend_mode/0 to query published local runtime context.

Relationship with Backend.Selector

The TermUI.Backend.Selector determines which terminal backend to use (Raw or TTY). This module, TermUI.Input.Selector, then selects the corresponding input handler:

Backend ModeBackend ModuleInput Handler
:rawTermUI.Backend.RawTermUI.Input.Raw
:ttyTermUI.Backend.TTYTermUI.Input.TTY

Usage

There are two ways to select an input handler:

Explicit Selection

When you know which mode you want, use select/1:

# Get the Raw input handler
handler = TermUI.Input.Selector.select(:raw)
# => TermUI.Input.Raw

# Get the TTY input handler
handler = TermUI.Input.Selector.select(:tty)
# => TermUI.Input.TTY

Auto-Detection

When you want to match the current backend, use select/0:

# Automatically select based on current backend
handler = TermUI.Input.Selector.select()
# => TermUI.Input.Raw or TermUI.Input.TTY

State-Based Selection

For runtime code that already has a Backend.State struct, you can extract the mode and pass it directly:

backend_state = %TermUI.Backend.State{backend_mode: :tty, ...}
handler = TermUI.Input.Selector.select(backend_state.backend_mode)

Input Handler Contract

Both TermUI.Input.Raw and TermUI.Input.TTY implement the TermUI.Input behaviour, providing a consistent interface:

  • new/0 - Create initial handler state
  • poll/2 - Poll for input with timeout
  • mode/1 - Return the handler's mode (:raw or :tty)

Example Integration

# Typical usage in runtime initialization
case TermUI.Backend.Selector.select() do
  {:raw, backend_state} ->
    input_handler = TermUI.Input.Selector.select(:raw)
    input_state = input_handler.new()
    # ...

  {:tty, capabilities} ->
    input_handler = TermUI.Input.Selector.select(:tty)
    input_state = input_handler.new()
    # ...
end

Note on LineReader

TermUI.Input.LineReader is not included in the selector. LineReader is a specialized module for line-based input (used by TextInput.Line) and does not implement the TermUI.Input behaviour. Use LineReader directly when you need line-based input with shell editing.

Summary

Types

Input handler module that implements the TermUI.Input behaviour.

Valid input mode atoms.

Functions

Selects the appropriate input handler based on the current backend mode.

Selects the input handler for the specified mode.

Types

handler()

@type handler() :: module()

Input handler module that implements the TermUI.Input behaviour.

mode()

@type mode() :: :raw | :tty

Valid input mode atoms.

Functions

select()

@spec select() :: handler()

Selects the appropriate input handler based on the current backend mode.

This function auto-detects the current backend mode by attempting to determine whether raw mode is active. If detection cannot determine the mode, it defaults to TTY mode as the safer fallback.

Returns

Examples

handler = TermUI.Input.Selector.select()
state = handler.new()
{result, state} = handler.poll(state, 100)

Implementation Note

This function uses TermUI.Backend.Selector.select/0 to determine the current mode. This means it will attempt raw mode detection each time it's called. For performance, prefer using select/1 with an explicit mode when the mode is already known from backend initialization.

select(mode)

@spec select(mode()) :: handler()

Selects the input handler for the specified mode.

This function provides explicit selection when the mode is already known, avoiding the overhead of backend detection.

Arguments

  • mode - The input mode: :raw or :tty

Returns

Raises

Examples

# Select Raw input handler
handler = TermUI.Input.Selector.select(:raw)
# => TermUI.Input.Raw

# Select TTY input handler
handler = TermUI.Input.Selector.select(:tty)
# => TermUI.Input.TTY

# Using with Backend.State
backend_state = %TermUI.Backend.State{backend_mode: :tty, ...}
handler = TermUI.Input.Selector.select(backend_state.backend_mode)

# Invalid mode raises
TermUI.Input.Selector.select(:invalid)
# ** (ArgumentError) invalid input mode: :invalid, expected :raw or :tty