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 operation_processor.ex
Raw

lib/raxol/terminal/buffer/operation_processor.ex

defmodule Raxol.Terminal.Buffer.OperationProcessor do
@moduledoc """
Handles processing and batching of buffer operations.
This module is responsible for:
- Processing individual operations (set_cell, write_string, fill_region, etc.)
- Batching operations for performance
- Managing operation queues
- Error handling during operation processing
"""
require Logger
alias Raxol.Terminal.Buffer.Content
alias Raxol.Terminal.Buffer.Operations, as: Buffer
alias Raxol.Terminal.Buffer.State
@type operation ::
{:set_cell, non_neg_integer(), non_neg_integer(), term()}
| {:write_string, non_neg_integer(), non_neg_integer(), String.t()}
| {:fill_region, non_neg_integer(), non_neg_integer(),
non_neg_integer(), non_neg_integer(), term()}
| {:scroll, integer()}
| {:resize, non_neg_integer(), non_neg_integer()}
@doc """
Processes a single operation on the buffer.
"""
@spec process_operation(operation(), term()) :: term()
def process_operation({:set_cell, x, y, cell}, buffer) do
if valid_coordinates?(buffer, x, y) do
Content.write_char(buffer, x, y, cell.char, cell)
else
buffer
end
end
def process_operation(
{:set_cell, _x, _y, _cell, :invalid_coordinates},
buffer
) do
buffer
end
def process_operation({:write_string, x, y, string}, buffer) do
if valid_coordinates?(buffer, x, y) do
Content.write_string(buffer, x, y, string)
else
buffer
end
end
def process_operation(
{:write_string, _x, _y, _string, :invalid_coordinates},
buffer
) do
buffer
end
def process_operation({:fill_region, x, y, width, height, cell}, buffer) do
if valid_coordinates?(buffer, x, y) and x + width <= buffer.width and
y + height <= buffer.height do
fill_region_helper(buffer, x, y, width, height, cell)
else
buffer
end
end
def process_operation(
{:fill_region, _x, _y, _width, _height, _cell, :invalid_coordinates},
buffer
) do
buffer
end
def process_operation({:scroll, lines}, buffer) do
Buffer.scroll(buffer, lines)
end
def process_operation({:resize, width, height}, buffer) do
State.resize(buffer, width, height)
end
@doc """
Processes a batch of operations on the buffer.
"""
@spec process_batch([operation()], term()) :: term()
def process_batch(operations, buffer) do
Enum.reduce(operations, buffer, &process_operation/2)
end
@doc """
Processes all operations in a queue until empty.
"""
@spec process_all_operations([operation()], term()) :: term()
def process_all_operations(operations, buffer) do
process_batch(operations, buffer)
end
@doc """
Validates if coordinates are within buffer bounds.
"""
@spec valid_coordinates?(term(), non_neg_integer(), non_neg_integer()) ::
boolean()
def valid_coordinates?(buffer, x, y) do
x >= 0 and y >= 0 and x < buffer.width and y < buffer.height
end
@doc """
Validates if fill region coordinates are valid.
"""
@spec valid_fill_region_coordinates?(
term(),
non_neg_integer(),
non_neg_integer(),
non_neg_integer(),
non_neg_integer()
) :: boolean()
def valid_fill_region_coordinates?(buffer, x, y, width, height) do
valid_coordinates?(buffer, x, y) and x + width <= buffer.width and
y + height <= buffer.height
end
# Private helper functions
defp fill_region_helper(buffer, x, y, width, height, cell) do
Enum.reduce(y..(y + height - 1), buffer, fn row_y, acc ->
Enum.reduce(x..(x + width - 1), acc, fn col_x, acc ->
Content.write_char(acc, col_x, row_y, cell.char, cell)
end)
end)
end
end