From 2b0a2771bb5fcb57bfeeb6b20ec2d3f19ad7f2be Mon Sep 17 00:00:00 2001
From: 魏曹先生 <1992414357@qq.com>
Date: Sun, 19 Jul 2026 06:04:42 +0800
Subject: docs: add GETTING_STARTED.md and update README icon size
---
GETTING_STARTED.md | 775 ++++++++++++++++++++++++++++++++++++++++++++++
README.md | 879 ++++-------------------------------------------------
verified-docs.toml | 1 +
3 files changed, 843 insertions(+), 812 deletions(-)
create mode 100644 GETTING_STARTED.md
diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md
new file mode 100644
index 0000000..dbea3d2
--- /dev/null
+++ b/GETTING_STARTED.md
@@ -0,0 +1,775 @@
+# Writing with Mingling
+
+## The Big Picture
+
+Mingling organizes your CLI program into three distinct phases:
+
+```
+Input → [Dispatcher] → Entry → [Chain(s)] → Result → [Renderer] → Output
+```
+
+**Step 1: Input** — The user's raw arguments flow in.
+**Step 2: Dispatch** — The **Dispatcher** receives them and wraps them into an **Entry** type.
+**Step 3: Chain** — The Entry is handed to a **Chain** function for processing.
+**Step 4: Render** — The **Renderer** receives the result and writes it to the terminal.
+
+> [!NOTE]
+> A Chain can produce a **State** type, passed to the next Chain for further processing,
+>
+> or it can produce a **Result** type, handed to the Renderer for output.
+
+Every step in this pipeline is a **pure function** annotated with an attribute macro, and the framework recognizes them as long as they meet the requirements.
+
+---
+
+## 1. Defining Commands — `dispatcher!`
+
+The entry point for every subcommand is the `dispatcher!` macro. It generates two structs for you: a **Dispatcher** (used to register the command with the program) and an **Entry** (a wrapper around `Vec` that holds the raw arguments).
+
+```rust
+use mingling::prelude::*;
+
+// command.name Dispatcher EntryType
+// │ │ │
+dispatcher!("greet", CMDGreet => EntryGreet);
+
+// Nested subcommand: `remote add`
+dispatcher!("remote.add", CMDRemoteAdd => EntryRemoteAdd);
+```
+
+Then in `main()`, register the dispatcher with the program:
+
+```rust
+dispatcher!("greet", CMDGreet => EntryGreet);
+
+fn main() {
+ let mut program = ThisProgram::new();
+ program.with_dispatcher(CMDGreet);
+ program.exec_and_exit();
+}
+```
+
+Mingling also supports an abbreviated form (with the `extra_macros` feature):
+
+```rust
+// Features: ["extra_macros"]
+
+// Auto-generates CMDGreet / EntryGreet from "greet"
+dispatcher!("greet");
+```
+
+---
+
+## 2. The Chain — "#[chain]" — Where Logic Lives
+
+The `#[chain]` attribute turns a plain function into an execution step. Think of it as "the logic that transforms one typed value into another."
+
+```rust
+dispatcher!("greet", CMDGreet => EntryGreet);
+
+pack!(ResultGreeting = String);
+
+#[chain]
+fn handle_greet(args: EntryGreet) -> Next {
+ let greeting = args
+ .inner
+ .first()
+ .cloned()
+ .unwrap_or_else(|| "World".to_string());
+ ResultGreeting::new(greeting).into()
+}
+```
+
+Key points:
+
+- The return type is `Next` — a type alias for `ChainProcess`.
+- You chain results by calling `.to_chain()` on any `pack!`-ed type.
+- You can have **multiple chain functions** for the same command, each transforming the data further.
+- With the `async` feature, chain functions can be `async fn`.
+
+---
+
+## 3. The Renderer — "#[renderer]" — How Output Works
+
+The `#[renderer]` attribute turns a function into an output handler. It receives the final result of a chain and returns a `RenderResult`.
+
+```rust
+use mingling::macros::pack;
+use mingling::prelude::*;
+use std::io::Write;
+
+pack!(ResultGreeting = String);
+
+#[renderer]
+fn render_greeting(greeting: ResultGreeting) -> RenderResult {
+ let mut result = RenderResult::new();
+ writeln!(result, "Hello, {}!", *greeting).ok();
+ result
+}
+```
+
+Inside a renderer, create a `RenderResult`, write to it using `write!` / `writeln!` (from [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html)), and return it. The output is captured in the buffer and flushed by the framework at the end of the pipeline.
+
+You can write renderers for **any type** in your program, including error types:
+
+```rust
+use mingling::prelude::*;
+use std::io::Write;
+
+#[renderer]
+fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) -> RenderResult {
+ let mut result = RenderResult::new();
+ writeln!(result, "Command not found: [{}]", err.join(" ")).ok();
+ result
+}
+```
+
+---
+
+## 4. Parsing Arguments — The Picker
+
+Mingling provides a **Picker** for zero-cost argument extraction. You use `pick()` or `pick_or()` on an entry to extract typed values, then `unpack()` to get the final tuple.
+
+```rust
+// Features: ["parser"]
+
+use mingling::parser::Picker;
+
+dispatcher!("greet", CMDGreet => EntryGreet);
+pack!(ResultGreeting = String);
+
+#[chain]
+fn handle_greet(args: EntryGreet) -> Next {
+ let (name, count) = Picker::new(args.inner)
+ .pick::(()) // positional: first string
+ .pick_or::(["-r", "--repeat"], 1) // optional flag with default
+ .unpack();
+ ResultGreeting::new(format!("{} x{}", name, count)).into()
+}
+```
+
+With the `parser` feature, the `AsPicker` trait provides a shorthand directly on entries:
+
+```rust
+// Features: ["parser"]
+
+dispatcher!("greet", CMDGreet => EntryGreet);
+pack!(ResultGreeting = String);
+
+#[chain]
+fn handle(args: EntryGreet) -> Next {
+ let (name, count) = args
+ .pick::
-> [!WARNING]
->
-> **Note**: Mingling is still under active development, and its API may change. Feel free to try it out and give us feedback!
-> **Hint**: This note will be removed in version `0.5.0`
+## What is Mingling?
-
- What is Mingling?
-
+[`Mingling`](https://github.com/mingling-rs/mingling) is a **state-driven and data-driven** CLI workflow orchestration framework built in Rust.
-[`Mingling`](https://github.com/mingling-rs/mingling) is a **proc-macro and type-system based** Rust CLI framework, suitable for developing complex command-line programs with numerous subcommands.
+💡 Its name comes from the Chinese pinyin **"Mìng Lìng"**, which means **"command"**.
-> Its name comes from the Chinese Pinyin **"Mìng Lìng"**, meaning **"Command"**.
+## WARNING
-### Mingling's Core Capabilities
+Mingling is currently usable at a basic level, but it is still under active development, so many APIs are not yet mature. Any changes to the public API will be documented in detail in the [Changelog](https://github.com/mingling-rs/mingling/blob/main/CHANGELOG.md).
-1. **Separation of Concerns, Clear Logic**: Mingling decouples logic by responsibility, helping you organize your CLI program more clearly.
- See example: [Example](https://github.com/mingling-rs/mingling/blob/main/examples/example-basic/src/main.rs)
-2. **"All Logic is Functions"**: Execution logic, rendering logic, completion logic, help logic — everything is a function. Just attach the corresponding attribute macro to bind them to your program.
-3. **Fully Dynamic Completion System**: With the `comp` feature, you can flexibly implement dynamic completion logic for any subcommand.
- See examples: [Example](https://github.com/mingling-rs/mingling/blob/main/examples/example-completion/src/main.rs)
-4. **Lightning-Fast Subcommand Dispatch**: With the `dispatch_tree` feature, Mingling hardens the subcommand structure into a prefix tree at **compile time**, enabling blazing-fast subcommand lookup.
- See examples: [Example](https://github.com/mingling-rs/mingling/blob/main/examples/example-dispatch-tree/src/main.rs)
-5. **Lightweight Dependencies, On-Demand Importing**: Minimal core dependencies keep builds fast; enhanced features are imported on demand through fine-grained feature flags.
-6. **Structured Output**: Enabling the `structural_renderer` feature adds support for flags like `--json` and `--yaml`, providing structured output capabilities.
- See examples: [Example](https://github.com/mingling-rs/mingling/blob/main/examples/example-structural-renderer/src/main.rs)
+Additionally, the project is currently developed by me alone ([Weicao-CatilGrass](https://github.com/Weicao-CatilGrass)). If you are interested in this project, I warmly welcome your [contributions](https://github.com/mingling-rs/mingling/blob/main/CONTRIBUTING.md). You can reach me directly via [Github Issue](https://github.com/mingling-rs/mingling/issues).
----
+## About Mingling's Design
-**💡 To learn more, check out the following links:**
-
-- 📖 [Mainpage](https://mingling-rs.github.io/mingling/)
-- 📖 [Examples](https://mingling-rs.github.io/mingling/docs/examples.html)
-- 📖 [docs.rs](https://docs.rs/mingling/latest/mingling/)
-- 📖 [Helpdoc](https://mingling-rs.github.io/mingling/docs/doc.html#/) Or [帮助文档](https://mingling-rs.github.io/mingling/docs/_zh_CN/index.html#/)
-- 🔍 [Devdoc](https://mingling-rs.github.io/mingling/docs/dev/)
-
-
- Getting Started
-
-
-Add Mingling to your `Cargo.toml`:
-
-```toml
-[dependencies.mingling]
-version = "0.3.0"
-features = []
-```
-
-Or use the github version
-
-```toml
-[dependencies.mingling]
-git = "https://github.com/mingling-rs/mingling.git"
-tag = "unreleased"
-features = []
-```
-
-Or use the [template project](https://github.com/mingling-rs/mingling-template):
-
-```bash
-cargo generate --git mingling-rs/mingling-template
-```
-
-
- Writing with Mingling
-
-
-### The Big Picture
-
-Mingling organizes your CLI program into three distinct phases:
-
-```
-User Input → [Dispatcher] → Entry → [Chain(s)] → Result → [Renderer] → Output
-```
-
-**Step1: Input** — The user's raw arguments flow in.
-**Step2: Dispatch** — A **Dispatcher** picks them up and wraps them into an **Entry** type.
-**Step3: Chain** — The entry is handed off to a **Chain** function, which processes it.
-**Step4: Render** — A **Renderer** takes that result and writes it to the terminal.
-
-> [!NOTE]
-> A Chain can produce a **State** type to be passed to the next Chain for further processing,
->
-> or it can produce a **Result** type to be handed off to a Renderer.
-
-Everything in this pipeline is a **plain Rust function** with an attribute macro on top.
-
-You never need to manually implement traits or construct boilerplate.
-
----
-
-### 1. Defining Commands — `dispatcher!`
-
-The entry point for every subcommand is the `dispatcher!` macro. It generates two structs for you: a **Dispatcher** (used to register the command with the program) and an **Entry** (a wrapper around `Vec` that holds the raw arguments).
-
-```rust
-use mingling::prelude::*;
-
-// "command.name" Dispatcher EntryType
-// │ │ │
-dispatcher!("greet", CMDGreet => EntryGreet);
-
-// Nested subcommand: `remote add`
-dispatcher!("remote.add", CMDRemoteAdd => EntryRemoteAdd);
-```
-
-Then in `main()`, register the dispatcher with the program:
-
-```rust
-dispatcher!("greet", CMDGreet => EntryGreet);
-
-fn main() {
- let mut program = ThisProgram::new();
- program.with_dispatcher(CMDGreet);
- program.exec_and_exit();
-}
-```
-
-Mingling also supports an abbreviated form (with the `extra_macros` feature):
-
-```rust
-// Features: ["extra_macros"]
-
-// Auto-generates CMDGreet / EntryGreet from "greet"
-dispatcher!("greet");
-```
-
----
-
-### 2. The Chain — "#[chain]" — Where Logic Lives
-
-The `#[chain]` attribute turns a plain function into an execution step. Think of it as "the logic that transforms one typed value into another."
-
-```rust
-dispatcher!("greet", CMDGreet => EntryGreet);
-
-pack!(ResultGreeting = String);
-
-#[chain]
-fn handle_greet(args: EntryGreet) -> Next {
- let greeting = args
- .inner
- .first()
- .cloned()
- .unwrap_or_else(|| "World".to_string());
- ResultGreeting::new(greeting).into()
-}
-```
-
-Key points:
-
-- The return type is `Next` — a type alias for `ChainProcess`.
-- You chain results by calling `.to_chain()` on any `pack!`-ed type.
-- You can have **multiple chain functions** for the same command, each transforming the data further.
-- With the `async` feature, chain functions can be `async fn`.
-
----
-
-### 3. The Renderer — "#[renderer]" — How Output Works
-
-The `#[renderer]` attribute turns a function into an output handler. It receives the final result of a chain and returns a `RenderResult`.
-
-```rust
-use mingling::macros::pack;
-use mingling::prelude::*;
-use std::io::Write;
-
-pack!(ResultGreeting = String);
-
-#[renderer]
-fn render_greeting(greeting: ResultGreeting) -> RenderResult {
- let mut result = RenderResult::new();
- writeln!(result, "Hello, {}!", *greeting).ok();
- result
-}
-```
-
-Inside a renderer, create a `RenderResult`, write to it using `write!` / `writeln!` (from [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html)), and return it. The output is captured in the buffer and flushed by the framework at the end of the pipeline.
-
-You can write renderers for **any type** in your program, including error types:
-
-```rust
-use mingling::prelude::*;
-use std::io::Write;
-
-#[renderer]
-fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) -> RenderResult {
- let mut result = RenderResult::new();
- writeln!(result, "Command not found: [{}]", err.join(" ")).ok();
- result
-}
-```
-
----
-
-### 4. Parsing Arguments — The Picker
-
-Mingling provides a **Picker** for zero-cost argument extraction. You use `pick()` or `pick_or()` on an entry to extract typed values, then `unpack()` to get the final tuple.
-
-```rust
-// Features: ["parser"]
-
-use mingling::parser::Picker;
-
-dispatcher!("greet", CMDGreet => EntryGreet);
-pack!(ResultGreeting = String);
-
-#[chain]
-fn handle_greet(args: EntryGreet) -> Next {
- let (name, count) = Picker::new(args.inner)
- .pick::(()) // positional: first string
- .pick_or::(["-r", "--repeat"], 1) // optional flag with default
- .unpack();
- ResultGreeting::new(format!("{} x{}", name, count)).into()
-}
-```
-
-With the `parser` feature, the `AsPicker` trait provides a shorthand directly on entries:
-
-```rust
-// Features: ["parser"]
-
-dispatcher!("greet", CMDGreet => EntryGreet);
-pack!(ResultGreeting = String);
-
-#[chain]
-fn handle(args: EntryGreet) -> Next {
- let (name, count) = args
- .pick::