aboutsummaryrefslogtreecommitdiff
path: root/mingling_macros/src
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-08-17 05:49:19 +0800
committer魏曹先生 <1992414357@qq.com>2026-08-17 05:49:19 +0800
commit57c53affe3542cb6bd4e79ee4c18f20a1bd76b2d (patch)
tree1cd4aef44cb7a45a8cd9d520b598f5f181e24c76 /mingling_macros/src
parentef23cd944402939605c78a4a853ef6e33af02c21 (diff)
refactor!: replace pack! macros with derive-based pipeline types
Remove the `pack!`, `pack_err!`, `pack_structural!`, and `pack_err_structural!` macros, replacing all pipeline type definitions with `#[derive(Grouped)]` and `#[derive(Grouped, Wrap)]` attributes. This changes the generated struct shape from named-field structs with an `inner` field to tuple structs accessed via `.0`, and removes the auto-generated `name` and `info` fields from error types.
Diffstat (limited to 'mingling_macros/src')
-rw-r--r--mingling_macros/src/attr/dispatcher_clap.rs7
-rw-r--r--mingling_macros/src/func.rs7
-rw-r--r--mingling_macros/src/func/dispatcher.rs10
-rw-r--r--mingling_macros/src/func/entry.rs2
-rw-r--r--mingling_macros/src/func/gen_program.rs3
-rw-r--r--mingling_macros/src/func/pack.rs154
-rw-r--r--mingling_macros/src/func/pack_err.rs108
-rw-r--r--mingling_macros/src/func/pack_err_structural.rs121
-rw-r--r--mingling_macros/src/func/pack_structural.rs170
-rw-r--r--mingling_macros/src/func/program_comp_gen.rs15
-rw-r--r--mingling_macros/src/func/program_fallback_gen.rs8
-rw-r--r--mingling_macros/src/func/program_final_gen.rs4
-rw-r--r--mingling_macros/src/lib.rs238
-rw-r--r--mingling_macros/src/systems.rs5
-rw-r--r--mingling_macros/src/systems/structural_data.rs7
15 files changed, 76 insertions, 783 deletions
diff --git a/mingling_macros/src/attr/dispatcher_clap.rs b/mingling_macros/src/attr/dispatcher_clap.rs
index 46238d6..c2dd952 100644
--- a/mingling_macros/src/attr/dispatcher_clap.rs
+++ b/mingling_macros/src/attr/dispatcher_clap.rs
@@ -133,7 +133,7 @@ pub(crate) fn dispatcher_clap_attr(attr: TokenStream, item: TokenStream) -> Toke
match <#struct_name as ::clap::Parser>::try_parse_from(clap_args) {
Ok(parsed) => ::mingling::Routable::<#program_path>::to_chain(parsed),
Err(e) => {
- return ::mingling::Routable::<#program_path>::to_render(#error_struct::new(format!("{}", e.render().ansi())))
+ return ::mingling::Routable::<#program_path>::to_render(#error_struct(format!("{}", e.render().ansi())))
},
}
}
@@ -143,7 +143,8 @@ pub(crate) fn dispatcher_clap_attr(attr: TokenStream, item: TokenStream) -> Toke
// Generate the error pack type
let error_pack = options.error_struct.as_ref().map(|error_struct| {
quote! {
- ::mingling::macros::pack!(#error_struct = String);
+ #[derive(::mingling::Grouped, ::mingling::Wrap, Default)]
+ pub struct #error_struct(pub ::std::string::String);
}
});
@@ -188,7 +189,7 @@ pub(crate) fn dispatcher_clap_attr(attr: TokenStream, item: TokenStream) -> Toke
// Keep the original struct definition
#input_struct
- // Generate the error wrapper type via pack!
+ // Generate the error wrapper type
#error_pack
// Generate the help block if enabled
diff --git a/mingling_macros/src/func.rs b/mingling_macros/src/func.rs
index 57d0ec5..baa23db 100644
--- a/mingling_macros/src/func.rs
+++ b/mingling_macros/src/func.rs
@@ -9,13 +9,6 @@ pub(crate) mod gen_program;
pub(crate) mod group;
#[cfg(all(feature = "structural_renderer", feature = "extras"))]
pub(crate) mod group_structural;
-pub(crate) mod pack;
-#[cfg(feature = "extras")]
-pub(crate) mod pack_err;
-#[cfg(all(feature = "structural_renderer", feature = "extras"))]
-pub(crate) mod pack_err_structural;
-#[cfg(feature = "structural_renderer")]
-pub(crate) mod pack_structural;
#[cfg(feature = "comp")]
pub(crate) mod program_comp_gen;
pub(crate) mod program_fallback_gen;
diff --git a/mingling_macros/src/func/dispatcher.rs b/mingling_macros/src/func/dispatcher.rs
index c4d67a9..41dd2d0 100644
--- a/mingling_macros/src/func/dispatcher.rs
+++ b/mingling_macros/src/func/dispatcher.rs
@@ -115,7 +115,9 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream {
let program_type = crate::default_program_path();
let expanded = quote! {
- ::mingling::macros::pack!(#(#entry_attrs)* #pack = Vec<String>);
+ #[derive(::mingling::Grouped, ::mingling::Wrap, Default)]
+ #(#entry_attrs)*
+ pub struct #pack(pub ::std::vec::Vec<::std::string::String>);
#(#cmd_attrs)*
#[doc(hidden)]
@@ -127,7 +129,7 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream {
impl From<#pack> for crate::Entry {
fn from(value: #pack) -> Self {
- crate::Entry::new(value.inner)
+ crate::Entry(value.0)
}
}
@@ -136,7 +138,7 @@ pub(crate) fn dispatcher(input: TokenStream) -> TokenStream {
impl ::mingling::Dispatcher<#program_type> for #hidden_dispatcher {
fn begin(&self, args: Vec<String>) -> ::mingling::ChainProcess<#program_type> {
use ::mingling::Grouped;
- ::mingling::Routable::to_chain(#pack::new(args))
+ ::mingling::Routable::to_chain(#pack(args))
}
}
};
@@ -149,7 +151,7 @@ fn get_comp_entry(entry_name: &Ident) -> TokenStream2 {
let comp_entry = quote! {
impl ::mingling::CompletionEntry for #entry_name {
fn get_input(self) -> Vec<String> {
- self.inner.clone()
+ self.0.clone()
}
}
};
diff --git a/mingling_macros/src/func/entry.rs b/mingling_macros/src/func/entry.rs
index 82dfd3e..18e485f 100644
--- a/mingling_macros/src/func/entry.rs
+++ b/mingling_macros/src/func/entry.rs
@@ -57,7 +57,7 @@ pub(crate) fn entry(input: TokenStream) -> TokenStream {
let expanded = match parsed {
EntryInput::Typed { ident, .. } => {
quote! {
- #ident::new(vec![#(#string_exprs),*])
+ #ident(vec![#(#string_exprs),*])
}
}
EntryInput::Untyped { .. } => {
diff --git a/mingling_macros/src/func/gen_program.rs b/mingling_macros/src/func/gen_program.rs
index a53f86f..c0a7ea8 100644
--- a/mingling_macros/src/func/gen_program.rs
+++ b/mingling_macros/src/func/gen_program.rs
@@ -57,7 +57,8 @@ pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream {
/// Alias for the current program type `ThisProgram`
pub type Next = ::mingling::ChainProcess<ThisProgram>;
- ::mingling::macros::pack!(Entry = Vec<String>);
+ #[derive(::mingling::Grouped, ::mingling::Wrap, Default)]
+ pub struct Entry(pub ::std::vec::Vec<::std::string::String>);
impl ::mingling::Routable<ThisProgram> for ::mingling::ChainProcess<ThisProgram>
{
diff --git a/mingling_macros/src/func/pack.rs b/mingling_macros/src/func/pack.rs
deleted file mode 100644
index d4fcb60..0000000
--- a/mingling_macros/src/func/pack.rs
+++ /dev/null
@@ -1,154 +0,0 @@
-// Doc Not Optimize
-use proc_macro::TokenStream;
-use quote::quote;
-use syn::parse::{Parse, ParseStream};
-use syn::{Attribute, Ident, Result as SynResult, Token, Type};
-
-struct PackInput {
- attrs: Vec<Attribute>,
- type_name: Ident,
- inner_type: Type,
-}
-
-impl Parse for PackInput {
- fn parse(input: ParseStream) -> SynResult<Self> {
- let attrs = input.call(Attribute::parse_outer)?;
- let type_name: Ident = input.parse()?;
- input.parse::<Token![=]>()?;
- let inner_type: Type = input.parse()?;
-
- Ok(Self {
- attrs,
- type_name,
- inner_type,
- })
- }
-}
-
-#[allow(clippy::too_many_lines)]
-pub(crate) fn pack(input: TokenStream) -> TokenStream {
- let pack_input = syn::parse_macro_input!(input as PackInput);
-
- let group_name = crate::default_program_path();
- let type_name = pack_input.type_name;
- let inner_type = pack_input.inner_type;
- let attrs = pack_input.attrs;
-
- // Generate the struct definition
- // Note: No longer derives Serialize under structural_renderer.
- // Use pack_structual! for structured output support.
- let struct_def = quote! {
- #(#attrs)*
- pub struct #type_name {
- pub(crate) inner: #inner_type,
- }
- };
-
- // Generate the new() method
- let new_impl = quote! {
- impl #type_name {
- /// Creates a new instance of the wrapper type
- pub fn new(inner: #inner_type) -> Self {
- Self { inner }
- }
- }
- };
-
- // Generate From and Into implementations
- let from_into_impl = quote! {
- impl From<#inner_type> for #type_name {
- fn from(inner: #inner_type) -> Self {
- Self::new(inner)
- }
- }
-
- impl From<#type_name> for #inner_type {
- fn from(wrapper: #type_name) -> #inner_type {
- wrapper.inner
- }
- }
- };
-
- // Generate AsRef and AsMut implementations
- let as_ref_impl = quote! {
- impl ::std::convert::AsRef<#inner_type> for #type_name {
- fn as_ref(&self) -> &#inner_type {
- &self.inner
- }
- }
-
- impl ::std::convert::AsMut<#inner_type> for #type_name {
- fn as_mut(&mut self) -> &mut #inner_type {
- &mut self.inner
- }
- }
- };
-
- // Generate Deref and DerefMut implementations
- let deref_impl = quote! {
- impl ::std::ops::Deref for #type_name {
- type Target = #inner_type;
-
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
- }
-
- impl ::std::ops::DerefMut for #type_name {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.inner
- }
- }
- };
-
- // Check if the inner type implements Default by generating conditional code
- let default_impl = quote! {
- impl ::std::default::Default for #type_name
- where
- #inner_type: ::std::default::Default,
- {
- fn default() -> Self {
- Self::new(::std::default::Default::default())
- }
- }
- };
-
- let register_impl = quote! {
- ::mingling::macros::register_type!(#type_name);
- };
-
- let expanded = quote! {
- #struct_def
-
- #new_impl
- #from_into_impl
- #as_ref_impl
- #deref_impl
- #default_impl
- #register_impl
-
- impl Into<mingling::AnyOutput<#group_name>> for #type_name {
- fn into(self) -> mingling::AnyOutput<#group_name> {
- mingling::AnyOutput::new(self)
- }
- }
-
- impl Into<mingling::ChainProcess<#group_name>> for #type_name {
- fn into(self) -> mingling::ChainProcess<#group_name> {
- mingling::AnyOutput::new(self).route_chain()
- }
- }
-
- /// SAFETY: This is an internal implementation of the `pack!` macro,
- /// guaranteeing that the enum value registered by the `register_type!` macro
- /// is exactly the same as the actual return value,
- /// which can be confirmed via the `Ident` in the `quote!` block.
- unsafe impl ::mingling::Grouped<#group_name> for #type_name {
- fn member_id() -> #group_name {
- #group_name::#type_name
- }
- }
- };
-
- expanded.into()
-}
diff --git a/mingling_macros/src/func/pack_err.rs b/mingling_macros/src/func/pack_err.rs
deleted file mode 100644
index e925b82..0000000
--- a/mingling_macros/src/func/pack_err.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-// Doc Not Optimize
-use just_fmt::snake_case;
-use proc_macro::TokenStream;
-use quote::quote;
-use syn::{Ident, Token, Type, parse_macro_input};
-
-enum PackErrInput {
- /// `pack_err!(ErrorNotFound)`
- Simple { type_name: Ident },
- /// `pack_err!(ErrorNotDir = PathBuf)`
- Typed {
- type_name: Ident,
- inner_type: Box<Type>,
- },
-}
-
-impl syn::parse::Parse for PackErrInput {
- fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
- let type_name: Ident = input.parse()?;
-
- if input.peek(Token![=]) {
- input.parse::<Token![=]>()?;
- let inner_type: Type = input.parse()?;
- Ok(Self::Typed {
- type_name,
- inner_type: Box::new(inner_type),
- })
- } else {
- Ok(Self::Simple { type_name })
- }
- }
-}
-
-#[allow(clippy::too_many_lines)]
-pub(crate) fn pack_err(input: TokenStream) -> TokenStream {
- let parsed = parse_macro_input!(input as PackErrInput);
-
- match parsed {
- PackErrInput::Simple { type_name } => {
- let name_str = type_name.to_string();
- let snake_name = snake_case!(&name_str);
-
- // Note: No longer derives Serialize under structural_renderer.
- // Use pack_err_structural for structured output support.
- let derive = quote! {
- #[derive(::mingling::Grouped)]
- };
-
- let expanded = quote! {
- #derive
- pub struct #type_name {
- /// The snake_case name of this error, automatically set at compile time.
- pub name: String,
- }
-
- impl ::std::default::Default for #type_name {
- fn default() -> Self {
- Self {
- name: #snake_name.into(),
- }
- }
- }
-
- ::mingling::macros::register_type!(#type_name);
- };
-
- expanded.into()
- }
- PackErrInput::Typed {
- type_name,
- inner_type,
- } => {
- let name_str = type_name.to_string();
- let snake_name = snake_case!(&name_str);
-
- // Note: No longer derives Serialize under structural_renderer.
- // Use pack_err_structural for structured output support.
- let derive = quote! {
- #[derive(::mingling::Grouped)]
- };
-
- let expanded = quote! {
- #derive
- pub struct #type_name {
- /// The snake_case name of this error, automatically set at compile time.
- pub name: String,
- /// Additional context info for this error.
- pub info: #inner_type,
- }
-
- impl #type_name {
- /// Creates a new error with the given info.
- /// The `name` field is automatically set to the snake_case of the struct name.
- pub fn new(info: #inner_type) -> Self {
- Self {
- name: #snake_name.into(),
- info,
- }
- }
- }
-
- ::mingling::macros::register_type!(#type_name);
- };
-
- expanded.into()
- }
- }
-}
diff --git a/mingling_macros/src/func/pack_err_structural.rs b/mingling_macros/src/func/pack_err_structural.rs
deleted file mode 100644
index 950b8dc..0000000
--- a/mingling_macros/src/func/pack_err_structural.rs
+++ /dev/null
@@ -1,121 +0,0 @@
-// Doc Not Optimize
-use just_fmt::snake_case;
-use proc_macro::TokenStream;
-use quote::quote;
-use syn::{Ident, Token, Type, parse_macro_input};
-
-/// `pack_err_structural!` — like `pack_err!` but also marks the type as
-/// supporting structured output via `StructuralData`.
-pub(crate) fn pack_err_structural(input: TokenStream) -> TokenStream {
- let parsed = parse_macro_input!(input as PackErrInput);
-
- let type_name = match &parsed {
- PackErrInput::Simple { type_name } | PackErrInput::Typed { type_name, .. } => {
- type_name.clone()
- }
- };
-
- // Register in STRUCTURED_TYPES
- let type_name_str = type_name.to_string();
- crate::get_global_set(&crate::STRUCTURED_TYPES)
- .lock()
- .unwrap()
- .insert(type_name_str);
-
- let structural_data = quote! {
- impl ::mingling::__private::StructuralDataSealed<crate::ThisProgram> for #type_name {}
- impl ::mingling::__private::StructuralData<crate::ThisProgram> for #type_name {}
- };
-
- // Generate the struct + impls (same as pack_err! but with Serialize derive + sealed)
- match parsed {
- PackErrInput::Simple { type_name } => {
- let name_str = type_name.to_string();
- let snake_name = snake_case!(&name_str);
-
- let expanded = quote! {
- #[derive(::mingling::Grouped, ::serde::Serialize)]
- pub struct #type_name {
- /// The snake_case name of this error, automatically set at compile time.
- pub name: String,
- }
-
- impl ::std::default::Default for #type_name {
- fn default() -> Self {
- Self {
- name: #snake_name.into(),
- }
- }
- }
-
- ::mingling::macros::register_type!(#type_name);
-
- #structural_data
- };
-
- expanded.into()
- }
- PackErrInput::Typed {
- type_name,
- inner_type,
- } => {
- let name_str = type_name.to_string();
- let snake_name = snake_case!(&name_str);
-
- let expanded = quote! {
- #[derive(::mingling::Grouped, ::serde::Serialize)]
- pub struct #type_name {
- /// The snake_case name of this error, automatically set at compile time.
- pub name: String,
- /// Additional context info for this error.
- pub info: #inner_type,
- }
-
- impl #type_name {
- /// Creates a new error with the given info.
- /// The `name` field is automatically set to the snake_case of the struct name.
- pub fn new(info: #inner_type) -> Self {
- Self {
- name: #snake_name.into(),
- info,
- }
- }
- }
-
- ::mingling::macros::register_type!(#type_name);
-
- #structural_data
- };
-
- expanded.into()
- }
- }
-}
-
-// Re-use pack_err's input parser
-enum PackErrInput {
- Simple {
- type_name: Ident,
- },
- Typed {
- type_name: Ident,
- inner_type: Box<Type>,
- },
-}
-
-impl syn::parse::Parse for PackErrInput {
- fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
- let type_name: Ident = input.parse()?;
-
- if input.peek(Token![=]) {
- input.parse::<Token![=]>()?;
- let inner_type: Type = input.parse()?;
- Ok(Self::Typed {
- type_name,
- inner_type: Box::new(inner_type),
- })
- } else {
- Ok(Self::Simple { type_name })
- }
- }
-}
diff --git a/mingling_macros/src/func/pack_structural.rs b/mingling_macros/src/func/pack_structural.rs
deleted file mode 100644
index fb13fbf..0000000
--- a/mingling_macros/src/func/pack_structural.rs
+++ /dev/null
@@ -1,170 +0,0 @@
-// Doc Not Optimize
-use proc_macro::TokenStream;
-use quote::quote;
-use syn::Ident;
-
-use crate::get_global_set;
-
-/// `pack_structural!` — like `pack!` but also marks the type as supporting
-/// structured output via `StructuralData`.
-#[allow(clippy::too_many_lines)]
-pub(crate) fn pack_structural(input: TokenStream) -> TokenStream {
- // Parse same input format as `pack!`
- let input_parsed = syn::parse_macro_input!(input as PackStructuralInput);
- let type_name = input_parsed.type_name;
- let inner_type = input_parsed.inner_type;
- let attrs = input_parsed.attrs;
- let program_path = crate::default_program_path();
-
- // Register in STRUCTURED_TYPES
- let type_name_str = type_name.to_string();
- get_global_set(&crate::STRUCTURED_TYPES)
- .lock()
- .unwrap()
- .insert(type_name_str);
-
- // Struct definition (with Serialize derive, same as pack! under structural_renderer)
- #[cfg(not(feature = "structural_renderer"))]
- let struct_def = quote! {
- #(#attrs)*
- pub struct #type_name {
- pub inner: #inner_type,
- }
- };
-
- #[cfg(feature = "structural_renderer")]
- let struct_def = quote! {
- #(#attrs)*
- #[derive(serde::Serialize)]
- pub struct #type_name {
- pub inner: #inner_type,
- }
- };
-
- // Helper impls (same as pack!)
- let new_impl = quote! {
- impl #type_name {
- pub fn new(inner: #inner_type) -> Self {
- Self { inner }
- }
- }
- };
-
- let from_into_impl = quote! {
- impl From<#inner_type> for #type_name {
- fn from(inner: #inner_type) -> Self {
- Self::new(inner)
- }
- }
- impl From<#type_name> for #inner_type {
- fn from(wrapper: #type_name) -> #inner_type {
- wrapper.inner
- }
- }
- };
-
- let as_ref_impl = quote! {
- impl ::std::convert::AsRef<#inner_type> for #type_name {
- fn as_ref(&self) -> &#inner_type {
- &self.inner
- }
- }
- impl ::std::convert::AsMut<#inner_type> for #type_name {
- fn as_mut(&mut self) -> &mut #inner_type {
- &mut self.inner
- }
- }
- };
-
- let deref_impl = quote! {
- impl ::std::ops::Deref for #type_name {
- type Target = #inner_type;
- fn deref(&self) -> &Self::Target {
- &self.inner
- }
- }
- impl ::std::ops::DerefMut for #type_name {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.inner
- }
- }
- };
-
- let default_impl = quote! {
- impl ::std::default::Default for #type_name
- where
- #inner_type: ::std::default::Default,
- {
- fn default() -> Self {
- Self::new(::std::default::Default::default())
- }
- }
- };
-
- let register_impl = quote! {
- ::mingling::macros::register_type!(#type_name);
- };
-
- // StructuralData impl + sealed + registration
- let structural_impl = quote! {
- impl ::mingling::__private::StructuralDataSealed<crate::ThisProgram> for #type_name {}
- impl ::mingling::__private::StructuralData<crate::ThisProgram> for #type_name {}
- };
-
- let expanded = quote! {
- #struct_def
-
- #new_impl
- #from_into_impl
- #as_ref_impl
- #deref_impl
- #default_impl
- #register_impl
- #structural_impl
-
- impl Into<::mingling::AnyOutput<#program_path>> for #type_name {
- fn into(self) -> ::mingling::AnyOutput<#program_path> {
- ::mingling::AnyOutput::new(self)
- }
- }
-
- impl Into<::mingling::ChainProcess<#program_path>> for #type_name {
- fn into(self) -> ::mingling::ChainProcess<#program_path> {
- ::mingling::AnyOutput::new(self).route_chain()
- }
- }
-
- /// SAFETY: This is an internal implementation of the `pack_structural!` macro,
- /// guaranteeing that the enum value registered by the `register_type!` macro
- /// is exactly the same as the actual return value,
- /// which can be confirmed via the `Ident` in the `quote!` block.
- unsafe impl ::mingling::Grouped<#program_path> for #type_name {
- fn member_id() -> #program_path {
- #program_path::#type_name
- }
- }
- };
-
- expanded.into()
-}
-
-/// Input for `pack_structural!` — same format as `pack!`.
-struct PackStructuralInput {
- attrs: Vec<syn::Attribute>,
- type_name: Ident,
- inner_type: syn::Type,
-}
-
-impl syn::parse::Parse for PackStructuralInput {
- fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
- let attrs = input.call(syn::Attribute::parse_outer)?;
- let type_name: Ident = input.parse()?;
- input.parse::<syn::Token![=]>()?;
- let inner_type: syn::Type = input.parse()?;
- Ok(Self {
- attrs,
- type_name,
- inner_type,
- })
- }
-}
diff --git a/mingling_macros/src/func/program_comp_gen.rs b/mingling_macros/src/func/program_comp_gen.rs
index ed04379..cdd2597 100644
--- a/mingling_macros/src/func/program_comp_gen.rs
+++ b/mingling_macros/src/func/program_comp_gen.rs
@@ -11,11 +11,11 @@ pub(crate) fn program_comp_gen_impl(_input: TokenStream) -> TokenStream {
pub async fn __exec_completion(prev: CompletionContext) -> Next {
use ::mingling::Grouped;
- let read_ctx = ::mingling::ShellContext::try_from(prev.inner);
+ let read_ctx = ::mingling::ShellContext::try_from(prev.0);
match read_ctx {
Ok(ctx) => {
let suggest = ::mingling::CompletionHelper::exec_completion::<crate::ThisProgram>(&ctx);
- ::mingling::Routable::<crate::ThisProgram>::to_render(CompletionSuggest::new((ctx, suggest)))
+ ::mingling::Routable::<crate::ThisProgram>::to_render(CompletionSuggest((ctx, suggest)))
}
Err(_) => std::process::exit(1),
}
@@ -29,11 +29,11 @@ pub(crate) fn program_comp_gen_impl(_input: TokenStream) -> TokenStream {
pub fn __exec_completion(prev: CompletionContext) -> Next {
use ::mingling::Grouped;
- let read_ctx = ::mingling::ShellContext::try_from(prev.inner);
+ let read_ctx = ::mingling::ShellContext::try_from(prev.0);
match read_ctx {
Ok(ctx) => {
let suggest = ::mingling::CompletionHelper::exec_completion::<crate::ThisProgram>(&ctx);
- ::mingling::Routable::<crate::ThisProgram>::to_render(CompletionSuggest::new((ctx, suggest)))
+ ::mingling::Routable::<crate::ThisProgram>::to_render(CompletionSuggest((ctx, suggest)))
}
Err(_) => std::process::exit(1),
}
@@ -50,9 +50,8 @@ pub(crate) fn program_comp_gen_impl(_input: TokenStream) -> TokenStream {
mod __internal_completion_mod {
use ::mingling::Grouped;
::mingling::macros::dispatcher!("__comp", CompletionContext);
- ::mingling::macros::pack!(
- CompletionSuggest = (::mingling::ShellContext, ::mingling::Suggest)
- );
+ #[derive(::mingling::Grouped, ::mingling::Wrap)]
+ pub struct CompletionSuggest(pub (::mingling::ShellContext, ::mingling::Suggest));
}
#internal_dispatcher_comp
use __internal_completion_mod::CompletionContext;
@@ -67,7 +66,7 @@ pub(crate) fn program_comp_gen_impl(_input: TokenStream) -> TokenStream {
#[::mingling::macros::renderer]
pub fn __render_completion(prev: CompletionSuggest) -> ::mingling::RenderResult {
let result = ::mingling::RenderResult::default();
- let (ctx, suggest) = prev.inner;
+ let (ctx, suggest) = prev.0;
::mingling::CompletionHelper::render_suggest::<crate::ThisProgram>(&ctx, suggest);
result
}
diff --git a/mingling_macros/src/func/program_fallback_gen.rs b/mingling_macros/src/func/program_fallback_gen.rs
index df53c60..1f3fdce 100644
--- a/mingling_macros/src/func/program_fallback_gen.rs
+++ b/mingling_macros/src/func/program_fallback_gen.rs
@@ -16,8 +16,12 @@ pub(crate) fn program_fallback_gen_impl(_input: TokenStream) -> TokenStream {
};
let expanded = quote! {
- ::mingling::macros::pack!(ErrorRendererNotFound = String);
- ::mingling::macros::pack!(EntryFallback = Vec<String>);
+ #[derive(::mingling::Grouped, ::mingling::Wrap, Default)]
+ pub struct ErrorRendererNotFound(pub ::std::string::String);
+
+ #[derive(::mingling::Grouped, ::mingling::Wrap, Default)]
+ pub struct EntryFallback(pub ::std::vec::Vec<::std::string::String>);
+
#pack_empty
};
TokenStream::from(expanded)
diff --git a/mingling_macros/src/func/program_final_gen.rs b/mingling_macros/src/func/program_final_gen.rs
index d549a2b..8123eaf 100644
--- a/mingling_macros/src/func/program_final_gen.rs
+++ b/mingling_macros/src/func/program_final_gen.rs
@@ -376,10 +376,10 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream {
type ResultEmpty = ResultEmpty;
fn build_renderer_not_found(member_id: Self::Enum) -> ::mingling::AnyOutput<Self::Enum> {
- ::mingling::AnyOutput::new(ErrorRendererNotFound::new(member_id.to_string()))
+ ::mingling::AnyOutput::new(ErrorRendererNotFound(member_id.to_string()))
}
fn build_entry_fallback(args: Vec<String>) -> ::mingling::AnyOutput<Self::Enum> {
- ::mingling::AnyOutput::new(EntryFallback::new(args))
+ ::mingling::AnyOutput::new(EntryFallback(args))
}
fn build_empty_result() -> ::mingling::AnyOutput<Self::Enum> {
::mingling::AnyOutput::new(ResultEmpty)
diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs
index 7da7db3..d0556dc 100644
--- a/mingling_macros/src/lib.rs
+++ b/mingling_macros/src/lib.rs
@@ -34,15 +34,13 @@ use attr::dispatcher_clap;
use attr::program_setup;
use attr::{chain, help, metadata, renderer};
use derive::{enum_tag, grouped, wrap};
+use func::dispatcher;
#[cfg(feature = "extras")]
use func::entry;
#[cfg(feature = "extras")]
pub(crate) use func::group as group_impl;
-#[cfg(feature = "extras")]
-use func::pack_err;
#[cfg(feature = "comp")]
use func::suggest;
-use func::{dispatcher, pack};
use systems::res_injection;
pub(crate) fn default_program_path() -> proc_macro2::TokenStream {
quote::quote! { crate::ThisProgram }
@@ -60,7 +58,7 @@ pub(crate) type Registry = OnceLock<Mutex<BTreeSet<String>>>;
pub(crate) static STRUCTURAL_RENDERERS: Registry = OnceLock::new();
/// Types explicitly marked with `#[derive(StructuralData)]` or created via
-/// `pack_structural!` / `group_structural!`.
+/// `group_structural!`.
#[cfg(feature = "structural_renderer")]
pub(crate) static STRUCTURED_TYPES: Registry = OnceLock::new();
@@ -183,163 +181,6 @@ pub fn group_structural(input: TokenStream) -> TokenStream {
func::group_structural::group_structural(input)
}
-/// Creates a type-safe wrapper struct around an inner type, with automatic
-/// trait implementations for use in the Mingling chain/render pipeline.
-///
-/// The generated struct implements: `From`/`Into`, `AsRef`/`AsMut`, `Deref`/`DerefMut`,
-/// `Default` (conditional on inner type), and conversion into `AnyOutput` /
-/// `ChainProcess` for routing.
-///
-/// # Syntax
-///
-/// ```rust,ignore
-/// // Default program name (uses `ThisProgram`):
-/// pack!(TypeName = InnerType);
-///
-/// // Explicit program name:
-/// pack!(MyProgram, TypeName = InnerType);
-/// ```
-///
-/// # Example
-///
-/// ```rust,ignore
-/// use mingling::macros::pack;
-///
-/// // Creates `Hello` wrapping `String`, registered under `ThisProgram`:
-/// pack!(Hello = String);
-///
-/// // Creates `Greeting` wrapping `String`, registered under `MyApp`:
-/// pack!(MyApp, Greeting = String);
-/// ```
-///
-/// After expansion, `Hello` has:
-/// - `Hello::new(String)` — constructor
-/// - `Hello::to_chain()` — routes to the next chain processor
-/// - `Hello::to_render()` — routes to a renderer
-/// - `From<String> for Hello`, `From<Hello> for String`
-/// - `Deref<Target = String>`, `DerefMut`
-/// - `AsRef<String>`, `AsMut<String>`
-/// - `Default` if `String: Default`
-/// - `Into<AnyOutput<ThisProgram>>`, `Into<ChainProcess<ThisProgram>>`
-/// - Implements `Grouped<ThisProgram>` with `member_id()` returning the enum variant
-///
-/// The struct is also registered via `register_type!` so that `gen_program!`
-/// can include it in the program enum.
-///
-/// When the `structural_renderer` feature is enabled, the struct also gets
-/// `#[derive(serde::Serialize)]`.
-#[proc_macro]
-pub fn pack(input: TokenStream) -> TokenStream {
- pack::pack(input)
-}
-
-/// Like `pack!` but also marks the type as supporting structured output
-/// (JSON / YAML / TOML / RON) via `StructuralData`.
-///
-/// # Syntax
-///
-/// ```rust,ignore
-/// pack_structural!(Info = (String, i32));
-/// ```
-///
-/// This is equivalent to:
-/// ```rust,ignore
-/// pack!(Info = (String, i32));
-/// impl ::mingling::StructuralData for Info {}
-/// ```
-///
-/// Requires the `structural_renderer` feature.
-#[cfg(feature = "structural_renderer")]
-#[proc_macro]
-pub fn pack_structural(input: TokenStream) -> TokenStream {
- func::pack_structural::pack_structural(input)
-}
-
-/// Creates an error struct with a `name: String` field and optional `info: Type` field.
-///
-/// This macro provides a concise way to define error types that implement `Grouped`
-/// and are registered for inclusion in the program enum.
-///
-/// The `name` field is automatically set to the `snake_case` version of the struct name
-/// at compile time.
-///
-/// # Syntax
-///
-/// Two forms are supported:
-///
-/// ```rust,ignore
-/// // Simple form — generates a struct with only `name: String` and a `Default` impl:
-/// pack_err!(ErrorNotFound);
-///
-/// // Typed form — generates a struct with `name: String` + `info: Type` and a `new(info)` constructor:
-/// pack_err!(ErrorNotDir = PathBuf);
-/// ```
-///
-/// # Generated code
-///
-/// For `pack_err!(ErrorNotFound)`:
-///
-/// ```rust,ignore
-/// #[derive(::mingling::Grouped)]
-/// pub struct ErrorNotFound {
-/// name: String,
-/// }
-///
-/// impl Default for ErrorNotFound {
-/// fn default() -> Self {
-/// Self {
-/// name: "error_not_found".into(),
-/// }
-/// }
-/// }
-/// ```
-///
-/// For `pack_err!(ErrorNotDir = PathBuf)`:
-///
-/// ```rust,ignore
-/// #[derive(::mingling::Grouped)]
-/// pub struct ErrorNotDir {
-/// name: String,
-/// info: PathBuf,
-/// }
-///
-/// impl ErrorNotDir {
-/// pub fn new(info: PathBuf) -> Self {
-/// Self {
-/// name: "error_not_dir".into(),
-/// info,
-/// }
-/// }
-/// }
-/// ```
-///
-/// When the `structural_renderer` feature is enabled, the struct also gets
-/// `#[derive(serde::Serialize)]`.
-///
-/// This macro is only available with the `extras` feature.
-#[cfg(feature = "extras")]
-#[proc_macro]
-pub fn pack_err(input: TokenStream) -> TokenStream {
- pack_err::pack_err(input)
-}
-
-/// Like `pack_err!` but also marks the type for structured output
-/// (JSON / YAML / TOML / RON) via `StructuralData`.
-///
-/// # Syntax
-///
-/// ```rust,ignore
-/// pack_err_structural!(ErrorNotFound);
-/// pack_err_structural!(ErrorNotDir = PathBuf);
-/// ```
-///
-/// Requires the `structural_renderer` and `extras` features.
-#[cfg(all(feature = "structural_renderer", feature = "extras"))]
-#[proc_macro]
-pub fn pack_err_structural(input: TokenStream) -> TokenStream {
- func::pack_err_structural::pack_err_structural(input)
-}
-
/// Early-returns the error from a `Result`, converting the `Ok` branch to the
/// next chain process value.
///
@@ -555,7 +396,7 @@ pub fn empty_result(input: TokenStream) -> TokenStream {
///
/// The macro generates:
///
-/// 1. **Entry struct** — A `pack!`-style wrapper around `Vec<String>` (the raw args).
+/// 1. **Entry struct** — A newtype wrapper around `Vec<String>` (the raw args).
/// Registered in the program enum via `register_type!`.
/// 2. **Dispatcher struct** — A hidden zero-sized struct implementing [`Dispatcher<Program>`]:
/// - `begin(args)` wraps `args` into the entry type and routes to chain.
@@ -664,78 +505,89 @@ pub fn dispatcher(input: TokenStream) -> TokenStream {
/// # Sync Example
///
/// ```rust,ignore
-/// use mingling::macros::{chain, pack, gen_program};
+/// use mingling::macros::{chain, gen_program};
+/// use mingling::{Grouped, Wrap};
///
-/// pack!(MyOutput = String);
+/// #[derive(Grouped, Wrap)]
+/// pub struct MyOutput(String);
///
/// #[chain]
/// fn greet(prev: HelloEntry) -> Next {
/// let name = prev.first().cloned().unwrap_or_else(|| "World".to_string());
-/// MyOutput::new(name)
+/// MyOutput(name)
/// }
/// ```
///
/// # Sync Example with Resource Injection
///
/// ```rust,ignore
-/// use mingling::macros::{chain, pack, gen_program};
+/// use mingling::macros::{chain, gen_program};
+/// use mingling::{Grouped, Wrap};
///
/// #[derive(Default, Clone)]
/// struct UserName(String);
///
-/// pack!(Greeting = String);
-/// pack!(DisplayCount = ());
+/// #[derive(Grouped, Wrap)]
+/// pub struct Greeting(String);
+/// #[derive(Grouped, Wrap)]
+/// pub struct DisplayCount(());
///
/// #[chain]
/// fn greet(prev: HelloEntry, user_name: &UserName, count: &mut u64) -> Next {
/// *count += 1;
-/// Greeting::new(format!("Hello, {}!", user_name.0))
+/// Greeting(format!("Hello, {}!", user_name.0))
/// }
/// ```
///
/// # Async Example (with `async` feature)
///
/// ```rust,ignore
-/// use mingling::macros::{chain, pack, gen_program};
+/// use mingling::macros::{chain, gen_program};
+/// use mingling::{Grouped, Wrap};
///
-/// pack!(MyOutput = String);
+/// #[derive(Grouped, Wrap)]
+/// pub struct MyOutput(String);
///
/// #[chain]
/// async fn greet(prev: HelloEntry) -> Next {
/// let name = prev.first().cloned().unwrap_or_else(|| "World".to_string());
/// some_async_fn(&name).await;
-/// MyOutput::new(name)
+/// MyOutput(name)
/// }
/// ```
///
/// # Async Example with Immutable Resource Injection
///
/// ```rust,ignore
-/// use mingling::macros::{chain, pack, gen_program};
+/// use mingling::macros::{chain, gen_program};
+/// use mingling::{Grouped, Wrap};
///
-/// pack!(MyOutput = String);
+/// #[derive(Grouped, Wrap)]
+/// pub struct MyOutput(String);
///
/// #[chain]
/// async fn greet(prev: HelloEntry, prefix: &Prefix) -> Next {
/// let name = prev.first().cloned().unwrap_or_else(|| "World".to_string());
/// some_async_fn(&name).await;
-/// MyOutput::new(format!("{}{}", prefix.0, name))
+/// MyOutput(format!("{}{}", prefix.0, name))
/// }
/// ```
///
/// # Async Example with Mutable Resource Injection
///
/// ```rust,ignore
-/// use mingling::macros::{chain, pack, gen_program};
+/// use mingling::macros::{chain, gen_program};
+/// use mingling::{Grouped, Wrap};
///
-/// pack!(MyOutput = String);
+/// #[derive(Grouped, Wrap)]
+/// pub struct MyOutput(String);
///
/// #[chain]
/// async fn greet(prev: HelloEntry, ec: &mut ResExitCode) -> Next {
/// let name = prev.first().cloned().unwrap_or_else(|| "World".to_string());
/// ec.exit_code = 42;
/// some_async_fn(&name).await;
-/// MyOutput::new(name)
+/// MyOutput(name)
/// }
/// ```
///
@@ -777,10 +629,12 @@ pub fn chain(attr: TokenStream, item: TokenStream) -> TokenStream {
/// # Example
///
/// ```rust,ignore
-/// use mingling::macros::{renderer, pack, gen_program};
+/// use mingling::macros::{renderer, gen_program};
+/// use mingling::{Grouped, Wrap};
/// use std::io::Write;
///
-/// pack!(Greeting = String);
+/// #[derive(Grouped, Wrap)]
+/// pub struct Greeting(String);
///
/// #[renderer]
/// fn render_greeting(prev: Greeting) -> RenderResult {
@@ -1063,7 +917,7 @@ pub fn dispatcher_clap(attr: TokenStream, item: TokenStream) -> TokenStream {
/// Creates a packed entry value from a list of string literals.
///
/// This is a convenience macro for constructing entry wrapper types (created
-/// via `pack!` or `dispatcher!`) with test data, typically used in unit tests
+/// via `dispatcher!`) with test data, typically used in unit tests
/// or quick prototypes.
///
/// # Syntax
@@ -1071,9 +925,9 @@ pub fn dispatcher_clap(attr: TokenStream, item: TokenStream) -> TokenStream {
/// Two forms:
///
/// ```rust,ignore
-/// // Named form — wraps into a specific pack type:
+/// // Named form — wraps into a specific entry type:
/// entry!(MyEntry, ["a", "b", "c"])
-/// // Expands to: MyEntry::new(vec!["a".to_string(), "b".to_string(), "c".to_string()])
+/// // Expands to: MyEntry(vec!["a".to_string(), "b".to_string(), "c".to_string()])
///
/// // Bracket form — returns Vec<String>.into() for type inference:
/// entry!["a", "b", "c"]
@@ -1085,7 +939,7 @@ pub fn dispatcher_clap(attr: TokenStream, item: TokenStream) -> TokenStream {
/// ```rust,ignore
/// use mingling::macros::entry;
///
-/// // Named form (with a specific pack type):
+/// // Named form (with a specific entry type):
/// let args = entry!(MyEntry, ["--name", "Alice", "--count", "5"]);
///
/// // Bracket form (type inference):
@@ -1094,8 +948,7 @@ pub fn dispatcher_clap(attr: TokenStream, item: TokenStream) -> TokenStream {
///
/// # See also
///
-/// - `pack!` — For creating the wrapper types used with `entry!`.
-/// - `dispatcher!` — Which implicitly creates entry types via `pack!`.
+/// - `dispatcher!` — Which implicitly creates entry types.
#[cfg(feature = "extras")]
#[proc_macro]
pub fn entry(input: TokenStream) -> TokenStream {
@@ -1204,11 +1057,12 @@ pub fn register_dispatcher(input: TokenStream) -> TokenStream {
/// # Example
///
/// ```rust,ignore
-/// use mingling::macros::{help, pack, gen_program};
+/// use mingling::macros::{help, gen_program};
/// use mingling::{prelude::*, setup::BasicProgramSetup, RenderResult};
/// use std::io::Write;
///
-/// pack!(MyEntry = Vec<String>);
+/// #[derive(Grouped, Wrap)]
+/// pub struct MyEntry(Vec<String>);
///
/// #[help]
/// fn help_my_entry(prev: MyEntry) -> RenderResult {
@@ -1620,8 +1474,8 @@ pub fn derive_wrap(input: TokenStream) -> TokenStream {
/// }
/// ```
///
-/// This is equivalent to using `pack!` but works with custom structs that
-/// have named fields. For simple wrappers, prefer `pack!`.
+/// This is equivalent to using `#[derive(Grouped)]` but works with custom structs that
+/// have named fields.
#[proc_macro_derive(Grouped, attributes(group))]
pub fn derive_grouped(input: TokenStream) -> TokenStream {
grouped::derive_grouped(input)
@@ -1813,7 +1667,7 @@ pub fn program_comp_gen(input: TokenStream) -> TokenStream {
/// Registers a type into the global packed types registry for inclusion in
/// the program enum generated by `gen_program!`.
///
-/// This macro is called internally by `pack!` and `#[derive(Grouped)]`(`macro.derive_grouped.html`)
+/// This macro is called internally by `#[derive(Grouped)]` (`macro.derive_grouped.html`)
/// and is generally not needed in user code. However, it can be used for manual
/// registration if you are implementing custom type registration outside of
/// the standard macros.
@@ -1885,7 +1739,7 @@ pub fn program_fallback_gen(input: TokenStream) -> TokenStream {
/// and its `ProgramCollect` implementation.
///
/// This is the core code generation macro that:
-/// 1. Collects all registered types (from `pack!`, `#[derive(Grouped)]`, etc.) and
+/// 1. Collects all registered types (from `#[derive(Grouped)]`, etc.) and
/// creates an enum with each type as a variant.
/// 2. Generates the `Display` implementation for the enum.
/// 3. Generates the `ProgramCollect` implementation that dispatches to all
diff --git a/mingling_macros/src/systems.rs b/mingling_macros/src/systems.rs
index ef3624e..3279b51 100644
--- a/mingling_macros/src/systems.rs
+++ b/mingling_macros/src/systems.rs
@@ -1,8 +1,7 @@
-// Doc Not Optimize
#[cfg(not(feature = "dispatch_tree"))]
pub(crate) mod dispatch_list_gen;
+
#[cfg(feature = "dispatch_tree")]
pub(crate) mod dispatch_tree_gen;
+
pub(crate) mod res_injection;
-#[cfg(feature = "structural_renderer")]
-pub(crate) mod structural_data;
diff --git a/mingling_macros/src/systems/structural_data.rs b/mingling_macros/src/systems/structural_data.rs
deleted file mode 100644
index ac9b1ca..0000000
--- a/mingling_macros/src/systems/structural_data.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// Doc Not Optimize
-//! Legacy structural data module.
-//!
-//! Functions have been moved to:
-//! - `derive::structural_data` — `derive_structural_data`
-//! - `func::pack_structural` — `pack_structural`
-//! - `func::group_structural` — `group_structural`