1use proc_macro::TokenStream;
2
3#[proc_macro]
4pub fn msg_macros(tokens: TokenStream) -> TokenStream {
5 let items: Vec<String> = tokens.into_iter().map(|item| item.to_string()).collect();
6 let macro_name = items.get(0).expect("No macro name was supplied");
7 let msg_type = items
8 .get(2)
9 .expect("No message type was specified")
10 .trim_start_matches('"')
11 .trim_end_matches('"');
12 let msg_prefix = items.get(4).expect("No message prefix was specified");
13 let msg_color = items.get(6).expect("No message color was specified");
14 let target_macro = items
15 .get(8)
16 .expect("No target printing macro was specified");
17
18 let gen_macro = |name, fmt_macro, action, suffix, fmt_note| {
19 format!(
20 r#"
21 /// {action} a message suitable for {msg_type} information{suffix}.
22 /// It takes the same arguments as [`{fmt_macro}!`].{}
23 #[macro_export]
24 macro_rules! {name} {{
25 ($($arg:tt)*) => {{{{
26 let prefix = {{
27 use $crate::colored::Colorize;
28 {msg_prefix}.{msg_color}().bold()
29 }};
30 {fmt_macro}!("{{}}: {{}}", prefix, format!($($arg)*))
31 }}}}
32 }}
33 "#,
34 if fmt_note {
35 format!(
36 "\n///\n/// It outputs to [`std::io::{}`] by default. If you need more control than that, use [`{macro_name}fmt!`] instead.",
37 if target_macro == "print" {
38 "Stdout"
39 } else {
40 "Stderr"
41 }
42 )
43 } else {
44 "".to_owned()
45 }
46 )
47 };
48 let mut macros = gen_macro(format!("{macro_name}fmt"), "format", "Format", "", false);
49 macros += &gen_macro(macro_name.to_owned(), target_macro, "Print", "", true);
50 macros += &gen_macro(
51 format!("{macro_name}ln"),
52 &format!("{target_macro}ln"),
53 "Print",
54 ", with a newline at the end",
55 true,
56 );
57 macros.parse().unwrap()
59}