-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.