use litext::litext;
use proc_macro::TokenStream;
use quote::quote;
fn load_registry() {
let out_dir = std::env::var("OUT_DIR").unwrap_or_default();
let path = std::path::Path::new(&out_dir).join("farben_registry.lsv");
if let Ok(content) = std::fs::read_to_string(&path) {
let mut sections = content.splitn(2, "---\n");
let styles_section = sections.next().unwrap_or("");
let prefixes_section = sections.next().unwrap_or("");
for line in styles_section.lines() {
if line.is_empty() {
continue;
}
let (key, value) = line.split_once('=').unwrap();
farben_core::registry::insert_style(
key,
farben_core::ansi::Style::parse(format!("[{value}]"))
.unwrap_or_else(|e| panic!("farben: invalid style in registry '{key}': {e}")),
)
.unwrap_or_else(|e| panic!("farben: invalid style name in registry '{key}': {e}"));
}
for line in prefixes_section.lines() {
if line.is_empty() {
continue;
}
let (key, value) = line.split_once('=').unwrap();
farben_core::registry::set_prefix(key, value)
.unwrap_or_else(|e| panic!("farben: failure while setting prefix '{key}': {e}"));
}
}
}
#[proc_macro]
pub fn color(input: TokenStream) -> TokenStream {
load_registry();
let input = litext!(input as litext::LitStr);
let value = input.value();
let tokens = match farben_core::lexer::tokenize(value) {
Ok(t) => t,
Err(e) => {
let msg = e.to_string();
return comperr::error(input.span(), msg).into();
}
};
let styled = format!("{}\x1b[0m", farben_core::parser::render_forced(tokens));
let plain = farben_core::strip::strip_markup(input.value());
quote! {
::farben::FarbenStr { styled: #styled, plain: #plain }
}
.into()
}
#[proc_macro]
pub fn colorb(input: TokenStream) -> TokenStream {
load_registry();
let input = litext!(input as litext::LitStr);
let value = input.value();
let tokens = match farben_core::lexer::tokenize(value) {
Ok(t) => t,
Err(e) => {
let msg = e.to_string();
return comperr::error(input.span(), msg).into();
}
};
let styled = farben_core::parser::render_forced(tokens);
let plain = farben_core::strip::strip_markup(input.value());
quote! {
::farben::FarbenStr { styled: #styled, plain: #plain }
}
.into()
}
#[proc_macro]
pub fn validate_color(input: TokenStream) -> TokenStream {
load_registry();
let original = input.clone();
let input = litext!(input as litext::LitStr);
let value = input.value();
match farben_core::lexer::tokenize(value) {
Ok(_) => original,
Err(e) => {
let msg = e.to_string();
comperr::error(input.span(), msg).into()
}
}
}
#[cfg(feature = "markdown")]
#[deprecated]
#[proc_macro]
pub fn markdown(input: TokenStream) -> TokenStream {
let input = litext!(input as litext::LitStr);
let value = input.value();
let result = farben_md::renderer::render(&farben_md::lexer::tokenize(&input.value()));
quote! { #result }.into()
}