Current section
Files
Jump to
Current section
Files
src/prequel@span.erl
-module(prequel@span).
-compile([no_auto_import, nowarn_unused_vars]).
-export([new/4, segment/3, point/2, merge/2, lines/1, max_line/1, min_line/1, columns/1, max_column/1, min_column/1, is_segment/1, starts_at_line/2, ends_on_line/2, contains_line/2, classify_line/2]).
-export_type([span/0, position/0]).
-type span() :: {span, integer(), integer(), integer(), integer()}.
-type position() :: first | inside | last | outside.
-spec new(integer(), integer(), integer(), integer()) -> span().
new(Start_line, End_line, Start_column, End_column) ->
{span, Start_line, End_line, Start_column, End_column}.
-spec segment(integer(), integer(), integer()) -> span().
segment(Line, Start_column, End_column) ->
{span, Line, Line, Start_column, End_column}.
-spec point(integer(), integer()) -> span().
point(Line, Column) ->
{span, Line, Line, Column, Column}.
-spec merge(span(), span()) -> span().
merge(One, Other) ->
{span,
gleam@int:min(erlang:element(2, One), erlang:element(2, Other)),
gleam@int:max(erlang:element(3, One), erlang:element(3, Other)),
gleam@int:min(erlang:element(4, One), erlang:element(4, Other)),
gleam@int:max(erlang:element(5, One), erlang:element(5, Other))}.
-spec lines(span()) -> non_empty_list:non_empty_list(integer()).
lines(Span) ->
_pipe = non_empty_list:new(
erlang:element(2, Span),
[erlang:element(3, Span)]
),
non_empty_list:unique(_pipe).
-spec max_line(non_empty_list:non_empty_list(span())) -> integer().
max_line(Spans) ->
_pipe = non_empty_list:flat_map(Spans, fun lines/1),
non_empty_list:reduce(_pipe, fun gleam@int:max/2).
-spec min_line(non_empty_list:non_empty_list(span())) -> integer().
min_line(Spans) ->
_pipe = non_empty_list:flat_map(Spans, fun lines/1),
non_empty_list:reduce(_pipe, fun gleam@int:min/2).
-spec columns(span()) -> non_empty_list:non_empty_list(integer()).
columns(Span) ->
_pipe = non_empty_list:new(
erlang:element(4, Span),
[erlang:element(5, Span)]
),
non_empty_list:unique(_pipe).
-spec max_column(non_empty_list:non_empty_list(span())) -> integer().
max_column(Spans) ->
_pipe = non_empty_list:flat_map(Spans, fun columns/1),
non_empty_list:reduce(_pipe, fun gleam@int:max/2).
-spec min_column(non_empty_list:non_empty_list(span())) -> integer().
min_column(Spans) ->
_pipe = non_empty_list:flat_map(Spans, fun columns/1),
non_empty_list:reduce(_pipe, fun gleam@int:min/2).
-spec is_segment(span()) -> boolean().
is_segment(Span) ->
erlang:element(2, Span) =:= erlang:element(3, Span).
-spec starts_at_line(span(), integer()) -> boolean().
starts_at_line(Span, Line) ->
erlang:element(2, Span) =:= Line.
-spec ends_on_line(span(), integer()) -> boolean().
ends_on_line(Span, Line) ->
erlang:element(3, Span) =:= Line.
-spec contains_line(span(), integer()) -> boolean().
contains_line(Span, Line) ->
(erlang:element(2, Span) =< Line) andalso (Line =< erlang:element(3, Span)).
-spec classify_line(span(), integer()) -> position().
classify_line(Span, Line) ->
gleam@bool:guard(
starts_at_line(Span, Line),
first,
fun() ->
gleam@bool:guard(
ends_on_line(Span, Line),
last,
fun() ->
gleam@bool:guard(
contains_line(Span, Line),
inside,
fun() -> outside end
)
end
)
end
).