TermUI.Runtime (TermUI v0.2.0)
View SourceThe central runtime orchestrator for TermUI applications.
The runtime implements The Elm Architecture dispatch loop:
- Receive event from terminal
- Route to appropriate component
- Call component's event_to_msg
- Call component's update with message
- Collect commands from update
- Mark component dirty
- On render timer, call view and render
Usage
# Start with a root component
{:ok, runtime} = Runtime.start_link(root: MyApp.Root)
# Send events (usually from terminal input)
Runtime.send_event(runtime, Event.key(:enter))
# Shutdown gracefully
Runtime.shutdown(runtime)
Summary
Functions
Returns a specification to start this module under a supervisor.
Delivers a command result back to the runtime.
Forces an immediate render (bypassing framerate limiter).
Gets the current runtime state (for testing/debugging).
Starts the runtime and blocks until it shuts down.
Sends an event to the runtime for processing.
Sends a message directly to a component.
Initiates graceful shutdown of the runtime.
Starts the runtime with the given options.
Synchronously waits for all pending events and messages to be processed.
Types
@type option() :: {:root, module()} | {:name, GenServer.name()} | {:render_interval, pos_integer()}
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec command_result(GenServer.server(), term(), term(), term()) :: :ok
Delivers a command result back to the runtime.
@spec force_render(GenServer.server()) :: :ok
Forces an immediate render (bypassing framerate limiter).
@spec get_state(GenServer.server()) :: TermUI.Runtime.State.t()
Gets the current runtime state (for testing/debugging).
Starts the runtime and blocks until it shuts down.
This is the main entry point for running a TUI application. It starts the runtime, takes over the terminal, and blocks the calling process until the application exits (e.g., user presses quit key).
Options
Same as start_link/1.
Example
# In your application entry point:
TermUI.Runtime.run(root: MyApp.Root)
# This blocks until the app exits
@spec send_event(GenServer.server(), TermUI.Event.t()) :: :ok
Sends an event to the runtime for processing.
@spec send_message(GenServer.server(), term(), term()) :: :ok
Sends a message directly to a component.
@spec shutdown(GenServer.server()) :: :ok
Initiates graceful shutdown of the runtime.
@spec start_link([option()]) :: GenServer.on_start()
Starts the runtime with the given options.
Options
:root- The root component module (required):name- GenServer name (optional):render_interval- Milliseconds between renders (default: 16)
@spec sync(GenServer.server(), timeout()) :: :ok
Synchronously waits for all pending events and messages to be processed.
This is primarily useful for testing to avoid race conditions from Process.sleep. It processes all queued messages and returns when complete.
Example
Runtime.send_event(runtime, Event.key(:up))
Runtime.send_event(runtime, Event.key(:up))
Runtime.sync(runtime) # Wait for both events to be processed
state = Runtime.get_state(runtime)
assert state.root_state.count == 2