Packages

Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.

Current section

Files

Jump to
raxol lib raxol terminal buffer safe_manager.ex
Raw

lib/raxol/terminal/buffer/safe_manager.ex

defmodule Raxol.Terminal.Buffer.SafeManager do
@moduledoc """
Safe buffer manager that handles buffer operations with error recovery.
This module provides a safe interface to buffer operations, ensuring
that failures don't crash the system and providing fallback behavior.
"""
@doc """
Starts a safe manager process.
"""
@spec start_link() :: {:ok, pid()} | {:error, term()}
def start_link do
# For now, delegate to regular Manager
GenServer.start_link(Raxol.Terminal.ScreenBuffer.Manager, %{},
name: __MODULE__
)
end
@doc """
Safely writes data to the buffer.
"""
@spec write(pid() | atom(), binary()) :: :ok | {:error, term()}
def write(manager, data) when is_binary(data) do
GenServer.call(manager, {:write, data})
rescue
error -> {:error, error}
catch
:exit, reason -> {:error, {:exit, reason}}
end
def write(_manager, _data), do: {:error, :invalid_data}
@doc """
Safely reads from the buffer.
"""
@spec read(pid() | atom(), non_neg_integer()) ::
{:ok, binary()} | {:error, term()}
def read(manager, count) when is_integer(count) and count > 0 do
GenServer.call(manager, {:read, count})
rescue
error -> {:error, error}
catch
:exit, reason -> {:error, {:exit, reason}}
end
def read(_manager, _count), do: {:error, :invalid_count}
@doc """
Safely resizes the buffer.
"""
@spec resize(pid() | atom(), non_neg_integer(), non_neg_integer()) ::
:ok | {:error, term()}
def resize(manager, width, height)
when is_integer(width) and width > 0 and
is_integer(height) and height > 0 do
GenServer.call(manager, {:resize, width, height})
rescue
error -> {:error, error}
catch
:exit, reason -> {:error, {:exit, reason}}
end
def resize(_manager, _width, _height), do: {:error, :invalid_dimensions}
@doc """
Safely clears the buffer.
"""
@spec clear(pid() | atom()) :: :ok | {:error, term()}
def clear(manager) do
GenServer.call(manager, :clear)
rescue
error -> {:error, error}
catch
:exit, reason -> {:error, {:exit, reason}}
end
@doc """
Gets buffer info safely.
"""
@spec info(pid() | atom()) :: {:ok, map()} | {:error, term()}
def info(manager) do
GenServer.call(manager, :info)
rescue
error -> {:error, error}
catch
:exit, reason -> {:error, {:exit, reason}}
end
@doc """
Safely gets a cell from the buffer.
"""
@spec get_cell(pid() | atom(), non_neg_integer(), non_neg_integer()) ::
{:ok, map()} | {:error, term()}
def get_cell(manager, x, y)
when is_integer(x) and x >= 0 and
is_integer(y) and y >= 0 do
GenServer.call(manager, {:get_cell, x, y})
rescue
error -> {:error, error}
catch
:exit, reason -> {:error, {:exit, reason}}
end
def get_cell(_manager, _x, _y), do: {:error, :invalid_coordinates}
@doc """
Safely sets a cell in the buffer.
"""
@spec set_cell(pid() | atom(), non_neg_integer(), non_neg_integer(), map()) ::
:ok | {:error, term()}
def set_cell(manager, x, y, cell)
when is_integer(x) and x >= 0 and
is_integer(y) and y >= 0 and
is_map(cell) do
GenServer.call(manager, {:set_cell, x, y, cell})
rescue
error -> {:error, error}
catch
:exit, reason -> {:error, {:exit, reason}}
end
def set_cell(_manager, _x, _y, _cell), do: {:error, :invalid_arguments}
@doc """
Safely scrolls the buffer.
"""
@spec scroll(pid() | atom(), integer()) :: :ok | {:error, term()}
def scroll(manager, lines) when is_integer(lines) do
GenServer.call(manager, {:scroll, lines})
rescue
error -> {:error, error}
catch
:exit, reason -> {:error, {:exit, reason}}
end
def scroll(_manager, _lines), do: {:error, :invalid_lines}
end