1#![feature(proc_macro_diagnostic)]
2
3use proc_macro::TokenStream;
4
5use quote::quote;
6use syn::{parse_macro_input, ItemFn};
7
8#[proc_macro_attribute]
11pub fn main(_args: TokenStream, input: TokenStream) -> TokenStream {
12 let input = parse_macro_input!(input as ItemFn);
13
14 if input.sig.ident != "main" {
15 input
16 .sig
17 .ident
18 .span()
19 .unwrap()
20 .error("cli_errors::main must be used on the main method.")
21 .emit();
22 }
23
24 let wrapped_code = input.block;
25 TokenStream::from(quote! {
26 fn main() {
27 if let Err(e) = wrapped_main() {
28 if let Some(source) = e.source {
29 eprintln!("{:?}", source);
30 }
31 std::process::exit(e.code);
32 }
33 }
34
35 fn wrapped_main() -> cli_errors::CliResult<()> {
36 #wrapped_code
37 }
38 })
39}