-module(etui@style).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/etui/style.gleam").
-export([none/0, bold/0, dim/0, italic/0, underline/0, blink/0, reverse/0, strikethrough/0, add/2, remove/2, has/2, is_none/1, modifier_equal/2, default_style/0, with_fg/2, with_bg/2, with_modifier/2, bold_style/0, reversed/0, italic_style/0, dim_style/0, underline_style/0, add_modifier/2, remove_modifier/2, color_from_hex/1, patch/2, ansi_fg/1, ansi_bg/1, ansi_modifier/1, ansi_reset/0]).
-export_type([color/0, modifier/0, style/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 color() :: default |
{indexed, integer()} |
{rgb, integer(), integer(), integer()}.
-opaque modifier() :: {modifier, integer()}.
-type style() :: {style, color(), color(), modifier()}.
-file("src/etui/style.gleam", 27).
?DOC(" No modifiers active.\n").
-spec none() -> modifier().
none() ->
{modifier, 0}.
-file("src/etui/style.gleam", 32).
?DOC(" Bold / increased intensity.\n").
-spec bold() -> modifier().
bold() ->
{modifier, 1}.
-file("src/etui/style.gleam", 37).
?DOC(" Dim / decreased intensity.\n").
-spec dim() -> modifier().
dim() ->
{modifier, 2}.
-file("src/etui/style.gleam", 42).
?DOC(" Italic text.\n").
-spec italic() -> modifier().
italic() ->
{modifier, 4}.
-file("src/etui/style.gleam", 47).
?DOC(" Underline.\n").
-spec underline() -> modifier().
underline() ->
{modifier, 8}.
-file("src/etui/style.gleam", 52).
?DOC(" Blinking text (terminal support varies).\n").
-spec blink() -> modifier().
blink() ->
{modifier, 16}.
-file("src/etui/style.gleam", 57).
?DOC(" Swap foreground and background colors.\n").
-spec reverse() -> modifier().
reverse() ->
{modifier, 32}.
-file("src/etui/style.gleam", 62).
?DOC(" Strikethrough.\n").
-spec strikethrough() -> modifier().
strikethrough() ->
{modifier, 64}.
-file("src/etui/style.gleam", 70).
?DOC(" Combine two modifiers (bitwise OR).\n").
-spec add(modifier(), modifier()) -> modifier().
add(A, B) ->
{modifier, erlang:'bor'(erlang:element(2, A), erlang:element(2, B))}.
-file("src/etui/style.gleam", 75).
?DOC(" Remove modifier bits from `a` that are set in `b`.\n").
-spec remove(modifier(), modifier()) -> modifier().
remove(A, B) ->
{modifier,
erlang:'band'(erlang:element(2, A), erlang:'bnot'(erlang:element(2, B)))}.
-file("src/etui/style.gleam", 80).
?DOC(" Check if `flag` bits are set in `m`.\n").
-spec has(modifier(), modifier()) -> boolean().
has(M, Flag) ->
erlang:'band'(erlang:element(2, M), erlang:element(2, Flag)) /= 0.
-file("src/etui/style.gleam", 85).
?DOC(" True when no modifier bits are set.\n").
-spec is_none(modifier()) -> boolean().
is_none(M) ->
erlang:element(2, M) =:= 0.
-file("src/etui/style.gleam", 90).
?DOC(" Structural equality for modifiers.\n").
-spec modifier_equal(modifier(), modifier()) -> boolean().
modifier_equal(A, B) ->
erlang:element(2, A) =:= erlang:element(2, B).
-file("src/etui/style.gleam", 103).
?DOC(" Default style: terminal colors, no modifiers.\n").
-spec default_style() -> style().
default_style() ->
{style, default, default, none()}.
-file("src/etui/style.gleam", 108).
?DOC(" Set foreground color on a style.\n").
-spec with_fg(style(), color()) -> style().
with_fg(S, Fg) ->
{style, Fg, erlang:element(3, S), erlang:element(4, S)}.
-file("src/etui/style.gleam", 113).
?DOC(" Set background color on a style.\n").
-spec with_bg(style(), color()) -> style().
with_bg(S, Bg) ->
{style, erlang:element(2, S), Bg, erlang:element(4, S)}.
-file("src/etui/style.gleam", 118).
?DOC(" Set modifier on a style.\n").
-spec with_modifier(style(), modifier()) -> style().
with_modifier(S, M) ->
{style, erlang:element(2, S), erlang:element(3, S), M}.
-file("src/etui/style.gleam", 123).
?DOC(" Default colors with bold modifier.\n").
-spec bold_style() -> style().
bold_style() ->
{style, default, default, bold()}.
-file("src/etui/style.gleam", 128).
?DOC(" Default colors with reverse modifier (swap fg/bg).\n").
-spec reversed() -> style().
reversed() ->
{style, default, default, reverse()}.
-file("src/etui/style.gleam", 133).
?DOC(" Default colors with italic modifier.\n").
-spec italic_style() -> style().
italic_style() ->
{style, default, default, italic()}.
-file("src/etui/style.gleam", 138).
?DOC(" Default colors with dim modifier.\n").
-spec dim_style() -> style().
dim_style() ->
{style, default, default, dim()}.
-file("src/etui/style.gleam", 143).
?DOC(" Default colors with underline modifier.\n").
-spec underline_style() -> style().
underline_style() ->
{style, default, default, underline()}.
-file("src/etui/style.gleam", 148).
?DOC(" Add a modifier to a `Style` (bitwise OR).\n").
-spec add_modifier(style(), modifier()) -> style().
add_modifier(S, M) ->
{style,
erlang:element(2, S),
erlang:element(3, S),
add(erlang:element(4, S), M)}.
-file("src/etui/style.gleam", 153).
?DOC(" Remove modifier bits from a `Style`.\n").
-spec remove_modifier(style(), modifier()) -> style().
remove_modifier(S, M) ->
{style,
erlang:element(2, S),
erlang:element(3, S),
remove(erlang:element(4, S), M)}.
-file("src/etui/style.gleam", 192).
-spec hex_digit(binary()) -> {ok, integer()} | {error, nil}.
hex_digit(C) ->
case C of
<<"0"/utf8>> ->
{ok, 0};
<<"1"/utf8>> ->
{ok, 1};
<<"2"/utf8>> ->
{ok, 2};
<<"3"/utf8>> ->
{ok, 3};
<<"4"/utf8>> ->
{ok, 4};
<<"5"/utf8>> ->
{ok, 5};
<<"6"/utf8>> ->
{ok, 6};
<<"7"/utf8>> ->
{ok, 7};
<<"8"/utf8>> ->
{ok, 8};
<<"9"/utf8>> ->
{ok, 9};
<<"a"/utf8>> ->
{ok, 10};
<<"A"/utf8>> ->
{ok, 10};
<<"b"/utf8>> ->
{ok, 11};
<<"B"/utf8>> ->
{ok, 11};
<<"c"/utf8>> ->
{ok, 12};
<<"C"/utf8>> ->
{ok, 12};
<<"d"/utf8>> ->
{ok, 13};
<<"D"/utf8>> ->
{ok, 13};
<<"e"/utf8>> ->
{ok, 14};
<<"E"/utf8>> ->
{ok, 14};
<<"f"/utf8>> ->
{ok, 15};
<<"F"/utf8>> ->
{ok, 15};
_ ->
{error, nil}
end.
-file("src/etui/style.gleam", 185).
-spec hex_pair(binary(), binary()) -> {ok, integer()} | {error, nil}.
hex_pair(Hi, Lo) ->
case {hex_digit(Hi), hex_digit(Lo)} of
{{ok, H}, {ok, L}} ->
{ok, (H * 16) + L};
{_, _} ->
{error, nil}
end.
-file("src/etui/style.gleam", 164).
?DOC(
" Parse an RGB color from a hex string (`\"#RRGGBB\"` or `\"RRGGBB\"`).\n"
" Returns `Error(Nil)` for malformed input.\n"
"\n"
" ```gleam\n"
" style.color_from_hex(\"#1e1e2e\") // Ok(Rgb(30, 30, 46))\n"
" style.color_from_hex(\"ff5555\") // Ok(Rgb(255, 85, 85))\n"
" ```\n"
).
-spec color_from_hex(binary()) -> {ok, color()} | {error, nil}.
color_from_hex(Hex) ->
S = case gleam_stdlib:string_starts_with(Hex, <<"#"/utf8>>) of
true ->
gleam@string:drop_start(Hex, 1);
false ->
Hex
end,
case string:length(S) =:= 6 of
false ->
{error, nil};
true ->
Chars = gleam@string:to_graphemes(S),
case Chars of
[R1, R2, G1, G2, B1, B2] ->
case {hex_pair(R1, R2), hex_pair(G1, G2), hex_pair(B1, B2)} of
{{ok, R}, {ok, G}, {ok, B}} ->
{ok, {rgb, R, G, B}};
{_, _, _} ->
{error, nil}
end;
_ ->
{error, nil}
end
end.
-file("src/etui/style.gleam", 217).
?DOC(
" Apply `over` on top of `base`. Default fg/bg fall back to `base`.\n"
" Modifier: if `over` has any bits set, they are OR'd into `base`;\n"
" `none()` in `over` means \"no modifier override\" (keep base).\n"
).
-spec patch(style(), style()) -> style().
patch(Base, Over) ->
Fg = case erlang:element(2, Over) of
default ->
erlang:element(2, Base);
C ->
C
end,
Bg = case erlang:element(3, Over) of
default ->
erlang:element(3, Base);
C@1 ->
C@1
end,
Modifier = case is_none(erlang:element(4, Over)) of
true ->
erlang:element(4, Base);
false ->
add(erlang:element(4, Base), erlang:element(4, Over))
end,
{style, Fg, Bg, Modifier}.
-file("src/etui/style.gleam", 237).
?DOC(" Foreground color escape sequence.\n").
-spec ansi_fg(color()) -> binary().
ansi_fg(Color) ->
case Color of
default ->
<<""/utf8>>;
{indexed, 0} ->
<<"\x{001B}[30m"/utf8>>;
{indexed, 1} ->
<<"\x{001B}[31m"/utf8>>;
{indexed, 2} ->
<<"\x{001B}[32m"/utf8>>;
{indexed, 3} ->
<<"\x{001B}[33m"/utf8>>;
{indexed, 4} ->
<<"\x{001B}[34m"/utf8>>;
{indexed, 5} ->
<<"\x{001B}[35m"/utf8>>;
{indexed, 6} ->
<<"\x{001B}[36m"/utf8>>;
{indexed, 7} ->
<<"\x{001B}[37m"/utf8>>;
{indexed, 8} ->
<<"\x{001B}[90m"/utf8>>;
{indexed, 9} ->
<<"\x{001B}[91m"/utf8>>;
{indexed, 10} ->
<<"\x{001B}[92m"/utf8>>;
{indexed, 11} ->
<<"\x{001B}[93m"/utf8>>;
{indexed, 12} ->
<<"\x{001B}[94m"/utf8>>;
{indexed, 13} ->
<<"\x{001B}[95m"/utf8>>;
{indexed, 14} ->
<<"\x{001B}[96m"/utf8>>;
{indexed, 15} ->
<<"\x{001B}[97m"/utf8>>;
{indexed, N} ->
<<<<"\x{001B}[38;5;"/utf8, (erlang:integer_to_binary(N))/binary>>/binary,
"m"/utf8>>;
{rgb, R, G, B} ->
<<<<<<<<<<<<"\x{001B}[38;2;"/utf8,
(erlang:integer_to_binary(R))/binary>>/binary,
";"/utf8>>/binary,
(erlang:integer_to_binary(G))/binary>>/binary,
";"/utf8>>/binary,
(erlang:integer_to_binary(B))/binary>>/binary,
"m"/utf8>>
end.
-file("src/etui/style.gleam", 269).
?DOC(" Background color escape sequence.\n").
-spec ansi_bg(color()) -> binary().
ansi_bg(Color) ->
case Color of
default ->
<<""/utf8>>;
{indexed, 0} ->
<<"\x{001B}[40m"/utf8>>;
{indexed, 1} ->
<<"\x{001B}[41m"/utf8>>;
{indexed, 2} ->
<<"\x{001B}[42m"/utf8>>;
{indexed, 3} ->
<<"\x{001B}[43m"/utf8>>;
{indexed, 4} ->
<<"\x{001B}[44m"/utf8>>;
{indexed, 5} ->
<<"\x{001B}[45m"/utf8>>;
{indexed, 6} ->
<<"\x{001B}[46m"/utf8>>;
{indexed, 7} ->
<<"\x{001B}[47m"/utf8>>;
{indexed, 8} ->
<<"\x{001B}[100m"/utf8>>;
{indexed, 9} ->
<<"\x{001B}[101m"/utf8>>;
{indexed, 10} ->
<<"\x{001B}[102m"/utf8>>;
{indexed, 11} ->
<<"\x{001B}[103m"/utf8>>;
{indexed, 12} ->
<<"\x{001B}[104m"/utf8>>;
{indexed, 13} ->
<<"\x{001B}[105m"/utf8>>;
{indexed, 14} ->
<<"\x{001B}[106m"/utf8>>;
{indexed, 15} ->
<<"\x{001B}[107m"/utf8>>;
{indexed, N} ->
<<<<"\x{001B}[48;5;"/utf8, (erlang:integer_to_binary(N))/binary>>/binary,
"m"/utf8>>;
{rgb, R, G, B} ->
<<<<<<<<<<<<"\x{001B}[48;2;"/utf8,
(erlang:integer_to_binary(R))/binary>>/binary,
";"/utf8>>/binary,
(erlang:integer_to_binary(G))/binary>>/binary,
";"/utf8>>/binary,
(erlang:integer_to_binary(B))/binary>>/binary,
"m"/utf8>>
end.
-file("src/etui/style.gleam", 301).
?DOC(" Text modifier escape sequence. Emits all active modifier bits.\n").
-spec ansi_modifier(modifier()) -> binary().
ansi_modifier(M) ->
case is_none(M) of
true ->
<<""/utf8>>;
false ->
Parts = [],
Parts@1 = case has(M, bold()) of
true ->
[<<"1"/utf8>> | Parts];
false ->
Parts
end,
Parts@2 = case has(M, dim()) of
true ->
[<<"2"/utf8>> | Parts@1];
false ->
Parts@1
end,
Parts@3 = case has(M, italic()) of
true ->
[<<"3"/utf8>> | Parts@2];
false ->
Parts@2
end,
Parts@4 = case has(M, underline()) of
true ->
[<<"4"/utf8>> | Parts@3];
false ->
Parts@3
end,
Parts@5 = case has(M, blink()) of
true ->
[<<"5"/utf8>> | Parts@4];
false ->
Parts@4
end,
Parts@6 = case has(M, reverse()) of
true ->
[<<"7"/utf8>> | Parts@5];
false ->
Parts@5
end,
Parts@7 = case has(M, strikethrough()) of
true ->
[<<"9"/utf8>> | Parts@6];
false ->
Parts@6
end,
<<<<"\x{001B}["/utf8,
(gleam@string:join(Parts@7, <<";"/utf8>>))/binary>>/binary,
"m"/utf8>>
end.
-file("src/etui/style.gleam", 340).
?DOC(" Reset all styles.\n").
-spec ansi_reset() -> binary().
ansi_reset() ->
<<"\x{001B}[0m"/utf8>>.