farben_macros/lib.rs
1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{LitStr, parse_macro_input};
4
5/// Parses and colorizes a farben markup string at compile time.
6///
7/// Tokenizes and renders the input at compile time, emitting the final ANSI-escaped
8/// string as a string literal baked into the binary. Invalid markup produces a
9/// compiler error at the call site.
10///
11/// # Examples
12///
13/// ```rust
14/// use farben_macros::color;
15/// println!("{}", color!("[bold red]Hello!"));
16/// ```
17#[proc_macro]
18pub fn color(input: TokenStream) -> TokenStream {
19 let input = parse_macro_input!(input as LitStr);
20 let value = input.value();
21 let tokens = match farben_core::lexer::tokenize(&value) {
22 Ok(t) => t,
23 Err(e) => {
24 let msg = e.to_string();
25 return syn::Error::new_spanned(&input, msg)
26 .to_compile_error()
27 .into();
28 }
29 };
30 let result = format!("{}\x1b[0m", farben_core::parser::render(tokens));
31 quote! { #result }.into()
32}
33
34/// Parses and colorizes a farben markup string at compile time, without appending a
35/// trailing SGR reset.
36///
37/// Behaves identically to [`color!`] except the final `\x1b[0m` reset is omitted.
38/// Styles applied by this macro bleed into subsequent terminal output, making it
39/// useful for chaining multiple colored segments where the style should carry forward.
40///
41/// Invalid markup produces a compiler error at the call site.
42///
43/// # Examples
44///
45/// ```rust
46/// use farben_macros::colorb;
47/// // Style bleeds — subsequent output inherits bold red until a reset is issued.
48/// print!("{}", colorb!("[bold red]Warning: "));
49/// println!("this text is still bold red");
50/// ```
51#[proc_macro]
52pub fn colorb(input: TokenStream) -> TokenStream {
53 let input = parse_macro_input!(input as LitStr);
54 let value = input.value();
55 let tokens = match farben_core::lexer::tokenize(&value) {
56 Ok(t) => t,
57 Err(e) => {
58 let msg = e.to_string();
59 return syn::Error::new_spanned(&input, msg)
60 .to_compile_error()
61 .into();
62 }
63 };
64 let result = farben_core::parser::render(tokens);
65 quote! { #result }.into()
66}
67
68/// Validates farben markup at compile time and returns the original string literal unchanged.
69///
70/// On success, emits the input string literal as-is. On failure, emits a compiler error
71/// at the call site. Used internally by `color_fmt!`, `cprint!`, and `cprintln!` to validate
72/// the format string before runtime processing with format arguments.
73///
74/// This macro is part of the internal API. Prefer [`color!`] for static strings or
75/// [`color_fmt!`] for strings with format arguments.
76#[proc_macro]
77pub fn validate_color(input: TokenStream) -> TokenStream {
78 let input = parse_macro_input!(input as LitStr);
79 let value = input.value();
80
81 match farben_core::lexer::tokenize(&value) {
82 Ok(_) => quote! { #input }.into(),
83 Err(e) => {
84 let msg = e.to_string();
85 syn::Error::new_spanned(&input, msg)
86 .to_compile_error()
87 .into()
88 }
89 }
90}