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
Current section
Files
lib/raxol/terminal/commands/cursor_utils.ex
defmodule Raxol.Terminal.Commands.CursorUtils do
@moduledoc """
Shared utility functions for cursor handling commands.
Eliminates code duplication between CursorHandler and CSIHandler.
"""
@doc """
Calculates new cursor position based on direction and movement amount.
Ensures the new position is within the emulator bounds.
## Parameters
- current_pos: Current {row, col} position
- direction: Direction to move (:up, :down, :left, :right)
- amount: Number of positions to move
- width: Emulator width for boundary checking
- height: Emulator height for boundary checking
## Returns
New {row, col} position clamped to bounds
"""
@spec calculate_new_cursor_position(
{non_neg_integer(), non_neg_integer()},
atom(),
non_neg_integer(),
pos_integer(),
pos_integer()
) :: {non_neg_integer(), non_neg_integer()}
def calculate_new_cursor_position(
{row, col},
direction,
amount,
width,
height
) do
case direction do
:up -> {max(0, row - amount), col}
:down -> {min(height - 1, row + amount), col}
:left -> {row, max(0, col - amount)}
:right -> {row, min(width - 1, col + amount)}
end
end
@doc """
Saves the current cursor position into the emulator state.
"""
def save_cursor_position(emulator) do
cursor = emulator.cursor
updated_cursor = %{
cursor
| saved_row: cursor.row,
saved_col: cursor.col,
saved_position: {cursor.row, cursor.col}
}
saved_cursor = cursor
%{emulator | cursor: updated_cursor, saved_cursor: saved_cursor}
end
@doc """
Restores a previously saved cursor position from the emulator state.
"""
def restore_cursor_position(emulator) do
case Map.get(emulator, :saved_cursor) do
nil ->
cursor = emulator.cursor
{new_row, new_col} =
case {cursor.saved_row, cursor.saved_col} do
{nil, nil} -> {cursor.row, cursor.col}
{row, col} -> {row, col}
end
updated_cursor = %{
cursor
| row: new_row,
col: new_col,
position: {new_row, new_col}
}
%{emulator | cursor: updated_cursor}
saved_cursor ->
row = saved_cursor.row
col = saved_cursor.col
updated_cursor = %{
emulator.cursor
| row: row,
col: col,
position: {row, col},
shape: Map.get(saved_cursor, :shape, emulator.cursor.shape),
visible: Map.get(saved_cursor, :visible, emulator.cursor.visible)
}
%{emulator | cursor: updated_cursor}
end
end
end