s_macro/
lib.rs

1extern crate proc_macro;
2use proc_macro::TokenStream;
3
4use quote::quote;
5use syn::{Expr, Lit};
6
7/// Convenient way of making a `String`.
8///
9/// 1. `s!()`
10/// 2. `s!(123 + 321)`
11/// 3. `s!("hello, {}", "world")`
12///
13/// # Examples
14///
15/// ```
16/// use s_macro::s;
17///
18/// assert!(s!()                   == String::new());
19/// assert!(s!("hello, world")     == String::from("hello, world"));
20/// assert!(s!(123 + 321)          == format!("{}", 123 + 321));
21///
22/// let world = "world";
23/// assert!(s!("hello, {}", world) == format!("hello, {}", world));
24/// assert!(s!("hello, {world}")   == format!("hello, {world}"));
25/// ```
26#[proc_macro]
27pub fn s(input: TokenStream) -> TokenStream {
28    if input.is_empty() {
29        quote! { String::new() }.into()
30    }
31
32    else if let Ok(expr) = syn::parse::<Expr>(input.clone()) {
33        if let Expr::Lit(ref lit) = expr {
34            if let Lit::Str(_) = lit.lit {
35                return quote! { format!(#expr) }.into();
36            }
37        }
38
39        quote! { format!("{}", #expr) }.into()
40    }
41
42    else {
43        let input = proc_macro2::TokenStream::from(input);
44        quote! { format!(#input) }.into()
45    }
46}