rpc_toolkit_macro_internals/run_cli/
build.rs1use 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}