-module(spruce@style).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/spruce/style.gleam").
-export([new/0, fg/2, bg/2, complete/3, adaptive/2, bold/1, dim/1, italic/1, underline/1, strikethrough/1, reverse/1, faint/1, inline/1, render/3]).
-export_type([color/0, basic_candidate/0, rgb_value/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.
?MODULEDOC(
" Composable ANSI styling helpers.\n"
"\n"
" A `Style` is an immutable value built with `new` and refined through piped\n"
" combinators such as `fg`, `bold`, and `underline`. Apply it to text with\n"
" `render`, which downgrades or drops colors to match the context's color\n"
" level and resolves adaptive colors against its background.\n"
"\n"
" ```gleam\n"
" import spruce\n"
" import spruce/style\n"
"\n"
" pub fn main() {\n"
" let sp = spruce.detect()\n"
" let heading = style.new() |> style.fg(style.Cyan) |> style.bold\n"
" echo style.render(sp, heading, \"Hello\")\n"
" }\n"
" ```\n"
).
-type color() :: black |
red |
green |
yellow |
blue |
magenta |
cyan |
white |
gray |
bright_red |
bright_green |
bright_yellow |
bright_blue |
bright_magenta |
bright_cyan |
bright_white |
{rgb, integer(), integer(), integer()} |
{hex, integer()} |
{ansi256, integer()} |
{complete, color(), color(), color()} |
{adaptive, color(), color()}.
-type basic_candidate() :: {basic_candidate, color(), rgb_value()}.
-type rgb_value() :: {rgb_value, integer(), integer(), integer()}.
-opaque style() :: {style,
gleam@option:option(color()),
gleam@option:option(color()),
boolean(),
boolean(),
boolean(),
boolean(),
boolean(),
boolean(),
boolean(),
boolean()}.
-file("src/spruce/style.gleam", 85).
?DOC(" Create an empty style with no color and no attributes set.\n").
-spec new() -> style().
new() ->
{style, none, none, false, false, false, false, false, false, false, false}.
-file("src/spruce/style.gleam", 101).
?DOC(" Set the foreground (text) color.\n").
-spec fg(style(), color()) -> style().
fg(Style, Color) ->
{style,
{some, Color},
erlang:element(3, Style),
erlang:element(4, Style),
erlang:element(5, Style),
erlang:element(6, Style),
erlang:element(7, Style),
erlang:element(8, Style),
erlang:element(9, Style),
erlang:element(10, Style),
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 106).
?DOC(" Set the background color.\n").
-spec bg(style(), color()) -> style().
bg(Style, Color) ->
{style,
erlang:element(2, Style),
{some, Color},
erlang:element(4, Style),
erlang:element(5, Style),
erlang:element(6, Style),
erlang:element(7, Style),
erlang:element(8, Style),
erlang:element(9, Style),
erlang:element(10, Style),
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 113).
?DOC(
" Build a color with an explicit variant per color level: `ansi` for basic\n"
" terminals, `ansi256` for 256-color, and `truecolor` for truecolor. The\n"
" level detected in the context selects which variant is used at render time.\n"
).
-spec complete(color(), color(), color()) -> color().
complete(Ansi, Ansi256, Truecolor) ->
{complete, Ansi, Ansi256, Truecolor}.
-file("src/spruce/style.gleam", 125).
?DOC(
" Build a color that adapts to the terminal background: `light` is used on a\n"
" light background, `dark` on a dark (or `Unknown`) background. Each side may\n"
" be any `Color`, including `complete`, so this also covers\n"
" \"complete-adaptive\" colors. Resolved against `spruce.background` at render.\n"
).
-spec adaptive(color(), color()) -> color().
adaptive(Light, Dark) ->
{adaptive, Light, Dark}.
-file("src/spruce/style.gleam", 130).
?DOC(" Enable bold text.\n").
-spec bold(style()) -> style().
bold(Style) ->
{style,
erlang:element(2, Style),
erlang:element(3, Style),
true,
erlang:element(5, Style),
erlang:element(6, Style),
erlang:element(7, Style),
erlang:element(8, Style),
erlang:element(9, Style),
erlang:element(10, Style),
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 135).
?DOC(" Enable dim (faint) text.\n").
-spec dim(style()) -> style().
dim(Style) ->
{style,
erlang:element(2, Style),
erlang:element(3, Style),
erlang:element(4, Style),
true,
erlang:element(6, Style),
erlang:element(7, Style),
erlang:element(8, Style),
erlang:element(9, Style),
erlang:element(10, Style),
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 140).
?DOC(" Enable italic text.\n").
-spec italic(style()) -> style().
italic(Style) ->
{style,
erlang:element(2, Style),
erlang:element(3, Style),
erlang:element(4, Style),
erlang:element(5, Style),
true,
erlang:element(7, Style),
erlang:element(8, Style),
erlang:element(9, Style),
erlang:element(10, Style),
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 145).
?DOC(" Enable underlined text.\n").
-spec underline(style()) -> style().
underline(Style) ->
{style,
erlang:element(2, Style),
erlang:element(3, Style),
erlang:element(4, Style),
erlang:element(5, Style),
erlang:element(6, Style),
true,
erlang:element(8, Style),
erlang:element(9, Style),
erlang:element(10, Style),
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 150).
?DOC(" Enable strikethrough text.\n").
-spec strikethrough(style()) -> style().
strikethrough(Style) ->
{style,
erlang:element(2, Style),
erlang:element(3, Style),
erlang:element(4, Style),
erlang:element(5, Style),
erlang:element(6, Style),
erlang:element(7, Style),
true,
erlang:element(9, Style),
erlang:element(10, Style),
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 155).
?DOC(" Enable reverse video, swapping the foreground and background colors.\n").
-spec reverse(style()) -> style().
reverse(Style) ->
{style,
erlang:element(2, Style),
erlang:element(3, Style),
erlang:element(4, Style),
erlang:element(5, Style),
erlang:element(6, Style),
erlang:element(7, Style),
erlang:element(8, Style),
true,
erlang:element(10, Style),
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 160).
?DOC(" Enable faint text. This is an alias for `dim`.\n").
-spec faint(style()) -> style().
faint(Style) ->
{style,
erlang:element(2, Style),
erlang:element(3, Style),
erlang:element(4, Style),
erlang:element(5, Style),
erlang:element(6, Style),
erlang:element(7, Style),
erlang:element(8, Style),
erlang:element(9, Style),
true,
erlang:element(11, Style)}.
-file("src/spruce/style.gleam", 166).
?DOC(
" Collapse newlines in the text to single spaces when rendering, keeping a\n"
" styled value on one line.\n"
).
-spec inline(style()) -> style().
inline(Style) ->
{style,
erlang:element(2, Style),
erlang:element(3, Style),
erlang:element(4, Style),
erlang:element(5, Style),
erlang:element(6, Style),
erlang:element(7, Style),
erlang:element(8, Style),
erlang:element(9, Style),
erlang:element(10, Style),
true}.
-file("src/spruce/style.gleam", 632).
-spec render_faint(binary(), boolean()) -> binary().
render_faint(Text, Enabled) ->
gleam@bool:guard(
not Enabled,
Text,
fun() -> gleam_community@ansi:dim(Text) end
).
-file("src/spruce/style.gleam", 627).
-spec render_reverse(binary(), boolean()) -> binary().
render_reverse(Text, Enabled) ->
gleam@bool:guard(
not Enabled,
Text,
fun() -> gleam_community@ansi:inverse(Text) end
).
-file("src/spruce/style.gleam", 622).
-spec render_strikethrough(binary(), boolean()) -> binary().
render_strikethrough(Text, Enabled) ->
gleam@bool:guard(
not Enabled,
Text,
fun() -> gleam_community@ansi:strikethrough(Text) end
).
-file("src/spruce/style.gleam", 617).
-spec render_underline(binary(), boolean()) -> binary().
render_underline(Text, Enabled) ->
gleam@bool:guard(
not Enabled,
Text,
fun() -> gleam_community@ansi:underline(Text) end
).
-file("src/spruce/style.gleam", 612).
-spec render_italic(binary(), boolean()) -> binary().
render_italic(Text, Enabled) ->
gleam@bool:guard(
not Enabled,
Text,
fun() -> gleam_community@ansi:italic(Text) end
).
-file("src/spruce/style.gleam", 607).
-spec render_dim(binary(), boolean()) -> binary().
render_dim(Text, Enabled) ->
gleam@bool:guard(
not Enabled,
Text,
fun() -> gleam_community@ansi:dim(Text) end
).
-file("src/spruce/style.gleam", 602).
-spec render_bold(binary(), boolean()) -> binary().
render_bold(Text, Enabled) ->
gleam@bool:guard(
not Enabled,
Text,
fun() -> gleam_community@ansi:bold(Text) end
).
-file("src/spruce/style.gleam", 397).
-spec choose_complete_color(color(), color(), color(), tty:color_level()) -> color().
choose_complete_color(Ansi, Ansi256, Truecolor, Color_level) ->
case Color_level of
basic ->
Ansi;
ansi256 ->
Ansi256;
true_color ->
Truecolor;
no_color ->
Ansi
end.
-file("src/spruce/style.gleam", 430).
-spec clamp_component(integer()) -> integer().
clamp_component(Value) ->
gleam@int:clamp(Value, 0, 255).
-file("src/spruce/style.gleam", 425).
-spec clamp_rgb(rgb_value()) -> rgb_value().
clamp_rgb(Rgb) ->
{rgb_value, R, G, B} = Rgb,
{rgb_value, clamp_component(R), clamp_component(G), clamp_component(B)}.
-file("src/spruce/style.gleam", 458).
-spec distance_squared(rgb_value(), rgb_value()) -> integer().
distance_squared(Left, Right) ->
{rgb_value, Left_r, Left_g, Left_b} = clamp_rgb(Left),
{rgb_value, Right_r, Right_g, Right_b} = clamp_rgb(Right),
Red_distance = Left_r - Right_r,
Green_distance = Left_g - Right_g,
Blue_distance = Left_b - Right_b,
((Red_distance * Red_distance) + (Green_distance * Green_distance)) + (Blue_distance
* Blue_distance).
-file("src/spruce/style.gleam", 453).
-spec candidate_distance(basic_candidate(), rgb_value()) -> integer().
candidate_distance(Candidate, Rgb) ->
{basic_candidate, _, Candidate_rgb} = Candidate,
distance_squared(Candidate_rgb, Rgb).
-file("src/spruce/style.gleam", 472).
-spec basic_candidates() -> list(basic_candidate()).
basic_candidates() ->
[{basic_candidate, black, {rgb_value, 0, 0, 0}},
{basic_candidate, red, {rgb_value, 128, 0, 0}},
{basic_candidate, green, {rgb_value, 0, 128, 0}},
{basic_candidate, yellow, {rgb_value, 128, 128, 0}},
{basic_candidate, blue, {rgb_value, 0, 0, 128}},
{basic_candidate, magenta, {rgb_value, 128, 0, 128}},
{basic_candidate, cyan, {rgb_value, 0, 128, 128}},
{basic_candidate, white, {rgb_value, 192, 192, 192}},
{basic_candidate, gray, {rgb_value, 128, 128, 128}},
{basic_candidate, bright_red, {rgb_value, 255, 0, 0}},
{basic_candidate, bright_green, {rgb_value, 0, 255, 0}},
{basic_candidate, bright_yellow, {rgb_value, 255, 255, 0}},
{basic_candidate, bright_blue, {rgb_value, 0, 0, 255}},
{basic_candidate, bright_magenta, {rgb_value, 255, 0, 255}},
{basic_candidate, bright_cyan, {rgb_value, 0, 255, 255}},
{basic_candidate, bright_white, {rgb_value, 255, 255, 255}}].
-file("src/spruce/style.gleam", 434).
-spec nearest_basic_color(rgb_value()) -> color().
nearest_basic_color(Rgb) ->
case basic_candidates() of
[] ->
black;
[First | Rest] ->
Best@1 = gleam@list:fold(
Rest,
First,
fun(Best, Candidate) ->
case candidate_distance(Candidate, Rgb) < candidate_distance(
Best,
Rgb
) of
true ->
Candidate;
false ->
Best
end
end
),
{basic_candidate, Color, _} = Best@1,
Color
end.
-file("src/spruce/style.gleam", 393).
-spec clamp_ansi256_index(integer()) -> integer().
clamp_ansi256_index(Index) ->
gleam@int:clamp(Index, 0, 255).
-file("src/spruce/style.gleam", 388).
-spec render_bg_ansi256_sequence(binary(), integer()) -> binary().
render_bg_ansi256_sequence(Text, Index) ->
Index@1 = clamp_ansi256_index(Index),
<<<<<<<<"\x{001b}[48;5;"/utf8, (erlang:integer_to_binary(Index@1))/binary>>/binary,
"m"/utf8>>/binary,
Text/binary>>/binary,
"\x{001b}[49m"/utf8>>.
-file("src/spruce/style.gleam", 420).
-spec rgb_to_hex(rgb_value()) -> integer().
rgb_to_hex(Rgb) ->
{rgb_value, R, G, B} = clamp_rgb(Rgb),
((R * 16#10000) + (G * 16#100)) + B.
-file("src/spruce/style.gleam", 515).
-spec ansi256_cube_component(integer()) -> integer().
ansi256_cube_component(Value) ->
case Value of
0 ->
0;
_ ->
55 + (Value * 40)
end.
-file("src/spruce/style.gleam", 522).
-spec ansi256_basic_color(integer()) -> color().
ansi256_basic_color(Index) ->
case Index of
0 ->
black;
1 ->
red;
2 ->
green;
3 ->
yellow;
4 ->
blue;
5 ->
magenta;
6 ->
cyan;
7 ->
white;
8 ->
gray;
9 ->
bright_red;
10 ->
bright_green;
11 ->
bright_yellow;
12 ->
bright_blue;
13 ->
bright_magenta;
14 ->
bright_cyan;
_ ->
bright_white
end.
-file("src/spruce/style.gleam", 411).
-spec hex_to_rgb(integer()) -> rgb_value().
hex_to_rgb(Value) ->
Value@1 = gleam@int:clamp(Value, 0, 16#ffffff),
{rgb_value,
begin
_pipe = erlang:'bsr'(Value@1, 16),
erlang:'band'(_pipe, 16#ff)
end,
begin
_pipe@1 = erlang:'bsr'(Value@1, 8),
erlang:'band'(_pipe@1, 16#ff)
end,
erlang:'band'(Value@1, 16#ff)}.
-file("src/spruce/style.gleam", 543).
-spec basic_color_rgb(color()) -> rgb_value().
basic_color_rgb(Color) ->
case Color of
black ->
{rgb_value, 0, 0, 0};
red ->
{rgb_value, 128, 0, 0};
green ->
{rgb_value, 0, 128, 0};
yellow ->
{rgb_value, 128, 128, 0};
blue ->
{rgb_value, 0, 0, 128};
magenta ->
{rgb_value, 128, 0, 128};
cyan ->
{rgb_value, 0, 128, 128};
white ->
{rgb_value, 192, 192, 192};
gray ->
{rgb_value, 128, 128, 128};
bright_red ->
{rgb_value, 255, 0, 0};
bright_green ->
{rgb_value, 0, 255, 0};
bright_yellow ->
{rgb_value, 255, 255, 0};
bright_blue ->
{rgb_value, 0, 0, 255};
bright_magenta ->
{rgb_value, 255, 0, 255};
bright_cyan ->
{rgb_value, 0, 255, 255};
bright_white ->
{rgb_value, 255, 255, 255};
{rgb, R, G, B} ->
{rgb_value, R, G, B};
{hex, Value} ->
hex_to_rgb(Value);
{ansi256, Index} ->
ansi256_to_rgb(Index);
{complete, Ansi, _, _} ->
basic_color_rgb(Ansi);
{adaptive, _, Dark} ->
basic_color_rgb(Dark)
end.
-file("src/spruce/style.gleam", 493).
-spec ansi256_to_rgb(integer()) -> rgb_value().
ansi256_to_rgb(Index) ->
Index@1 = gleam@int:clamp(Index, 0, 255),
case Index@1 < 16 of
true ->
basic_color_rgb(ansi256_basic_color(Index@1));
false ->
case Index@1 < 232 of
true ->
Offset = Index@1 - 16,
{rgb_value,
ansi256_cube_component(Offset div 36),
ansi256_cube_component((Offset rem 36) div 6),
ansi256_cube_component(Offset rem 6)};
false ->
Gray = 8 + ((Index@1 - 232) * 10),
{rgb_value, Gray, Gray, Gray}
end
end.
-file("src/spruce/style.gleam", 592).
-spec rgb_to_ansi256_grayscale_index(rgb_value()) -> integer().
rgb_to_ansi256_grayscale_index(Rgb) ->
{rgb_value, R, G, B} = clamp_rgb(Rgb),
Average = ((R + G) + B) div 3,
232 + gleam@int:clamp(((Average - 8) + 5) div 10, 0, 23).
-file("src/spruce/style.gleam", 598).
-spec quantize_ansi256_cube_channel(integer()) -> integer().
quantize_ansi256_cube_channel(Value) ->
((clamp_component(Value) * 5) + 127) div 255.
-file("src/spruce/style.gleam", 582).
-spec rgb_to_ansi256_cube_index(rgb_value()) -> integer().
rgb_to_ansi256_cube_index(Rgb) ->
{rgb_value, R, G, B} = clamp_rgb(Rgb),
((16 + (36 * quantize_ansi256_cube_channel(R))) + (6 * quantize_ansi256_cube_channel(
G
)))
+ quantize_ansi256_cube_channel(B).
-file("src/spruce/style.gleam", 569).
-spec rgb_to_ansi256_index(rgb_value()) -> integer().
rgb_to_ansi256_index(Rgb) ->
Rgb@1 = clamp_rgb(Rgb),
Cube_index = rgb_to_ansi256_cube_index(Rgb@1),
Grayscale_index = rgb_to_ansi256_grayscale_index(Rgb@1),
Cube_rgb = ansi256_to_rgb(Cube_index),
Grayscale_rgb = ansi256_to_rgb(Grayscale_index),
case distance_squared(Grayscale_rgb, Rgb@1) < distance_squared(
Cube_rgb,
Rgb@1
) of
true ->
Grayscale_index;
false ->
Cube_index
end.
-file("src/spruce/style.gleam", 369).
-spec render_bg_ansi256(binary(), integer(), tty:color_level()) -> binary().
render_bg_ansi256(Text, Index, Color_level) ->
Rgb = ansi256_to_rgb(Index),
case Color_level of
true_color ->
gleam_community@ansi:bg_hex(Text, rgb_to_hex(Rgb));
ansi256 ->
render_bg_ansi256_sequence(Text, Index);
basic ->
render_bg_color(Text, nearest_basic_color(Rgb), Color_level);
no_color ->
render_bg_color(Text, nearest_basic_color(Rgb), Color_level)
end.
-file("src/spruce/style.gleam", 342).
-spec render_bg_rgb(binary(), rgb_value(), tty:color_level()) -> binary().
render_bg_rgb(Text, Rgb, Color_level) ->
case Color_level of
true_color ->
gleam_community@ansi:bg_hex(Text, rgb_to_hex(Rgb));
ansi256 ->
render_bg_ansi256_sequence(Text, rgb_to_ansi256_index(Rgb));
basic ->
render_bg_color(Text, nearest_basic_color(Rgb), Color_level);
no_color ->
render_bg_color(Text, nearest_basic_color(Rgb), Color_level)
end.
-file("src/spruce/style.gleam", 294).
-spec render_bg_color(binary(), color(), tty:color_level()) -> binary().
render_bg_color(Text, Color, Color_level) ->
case Color of
black ->
gleam_community@ansi:bg_black(Text);
red ->
gleam_community@ansi:bg_red(Text);
green ->
gleam_community@ansi:bg_green(Text);
yellow ->
gleam_community@ansi:bg_yellow(Text);
blue ->
gleam_community@ansi:bg_blue(Text);
magenta ->
gleam_community@ansi:bg_magenta(Text);
cyan ->
gleam_community@ansi:bg_cyan(Text);
white ->
gleam_community@ansi:bg_white(Text);
gray ->
gleam_community@ansi:bg_bright_black(Text);
bright_red ->
gleam_community@ansi:bg_bright_red(Text);
bright_green ->
gleam_community@ansi:bg_bright_green(Text);
bright_yellow ->
gleam_community@ansi:bg_bright_yellow(Text);
bright_blue ->
gleam_community@ansi:bg_bright_blue(Text);
bright_magenta ->
gleam_community@ansi:bg_bright_magenta(Text);
bright_cyan ->
gleam_community@ansi:bg_bright_cyan(Text);
bright_white ->
gleam_community@ansi:bg_bright_white(Text);
{rgb, R, G, B} ->
render_bg_rgb(Text, {rgb_value, R, G, B}, Color_level);
{hex, Value} ->
render_bg_rgb(Text, hex_to_rgb(Value), Color_level);
{ansi256, Index} ->
render_bg_ansi256(Text, Index, Color_level);
{complete, Ansi, Ansi256, Truecolor} ->
render_bg_color(
Text,
choose_complete_color(Ansi, Ansi256, Truecolor, Color_level),
Color_level
);
{adaptive, _, Dark} ->
render_bg_color(Text, Dark, Color_level)
end.
-file("src/spruce/style.gleam", 248).
-spec render_bg(binary(), gleam@option:option(color()), tty:color_level()) -> binary().
render_bg(Text, Color, Color_level) ->
case Color of
none ->
Text;
{some, Color@1} ->
render_bg_color(Text, Color@1, Color_level)
end.
-file("src/spruce/style.gleam", 383).
-spec render_fg_ansi256_sequence(binary(), integer()) -> binary().
render_fg_ansi256_sequence(Text, Index) ->
Index@1 = clamp_ansi256_index(Index),
<<<<<<<<"\x{001b}[38;5;"/utf8, (erlang:integer_to_binary(Index@1))/binary>>/binary,
"m"/utf8>>/binary,
Text/binary>>/binary,
"\x{001b}[39m"/utf8>>.
-file("src/spruce/style.gleam", 355).
-spec render_fg_ansi256(binary(), integer(), tty:color_level()) -> binary().
render_fg_ansi256(Text, Index, Color_level) ->
Rgb = ansi256_to_rgb(Index),
case Color_level of
true_color ->
gleam_community@ansi:hex(Text, rgb_to_hex(Rgb));
ansi256 ->
render_fg_ansi256_sequence(Text, Index);
basic ->
render_fg_color(Text, nearest_basic_color(Rgb), Color_level);
no_color ->
render_fg_color(Text, nearest_basic_color(Rgb), Color_level)
end.
-file("src/spruce/style.gleam", 329).
-spec render_fg_rgb(binary(), rgb_value(), tty:color_level()) -> binary().
render_fg_rgb(Text, Rgb, Color_level) ->
case Color_level of
true_color ->
gleam_community@ansi:hex(Text, rgb_to_hex(Rgb));
ansi256 ->
render_fg_ansi256_sequence(Text, rgb_to_ansi256_index(Rgb));
basic ->
render_fg_color(Text, nearest_basic_color(Rgb), Color_level);
no_color ->
render_fg_color(Text, nearest_basic_color(Rgb), Color_level)
end.
-file("src/spruce/style.gleam", 259).
-spec render_fg_color(binary(), color(), tty:color_level()) -> binary().
render_fg_color(Text, Color, Color_level) ->
case Color of
black ->
gleam_community@ansi:black(Text);
red ->
gleam_community@ansi:red(Text);
green ->
gleam_community@ansi:green(Text);
yellow ->
gleam_community@ansi:yellow(Text);
blue ->
gleam_community@ansi:blue(Text);
magenta ->
gleam_community@ansi:magenta(Text);
cyan ->
gleam_community@ansi:cyan(Text);
white ->
gleam_community@ansi:white(Text);
gray ->
gleam_community@ansi:gray(Text);
bright_red ->
gleam_community@ansi:bright_red(Text);
bright_green ->
gleam_community@ansi:bright_green(Text);
bright_yellow ->
gleam_community@ansi:bright_yellow(Text);
bright_blue ->
gleam_community@ansi:bright_blue(Text);
bright_magenta ->
gleam_community@ansi:bright_magenta(Text);
bright_cyan ->
gleam_community@ansi:bright_cyan(Text);
bright_white ->
gleam_community@ansi:bright_white(Text);
{rgb, R, G, B} ->
render_fg_rgb(Text, {rgb_value, R, G, B}, Color_level);
{hex, Value} ->
render_fg_rgb(Text, hex_to_rgb(Value), Color_level);
{ansi256, Index} ->
render_fg_ansi256(Text, Index, Color_level);
{complete, Ansi, Ansi256, Truecolor} ->
render_fg_color(
Text,
choose_complete_color(Ansi, Ansi256, Truecolor, Color_level),
Color_level
);
{adaptive, _, Dark} ->
render_fg_color(Text, Dark, Color_level)
end.
-file("src/spruce/style.gleam", 237).
-spec render_fg(binary(), gleam@option:option(color()), tty:color_level()) -> binary().
render_fg(Text, Color, Color_level) ->
case Color of
none ->
Text;
{some, Color@1} ->
render_fg_color(Text, Color@1, Color_level)
end.
-file("src/spruce/style.gleam", 212).
?DOC(
" Resolve `Adaptive` colors against the terminal background, treating\n"
" `Unknown` as `Dark`. Recurses through `Complete` so adaptive colors may nest\n"
" inside complete colors (and vice versa).\n"
).
-spec resolve_adaptive(color(), tty:background()) -> color().
resolve_adaptive(Color, Background) ->
case Color of
{adaptive, Light, Dark} ->
case Background of
light ->
resolve_adaptive(Light, Background);
dark ->
resolve_adaptive(Dark, Background);
unknown ->
resolve_adaptive(Dark, Background)
end;
{complete, Ansi, Ansi256, Truecolor} ->
{complete,
resolve_adaptive(Ansi, Background),
resolve_adaptive(Ansi256, Background),
resolve_adaptive(Truecolor, Background)};
Other ->
Other
end.
-file("src/spruce/style.gleam", 199).
-spec resolve_adaptive_option(gleam@option:option(color()), tty:background()) -> gleam@option:option(color()).
resolve_adaptive_option(Color, Background) ->
case Color of
none ->
none;
{some, Color@1} ->
{some, resolve_adaptive(Color@1, Background)}
end.
-file("src/spruce/style.gleam", 229).
-spec render_inline(binary(), boolean()) -> binary().
render_inline(Text, Enabled) ->
gleam@bool:guard(not Enabled, Text, fun() -> _pipe = Text,
_pipe@1 = gleam@string:replace(_pipe, <<"\r\n"/utf8>>, <<" "/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"\n"/utf8>>, <<" "/utf8>>),
gleam@string:replace(_pipe@2, <<"\r"/utf8>>, <<" "/utf8>>) end).
-file("src/spruce/style.gleam", 176).
?DOC(
" Apply a style to `text`, returning the styled string.\n"
"\n"
" When the context does not support color, all color and attribute styling is\n"
" dropped (only the `inline` transform is applied). Colors the terminal cannot\n"
" represent are downgraded to the nearest available color, and `Adaptive`\n"
" colors are resolved against the context's background.\n"
).
-spec render(spruce:spruce(), style(), binary()) -> binary().
render(Sp, Style, Text) ->
Text@1 = render_inline(Text, erlang:element(11, Style)),
case spruce:supports_color(Sp) of
false ->
Text@1;
true ->
Background = spruce:background(Sp),
Fg = resolve_adaptive_option(erlang:element(2, Style), Background),
Bg = resolve_adaptive_option(erlang:element(3, Style), Background),
_pipe = Text@1,
_pipe@1 = render_fg(_pipe, Fg, spruce:color_level(Sp)),
_pipe@2 = render_bg(_pipe@1, Bg, spruce:color_level(Sp)),
_pipe@3 = render_bold(_pipe@2, erlang:element(4, Style)),
_pipe@4 = render_dim(_pipe@3, erlang:element(5, Style)),
_pipe@5 = render_italic(_pipe@4, erlang:element(6, Style)),
_pipe@6 = render_underline(_pipe@5, erlang:element(7, Style)),
_pipe@7 = render_strikethrough(_pipe@6, erlang:element(8, Style)),
_pipe@8 = render_reverse(_pipe@7, erlang:element(9, Style)),
render_faint(_pipe@8, erlang:element(10, Style))
end.