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 screen_buffer write_ops.ex
Raw

lib/raxol/terminal/screen_buffer/write_ops.ex

defmodule Raxol.Terminal.ScreenBuffer.WriteOps do
@moduledoc false
alias Raxol.Terminal.Cell
alias Raxol.Terminal.Buffer.Writer
def resize(buffer, new_width, new_height) do
default_cell = %Cell{
char: " ",
style: nil,
dirty: nil,
wide_placeholder: false
}
new_cells =
List.duplicate(List.duplicate(default_cell, new_width), new_height)
cells = buffer.cells || []
new_cells =
Enum.reduce(0..min(buffer.height - 1, new_height - 1), new_cells, fn row, acc ->
row_data = Enum.at(cells, row, [])
Enum.reduce(0..min(buffer.width - 1, new_width - 1), acc, fn col, row_acc ->
existing_cell =
Enum.at(row_data, col) || default_cell
current_row =
Enum.at(row_acc, row, List.duplicate(default_cell, new_width))
updated_row = List.replace_at(current_row, col, existing_cell)
List.replace_at(row_acc, row, updated_row)
end)
end)
%{
buffer
| width: new_width,
height: new_height,
cells: new_cells,
selection: nil,
scroll_region: nil
}
end
def write_char(buffer, x, y, char) do
write_char(buffer, x, y, char, buffer.default_style)
end
def write_char(buffer, x, y, char, style) when x >= 0 and y >= 0 do
case {x < buffer.width, y < buffer.height} do
{true, true} ->
Writer.write_char(buffer, x, y, char, style)
_ ->
buffer
end
end
def write_string(buffer, x, y, string),
do: write_string(buffer, x, y, string, nil)
def write_string(buffer, x, y, string, style) when x >= 0 and y >= 0 do
case {x < buffer.width, y < buffer.height} do
{true, true} ->
Writer.write_string(buffer, x, y, string, style)
_ ->
buffer
end
end
def get_char(buffer, x, y) do
case {x >= 0 and x < buffer.width, y >= 0 and y < buffer.height} do
{true, true} ->
row = Enum.at(buffer.cells, y, [])
cell = Enum.at(row, x)
case cell do
%{char: char} -> char
_ -> " "
end
_ ->
" "
end
end
def get_cell(buffer, x, y) when x >= 0 and y >= 0 do
cell =
if x < buffer.width and y < buffer.height do
case buffer.cells do
nil ->
Cell.new()
cells ->
cells
|> Enum.at(y, [])
|> Enum.at(x, Cell.new())
end
else
Cell.new()
end
Map.from_struct(cell)
end
def get_cell(_, _, _), do: Map.from_struct(Cell.new())
def get_content(buffer) do
case buffer.cells do
nil ->
""
cells when is_list(cells) ->
cells
|> Enum.map(fn line when is_list(line) ->
line
|> Enum.map_join("", fn
%Cell{char: char} ->
char
cell ->
case Map.get(cell, :char) do
nil -> " "
char -> char
end
end)
|> String.trim_trailing()
end)
|> Enum.reverse()
|> Enum.drop_while(&(&1 == ""))
|> Enum.reverse()
|> case do
[] -> ""
lines -> Enum.join(lines, "\n")
end
_ ->
""
end
end
def put_line(buffer, y, line) when y >= 0 and y < buffer.height do
new_cells = List.replace_at(buffer.cells || [], y, line)
%{buffer | cells: new_cells}
end
def put_line(buffer, _, _), do: buffer
end