struct-input-derive 0.1.1

Procedural derive macro for the struct-input crate, enabling automatic mapping of CLI inputs to struct fields.
Documentation
use std::any::Any;
use darling::FromMeta;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use syn::Type;
use crate::derive::attr::FieldArgs;

pub fn field_to_quote(field_args: &FieldArgs) -> TokenStream {
    let name = &field_args.ident;

    let format = extract_format(&field_args.format);
    let prompt = extract_prompt(&field_args);

    match get_type_name(&field_args.ty).as_deref() {
        Some("Option") => quote! {#name: ::struct_input::read_string_option(#prompt, ::struct_input::Format::#format).await},
        Some("String") => {
            let default = extract_default(&field_args.default);
            quote! {
                #name: ::struct_input::read_string(#prompt, ::struct_input::Format::#format, #default).await
            }
        },
        Some("i32") => quote! {#name: ::struct_input::read_int(#prompt).await},
        _ => panic!(""),
    }
}

fn get_type_name(ty: &Type) -> Option<String> {
    if let Type::Path(type_path) = ty {
        if let Some(segment) = type_path.path.segments.last() {
            return Some(segment.ident.to_string());
        }
    }
    None
}

fn extract_prompt(field_args: &FieldArgs) -> String {
    let message = &field_args.message;

    if let Some(message) = message {
        message.to_string()
    } else {
        let name = &field_args.ident.as_ref();
        let name = name.unwrap().to_string();
        format!("--- type {name} ---")
    }
}

fn extract_format(format: &Option<String>) -> Ident {
    Ident::from_string(
        format.as_ref().unwrap_or(&String::from("None"))
    ).unwrap()
}

fn extract_default(default: &Option<String>) -> TokenStream {
     if let Some(default) = default {
         quote!(Some(String::from(#default)))
     } else {
         quote!(None)
     }
}