rpc_toolkit_macro_internals/run_cli/
build.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::spanned::Spanned;
4
5use super::*;
6
7pub fn build(args: RunCliArgs) -> TokenStream {
8    let mut command_handler = args.command.clone();
9    let mut arguments = std::mem::replace(
10        &mut command_handler.segments.last_mut().unwrap().arguments,
11        PathArguments::None,
12    );
13    let command = command_handler.clone();
14    if let PathArguments::AngleBracketed(a) = &mut arguments {
15        a.args.push(syn::parse2(quote! { () }).unwrap());
16        a.args.push(syn::parse2(quote! { _ }).unwrap());
17    }
18    command_handler.segments.push(PathSegment {
19        ident: Ident::new("cli_handler", command.span()),
20        arguments,
21    });
22    let app = if let Some(mut_app) = args.mut_app {
23        let ident = mut_app.app_ident;
24        let body = mut_app.body;
25        quote! {
26            {
27                let #ident = #command::build_app();
28                #body
29            }
30        }
31    } else {
32        quote! { #command::build_app() }
33    };
34    let make_ctx = if let Some(make_ctx) = args.make_ctx {
35        let ident = make_ctx.matches_ident;
36        let body = make_ctx.body;
37        quote! {
38            {
39                let #ident = &rpc_toolkit_matches;
40                #body
41            }
42        }
43    } else {
44        quote! { &rpc_toolkit_matches }
45    };
46    let parent_data = if let Some(data) = args.parent_data {
47        quote! { #data }
48    } else {
49        quote! { () }
50    };
51    let exit_fn = args.exit_fn.unwrap_or_else(|| {
52        syn::parse2(quote! { |err: ::rpc_toolkit::yajrc::RpcError| {
53            eprintln!("{}", err.message);
54            if let Some(data) = err.data {
55                eprintln!("{}", data);
56            }
57            std::process::exit(err.code);
58        } })
59        .unwrap()
60    });
61    quote! {
62        {
63            let rpc_toolkit_matches = #app.get_matches();
64            let rpc_toolkit_ctx = #make_ctx;
65            let rpc_toolkit_parent_data = #parent_data;
66            if let Err(err) = #command_handler(
67                rpc_toolkit_ctx,
68                rpc_toolkit_parent_data,
69                None,
70                &rpc_toolkit_matches,
71                "".into(),
72                (),
73            ) {
74                drop(rpc_toolkit_matches);
75                (#exit_fn)(err);
76            } else {
77                drop(rpc_toolkit_matches);
78            }
79        }
80    }
81}