-module(etui@focus).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/etui/focus.gleam").
-export([focus_new/1, focused/1, is_focused/2, current_index/1, size/1, focus_next/1, focus_prev/1, focus_id/2, focus_index/2]).
-export_type([focus_ring/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type focus_ring() :: {focus_ring, list(binary()), integer()}.
-file("src/etui/focus.gleam", 37).
?DOC(
" Create a focus ring from a list of slot IDs.\n"
" The first slot starts focused. Empty list creates an inert ring.\n"
).
-spec focus_new(list(binary())) -> focus_ring().
focus_new(Ids) ->
{focus_ring, Ids, 0}.
-file("src/etui/focus.gleam", 116).
-spec get_at(list(binary()), integer()) -> {ok, binary()} | {error, nil}.
get_at(Lst, Idx) ->
case Idx of
I when I < 0 ->
{error, nil};
0 ->
case Lst of
[H | _] ->
{ok, H};
[] ->
{error, nil}
end;
_ ->
case Lst of
[] ->
{error, nil};
[_ | Rest] ->
get_at(Rest, Idx - 1)
end
end.
-file("src/etui/focus.gleam", 45).
?DOC(" ID of the currently focused slot, or `None` if the ring is empty.\n").
-spec focused(focus_ring()) -> {ok, binary()} | {error, nil}.
focused(Ring) ->
get_at(erlang:element(2, Ring), erlang:element(3, Ring)).
-file("src/etui/focus.gleam", 50).
?DOC(" `True` if `id` is the currently focused slot.\n").
-spec is_focused(focus_ring(), binary()) -> boolean().
is_focused(Ring, Id) ->
case focused(Ring) of
{ok, Current_id} ->
Current_id =:= Id;
{error, _} ->
false
end.
-file("src/etui/focus.gleam", 58).
?DOC(" 0-based index of the currently focused slot.\n").
-spec current_index(focus_ring()) -> integer().
current_index(Ring) ->
erlang:element(3, Ring).
-file("src/etui/focus.gleam", 63).
?DOC(" Total number of slots in the ring.\n").
-spec size(focus_ring()) -> integer().
size(Ring) ->
erlang:length(erlang:element(2, Ring)).
-file("src/etui/focus.gleam", 143).
-spec unwrap_zero({ok, integer()} | {error, nil}) -> integer().
unwrap_zero(R) ->
case R of
{ok, N} ->
N;
{error, _} ->
0
end.
-file("src/etui/focus.gleam", 71).
?DOC(" Move focus to the next slot (wraps around).\n").
-spec focus_next(focus_ring()) -> focus_ring().
focus_next(Ring) ->
N = erlang:length(erlang:element(2, Ring)),
case N of
0 ->
Ring;
_ ->
{focus_ring,
erlang:element(2, Ring),
begin
_pipe = (erlang:element(3, Ring) + 1),
_pipe@1 = gleam@int:modulo(_pipe, N),
unwrap_zero(_pipe@1)
end}
end.
-file("src/etui/focus.gleam", 84).
?DOC(" Move focus to the previous slot (wraps around).\n").
-spec focus_prev(focus_ring()) -> focus_ring().
focus_prev(Ring) ->
N = erlang:length(erlang:element(2, Ring)),
case N of
0 ->
Ring;
_ ->
{focus_ring,
erlang:element(2, Ring),
begin
_pipe = ((erlang:element(3, Ring) + N) - 1),
_pipe@1 = gleam@int:modulo(_pipe, N),
unwrap_zero(_pipe@1)
end}
end.
-file("src/etui/focus.gleam", 132).
-spec index_of(list(binary()), binary(), integer()) -> {ok, integer()} |
{error, nil}.
index_of(Lst, Target, Acc) ->
case Lst of
[] ->
{error, nil};
[H | Rest] ->
case H =:= Target of
true ->
{ok, Acc};
false ->
index_of(Rest, Target, Acc + 1)
end
end.
-file("src/etui/focus.gleam", 97).
?DOC(" Move focus to the slot with the given `id`. No-op if `id` not found.\n").
-spec focus_id(focus_ring(), binary()) -> focus_ring().
focus_id(Ring, Id) ->
case index_of(erlang:element(2, Ring), Id, 0) of
{ok, I} ->
{focus_ring, erlang:element(2, Ring), I};
{error, _} ->
Ring
end.
-file("src/etui/focus.gleam", 105).
?DOC(" Move focus to the slot at the given index (clamped to valid range).\n").
-spec focus_index(focus_ring(), integer()) -> focus_ring().
focus_index(Ring, Idx) ->
N = erlang:length(erlang:element(2, Ring)),
case N of
0 ->
Ring;
_ ->
{focus_ring,
erlang:element(2, Ring),
gleam@int:clamp(Idx, 0, N - 1)}
end.