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