TermUI.Command (TermUI v0.2.0)

View Source

Commands 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 message to component after delay
  • :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 message to a component after delay.

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

command_type()

@type command_type() :: :timer | :interval | :file_read | :send_after | :quit | :none

t()

@type t() :: %TermUI.Command{
  id: reference() | nil,
  on_result: term(),
  payload: term(),
  timeout: pos_integer() | :infinity,
  type: atom()
}

Functions

assign_id(command)

@spec assign_id(t()) :: t()

Assigns a unique ID to a command for tracking.

file_read(path, on_result)

@spec file_read(Path.t(), term()) :: t()

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}}

interval(interval_ms, on_result)

@spec interval(pos_integer(), term()) :: t()

Creates an interval command that delivers repeated messages.

The interval continues until cancelled. Each tick delivers the on_result message.

Examples

Command.interval(100, :tick)

none()

@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()

quit(reason \\ :normal)

@spec quit(term()) :: t()

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)

send_after(component_id, message, delay_ms)

@spec send_after(atom(), term(), pos_integer()) :: t()

Creates a send_after command that sends a message to a component after delay.

Unlike timer which sends to the originating component, send_after can target any component.

Examples

Command.send_after(:other_component, :wake_up, 1000)

timer(delay_ms, on_result)

@spec timer(pos_integer(), term()) :: t()

Creates a timer command that delivers a message after delay.

Examples

Command.timer(1000, :timer_done)
Command.timer(500, {:tick, 1})

valid?(term)

@spec valid?(term()) :: boolean()

Checks if a term is a valid command.

validate(arg1)

@spec validate(t()) :: :ok | {:error, term()}

Validates a command structure.

Returns :ok if valid, {:error, reason} otherwise.

with_timeout(command, timeout_ms)

@spec with_timeout(t(), pos_integer()) :: t()

Sets a timeout for command execution.

If the command takes longer than the timeout, it's cancelled and an error message is sent.

Examples

Command.file_read(path, :loaded)
|> Command.with_timeout(5000)