cps 0.3.0

Assists in the creation of readable and maintainable macro_rules! macros
Documentation
use syn::ext::IdentExt;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{Ident, LitBool, Token};

enum Literal {
    True,
    False,
    Other(proc_macro2::Literal),
}

impl Parse for Literal {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        if input.peek(Ident::peek_any) {
            let ident: LitBool = input
                .parse()
                .map_err(|e| input.error(format!("{} when parsing token {}", e, input)))?;
            return match ident.value {
                true => Ok(Self::True),
                false => Ok(Self::False),
            };
        }
        Ok(Self::Other(input.parse().map_err(|e| {
            input.error(format!("{} when parsing token {}", e, input))
        })?))
    }
}

impl std::fmt::Display for Literal {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Other(lit) => match litrs::Literal::from(lit) {
                litrs::Literal::String(s) => s.value().fmt(f),
                litrs::Literal::Char(s) => s.value().fmt(f),
                v => v.fmt(f),
            },
            Self::True => write!(f, "true"),
            Self::False => write!(f, "false"),
        }
    }
}

struct ConcatInput {
    pub args: Punctuated<Literal, Token![,]>,
}

impl Parse for ConcatInput {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        Ok(Self {
            args: Punctuated::parse_terminated(input)?,
        })
    }
}

super::impl_std_cps!(
    use super::ConcatInput;

    fn concat(tokens: proc_macro2::TokenStream) -> proc_macro2::Literal {
        let err = format!("arguments given were not comma separated: {}", tokens);
        let parsed: ConcatInput = match syn::parse2(tokens) {
            Err(e) => panic!("error parsing concat input: {}, {}", err, e),
            Ok(v) => v,
        };

        let mut string = String::new();
        for token in parsed.args.into_iter() {
            string += &token.to_string();
        }
        proc_macro2::Literal::string(&string)
    }
);