Packages

Terminal emulation and driver infrastructure for Raxol. ANSI parsing, screen buffers, command processing, cursor management, input handling, session management, and termbox2 NIF integration.

Current section

Files

Jump to
raxol_terminal lib raxol terminal driver behaviour.ex
Raw

lib/raxol/terminal/driver/behaviour.ex

defmodule Raxol.Terminal.Driver.Behaviour do
@moduledoc """
Behaviour specification for terminal drivers.
This behaviour defines the contract that terminal drivers must implement
to provide terminal I/O functionality. Different implementations can
provide native (NIF-based), pure Elixir, or web-based terminal support.
## Implementations
- `Raxol.Terminal.Driver` - Main driver with automatic backend selection
- `Raxol.Terminal.IOTerminal` - Pure Elixir implementation
## Example Implementation
defmodule MyTerminalDriver do
@behaviour Raxol.Terminal.Driver.Behaviour
@impl true
def init(opts) do
# Initialize terminal
{:ok, %{}}
end
@impl true
def shutdown(state) do
# Cleanup
:ok
end
# ... implement other callbacks
end
"""
@typedoc "Driver state - implementation specific"
@type state :: term()
@typedoc "Terminal dimensions"
@type dimensions :: {width :: pos_integer(), height :: pos_integer()}
@typedoc "Terminal event"
@type event ::
{:key, key_data :: map()}
| {:mouse, mouse_data :: map()}
| {:resize, width :: pos_integer(), height :: pos_integer()}
| {:paste, content :: String.t()}
@typedoc "Color specification"
@type color ::
atom() | non_neg_integer() | {r :: 0..255, g :: 0..255, b :: 0..255}
@typedoc "Cell attributes"
@type attributes :: %{
optional(:fg) => color(),
optional(:bg) => color(),
optional(:bold) => boolean(),
optional(:italic) => boolean(),
optional(:underline) => boolean(),
optional(:reverse) => boolean(),
optional(:blink) => boolean()
}
# ============================================================================
# Lifecycle Callbacks
# ============================================================================
@doc """
Initialize the terminal driver.
Called when the driver process starts. Should set up the terminal
for raw input mode and prepare for rendering.
## Options
Implementation-specific options may include:
- `:width` - Initial width (for testing)
- `:height` - Initial height (for testing)
- `:output_device` - Output device (default: :stdio)
## Returns
- `{:ok, state}` - Initialization successful
- `{:error, reason}` - Initialization failed
"""
@callback init(opts :: keyword()) :: {:ok, state()} | {:error, term()}
@doc """
Shut down the terminal driver.
Called when the driver process terminates. Should restore the terminal
to its original state.
"""
@callback shutdown(state()) :: :ok
# ============================================================================
# Terminal Size
# ============================================================================
@doc """
Get the current terminal dimensions.
Returns the width and height in character cells.
"""
@callback get_size(state()) :: {:ok, dimensions()} | {:error, term()}
# ============================================================================
# Cursor Operations
# ============================================================================
@doc """
Move the cursor to the specified position.
Coordinates are 0-indexed, with (0, 0) at the top-left corner.
"""
@callback move_cursor(state(), x :: non_neg_integer(), y :: non_neg_integer()) ::
{:ok, state()} | {:error, term()}
@doc """
Show or hide the cursor.
"""
@callback set_cursor_visible(state(), visible :: boolean()) ::
{:ok, state()} | {:error, term()}
@doc """
Get the current cursor position.
"""
@callback get_cursor_position(state()) ::
{:ok, {x :: non_neg_integer(), y :: non_neg_integer()}}
| {:error, term()}
# ============================================================================
# Output Operations
# ============================================================================
@doc """
Write a string at the current cursor position.
"""
@callback write(state(), content :: String.t()) ::
{:ok, state()} | {:error, term()}
@doc """
Write a string at the specified position with optional attributes.
"""
@callback write_at(
state(),
x :: non_neg_integer(),
y :: non_neg_integer(),
content :: String.t(),
attrs :: attributes()
) :: {:ok, state()} | {:error, term()}
@doc """
Clear the entire screen.
"""
@callback clear(state()) :: {:ok, state()} | {:error, term()}
@doc """
Clear from cursor to end of line.
"""
@callback clear_line(state()) :: {:ok, state()} | {:error, term()}
@doc """
Flush any buffered output to the terminal.
"""
@callback flush(state()) :: {:ok, state()} | {:error, term()}
# ============================================================================
# Styling
# ============================================================================
@doc """
Set the foreground color for subsequent output.
"""
@callback set_foreground(state(), color()) ::
{:ok, state()} | {:error, term()}
@doc """
Set the background color for subsequent output.
"""
@callback set_background(state(), color()) ::
{:ok, state()} | {:error, term()}
@doc """
Set text attributes for subsequent output.
"""
@callback set_attributes(state(), attributes()) ::
{:ok, state()} | {:error, term()}
@doc """
Reset all styling to defaults.
"""
@callback reset_style(state()) :: {:ok, state()} | {:error, term()}
# ============================================================================
# Input Handling
# ============================================================================
@doc """
Poll for input events.
Returns the next available event or `:timeout` if no event is available
within the specified timeout (in milliseconds).
"""
@callback poll_event(state(), timeout :: non_neg_integer()) ::
{:ok, event(), state()} | {:timeout, state()} | {:error, term()}
# ============================================================================
# Optional Callbacks
# ============================================================================
@doc """
Set the terminal title.
This is an optional callback - implementations may return `{:ok, state}`
without taking action if not supported.
"""
@callback set_title(state(), title :: String.t()) ::
{:ok, state()} | {:error, term()}
@doc """
Enable or disable mouse input.
This is an optional callback - implementations may return `{:ok, state}`
without taking action if not supported.
"""
@callback set_mouse_enabled(state(), enabled :: boolean()) ::
{:ok, state()} | {:error, term()}
@doc """
Enable or disable bracketed paste mode.
This is an optional callback - implementations may return `{:ok, state}`
without taking action if not supported.
"""
@callback set_bracketed_paste(state(), enabled :: boolean()) ::
{:ok, state()} | {:error, term()}
@optional_callbacks [
set_title: 2,
set_mouse_enabled: 2,
set_bracketed_paste: 2
]
end