1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use proc_macro2::TokenStream;
use quote::quote;
use syn::spanned::Spanned;

use super::*;

pub fn build(args: RunCliArgs) -> TokenStream {
    let mut command_handler = args.command.clone();
    let mut arguments = std::mem::replace(
        &mut command_handler.segments.last_mut().unwrap().arguments,
        PathArguments::None,
    );
    let command = command_handler.clone();
    if let PathArguments::AngleBracketed(a) = &mut arguments {
        a.args.push(syn::parse2(quote! { () }).unwrap());
        a.args.push(syn::parse2(quote! { _ }).unwrap());
    }
    command_handler.segments.push(PathSegment {
        ident: Ident::new("cli_handler", command.span()),
        arguments,
    });
    let app = if let Some(mut_app) = args.mut_app {
        let ident = mut_app.app_ident;
        let body = mut_app.body;
        quote! {
            {
                let #ident = #command::build_app();
                #body
            }
        }
    } else {
        quote! { #command::build_app() }
    };
    let make_ctx = if let Some(make_ctx) = args.make_ctx {
        let ident = make_ctx.matches_ident;
        let body = make_ctx.body;
        quote! {
            {
                let #ident = &rpc_toolkit_matches;
                #body
            }
        }
    } else {
        quote! { &rpc_toolkit_matches }
    };
    let parent_data = if let Some(data) = args.parent_data {
        quote! { #data }
    } else {
        quote! { () }
    };
    let exit_fn = args.exit_fn.unwrap_or_else(|| {
        syn::parse2(quote! { |err: ::rpc_toolkit::yajrc::RpcError| {
            eprintln!("{}", err.message);
            if let Some(data) = err.data {
                eprintln!("{}", data);
            }
            std::process::exit(err.code);
        } })
        .unwrap()
    });
    quote! {
        {
            let rpc_toolkit_matches = #app.get_matches();
            let rpc_toolkit_ctx = #make_ctx;
            let rpc_toolkit_parent_data = #parent_data;
            if let Err(err) = #command_handler(
                rpc_toolkit_ctx,
                rpc_toolkit_parent_data,
                None,
                &rpc_toolkit_matches,
                "".into(),
                (),
            ) {
                drop(rpc_toolkit_matches);
                (#exit_fn)(err);
            } else {
                drop(rpc_toolkit_matches);
            }
        }
    }
}