Releases: razkar-studio/farben
v0.13.0 - I'm Lost!
Changelog
Farben is constantly updating. All notable changes to Farben will be documented here.
[0.9.0] - 2026-04-04 - farben-core
Added
- Lossy degrading. When the terminal does not support 24-bit true color, RGB values are
automatically degraded to the nearest ANSI256 color. When the terminal only supports
basic ANSI colors (8/16 colors), RGB and ANSI256 values are degraded to the nearest
named color. The degrader module uses theCOLORTERMandTERMenvironment variables
to detect terminal color capabilities at runtime. Opt-out-able vialossydefault feature. - Zero external dependencies added to core library internals.
[0.13.0] - 2026-04-04 - farben
Changed
farben-coredependency bumped to0.9.0, picking up lossy degrading support.- opt-out-able
lossydefault feature, piping tofarben-core's ownlossyfeature.
v0.12.0 - Write With Color
Changelog
Farben is constantly updating. Notable changes are documented here.
[0.12.0] - 2026-04-04 - farben
Added
cwrite!,cwriteln!,cwriteb!,cwritebln!- writer variants of the colored print macros.
Work with anyWriteimplementor. Useful for writing to files,Stringbuffers, or custom writers.
All four support the same markup features as the stdout variants (named colors, RGB, ANSI256, emphasis,
bleeding via thebvariants).
v0.11.0: Nice Errors Man
...shut up. Regardless,
Changelog
All notable changes to Farben will be documented here.
[0.8.0] - 2026-04-04 - farben-core
Added
RegistryErrorenum — a separate error type for registry operations (set_prefix,insert_style).
Split out fromLexErrorbecause registry errors have no source position (they occur outside markup
parsing). Has one variant:UnknownStyle(String).LexErrorDisplay<'a>struct — wraps a&LexErrorand the original&strinput to produce
compiler-style diagnostic output. Renders two lines: the full input string, then a caret (^)
aligned to the byte offset of the error. Example:| [bold unknown]text | ^^^^^^^ invalid tag: 'unknown'
Changed
- All
LexErrorvariants now carry aposition: usizefield (byte offset into the markup string).
Affected variants:UnclosedTag,InvalidTag,UnclosedValue,InvalidArgumentCount,
InvalidValue,InvalidResetTarget. Previously no variants stored position info. LexError::UnknownStyleremoved — registry errors now useRegistryError::UnknownStyleinstead.LexError'sDisplayimpl now includes position in every message
(e.g."invalid tag 'foo' at position 5").
[0.11.0] - 2026-04-04 - farben
Added
farben::preludemodule - the recommended import path going forward.use farben::prelude::*
brings every user-facing item into scope (functions, macros, types) gated by the same feature
flags as their definitions. Prefer this overuse farben::*, which also pulls in
color_runtimeandvalidate_color- items that arepubonly to satisfy macro expansion,
not intended for direct use.
Changed
farben-coredependency bumped to0.8.0, picking up position-awareLexErrorvariants and
the newLexErrorDisplaydiagnostic formatter.try_colorerror messages now include the byte
offset of the offending token.- All documentation and examples updated to use
use farben::prelude::*.
v0.10.0 - ANStripsI and Respects
Changelog
Farben is constantly shipping. Notable changes will be documented here.
[2026-04-04]
Added
ansi_strip!(...)— macro that acceptsformat!-style arguments, builds the string,
then strips all CSI ANSI escape sequences from the result. Non-CSIESCbytes pass
through unchanged. ReturnsString.strip_ansire-exported at thefarbencrate root fromfarben-core::strip::strip_ansi,
making it available viause farben::*and as the expansion target foransi_strip!.
Changed
farben-coredependency bumped to0.7.0.
[0.7.0] - 2026-04-04 - farben-core
Added
envmodule: runtime detection of whether ANSI color output should be enabled.
Respects theNO_COLORandFORCE_COLORenvironment variable conventions (in that
order), then falls back to TTY detection. Result is computed once per process and
cached viaOnceLock.color_enabled(): returns the cached bool for the current process.- TTY detection on Unix via
isatty(1); on Windows viaGetStdHandle+
GetConsoleMode;falseon all other targets.
stripmodule: utilities for removing ANSI escape sequences from strings.strip_ansi(input): strips CSI sequences (ESC [ ... <letter>) from a string
and returns plain text. Non-CSIESCbytes are passed through unchanged.
Useful for measuring display width, plain-text logging, or piping to tools that
do not interpret ANSI codes.
v0.9.0
v0.9.0: Errors, and nothing else.
All notable changes to Farben will be documented here.
[0.9.0] - 2026-03-20 - farben
Added
ceprint!,ceprintln!,ceprintb!,ceprintbln!— stderr variants of the colored print macros.mdeprint!,mdeprintln!— stderr variants of the inline markdown print macros.- Empty invocation support for all print macros.
cprintln!()now prints a bare newline,
cprint!()prints nothing — consistent with howprintln!()andprint!()behave in std.
Applies toceprint!,ceprintln!,mdprint!,mdprintln!,mdeprint!,mdeprintln!,
and all bleed variants.
Changed
src/lib.rssplit into focused modules:functions.rs,macros/color.rs,
macros/format.rs,macros/markdown.rs,macros/eprint.rs, andtests.rs.
No public API changes.
Mark That Down
[0.8.0] - 2026-03-17 - farben
Added
markdown()— runtime function that parses and renders inline markdown into
an ANSI-escaped string. Always succeeds. Enabled via themarkdownfeature.md_fmt!()— renders inline markdown with format arguments. Always runtime.
Enabled via themarkdownfeature.mdprint!()— prints inline markdown to stdout without a newline. Runtime
undermarkdown, compile-time undermarkdown-compile.mdprintln!()— prints inline markdown to stdout with a trailing newline.
Runtime undermarkdown, compile-time undermarkdown-compile.
Changed
style!()andprefix!()macros moved fromfarben-coretofarben,
under theformatfeature flag.
Added (features)
markdownfeature — enables runtime markdown rendering viafarben-md.markdown-compilefeature — enables bothmarkdownandcompile, with
compile-time markdown rendering viafarben-macros.
[0.8.0 / 0.4.0 / 0.1.0] - 2026-03-17 - Global
Markdown update. Introduces farben-md as a new workspace crate and wires
inline markdown rendering into the full Farben pipeline.
Added
farben-md— new crate providing inline markdown tokenization and rendering.
Depends onfarben-corefor ANSI encoding.color_to_ansi()andemphasis_to_ansi()made public infarben-core
0.6.2, enablingfarben-mdto delegate ANSI encoding without reimplementing it.
Dusting
Changelog
All notable changes to Farben will be documented here.
[0.3.0] - 2026-03-16
Changed
colorb!— replaced one-line stub doc ("Same ascolor!, but bleeds.") with a full
doc comment explaining what bleed means, when to use it, and how it differs from
color!. Includes a working example.validate_color!— removed misleading user-facing example. The macro is internal
infrastructure used bycolor_fmt!,cprint!, andcprintln!; the example implied
direct use was intended. Doc comment now explicitly marks it as internal and directs
users towardcolor!andcolor_fmt!instead.
[0.7.0] - 2026-03-16 - farben
Added
colorb— added missing doc comment explaining bleed behavior and when to use it
overcolor.color_fmt!(compile-time variant) — added missing doc comment. Previously the
runtime variant was documented but thecompile-feature counterpart had none.
Changed
- Crate-level doc comment revised: fixed grammar ("uses a markup-language-like syntax
to your string" → "applies a markup-like syntax to your strings") and capitalized
"German".
Fixed
cprint!(compile-time variant) — example referenced unbound variablemessage.
Addedlet message = "I don't know";to the example so it compiles as a doctest.cprintln!(compile-time variant) — example referenced unbound variableresult.
Addedlet result = "We did it!";to the example so it compiles as a doctest.test_try_color_inline_reset— strengthened assertion from
s.contains("\x1b[0m")(always true due to trailing reset) to a full equality check
against the expected output"\x1b[31mbefore\x1b[0mafter\x1b[0m".
[0.6.0] - 2026-03-16 - farben-core
Added
LexError::InvalidResetTarget— new error variant returned when a reset tag targets
something that cannot be reset (e.g.[//]or[/prefix]). Previously caused a panic.LexError::UnknownStyle— new error variant returned byregistry::set_prefixwhen
the given style name has not been registered.registry::set_prefixnow returnsResult<(), LexError>instead of(), allowing
callers to handle unknown style names without panicking.
Changed
ansi::style_to_ansipromoted frompub(crate)topub. Users building on top of
farben-corecan now call it directly to convert aStyleinto a combined SGR sequence.ansi::style_to_ansi— removed#[allow(unused)]attribute now that the function is
part of the public API.registry::prefix!macro updated to call.expect()on theResultreturned by
set_prefix, preserving the existing panic-on-misuse behavior at the macro callsite
while keeping the underlying function non-panicking.LexError::InvalidArgumentCountdisplay message improved from
"expected N, got M"to"expected N arguments, got M"for clarity.
Fixed
lexer::parse_part— replacedpanic!withErr(LexError::InvalidResetTarget)when
a reset tag targets aResetorPrefixnode. User-supplied markup can no longer crash
the process through thetry_colorpath.registry::set_prefix— replacedpanic!withErr(LexError::UnknownStyle)when the
style name is not found in the registry.errors.rs— corrected typo inUnclosedValuedisplay message:
"parantheses" → "parentheses".ansi::NamedColordoc comment — corrected "eight standard ANSI named colors" to
"sixteen ANSI named colors" (eight standard + eight bright variants).ansi::style_to_ansi— added a working doctest demonstrating bold + named color output.parser::render— removed unnecessary.as_str()calls onStringreturn values from
color_to_ansiandemphasis_to_ansi;push_straccepts&strviaDerefdirectly.
v0.6.0
0.6.0: Death To Inclusivity (IN RESETTING)
All notable changes to Farben will be documented here.
[0.6.0] - 2026-03-16
Global Farben Update
Added
- Specified resets —
[/bold],[/red],[/italic]etc. reset only the named style, leaving all other active styles intact TagType::Resetnow takesOption<Box<TagType>>—Nonefor full reset[/],Some(tag)for partial resetparser::rendernow maintains an active tag stack, re-emitting surviving styles after a partial reset- Panics if a partial reset targets
TagType::ResetorTagType::Prefix— both are invalid reset targets
Changed
TagType::Resetchanged from a unit variant toReset(Option<Box<TagType>>)- All existing
[/]full reset behavior is preserved viaReset(None)
Fixed
- Fixed a bug where
colorb!()did not exist when using thecompilefeature
[0.2.6] - 2026-03-16 - farben/farben-macros
Added
- Minor dependency update to
farben-core
v0.5.0
🎉 0.5.0: Halfway There!
All notable changes to Farben will be documented here.
[0.5.0] - 2026-03-15
Global Farben update due to changes to farben-core.
Added
- Added bugs
Style::prefixfield, optional text prepended before the style's ANSI codes when the style is appliedTagType::Prefix(String)variant, carries prefix text through the token pipeline to the rendererset_prefix(), sets the prefix on an existing registry entry, panics if the style is not foundprefix!()macro, user-facing API for binding a text prefix to a named stylestyle_to_tags()now emitsTagType::Prefixas the first tag when a prefix is presentparser::render()now handlesTagType::Prefixby appending the text directly to outputformatdefault feature, gates logic forstyle!()andprefix!()
Changed
style_to_tags()no longer returns early onresetwhen a prefix is present, prefix is always emitted firststyle!()is now gated to theformatfeature
[0.4.1] - 2026-03-15 - farben-core
Fixed
- Bug where
prefix!()interferes with actual color styling
[0.2.4] - 2026-03-15 - farben-macros
Added
- Minor dependency update to
farben-core
[0.2.3] - 2026-03-15 - farben-macros
Added
- Minor dependency update to
farben-core
v0.4.0
Changelog
All notable changes to Farben will be documented here.
[0.4.0] - 2026-03-15
Public Farben Update. Changes to farben-core, farben, and farben-macros is displayed here.
Added
Style::parse()— builds aStylefrom farben markup stringStyle::resetfield — whentrue, overrides all other style attributes with a full SGR resetregistrymodule — global style registry backed byOnceLock<Mutex<HashMap<String, Style>>>insert_style()— inserts a named style into the global registrysearch_registry()— looks up a named style from the global registrystyle!()macro — user-facing API for defining custom named stylesstyle_to_tags()— converts aStyleinto aVec<TagType>for lexer expansion- Custom tag resolution in
parse_part()— unknown tags now check the registry before returningInvalidTag parse_part()return type changed fromResult<TagType, LexError>toResult<Vec<TagType>, LexError>to support style expansioncolorb!()bleeds at compile-time with thecolorb()runtime counterpart
Changed
parse_tag()updated to flatten nestedVec<TagType>results fromparse_part()- All functions, when using
compilecan now benefit from compile-time processing instead of just validation
Fixed
color!()now auto-resets.