All notable changes to Farben will be documented here.
farben, farben-core, farben-macros, farben-build, farben-md. as frb / v, core, macros, build, md
frb0.19.0-alpha.3 core0.14.0-alpha.2
- New
inlinefeature that renders inline markdown-like syntax (backticks for code, underscores for italic, asterisks for bold) using thec*family, see this issue for more details. - To write a literal inline text, double them:
**literal**,__literal__,``literal``
- Custom style names can now be used as reset targets:
[style_name]reapplies all previously active styles in reverse order color_runtimeautomatically registers a default "code" style for wrapped text like`code`search_registryis now public in farben-core
- The
markdownfeature and related macros are now explicitly deprecated, will be removed after 0.19 stable
v0.19.0-alpha.2
cformat!andcformatb!macros as the new standard formatting interface, deprecatedcolor_fmt!- Expression match arms to
ansi_strip!andmarkup_strip!
- Prelude trimmed down: removed
try_color,strip_ansi,RegistryError,Style,insert_style,set_prefix, andcolor_fmt!. These remain accessible via explicit imports. md_fmt!,mdprint!,mdprintln!,mdeprint!,mdeprintln!,farben-mdwill be removed after 0.19 stable.
color_fmt!, usecformat!instead.
v0.19.0-alpha.1
- Escape syntax changed from
\[to[[for consistency with Rust's{{/}}format string escaping.\[is removed. ]]now produces a literal]. Multiple consecutive brackets follow greedy left-to-right pairing:]]]produces]].insert_stylenow returnsResult<(), RegistryError>instead of(). Style names containing[or]are rejected withRegistryError::InvalidName.farben's prelude andlib.rsnow exposes theRegistryErrorerror
\[no longer escapes brackets. Replace with[[.insert_stylesignature changed fromfn(name, style)tofn(name, style) -> Result<(), RegistryError>. Callers usingfarben-coredirectlFarben y must handle the result. Thestyle!()macro is unaffected.
- If you never used
\\[in markup strings and never calledinsert_styledirectly, you are safe. No changes needed. - Otherwise:
- Replace every
\\[in farben markup strings with[[.
// Before
cprintln!("Use \\[red] for red text.");
// After
cprintln!("Use [[red] for red text.");- If you call
insert_styledirectly fromfarben-core, handle the returnedResult.
// Before
farben_core::registry::insert_style("danger", style);
// After
farben_core::registry::insert_style("danger", style)
.unwrap_or_else(|e| panic!("{e}"));- The
style!()macro is unchanged.
Measured on the current alpha with Criterion. No v0.18 comparison is available for the new escape cases (they are new functionality); existing cases are compared against stored criterion baselines.
| Benchmark | Time | vs baseline |
|---|---|---|
| tokenize plain | 63.9 ns | +2.6% (extra ] scan per loop) |
| tokenize complex | 1.085 µs | within noise |
| render | 211 ns | -1.4% |
| pipeline (tokenize + render) | 1.361 µs | -10.0% |
| emphasis_to_ansi | 61.3 ns | -2.2% |
| color_to_ansi named | 65.5 ns | no change |
| color_to_ansi rgb | 269 ns | baseline |
| registry lookup via tokenize | 470 ns | baseline |
New escape baselines (no prior equivalent):
| Benchmark | Time |
|---|---|
tokenize [[ escape |
175 ns |
tokenize [[...]] symmetric |
200 ns |
| tokenize mixed escapes + tags | 705 ns |
tokenize bare ] in text |
197 ns |
tokenize ]] escape |
132 ns |
The only measurable cost from the ]] scanning addition is the +2.6% overhead on plain strings (no brackets). Strings with markup are unaffected within noise.
I'll try to increase the performance once this version is out of alpha.
Minor README update
Note
This implementation was suggested by redditor u/manpacket on the r/Rust subreddit. The post can be seen here. Thank you manpacket!
Important
This update introduces breaking changes to compile users. See the Breaking section down below and the migration guide.
strip_markup(input: &str) -> Stringinfarben-core::strip: strips farben markup tags from a string, returning plain text. Re-exported fromfarbenasfarben::strip_markup.markup_strip!macro that behaves the same asansi_strip!but usesstrip_markuprender_forced(tokens: Vec<Token>) -> Stringinfarben-core::parser: renders tokens to ANSI unconditionally, bypassingcolor_enabled(). Used internally by thecolor!andcolorb!proc macros to ensure the styled variant is always baked in regardless of the build environment.FarbenStrinfarben: a compile-time string pair holding both a styled (&'static str) and plain (&'static str) variant, resolved at the user's runtime viaFarbenStr::resolve()andDisplay.color_enabled()re-exported fromfarben: previously only accessible viafarben_core.- Doc comments of
init_styles()offarben-build.
color!andcolorb!now emit aFarbenStrinstead of a bare&'static str, baking both ANSI and plain variants into the binary and deferring theNO_COLOR/FORCE_COLOR/TTY decision to the end user's runtime.render()now delegates its ANSI rendering path torender_forced().
color!andcolorb!no longer return&'static str. Code storing the result as&strmust call.resolve()explicitly. Usage insidecprintln!,cprint!,cwrite!, and all other print/write macros is unaffected as they go throughDisplay.
- If you only use
cprintln!,cprint!, etc, then you are safe. No changes needed. - But when you directly use
color!and/orcolorb!, then follow the steps:
color!andcolorb!no longer return&'static str.- Change calls that use
color!,colorb!as an expression of&'static strto use.resolve() - Example:
use farben::prelude::*;
// change this
let previous: &str = color!("[bold red]Hi");
// to be
let new: &str = color!("[bold red]Hi").resolve();- Why? See changes above. The
color!,colorb!procedural macros now return a specialFarbenStrinstead of a&str.
coremodule, exposing some library internals for users that want to use them.- Documentation
LexError::display(input)infarben-core. Returns aLexErrorDisplaywrapper that formats the error with a caret pointing at the offending byte in the original input. Previously, this caret-style diagnostic was only available through the panic path infarben's macros; graceful callers oftry_colorcould only access the plain one-lineDisplayimpl. The new method exposes the rich diagnostic toResult-based error handling.
match try_color(input) {
Ok(s) => println!("{s}"),
Err(e) => eprintln!("{}", e.display(input)),
}active_stack(),set_active_stack(), andclear_active_stack()infarben-core— public API for managing the thread-local persisted style stack acrossrender()calls.farben-buildnow emitscargo:rerun-if-changeddirectives for each config file path, so edits to.frb.tomlfiles correctly invalidate cached builds without requiringcargo clean.
- Bleed-style prints (
cprintb!,cprintbln!) now correctly preserve the active style stack across calls. Previously,render()reset its internal stack between invocations, so a targeted reset like[/red]after a bleed call would emit a full reset and silently drop other active styles likebold. The stack is now persisted per-thread viathread_local!, resumed at the start of eachrender(), and cleared bycolor_runtime()after non-bleed prints append their trailing reset. farben-buildgenerated code now uses Rust'sDebugformatter to embed style and prefix names, properly escaping quotes, backslashes, and control characters. Previously, names containing special characters could produce invalid Rust in the generated file.
[farben-core 0.13.1 / farben-macros 0.5.2 / farben-build 0.1.1 / farben-md 0.2.2 / farben 0.17.1] - 2026-04-18 - DOCUMENTED!
- Comprehensive docstrings for all public items across the workspace!
- Fixed bugs
EmphasisType::Overline(SGR 53),EmphasisType::Invisible(SGR 8),EmphasisType::Reverse(SGR 7),EmphasisType::RapidBlink(SGR 6),EmphasisType::DoubleUnderline(SGR 21) — new emphasis variants with corresponding[overline],[invisible],[reverse],[rapid-blink],[double-underline]tags.debugmodule infarben-core—tokens_to_markup(tokens)reconstructs a farben markup string from a parsed token slice, collapsing consecutive tags into a single bracket.expand!(markup)infarben— diagnostic macro that prints three lines to stderr: the raw input, the fully expanded markup (registry styles resolved to their constituent tags), and the rendered ANSI escape string.
farben-coredependency infarbenbumped to0.13.0.
tokenizeno longer treats\x1b[(CSI ANSI escape sequences embedded in the input string) as tag openers. The byte preceding each[is now checked; if it isESC(0x1b), the character is pushed as plain text and the search continues. Previously, strings like"\x1b[31m"passed directly tocolor()or
farben::coremodule - exposesstyle_to_ansi()function for convertingfarben::Styleinto ANSI escape sequences.
anstyle!macro no longer requiresfarben_corecrate as a direct dependency for users, the macro now usesfarben::Styleinstead.- Tests no longer fail in non-TTY environments, the parser now respects the
FORCE_COLORenvironment variable in all tests.
anstylefeature flag - enables interoperability with theanstylecrate.anstyle_convmodule infarben-core- provides bidirectionalFromimplementations for converting between farben types (Color,NamedColor,Style) andanstyletypes (anstyle::Color,anstyle::AnsiColor,anstyle::Style).anstyle!macro infarben- parses farben markup and converts the result into ananstyle::Style. Requires theanstylefeature flag.anstylecrate added as an optional dependency to bothfarben-coreandfarben.
v0.15 is ~1.4x faster on average across the core pipeline (geometric mean of 7 benchmarks). ANSI encoding is the biggest winner: named color encoding is 1.9x faster, RGB encoding 1.7x faster, and emphasis sequences 1.6x faster. The full tokenize-to-render pipeline is 1.35x faster. All figures measured against the v0.14 criterion baseline on x86-64 Linux.
Important
Breaking changes in farben-core 0.11.0. See the Breaking Changes section below.
TagType::Reset(Option<Box<TagType>>)has been split into two variants.TagType::ResetAllreplacesReset(None)andTagType::ResetOne(Box<TagType>)replacesReset(Some(...)). Update all match arms that pattern-match onTagType::Reset.Token::Text(String)is nowToken::Text(Cow<'static, str>). Construction sites must useCow::Owned(string)for runtime strings orCow::Borrowed("literal")for static string literals. Pattern-matching andpush_strusage are unaffected, sinceCow<'static, str>deref-coerces to&str.
tokenizepre-allocates the tokenVecwith capacityinput.len() / 4, reducing reallocations for typical markup strings.parse_part(lexer) consolidates theansi(...)andrgb(...)prefix checks into a singlestrip_prefixcall each, removing a redundant scan of the tag string per call.- The style registry now stores
Arc<Style>internally. Each lookup clones anArc(one atomic increment) instead of cloning the fullStylestruct. emphasis_to_ansibypasses the intermediateVec<u8>and formats the escape sequence directly viaformat!, saving a heap allocation per emphasis tag.color_to_ansibypasses the intermediateVec<u8>for all color types, formatting the escape sequence directly. A new privatenamed_sgrconst fn mapsNamedColorto its base SGR code without a runtime lookup table.renderpre-allocates the output buffer with capacitytokens.len() * 16.- Release profile:
lto = "thin",codegen-units = 1,opt-level = 3added to rootCargo.toml, enabling cross-crate inlining in optimized builds. env.rsunsafe blocks now carry// SAFETY:comments documenting the invariants forisatty(1)(Unix) and theGetStdHandlequery path (Windows).
- Criterion benchmark suite in
farben-core/benches/farben_bench.rscovering: tokenize (plain and complex), render, full tokenize + render pipeline,emphasis_to_ansi,color_to_ansi(named and RGB), and registry lookup via tokenize. - Tests for
renderwith color disabled: verify that tag tokens are stripped and onlyToken::TextandToken::Tag(Prefix(...))content is emitted. - Edge case tests for
strip_ansi: empty string, bareESCbyte, sequences-only input, mixed content, RGB and ANSI256 sequences.
Measured against the v0.14 baseline using criterion 0.5.1 on x86-64 Linux (CachyOS, Rust 1.94.1):
| Benchmark | v0.14 | v0.15 | Change |
|---|---|---|---|
| tokenize plain | 61.1 ns | 50.6 ns | -22% |
| tokenize complex | 1.176 µs | 866.6 ns | -26% |
| render | 188.6 ns | 182.9 ns | -2% (within noise) |
| pipeline | 1.485 µs | 1.099 µs | -26% |
| emphasis_to_ansi | 91.1 ns | 56.0 ns | -37% |
| color_to_ansi named | 111.6 ns | 59.5 ns | -47% |
| color_to_ansi rgb | 367.3 ns | 214.3 ns | -43% |
| registry lookup | 361.3 ns | 346.6 ns | -5% |
[farben-build 0.1.0 / farben-macros 0.5.0 / farben-core 0.10.0 / farben-md 0.2.0 / farben 0.14.0] - 2026-04-05 - Global
farben-build0.1.0 - new build script helper crate. Callfarben_build::run()frombuild.rsto readfarben.frb.tomland generate two artifacts inOUT_DIR:farben_styles.rs- a Rust source file containing aninit_styles()function that registers all styles and prefixes at runtime. Include it viaload_styles!()at startup.farben_registry.lsv- a line-separated values file consumed byfarben-macrosproc macros at compile time, socolor!,colorb!, andvalidate_color!can see user-defined style tags. Usefarben_build::run_with(&[paths])to supply custom config file paths instead of the defaultfarben.frb.toml.- Config format: INI-like
[styles]and[prefixes]sections withkey = "value"pairs. Namespaced sections like[styles.myns]produce keys of the formmyns:key.
- Absolutely zero external dependencies added.
farben-macrosbumped to0.5.0. Every proc macro invocation now callsload_registry()at startup, which readsfarben_registry.lsvfromOUT_DIRand pre-populates the compile-time registry. As a result,color!("[myTag]text")now compiles successfully whenmyTagwas declared in a.frb.tomlconfig file.farben-corebumped to0.10.0. No new public API.farben-mdbumped to0.2.0, picking up thefarben-core 0.10.0dependency. No new public API.
- 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 the
COLORTERMandTERMenvironment variables to detect terminal color capabilities at runtime.
farben-coredependency bumped to0.9.0, picking up lossy degrading support.
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).
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'
- 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").
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 incolor_runtimeandvalidate_color- items that arepubonly to satisfy macro expansion, not intended for direct use.
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::*.
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!.
farben-coredependency bumped to0.7.0.
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.
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.
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.
prefix!macro no longer requires users to manually addfarben-coreas a dependency. Theset_prefixfunction is now re-exported throughfarbenand the macro expands viafarben::set_prefix.color_fmt!,cprint!,cprintln!,cprintb!, andcprintbln!(compile feature) no longer requirefarben-macrosas a direct dependency.validate_coloris now re-exported throughfarben.
tokenize_inner- unclosed delimiters (**,*,_,__,~~) were incorrectly producing styled tokens instead of falling back to plain text. The return type oftokenize_innerwas changed fromVec<MdToken>to(Vec<MdToken>, bool)so callers can distinguish between a found closing delimiter and end-of-input exhaustion.- Added
tokens_to_texthelper to correctly reconstruct plain text from partially parsed token trees when a closing delimiter is never found.
- Full unit test suite for
lexer.rsandrenderer.rscovering plain text, all six token types, nesting, unclosed delimiters, empty input, mixed content, and consecutive spans.
- Changed LICENSE to MIT/Apache-2.0
tokenize()- parses inline markdown into a recursiveMdTokentree. Supports**bold**,*italic*,_italic_,__underline__,~~strikethrough~~, and`inline code`. Unclosed delimiters are treated as plain text.render()- converts anMdTokentree into an ANSI-escaped string with a trailing reset. Nested spans are handled via an active style stack that re-emits surviving styles after each reset.MdToken- recursive token enum withText(String)as the only leaf node andBold,Italic,Underline,StrikethroughcarryingVec<MdToken>, andCode(String)for literal inline code.
markdown!()- proc macro that parses and renders inline markdown at compile time, emitting the final ANSI-escaped string as a string literal baked into the binary. Enabled via themarkdownfeature.
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.
style!()andprefix!()macros moved fromfarben-coretofarben, under theformatfeature flag.
markdownfeature - enables runtime markdown rendering viafarben-md.markdown-compilefeature - enables bothmarkdownandcompile, with compile-time markdown rendering viafarben-macros.
Markdown update. Introduces farben-md as a new workspace crate and wires
inline markdown rendering into the full Farben pipeline.
farben-md- new crate providing inline markdown tokenization and rendering. Depends onfarben-corefor ANSI encoding.color_to_ansi()andemphasis_to_ansi()made public infarben-core0.6.2, enablingfarben-mdto delegate ANSI encoding without reimplementing it.
- Made
style_to_ansi()andemphasis_to_ansi()public functions
style!()macro - moved fromfarben-coretofarben. Defines a named style in the global registry. Gated behind theformatfeature.prefix!()macro - moved fromfarben-coretofarben. Sets a prefix string on a previously defined named style. Gated behind theformatfeature.
style!()macro - moved tofarben. Users importing fromfarben-coredirectly should update to usefarben::style!()instead.prefix!()macro - moved tofarben. Users importing fromfarben-coredirectly should update to usefarben::prefix!()instead.
- Minor dependency update to
farben-core
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 fromcolor!. 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.
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.
- 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".
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 froms.contains("\x1b[0m")(always true due to trailing reset) to a full equality check against the expected output"\x1b[31mbefore\x1b[0mafter\x1b[0m".
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.
ansi::style_to_ansipromoted frompub(crate)topub. Users building on top offarben-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 byset_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.
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 fromcolor_to_ansiandemphasis_to_ansi;push_straccepts&strviaDerefdirectly.
Global Farben Update
- 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
TagType::Resetchanged from a unit variant toReset(Option<Box<TagType>>)- All existing
[/]full reset behavior is preserved viaReset(None)
- Fixed a bug where
colorb!()did not exist when using thecompilefeature
- Minor dependency update to
farben-core
- Minor dependency update to
farben-core
- Minor dependency update to
farben-core
- Bright ansi variants now exist, I guess.
Global Farben update due to changes to farben-core.
- 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!()
style_to_tags()no longer returns early onresetwhen a prefix is present, prefix is always emitted firststyle!()is now gated to theformatfeature
- Bug where
prefix!()interferes with actual color styling
- Minor dependency update to
farben-core
- Minor dependency update to
farben-core
Public Farben Update. Changes to farben-core, farben, and farben-macros is displayed here.
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
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
color!()now auto-resets.
- Dependency update to
farben_core colorb!()macro that bleeds
color!()now auto-resets
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 expansion
parse_tag()updated to flatten nestedVec<TagType>results fromparse_part()
cprintb!andcprintbln!for color bleeding printing.
- 100% documentation coverage
- 100% documentation coverage
cprint!()- prints farben-colored markup to stdout without a newline, behaves likeprint!cprintln!()- prints farben-colored markup to stdout with a trailing newline, behaves likeprintln!- Both macros support format args and compile-time validation when the
compilefeature is enabled
color!()- compile-time markup processing via optionalcompilefeature flagcolor_fmt!()- format args support with compile-time tag validation whencompilefeature is enabledvalidate_color!()- proc-macro that validates farben markup at compile timecolor_runtime()- internal runtime fallback used bycolor_fmt!bg:andfg:prefix support in color tags -[bg:red],[fg:white bg:blue]farben-coreandfarben-macrosas separate workspace cratescompilefeature flag for opt-in compile-time processing
- Internal logic moved to
farben-core color()replaced bycolor!proc-macro whencompilefeature is enabled
bg:andfg:prefix support for color tags -[bg:red],[fg:white], etc.Groundfield added toTagType::Colorvariant - nowTagType::Color { color, ground }- Background color support in
encode_color_sgrandcolor_to_ansi - New tests for background color parsing, tokenizing, and rendering
TagType::Color(Color)restructured toTagType::Color { color: Color, ground: Ground }
color!()- compile-time markup processing via optionalcompilefeature flagcolor_fmt!()- format args support with compile-time tag validation whencompilefeature is enabledvalidate_color!()- proc-macro that validates farben markup at compile time, emitting the original string literal unchanged on successcolor_runtime()- internal runtime fallback used bycolor_fmt!farben-core- extracted shared logic crate containing lexer, parser, ANSI encoding, and error typesfarben-macros- proc-macro crate powering compile-time processing- Cargo workspace setup with
farben,farben-core, andfarben-macrosas members compilefeature flag - opt-in compile-time processing viafarben-macros
color()is now replaced by thecolor!proc-macro when thecompilefeature is enabled- Internal logic extracted from
farbenintofarben-corefor shared use across crates
color()- colorizes a string using markup-like syntax, panics on invalid markuptry_color()- same ascolor()but returnsResult<String, LexError>- Named color tags:
[black],[red],[green],[yellow],[blue],[magenta],[cyan],[white] - 256-color palette support via
[ansi(n)] - 24-bit RGB support via
[rgb(r,g,b)] - Emphasis tags:
[bold],[dim],[italic],[underline],[blink],[strikethrough] - Multi-tag brackets:
[bold red],[italic rgb(255,0,0)] - Reset tag
[/]to clear all active styles - Escape sequence
\[to treat[as a literal character (replaced by[[in v0.18.2) LexErrorwith variantsUnclosedTag,InvalidTag,InvalidValue,InvalidArgumentCount- Foreground and background color support via
Groundenum - Automatic reset appended to all
color()andtry_color()output