From 0bed1f9063d81aab827dc8b26d925341b59d12e6 Mon Sep 17 00:00:00 2001
From: 魏曹先生 <1992414357@qq.com>
Date: Thu, 13 Aug 2026 01:53:21 +0800
Subject: docs: rename command macro issue as solved
---
docs/dev/pages/issues/_the-command-macro.md | 169 ++++++++++++++++++++++++++++
docs/dev/pages/issues/the-command-macro.md | 169 ----------------------------
2 files changed, 169 insertions(+), 169 deletions(-)
create mode 100644 docs/dev/pages/issues/_the-command-macro.md
delete mode 100644 docs/dev/pages/issues/the-command-macro.md
diff --git a/docs/dev/pages/issues/_the-command-macro.md b/docs/dev/pages/issues/_the-command-macro.md
new file mode 100644
index 0000000..47f1e51
--- /dev/null
+++ b/docs/dev/pages/issues/_the-command-macro.md
@@ -0,0 +1,169 @@
+
[Solved] The Command Macro
+
+ A macro for quickly building commands
+
+
+Mingling's macro syntax has been largely stabilized since 0.3.0, and significant changes are not expected going forward — now is the perfect time to introduce some syntactic sugar.
+
+## The Problem
+
+For a long time, creating a command in Mingling required the following steps:
+
+**Step 1: Declare the entry point with `dispatcher!`**
+
+```rust
+// Full form: declare dispatcher and entry types
+dispatcher!("greet", CMDGreet => EntryGreet);
+```
+
+Or use the implicit syntax provided by `extras` (automatically deriving `CMDGreet` and `EntryGreet`):
+
+```rust
+dispatcher!("greet");
+```
+
+**Step 2: Register the dispatcher in `main`**
+
+```rust
+fn main() {
+ let mut program = ThisProgram::new();
+ program.with_dispatcher(CMDGreet);
+ program.exec_and_exit();
+}
+```
+
+**Step 3: Write the handling logic with `#[chain]`**
+
+```rust
+#[chain]
+fn handle_greet(args: EntryGreet) -> Next {
+ // ...
+}
+```
+
+Three steps, three concepts (`dispatcher!`, `CMD*`, `#[chain]`), repeated for every new command. It made me wonder: do we really need to write this much boilerplate so often?
+
+## The Design: `#[command]`
+
+To provide a more concise approach, I plan to add the `#[command]` attribute macro, merging `dispatcher!` and `#[chain]` into a single step.
+
+### Basic Usage
+
+`#[command]` is applied to a function whose signature must satisfy two constraints:
+
+- **First argument**: Any type `T` such that `EntryGreet: Into` (equivalent to `T: From`)
+- **Return type**: Any type `R` such that `R: Into` (`Next` is `ChainProcess`, generated by `gen_program!()`)
+
+The `pack!(EntryGreet = Vec)` generated by `dispatcher!("greet")` automatically provides `From for Vec`, so the most common pattern is to use `Vec` as the first argument:
+
+```rust
+use mingling::prelude::*;
+
+#[command]
+fn greet(args: Vec) -> Next {
+ let name = args.first().cloned().unwrap_or_else(|| "World".into());
+ ResultName::new(name).into()
+}
+```
+
+This expands to:
+
+```rust
+// Automatically generates the dispatcher
+dispatcher!("greet");
+
+// Automatically generates the chain handler, bridging EntryGreet → T
+// Here T = Vec, EntryGreet: Into>
+#[chain]
+fn __command_handle_greet(args: EntryGreet) -> Next {
+ greet(args.into()).into()
+}
+
+// The original function remains unchanged
+fn greet(args: Vec) -> Next {
+ let name = args.first().cloned().unwrap_or_else(|| "World".into());
+ ResultName::new(name).into()
+}
+```
+
+| Mapping | Rule |
+| ----------------------- | ------------------------------------------------------------------------------------------------------- |
+| Command name | The function name is used directly as the command name, e.g. `fn greet(...)` → `"greet"` |
+| First argument | Any `T: From`, the macro-generated chain performs the conversion via `args.into()` |
+| Return value | Any `R: Into`, the macro-generated chain converts it via `.into()` to `ChainProcess` |
+| Dispatcher registration | You must manually call `program.with_dispatcher(CMDGreet)` in `main` |
+
+### Resource Injection
+
+`#[command]` also supports resource injection, following the same rules as `#[chain]` — from the second argument onward, use `&T` or `&mut T` to declare resource references:
+
+```rust
+#[command]
+fn greet(args: Vec, ec: &mut ResExitCode) -> Next {
+ ec.exit_code = 1;
+ let name = args.first().cloned().unwrap_or_else(|| "World".into());
+ ResultName::new(name).into()
+}
+```
+
+This expands to:
+
+```rust
+dispatcher!("greet");
+
+#[chain]
+fn __command_handle_greet(args: EntryGreet, ec: &mut ResExitCode) -> Next {
+ greet(args.into(), ec).into()
+}
+
+fn greet(args: Vec, ec: &mut ResExitCode) -> Next {
+ ec.exit_code = 1;
+ let name = args.first().cloned().unwrap_or_else(|| "World".into());
+ ResultName::new(name).into()
+}
+```
+
+### Implicit vs Explicit
+
+`#[command]` is syntactic sugar over `dispatcher!("name")` + `#[chain]`. It makes the generation of the `dispatcher` and `chain` more implicit, but dramatically reduces boilerplate:
+
+```rust
+// Before
+dispatcher!("greet", CMDGreet => EntryGreet);
+
+#[chain]
+fn handle_greet(args: EntryGreet) -> Next {
+ // ...
+}
+
+// After
+#[command]
+fn greet(args: Vec) -> Next {
+ // ...
+}
+```
+
+Whenever you need fine-grained control over the behavior of the Dispatcher or Chain (e.g., customizing the `node` path, adding extra derive attributes to the Entry type), you can always fall back to the original explicit form. The two approaches do not conflict.
+
+## On Naming
+
+In Mingling, there is no concept called `Command` — all behavior is the result of dispatchers producing Entry types that are routed through the Program pipeline. The combination of `Dispatcher` + `Chain` is the standard way to build a Command, so using `#[command]` to generate `dispatcher!` and `#[chain]` makes semantic sense.
+
+## Enabling
+
+This macro requires the `extras` feature. Enable it in your `Cargo.toml`:
+
+```toml
+[dependencies]
+mingling = { version = "...", features = ["extras"] }
+```
+
+## Caveats
+
+- The `CMDGreet` generated by `#[command]` is a regular struct and still needs to be manually registered with the Program via `program.with_dispatcher(CMDGreet)`.
+- If the function name contains non-alphabetic characters (such as underscores), the command name will be used as-is. For example, `fn add_remote(...)` corresponds to the command name `"add_remote"`.
+- Nested commands (e.g., `"remote.add"`) cannot be expressed directly with `#[command]`; use the traditional `dispatcher!("remote.add")` form instead.
+
+
+ Written by @Weicao-CatilGrass · Revised for clarity
+
diff --git a/docs/dev/pages/issues/the-command-macro.md b/docs/dev/pages/issues/the-command-macro.md
deleted file mode 100644
index 82d733c..0000000
--- a/docs/dev/pages/issues/the-command-macro.md
+++ /dev/null
@@ -1,169 +0,0 @@
-The Command Macro
-
- A macro for quickly building commands
-
-
-Mingling's macro syntax has been largely stabilized since 0.3.0, and significant changes are not expected going forward — now is the perfect time to introduce some syntactic sugar.
-
-## The Problem
-
-For a long time, creating a command in Mingling required the following steps:
-
-**Step 1: Declare the entry point with `dispatcher!`**
-
-```rust
-// Full form: declare dispatcher and entry types
-dispatcher!("greet", CMDGreet => EntryGreet);
-```
-
-Or use the implicit syntax provided by `extras` (automatically deriving `CMDGreet` and `EntryGreet`):
-
-```rust
-dispatcher!("greet");
-```
-
-**Step 2: Register the dispatcher in `main`**
-
-```rust
-fn main() {
- let mut program = ThisProgram::new();
- program.with_dispatcher(CMDGreet);
- program.exec_and_exit();
-}
-```
-
-**Step 3: Write the handling logic with `#[chain]`**
-
-```rust
-#[chain]
-fn handle_greet(args: EntryGreet) -> Next {
- // ...
-}
-```
-
-Three steps, three concepts (`dispatcher!`, `CMD*`, `#[chain]`), repeated for every new command. It made me wonder: do we really need to write this much boilerplate so often?
-
-## The Design: `#[command]`
-
-To provide a more concise approach, I plan to add the `#[command]` attribute macro, merging `dispatcher!` and `#[chain]` into a single step.
-
-### Basic Usage
-
-`#[command]` is applied to a function whose signature must satisfy two constraints:
-
-- **First argument**: Any type `T` such that `EntryGreet: Into` (equivalent to `T: From`)
-- **Return type**: Any type `R` such that `R: Into` (`Next` is `ChainProcess`, generated by `gen_program!()`)
-
-The `pack!(EntryGreet = Vec)` generated by `dispatcher!("greet")` automatically provides `From for Vec`, so the most common pattern is to use `Vec` as the first argument:
-
-```rust
-use mingling::prelude::*;
-
-#[command]
-fn greet(args: Vec) -> Next {
- let name = args.first().cloned().unwrap_or_else(|| "World".into());
- ResultName::new(name).into()
-}
-```
-
-This expands to:
-
-```rust
-// Automatically generates the dispatcher
-dispatcher!("greet");
-
-// Automatically generates the chain handler, bridging EntryGreet → T
-// Here T = Vec, EntryGreet: Into>
-#[chain]
-fn __command_handle_greet(args: EntryGreet) -> Next {
- greet(args.into()).into()
-}
-
-// The original function remains unchanged
-fn greet(args: Vec) -> Next {
- let name = args.first().cloned().unwrap_or_else(|| "World".into());
- ResultName::new(name).into()
-}
-```
-
-| Mapping | Rule |
-| ----------------------- | ------------------------------------------------------------------------------------------------------- |
-| Command name | The function name is used directly as the command name, e.g. `fn greet(...)` → `"greet"` |
-| First argument | Any `T: From`, the macro-generated chain performs the conversion via `args.into()` |
-| Return value | Any `R: Into`, the macro-generated chain converts it via `.into()` to `ChainProcess` |
-| Dispatcher registration | You must manually call `program.with_dispatcher(CMDGreet)` in `main` |
-
-### Resource Injection
-
-`#[command]` also supports resource injection, following the same rules as `#[chain]` — from the second argument onward, use `&T` or `&mut T` to declare resource references:
-
-```rust
-#[command]
-fn greet(args: Vec, ec: &mut ResExitCode) -> Next {
- ec.exit_code = 1;
- let name = args.first().cloned().unwrap_or_else(|| "World".into());
- ResultName::new(name).into()
-}
-```
-
-This expands to:
-
-```rust
-dispatcher!("greet");
-
-#[chain]
-fn __command_handle_greet(args: EntryGreet, ec: &mut ResExitCode) -> Next {
- greet(args.into(), ec).into()
-}
-
-fn greet(args: Vec, ec: &mut ResExitCode) -> Next {
- ec.exit_code = 1;
- let name = args.first().cloned().unwrap_or_else(|| "World".into());
- ResultName::new(name).into()
-}
-```
-
-### Implicit vs Explicit
-
-`#[command]` is syntactic sugar over `dispatcher!("name")` + `#[chain]`. It makes the generation of the `dispatcher` and `chain` more implicit, but dramatically reduces boilerplate:
-
-```rust
-// Before
-dispatcher!("greet", CMDGreet => EntryGreet);
-
-#[chain]
-fn handle_greet(args: EntryGreet) -> Next {
- // ...
-}
-
-// After
-#[command]
-fn greet(args: Vec) -> Next {
- // ...
-}
-```
-
-Whenever you need fine-grained control over the behavior of the Dispatcher or Chain (e.g., customizing the `node` path, adding extra derive attributes to the Entry type), you can always fall back to the original explicit form. The two approaches do not conflict.
-
-## On Naming
-
-In Mingling, there is no concept called `Command` — all behavior is the result of dispatchers producing Entry types that are routed through the Program pipeline. The combination of `Dispatcher` + `Chain` is the standard way to build a Command, so using `#[command]` to generate `dispatcher!` and `#[chain]` makes semantic sense.
-
-## Enabling
-
-This macro requires the `extras` feature. Enable it in your `Cargo.toml`:
-
-```toml
-[dependencies]
-mingling = { version = "...", features = ["extras"] }
-```
-
-## Caveats
-
-- The `CMDGreet` generated by `#[command]` is a regular struct and still needs to be manually registered with the Program via `program.with_dispatcher(CMDGreet)`.
-- If the function name contains non-alphabetic characters (such as underscores), the command name will be used as-is. For example, `fn add_remote(...)` corresponds to the command name `"add_remote"`.
-- Nested commands (e.g., `"remote.add"`) cannot be expressed directly with `#[command]`; use the traditional `dispatcher!("remote.add")` form instead.
-
-
- Written by @Weicao-CatilGrass · Revised for clarity
-
--
cgit