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::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
22 let tokens = match farben_core::lexer::tokenize(&value) {
23 Ok(t) => t,
24 Err(e) => {
25 let msg = e.to_string();
26 return syn::Error::new_spanned(&input, msg)
27 .to_compile_error()
28 .into();
29 }
30 };
31
32 let result = farben_core::parser::render(tokens);
33 quote! { #result }.into()
34}
35
36/// Validates farben markup at compile time and returns the original string literal unchanged.
37///
38/// On success, emits the input string literal as-is. On failure, emits a compiler error
39/// at the call site. Used internally by `color_fmt!` and `cprintln!` to validate the
40/// format string before runtime processing.
41///
42/// # Examples
43///
44/// ```rust
45/// // Valid markup passes through unchanged
46/// let s = farben_macros::validate_color!("[bold red]");
47/// assert_eq!(s, "[bold red]");
48/// ```
49#[proc_macro]
50pub fn validate_color(input: TokenStream) -> TokenStream {
51 let input = parse_macro_input!(input as LitStr);
52 let value = input.value();
53
54 match farben_core::lexer::tokenize(&value) {
55 Ok(_) => quote! { #input }.into(),
56 Err(e) => {
57 let msg = e.to_string();
58 syn::Error::new_spanned(&input, msg)
59 .to_compile_error()
60 .into()
61 }
62 }
63}