macron_str/
lib.rs

1//! See the documentation here [macron documentation](https://docs.rs/macron)
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{ punctuated::Punctuated, spanned::Spanned };
6
7/// Creates a new instance of [String](https://doc.rust-lang.org/stable/std/string/struct.String.html)
8#[proc_macro]
9pub fn str(input: TokenStream) -> TokenStream {
10    let Format { expr, args } = syn::parse_macro_input!(input as Format);
11    
12    match expr {
13        // literal string:
14        syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(fmt), .. }) => {
15            // str!("a format {}..", "text")
16            if args.is_some() {
17                let args = args.unwrap().into_iter();
18                
19                quote! { ::std::format!(#fmt, #(#args)*) }
20            }
21            // str!("a format {text}..")
22            else if fmt.value().contains(&['{', '}'][..])  {
23                quote! { ::std::format!(#fmt) }
24            }
25            // str!("a simple text..")
26            else {
27                quote! { #fmt.to_owned() }
28            }
29        },
30
31        _ => quote! { #expr.to_string() }
32    }.into()
33}
34
35// The string formatter
36struct Format {
37    pub expr: syn::Expr,
38    pub args: Option<Punctuated::<syn::Expr, syn::Token![,]>>,
39}
40
41impl syn::parse::Parse for Format {
42    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
43        let expr = input.parse()?;
44
45        let args = match input.parse::<syn::Token![,]>() {
46            Ok(_) => {
47                if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(_), .. }) = expr {
48                } else {
49                    return Err(syn::Error::new(expr.span(), "Expected the literal string by using format arguments, example: 'str!(\"format str {{}}\", \"arg1\", ..)'"));
50                }
51                
52                Some(Punctuated::parse_terminated(input)?)
53            }, 
54            Err(_) => None
55        };
56        
57        Ok(Self { expr, args })
58    }
59}