Current section
Files
Jump to
Current section
Files
lib/ex_term/console/cursor.ex
defmodule ExTerm.Console.Cursor do
@moduledoc false
alias ExTerm.Console
alias ExTerm.Console.Cell
alias ExTerm.Console.Update
use MatchSpec
@home IO.ANSI.home()
@clear IO.ANSI.clear()
@clear_line IO.ANSI.clear_line()
@spec from_ansi(String.t(), Console.t(), Console.location(), to_flush :: Update.cell_changes()) ::
:not_cursor | {:update, Console.location(), Update.t(), String.t()}
def from_ansi(@home <> rest, console, {cursor_row, _}, changes) do
Console.insert(console, changes)
{rows, cols} = Console.layout(console)
updates =
Enum.flat_map((cursor_row + 1)..(cursor_row + rows), fn row ->
case Console.columns(console, row) do
0 ->
# doesn't exist. Fill it out to the layout length, pad with sentinel.
[{{row, cols + 1}, Cell.sentinel()} | Enum.map(1..cols, &{{row, &1}, %Cell{}})]
length ->
Enum.map(1..length, &{{row, &1}, %Cell{}})
end
end)
Console.insert(console, updates)
new_cursor = {cursor_row + 1, 1}
{:update, new_cursor, {new_cursor, :end}, rest}
end
def from_ansi(@clear <> rest, console, cursor, changes) do
Console.insert(console, changes)
# this clears only the "current console". Do this by looking up the console layout and
# last row and fill out everything after that. Doesn't add in extra rows.
{rows, _} = Console.layout(console)
{last_row, _} = Console.last_cell(console)
clear_start = {last_row - rows + 1, 1}
to_clear = Console.select(console, select_clear_from(clear_start))
Console.insert(console, to_clear)
{:update, cursor, {clear_start, :end}, rest}
end
def from_ansi(@clear_line <> rest, console, cursor = {row, _}, changes) do
Console.insert(console, changes)
to_clear = Console.select(console, select_clear_row(row))
Console.insert(console, to_clear)
{:update, cursor, {{row, 1}, {row, :end}}, rest}
end
def from_ansi(_, _, _, _), do: :not_cursor
defmatchspecp select_clear_from(from) do
{location, cell} when location >= from and cell.char !== "\n" -> {location, %Cell{}}
end
defmatchspecp select_clear_row(row) do
{{^row, column}, cell} when cell.char !== "\n" -> {{row, column}, %Cell{}}
end
end