TermUI.Command (TermUI v1.0.0)
View SourceCommands represent side effects to be performed by the runtime.
Commands are data describing effects - they don't execute immediately. The runtime interprets commands and performs the actual effects, sending result messages back to components.
Command Types
:timer- Deliver message after delay:interval- Deliver repeated messages at interval:file_read- Read file contents:send_after- Send a delayed message to the root component:quit- Request application shutdown:none- No-op command (useful for conditional commands)
Usage
# In component update function
def update(:start_timer, state) do
cmd = Command.timer(1000, :timer_fired)
{%{state | timer_active: true}, [cmd]}
end
def update(:timer_fired, state) do
{%{state | timer_active: false, count: state.count + 1}, []}
end
Summary
Functions
Assigns a unique ID to a command for tracking.
Creates a file read command.
Creates an interval command that delivers repeated messages.
Creates a no-op command.
Creates a quit command to request application shutdown.
Creates a send_after command that sends a delayed message to a component ID.
Creates a timer command that delivers a message after delay.
Checks if a term is a valid command.
Validates a command structure.
Sets a timeout for command execution.
Types
@type command_type() :: :timer | :interval | :file_read | :send_after | :quit | :none
@type t() :: %TermUI.Command{ id: reference() | nil, on_result: term(), payload: term(), timeout: pos_integer() | :infinity, type: atom() }
Functions
Assigns a unique ID to a command for tracking.
Creates a file read command.
Returns {:ok, content} or {:error, reason} wrapped in the on_result message.
Examples
Command.file_read("/path/to/file", :file_loaded)
# Results in: {:file_loaded, {:ok, "contents"}}
# or: {:file_loaded, {:error, :enoent}}
@spec interval(pos_integer(), term()) :: t()
Creates an interval command that delivers repeated messages.
Each tick delivers the on_result message. The primary runtime cancels
intervals when the root shuts down, but its public API does not expose an
individual interval cancellation handle in 1.0.
Examples
Command.interval(100, :tick)
@spec none() :: t()
Creates a no-op command.
Useful for conditional commands where you might not need an effect.
Examples
cmd = if should_fetch?, do: Command.timer(100, :fetch), else: Command.none()
Creates a quit command to request application shutdown.
The runtime will initiate graceful shutdown, cleaning up all resources and restoring the terminal to its original state.
Examples
# Simple quit
Command.quit()
# Quit with reason
Command.quit(:normal)
Command.quit(:user_requested)
@spec send_after(atom(), term(), pos_integer()) :: t()
Creates a send_after command that sends a delayed message to a component ID.
The primary 1.0 runtime has only the reserved :root component, so use
:root there. Lower-level executor integrations may use another component
ID as their own routing key.
Examples
Command.send_after(:root, :wake_up, 1000)
@spec timer(non_neg_integer(), term()) :: t()
Creates a timer command that delivers a message after delay.
Examples
Command.timer(1000, :timer_done)
Command.timer(500, {:tick, 1})
Checks if a term is a valid command.
Validates a command structure.
Returns :ok if valid, {:error, reason} otherwise.
@spec with_timeout(t(), pos_integer()) :: t()
Sets a timeout for command execution.
The 1.0 executor enforces this field for timer/2 and file_read/2: if the
operation takes longer, it is cancelled and {:error, :timeout} is sent.
Interval and delayed-send execution do not currently enforce this field.
Examples
Command.file_read(path, :loaded)
|> Command.with_timeout(5000)