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/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