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

lib/raxol/terminal/commands/csi_handler/mode_processor.ex

defmodule Raxol.Terminal.Commands.CSIHandler.ModeProcessor do
@moduledoc false
alias Raxol.Terminal.Commands.CursorUtils
alias Raxol.Terminal.ModeManager
def handle_h_or_l(emulator, params, intermediates, final_byte) do
is_set = final_byte == ?h
is_private = intermediates == "?"
result =
Enum.reduce(params, emulator, fn param, acc ->
mode_value =
if is_integer(param), do: param, else: String.to_integer(param)
if is_private do
handle_private_mode(acc, mode_value, is_set)
else
handle_standard_mode(acc, mode_value, is_set)
end
end)
result
end
defp handle_private_mode(emulator, mode, is_set) do
mode_name = private_mode_name(mode)
if mode_name do
category = private_mode_category(mode)
updated_emulator =
apply_mode_change(emulator, mode_name, category, is_set)
apply_screen_buffer_switch(updated_emulator, mode_name, is_set)
else
emulator
end
end
defp private_mode_name(mode) do
case mode do
1 -> :decckm
3 -> :deccolm_132
5 -> :decscnm
6 -> :decom
7 -> :decawm
8 -> :decarm
9 -> :decinlm
12 -> :decsrm
25 -> :dectcem
47 -> :dec_alt_screen
1000 -> :mouse_report_x10
1002 -> :mouse_report_cell_motion
1003 -> :mouse_any_event
1004 -> :focus_events
1047 -> :dec_alt_screen_save
1048 -> :decsc_deccara
1049 -> :alt_screen_buffer
2004 -> :bracketed_paste
_ -> nil
end
end
defp private_mode_category(mode) do
case mode do
47 -> :screen_buffer
1047 -> :screen_buffer
1048 -> :screen_buffer
1049 -> :screen_buffer
_ -> :dec_private
end
end
defp apply_screen_buffer_switch(emulator, mode_name, is_set) do
case {mode_name, is_set} do
{:dec_alt_screen, true} ->
%{emulator | active_buffer_type: :alternate}
{:dec_alt_screen, false} ->
%{emulator | active_buffer_type: :main}
{:dec_alt_screen_save, true} ->
%{emulator | active_buffer_type: :alternate}
{:dec_alt_screen_save, false} ->
%{emulator | active_buffer_type: :main}
{:alt_screen_buffer, true} ->
emulator = save_cursor_position(emulator)
%{emulator | active_buffer_type: :alternate}
{:alt_screen_buffer, false} ->
emulator = %{emulator | active_buffer_type: :main}
restore_cursor_position(emulator)
_ ->
emulator
end
end
defp handle_standard_mode(emulator, mode, is_set) do
mode_name =
case mode do
4 -> :irm
12 -> :srm
20 -> :lnm
_ -> nil
end
if mode_name do
apply_mode_change(emulator, mode_name, :standard, is_set)
else
emulator
end
end
defp apply_mode_change(emulator, mode_name, category, is_set) do
if is_set do
case ModeManager.set_mode(emulator, [mode_name], category) do
{:ok, emu} -> emu
_ -> emulator
end
else
case ModeManager.reset_mode(emulator, [mode_name], category) do
{:ok, emu} -> emu
_ -> emulator
end
end
end
defp save_cursor_position(emulator),
do: CursorUtils.save_cursor_position(emulator)
defp restore_cursor_position(emulator),
do: CursorUtils.restore_cursor_position(emulator)
end