-module(spruce).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/spruce.gleam").
-export([detect/0, detect_stream/1, with_color_level/1, no_color/0, color_level/1, supports_color/1, background/1, with_background/2, depth/1, indented/1]).
-export_type([spruce/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(
" spruce — a terminal-UI kit for Gleam.\n"
"\n"
" spruce renders styled terminal output — colors, boxes, semantic message\n"
" lines, icons, deterministic hash-colors, ANSI-aware alignment, and\n"
" grouped/indented output — that automatically respects the terminal's color\n"
" support. It is logging-agnostic and targets both Erlang and JavaScript.\n"
"\n"
" ## The `Spruce` context\n"
"\n"
" Every render function takes an explicit `Spruce` value. The context carries\n"
" two things: the detected color level (so output is plain when color is\n"
" unsupported) and the current indent depth (so grouped output nests without\n"
" any global state).\n"
"\n"
" ```gleam\n"
" import spruce\n"
"\n"
" pub fn main() {\n"
" let sp = spruce.detect()\n"
" // pass `sp` to render functions in spruce/style, spruce/box, etc.\n"
" echo spruce.supports_color(sp)\n"
" }\n"
" ```\n"
"\n"
" Use `spruce.no_color()` in tests to get deterministic, escape-free output.\n"
).
-opaque spruce() :: {spruce, tty:color_level(), tty:background(), integer()}.
-file("src/spruce.gleam", 57).
?DOC(
" Build a context by auto-detecting the color support of standard output.\n"
"\n"
" Detection honors `NO_COLOR`, `FORCE_COLOR`, `TERM`, CI environment hints,\n"
" and TTY status (via the `tty` package), falling back to `NoColor` when\n"
" uncertain.\n"
).
-spec detect() -> spruce().
detect() ->
{spruce, tty:detect_color_level(stdout), tty:detect_background(stdout), 0}.
-file("src/spruce.gleam", 66).
?DOC(" Build a context by auto-detecting the color support of a specific stream.\n").
-spec detect_stream(tty:stream()) -> spruce().
detect_stream(Stream) ->
{spruce, tty:detect_color_level(Stream), tty:detect_background(Stream), 0}.
-file("src/spruce.gleam", 78).
?DOC(
" Build a context with an explicit color level, bypassing detection.\n"
" Useful for forcing a level in tests or honoring a user `--color` flag.\n"
" The background defaults to `Unknown` (treated as `Dark` by adaptive colors);\n"
" override it with `with_background`.\n"
).
-spec with_color_level(tty:color_level()) -> spruce().
with_color_level(Level) ->
{spruce, Level, unknown, 0}.
-file("src/spruce.gleam", 84).
?DOC(
" Build a context that never emits color. All output is plain text.\n"
" This is the recommended context for deterministic tests.\n"
).
-spec no_color() -> spruce().
no_color() ->
{spruce, no_color, unknown, 0}.
-file("src/spruce.gleam", 89).
?DOC(" Get the color level of a context.\n").
-spec color_level(spruce()) -> tty:color_level().
color_level(Sp) ->
erlang:element(2, Sp).
-file("src/spruce.gleam", 94).
?DOC(" Whether the context will emit any color (i.e. its level is not `NoColor`).\n").
-spec supports_color(spruce()) -> boolean().
supports_color(Sp) ->
erlang:element(2, Sp) /= no_color.
-file("src/spruce.gleam", 99).
?DOC(" Get the detected terminal background of a context.\n").
-spec background(spruce()) -> tty:background().
background(Sp) ->
erlang:element(3, Sp).
-file("src/spruce.gleam", 106).
?DOC(
" Return a copy of the context with an explicit terminal background, bypassing\n"
" detection. Useful for forcing light/dark adaptive colors in tests or honoring\n"
" a user `--background` flag.\n"
).
-spec with_background(spruce(), tty:background()) -> spruce().
with_background(Sp, Background) ->
{spruce, erlang:element(2, Sp), Background, erlang:element(4, Sp)}.
-file("src/spruce.gleam", 111).
?DOC(" Get the current indent depth of a context (0 at the top level).\n").
-spec depth(spruce()) -> integer().
depth(Sp) ->
erlang:element(4, Sp).
-file("src/spruce.gleam", 117).
?DOC(
" Return a copy of the context with its indent depth increased by one.\n"
" `spruce/group` uses this to hand a deeper context to grouped bodies.\n"
).
-spec indented(spruce()) -> spruce().
indented(Sp) ->
{spruce,
erlang:element(2, Sp),
erlang:element(3, Sp),
erlang:element(4, Sp) + 1}.