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 commands executor.ex
Raw

lib/raxol/terminal/commands/executor.ex

defmodule Raxol.Terminal.Commands.Executor do
@moduledoc false
alias Raxol.Terminal.Emulator
alias Raxol.Terminal.Commands.Parser
alias Raxol.Terminal.Commands.CSIHandlers
alias Raxol.Terminal.Commands.OSCHandlers
alias Raxol.Terminal.Commands.DCSHandlers
require Raxol.Core.Runtime.Log
@basic_commands [?m, ?H, ?r, ?J, ?K]
@cursor_commands [?A, ?B, ?C, ?D, ?E, ?F, ?G, ?d]
@screen_commands [?L, ?M, ?P, ?@, ?S, ?T, ?X]
@device_commands [?c, ?n, ?s, ?u, ?t]
@scs_commands [?(, ?), ?*, ?+]
@command_map %{
basic: &CSIHandlers.handle_basic_command/3,
cursor: &CSIHandlers.handle_cursor_command/3,
screen: &CSIHandlers.handle_screen_command/3,
device: &CSIHandlers.handle_device_command/4,
mode: &CSIHandlers.handle_h_or_l/4,
scs: &CSIHandlers.handle_scs/3,
deccusr: &CSIHandlers.handle_q_deccusr/2
}
@command_types %{
basic: @basic_commands,
cursor: @cursor_commands,
screen: @screen_commands,
device: @device_commands,
scs: @scs_commands
}
@spec execute_csi_command(
Emulator.t(),
String.t(),
String.t(),
non_neg_integer()
) :: Emulator.t()
def execute_csi_command(
emulator,
params_buffer,
intermediates_buffer,
final_byte
) do
Raxol.Core.Runtime.Log.debug(
"[Executor.execute_csi_command] BEFORE: scroll_region=#{inspect(emulator.scroll_region)}, final_byte=#{inspect(final_byte)}"
)
params = Parser.parse_params(params_buffer)
result =
dispatch_csi_command(
emulator,
params,
intermediates_buffer,
final_byte,
params_buffer
)
log_and_return_result(result)
end
defp dispatch_csi_command(
emulator,
params,
intermediates_buffer,
final_byte,
params_buffer
) do
case get_command_type(final_byte, intermediates_buffer) do
{:ok, type} ->
apply_handler(
type,
emulator,
params,
intermediates_buffer,
final_byte,
params_buffer
)
:unknown ->
log_unknown_csi(final_byte)
{:error, :unhandled_csi, emulator}
end
end
defp get_command_type(final_byte, intermediates_buffer) do
cond do
final_byte == ?q and intermediates_buffer == " " -> {:ok, :deccusr}
final_byte in [?h, ?l] -> {:ok, :mode}
true -> find_command_type(final_byte)
end
end
defp find_command_type(final_byte) do
Enum.find_value(@command_types, :unknown, fn {type, commands} ->
if final_byte in commands, do: {:ok, type}
end)
end
defp apply_handler(
:basic,
emulator,
params,
_intermediates,
final_byte,
_params_buffer
),
do: @command_map.basic.(emulator, params, final_byte)
defp apply_handler(
:mode,
emulator,
params,
intermediates,
final_byte,
_params_buffer
),
do: @command_map.mode.(emulator, params, intermediates, final_byte)
defp apply_handler(
:device,
emulator,
params,
intermediates,
final_byte,
_params_buffer
),
do: @command_map.device.(emulator, params, intermediates, final_byte)
defp apply_handler(
:scs,
emulator,
_params,
_intermediates,
final_byte,
params_buffer
),
do: @command_map.scs.(emulator, params_buffer, final_byte)
defp apply_handler(
:deccusr,
emulator,
params,
_intermediates,
_final_byte,
_params_buffer
),
do: @command_map.deccusr.(emulator, params)
defp apply_handler(
:cursor,
emulator,
params,
_intermediates,
final_byte,
_params_buffer
),
do: @command_map.cursor.(emulator, params, final_byte)
defp apply_handler(
:screen,
emulator,
params,
_intermediates,
final_byte,
_params_buffer
),
do: @command_map.screen.(emulator, params, final_byte)
defp log_and_return_result({:ok, emulator}) do
emulator
end
defp log_and_return_result({:ok, emulator, _output}) do
emulator
end
defp log_and_return_result({:error, reason}) do
require Logger
Logger.error("Executor error: #{inspect(reason)}")
{:error, reason}
end
defp log_and_return_result(%Raxol.Terminal.Emulator{} = emulator) do
emulator
end
defp log_unknown_csi(final_byte) do
Raxol.Core.Runtime.Log.warning_with_context(
"Unknown CSI command: #{inspect(final_byte)}",
%{}
)
end
@spec execute_osc_command(Emulator.t(), String.t()) :: Emulator.t()
def execute_osc_command(emulator, command_string) do
Raxol.Core.Runtime.Log.debug(
"Executing OSC command: #{inspect(command_string)}"
)
handle_osc_command(emulator, command_string)
end
@spec execute_osc_command(Emulator.t(), integer(), list()) :: Emulator.t()
def execute_osc_command(emulator, command, params) do
# Convert params to string format for the existing handler
command_string = "#{command};#{Enum.join(params, ";")}"
execute_osc_command(emulator, command_string)
end
defp handle_osc_command(emulator, command_string) do
with [ps_str, pt] <- String.split(command_string, ";", parts: 2),
{ps_code, ""} <- Integer.parse(ps_str) do
dispatch_osc_command(emulator, ps_code, pt)
else
_ ->
Raxol.Core.Runtime.Log.warning_with_context(
"OSC: Unexpected command format: \"#{command_string}\"",
%{}
)
{:error, :malformed_osc, emulator}
end
end
defp dispatch_osc_command(emulator, ps_code, pt) do
OSCHandlers.handle(emulator, ps_code, pt)
end
@spec execute_dcs_command(
Emulator.t(),
String.t(),
String.t(),
String.t()
) :: Emulator.t()
def execute_dcs_command(
emulator,
params_buffer,
intermediates_buffer,
data_string
) do
Raxol.Core.Runtime.Log.debug(
"Executing DCS command: #{inspect(data_string)}"
)
handle_dcs_command(
emulator,
params_buffer,
intermediates_buffer,
data_string
)
end
@spec execute_dcs_command(Emulator.t(), integer(), list()) :: Emulator.t()
def execute_dcs_command(emulator, _command, params) do
# Convert to string format for the existing handler
params_buffer = Enum.join(params, ";")
execute_dcs_command(emulator, params_buffer, "", "")
end
defp handle_dcs_command(
emulator,
params_buffer,
intermediates_buffer,
data_string
) do
case intermediates_buffer do
"" ->
DCSHandlers.handle_dcs(emulator, params_buffer, data_string)
_ ->
Raxol.Core.Runtime.Log.warning_with_context(
"DCS: Unhandled intermediate: \"#{intermediates_buffer}\"",
%{}
)
{:error, :unhandled_dcs, emulator}
end
end
end