From 57c53affe3542cb6bd4e79ee4c18f20a1bd76b2d Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Mon, 17 Aug 2026 05:49:19 +0800 Subject: 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. --- docs/pages/4-render-result.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'docs/pages/4-render-result.md') diff --git a/docs/pages/4-render-result.md b/docs/pages/4-render-result.md index fdf8b12..70ffc96 100644 --- a/docs/pages/4-render-result.md +++ b/docs/pages/4-render-result.md @@ -3,7 +3,7 @@ Declare a renderer using the #[renderer] macro to output results.

-Now we've created a Dispatcher and a Chain, and produced a Result type via `pack!`. The final step: **present the result to the user**. +Now we've created a Dispatcher and a Chain, and produced a Result type via `#[derive(Grouped, Wrap)]`. The final step: **present the result to the user**. ## The `#[renderer]` Macro @@ -11,7 +11,8 @@ Similar to `#[chain]`, `#[renderer]` marks a function that produces output: ```rust @@@use mingling::macros::buffer; -@@@pack!(ResultName = String); +@@@#[derive(Grouped, Wrap)] +@@@pub struct ResultName(String); #[renderer(buffer)] fn render_name(name: ResultName) { r_println!("Hello, {}!", *name); @@ -27,7 +28,8 @@ If you find explicitly creating and returning a `RenderResult` too verbose, you ```rust use mingling::macros::buffer; -@@@pack!(ResultName = String); +@@@#[derive(Grouped, Wrap)] +@@@pub struct ResultName(String); #[renderer(buffer)] fn render_name(name: ResultName) { r_println!("Hello, {}!", *name); @@ -54,17 +56,18 @@ use mingling::macros::buffer; // 1. Declare commands with a Dispatcher dispatcher!("greet", EntryGreet); -// 2. Declare result data with pack! -pack!(ResultName = String); +// 2. Declare result data with #[derive(Grouped, Wrap)] +#[derive(Grouped, Wrap)] +pub struct ResultName(String); // 3. Handle logic with a Chain #[chain] fn handle_greet(args: EntryGreet) -> Next { - let name = args.inner + let name = args.0 .first() .cloned() .unwrap_or_else(|| "World".to_string()); - ResultName::new(name).into() + ResultName(name).into() } // 4. Output results with a Renderer @@ -122,10 +125,10 @@ use mingling::macros::buffer; #[renderer(buffer)] fn render_entry_fallback(err: EntryFallback) { - if err.inner.is_empty() { + if err.0.is_empty() { r_println!("Unknown command"); } else { - r_println!("Command not found: \"{}\"", err.inner.join(" ")); + r_println!("Command not found: \"{}\"", err.0.join(" ")); } } ``` @@ -144,13 +147,13 @@ Command not found: "great" You've completed your first full Mingling program! Let's recap what you've learned: -| Concept | Macro / Function | One-liner | -| -------------- | ---------------- | --------------------------------------- | -| Declare cmds | `dispatcher!` | Tell the program what the user can type | -| Handle logic | `#[chain]` | What to do when args are received | -| Output results | `#[renderer]` | How to present results to the user | -| Type wrapping | `pack!` | Give your data a meaningful name | -| Program entry | `gen_program!()` | Auto-generate the pipeline wiring | +| Concept | Macro / Function | One-liner | +| -------------- | -------------------------- | --------------------------------------- | +| Declare cmds | `dispatcher!` | Tell the program what the user can type | +| Handle logic | `#[chain]` | What to do when args are received | +| Output results | `#[renderer]` | How to present results to the user | +| Type wrapping | `#[derive(Grouped, Wrap)]` | Give your data a meaningful name | +| Program entry | `gen_program!()` | Auto-generate the pipeline wiring | In real projects you'll also use advanced features like resource injection, hooks, completions, REPL, etc., but the core skeleton stays the same: **Dispatcher → Chain → Renderer**. -- cgit