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
Current section
Files
lib/raxol/terminal/parser/states/osc_string_state.ex
defmodule Raxol.Terminal.Parser.States.OSCStringState do
@moduledoc """
Handles the OSC String state in the terminal parser.
This state is entered when an OSC sequence is initiated.
"""
alias Raxol.Terminal.Emulator
alias Raxol.Terminal.Parser.ParserState, as: State
alias Raxol.Terminal.Commands.Executor
require Raxol.Core.Runtime.Log
@doc """
Processes input when the parser is in the :osc_string state.
Collects the OSC string until ST (ESC \) or BEL.
"""
@spec handle(Emulator.t(), State.t(), binary()) ::
{:continue, Emulator.t(), State.t(), binary()}
| {:finished, Emulator.t(), State.t()}
| {:incomplete, Emulator.t(), State.t()}
def handle(
emulator,
%State{state: :osc_string} = parser_state,
input
) do
case input do
<<>> ->
# Incomplete OSC string - return current state
Raxol.Core.Runtime.Log.debug(
"[Parser] Incomplete OSC string, input ended."
)
{:incomplete, emulator, parser_state}
# String Terminator (ST - ESC \) -- Use escape_char check first
<<27, rest_after_esc::binary>> ->
{:continue, emulator, %{parser_state | state: :osc_string_maybe_st},
rest_after_esc}
# BEL (7) is another valid terminator for OSC
<<7, rest_after_bel::binary>> ->
# Call the dispatcher function (now imported)
new_emulator =
Executor.execute_osc_command(
emulator,
parser_state.payload_buffer
)
next_parser_state = %{parser_state | state: :ground}
{:continue, new_emulator, next_parser_state, rest_after_bel}
# CAN/SUB abort OSC string
<<abort_byte, rest_after_abort::binary>>
when abort_byte == 0x18 or abort_byte == 0x1A ->
Raxol.Core.Runtime.Log.debug("Aborting OSC String due to CAN/SUB")
next_parser_state = %{parser_state | state: :ground}
{:continue, emulator, next_parser_state, rest_after_abort}
# Standard printable ASCII
<<char, rest::binary>> when char >= 32 and char <= 126 ->
# Append to payload buffer
next_parser_state = %{
parser_state
| payload_buffer: parser_state.payload_buffer <> <<char>>
}
{:continue, emulator, next_parser_state, rest}
# Unhandled byte
<<unhandled_byte, rest_after_unhandled::binary>> ->
Raxol.Core.Runtime.Log.warning_with_context(
"Unhandled byte in OSC String state: #{inspect(unhandled_byte)}",
%{}
)
# Go to ground state
next_parser_state = %{parser_state | state: :ground}
{:continue, emulator, next_parser_state, rest_after_unhandled}
end
end
end