bubbly-bub-test 0.3.1

Interactive mode extension crate to Command Line Arguments Parser (https://crates.io/crates/clap) (derive macros helper crate)
Documentation
extern crate proc_macro;

use proc_macro2::{Span, TokenStream};
use proc_macro_error::abort_call_site;
use quote::quote;
use syn;

use self::methods::interactive_clap_attrs_cli_field::InteractiveClapAttrsCliField;

mod methods;

pub fn impl_to_cli_args(ast: &syn::DeriveInput) -> TokenStream {
    let cli_name = &ast.ident;
    match &ast.data {
        syn::Data::Struct(data_struct) => {
            let mut args_subcommand = quote! {
                let mut args = std::collections::VecDeque::new();
            };
            let mut args_push_front_vec: Vec<proc_macro2::TokenStream> = Vec::new();

            for field in data_struct.clone().fields.iter() {
                match InteractiveClapAttrsCliField::new(field.clone()) {
                    InteractiveClapAttrsCliField::RegularField(regular_field_args) => {
                        args_push_front_vec.push(regular_field_args)
                    }
                    InteractiveClapAttrsCliField::SubcommandField(subcommand_args) => {
                        args_subcommand = subcommand_args
                    }
                }
            }
            let args_push_front_vec = args_push_front_vec.into_iter().rev();

            quote! {
                impl interactive_clap::ToCliArgs for #cli_name {
                    fn to_cli_args(&self) -> std::collections::VecDeque<String> {
                        #args_subcommand;
                        #(#args_push_front_vec; )*
                        args
                    }
                }
            }
        }
        syn::Data::Enum(syn::DataEnum { variants, .. }) => {
            let enum_variants = variants.iter().map(|variant| {
                let ident = &variant.ident;
                let variant_name_string =
                    crate::helpers::to_kebab_case::to_kebab_case(ident.to_string());
                let variant_name = &syn::LitStr::new(&variant_name_string, Span::call_site());

                match &variant.fields {
                    syn::Fields::Unnamed(_) => {
                        quote! {
                            Self::#ident(subcommand) => {
                                let mut args = subcommand.to_cli_args();
                                args.push_front(#variant_name.to_owned());
                                args
                            }
                        }
                    }
                    syn::Fields::Unit => {
                        quote! {
                            Self::#ident => {
                                let mut args = std::collections::VecDeque::new();
                                args.push_front(#variant_name.to_owned());
                                args
                            }
                        }
                    }
                    _ => abort_call_site!(
                        "Only options `Fields::Unnamed` or `Fields::Unit` are needed"
                    ),
                }
            });
            quote! {
                impl interactive_clap::ToCliArgs for #cli_name {
                    fn to_cli_args(&self) -> std::collections::VecDeque<String> {
                        match self {
                            #( #enum_variants, )*
                        }
                    }
                }
            }
        }
        _ => abort_call_site!("`#[derive(InteractiveClap)]` only supports structs and enums"),
    }
}