use proc_macro::TokenStream;
use quote::quote;
fn impl_as_command_from_arg(syn::DeriveInput {
ident, attrs, ..
}: &syn::DeriveInput, arguments: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
let description = crate::as_arg::impl_description(attrs.iter());
quote! {
impl clipv::describe::command::AsCommand for #ident {
fn command() -> clipv::describe::command::Command {
let mut cmd = clipv::describe::command::Command::new(
stringify!(#ident),
#description
);
cmd.set_arguments(vec![
clipv::describe::arg::Arg::with_type(
stringify!(#ident), None,
clipv::describe::arg::ArgType::Choices(
clipv::describe::arg::Choices(vec![#arguments])
)
)
]);
cmd
}
}
}
}
fn impl_as_command(ast: &syn::DeriveInput) -> Result<proc_macro2::TokenStream, syn::Error> {
match &ast.data {
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
let as_command = impl_as_command_from_arg(ast, crate::as_arg::impl_enum_variant_as_arg(variants.iter())?);
Ok(quote!{ #as_command })
},
syn::Data::Struct(syn::DataStruct { struct_token, .. }) => Err(
syn::Error::new_spanned(struct_token, "only enum can be defined as command")
),
syn::Data::Union(syn::DataUnion { union_token, .. }) => Err(
syn::Error::new_spanned(union_token, "Union aren't supported as commands")
)
}
}
pub(crate) fn impl_as_command_macro(ast: &syn::DeriveInput) -> TokenStream {
impl_as_command(ast)
.unwrap_or_else(|err| err.to_compile_error())
.into()
}