aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/_zh_CN/pages/11-resource-system.md2
-rw-r--r--docs/_zh_CN/pages/3-define-a-chain.md8
-rw-r--r--docs/_zh_CN/pages/4-render-result.md2
-rw-r--r--docs/_zh_CN/pages/5-multiple-commands.md8
-rw-r--r--docs/_zh_CN/pages/6-argument-parse-picker.md16
-rw-r--r--docs/_zh_CN/pages/7-argument-parse-clap.md4
-rw-r--r--docs/_zh_CN/pages/advanced/2-structural-renderer.md6
-rw-r--r--docs/_zh_CN/pages/concepts/3-any-output.md10
-rw-r--r--docs/_zh_CN/pages/other/features.md22
-rw-r--r--docs/_zh_CN/pages/other/naming_rule.md2
-rw-r--r--docs/dev/pages/abouts/ci.md35
-rw-r--r--docs/dev/pages/issues/add-picker2.md2
-rw-r--r--docs/example-pages/examples.json15
-rw-r--r--docs/pages/11-resource-system.md2
-rw-r--r--docs/pages/3-define-a-chain.md8
-rw-r--r--docs/pages/4-render-result.md2
-rw-r--r--docs/pages/5-multiple-commands.md8
-rw-r--r--docs/pages/6-argument-parse-picker.md14
-rw-r--r--docs/pages/7-argument-parse-clap.md4
-rw-r--r--docs/pages/advanced/2-structural-renderer.md6
-rw-r--r--docs/pages/concepts/3-any-output.md10
-rw-r--r--docs/pages/other/features.md22
-rw-r--r--docs/pages/other/naming_rule.md2
23 files changed, 133 insertions, 77 deletions
diff --git a/docs/_zh_CN/pages/11-resource-system.md b/docs/_zh_CN/pages/11-resource-system.md
index 152e5d6..a8aab4d 100644
--- a/docs/_zh_CN/pages/11-resource-system.md
+++ b/docs/_zh_CN/pages/11-resource-system.md
@@ -57,7 +57,7 @@ fn render_path(result: ResultPath) -> RenderResult {
#[chain]
fn handle_visit(_args: EntryVisit, counter: &mut ResVisitCount) -> Next {
counter.0 += 1;
- ResultDone::default()
+ ResultDone::default().into()
}
#[renderer]
diff --git a/docs/_zh_CN/pages/3-define-a-chain.md b/docs/_zh_CN/pages/3-define-a-chain.md
index 7ac5c60..f845d11 100644
--- a/docs/_zh_CN/pages/3-define-a-chain.md
+++ b/docs/_zh_CN/pages/3-define-a-chain.md
@@ -24,7 +24,7 @@ fn handle_greet(args: EntryGreet) -> Next {
// args 就是用户输入经过匹配后剩下的参数
let name = args.inner.first().cloned().unwrap_or_else(|| "World".to_string());
// 把结果包装成 Next,告诉调度器下一步去哪
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -48,7 +48,7 @@ Chain 函数签名里写着它需要什么——`args: EntryGreet`
```rust
// pack!(ResultName = String) 大概生成了这样的代码
-#[derive(Groupped)]
+#[derive(Grouped)]
pub struct ResultName {
pub inner: String,
}
@@ -88,7 +88,7 @@ fn handle_greet(args: EntryGreet) -> Next {
.cloned()
.unwrap_or_else(|| "World".to_string());
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -112,7 +112,7 @@ fn handle_greet(args: EntryGreet) -> Next {
.first()
.cloned()
.unwrap_or_else(|| "World".to_string());
- ResultName::new(name)
+ ResultName::new(name).into()
}
fn main() {
diff --git a/docs/_zh_CN/pages/4-render-result.md b/docs/_zh_CN/pages/4-render-result.md
index 7cf2d2b..81c5102 100644
--- a/docs/_zh_CN/pages/4-render-result.md
+++ b/docs/_zh_CN/pages/4-render-result.md
@@ -51,7 +51,7 @@ fn handle_greet(args: EntryGreet) -> Next {
.first()
.cloned()
.unwrap_or_else(|| "World".to_string());
- ResultName::new(name)
+ ResultName::new(name).into()
}
// 4. 用 Renderer 输出结果
diff --git a/docs/_zh_CN/pages/5-multiple-commands.md b/docs/_zh_CN/pages/5-multiple-commands.md
index 7d2617b..38ce2cf 100644
--- a/docs/_zh_CN/pages/5-multiple-commands.md
+++ b/docs/_zh_CN/pages/5-multiple-commands.md
@@ -20,13 +20,13 @@ pack!(ResultSum = i32);
#[chain]
fn handle_greet(args: EntryGreet) -> Next {
let name = args.inner.first().cloned().unwrap_or_else(|| "World".to_string());
- ResultGreeting::new(name)
+ ResultGreeting::new(name).into()
}
#[chain]
fn handle_add(args: EntryAdd) -> Next {
let sum: i32 = args.inner.iter().filter_map(|s| s.parse::<i32>().ok()).sum();
- ResultSum::new(sum)
+ ResultSum::new(sum).into()
}
#[renderer]
@@ -70,9 +70,9 @@ Sum: 6
@@@dispatcher!("add", CMDAdd => EntryAdd);
@@@pack!(ResultGreeting = String);
@@@pack!(ResultSum = i32);
-@@@#[chain] fn handle_greet(_args: EntryGreet) -> Next { ResultGreeting::new("ok".into()) }
+@@@#[chain] fn handle_greet(_args: EntryGreet) -> Next { ResultGreeting::new("ok".into()).into() }
@@@#[renderer] fn render_greet(_greeting: ResultGreeting) -> RenderResult { RenderResult::new() }
-@@@#[chain] fn handle_add(_args: EntryAdd) -> Next { ResultSum::new(0) }
+@@@#[chain] fn handle_add(_args: EntryAdd) -> Next { ResultSum::new(0).into() }
@@@#[renderer] fn render_sum(_sum: ResultSum) -> RenderResult { RenderResult::new() }
fn main() {
let mut program = ThisProgram::new();
diff --git a/docs/_zh_CN/pages/6-argument-parse-picker.md b/docs/_zh_CN/pages/6-argument-parse-picker.md
index b41f839..4bf162c 100644
--- a/docs/_zh_CN/pages/6-argument-parse-picker.md
+++ b/docs/_zh_CN/pages/6-argument-parse-picker.md
@@ -32,7 +32,7 @@ features = ["parser"]
#[chain]
fn handle_greet_entry(prev: EntryGreet) -> Next {
let name = prev.pick_or((), "World").unpack();
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -47,7 +47,7 @@ fn handle_greet_entry(prev: EntryGreet) -> Next {
@@@#[chain]
@@@fn handle_greet_entry(prev: EntryGreet) -> Next {
let name = prev.pick_or((), "World").unpack();
-@@@ResultName::new(name)
+@@@ResultName::new(name).into()
@@@}
```
@@ -82,7 +82,7 @@ let name = prev.pick_or((), "World").unpack();
#[chain]
fn handle_greet_entry(prev: EntryGreet) -> Next {
let name = prev.pick_or(["--name", "-n"], "World").unpack();
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -124,7 +124,7 @@ fn handle_test_entry(prev: EntryTest) -> Next {
.pick::<u32>(["--id", "-I"])
.unpack();
- ResultInfo::new((name, age, id))
+ ResultInfo::new((name, age, id)).into()
}
```
@@ -199,7 +199,7 @@ let name = match pick_result {
在您使用 `pick` 提取了用户输入后,可以使用 `after` 立刻处理该参数
-```rust
+````rust
// Features: ["parser"]
@@@dispatcher!("greet", CMDGreet => EntryGreet);
@@@pack!(ResultName = String);
@@ -217,7 +217,7 @@ fn handle_greet_entry(prev: EntryGreet) -> Next {
})
.unpack();
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -338,7 +338,7 @@ impl Pickable for Address {
#[chain]
fn handle_connect_entry(prev: EntryConnect) -> Next {
let address: Address = prev.pick("--addr").unpack();
- ResultConnected::new(address)
+ ResultConnected::new(address).into()
}
#[renderer]
@@ -379,7 +379,7 @@ impl PickableEnum for Fruits {}
#[chain]
fn handle_eat_entry(prev: EntryEat) -> Next {
let fruit: Fruits = prev.pick("--fruit").unpack();
- ResultFruit::new(fruit)
+ ResultFruit::new(fruit).into()
}
#[renderer]
diff --git a/docs/_zh_CN/pages/7-argument-parse-clap.md b/docs/_zh_CN/pages/7-argument-parse-clap.md
index 7dce301..21f886c 100644
--- a/docs/_zh_CN/pages/7-argument-parse-clap.md
+++ b/docs/_zh_CN/pages/7-argument-parse-clap.md
@@ -25,7 +25,7 @@ features = ["derive", "color"]
// Dependencies:
// clap = "4"
@@@ use mingling::macros::dispatcher_clap;
-#[derive(Default, clap::Parser, Groupped)]
+#[derive(Default, clap::Parser, Grouped)]
#[dispatcher_clap("greet", CMDGreet, help = true, error = ErrorGreetParsed)]
pub struct EntryGreet {
#[clap(default_value = "World")]
@@ -64,7 +64,7 @@ fn render_greet_parse_failed(err: ErrorGreetParsed) -> RenderResult {
// clap = "4"
@@@use mingling::setup::BasicProgramSetup;
@@@use mingling::macros::dispatcher_clap;
-@@@#[derive(Default, clap::Parser, Groupped)]
+@@@#[derive(Default, clap::Parser, Grouped)]
@@@#[dispatcher_clap("greet", CMDGreet)]
@@@pub struct EntryGreet {
@@@ name: String,
diff --git a/docs/_zh_CN/pages/advanced/2-structural-renderer.md b/docs/_zh_CN/pages/advanced/2-structural-renderer.md
index 9a4f111..70bed79 100644
--- a/docs/_zh_CN/pages/advanced/2-structural-renderer.md
+++ b/docs/_zh_CN/pages/advanced/2-structural-renderer.md
@@ -37,7 +37,7 @@ pack_structural!(ResultInfo = (String, i32));
fn handle_render(args: EntryRender) -> Next {
let name = args.inner.first().cloned().unwrap_or_default();
let age = args.inner.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
- ResultInfo::new((name, age))
+ ResultInfo::new((name, age)).into()
}
#[renderer]
@@ -62,7 +62,7 @@ fn render_info(r: ResultInfo) -> RenderResult {
## 自定义输出结构
-`pack_structural!` 的默认输出包含 `inner` 字段。要完全控制输出结构,可以用 `#[derive(StructuralData, Serialize, Groupped)]` 手动定义类型:
+`pack_structural!` 的默认输出包含 `inner` 字段。要完全控制输出结构,可以用 `#[derive(StructuralData, Serialize, Grouped)]` 手动定义类型:
```rust
// Features: ["structural_renderer"]
@@ -74,7 +74,7 @@ fn render_info(r: ResultInfo) -> RenderResult {
@@@use serde::Serialize;
@@@dispatcher!("render", CMDRender => EntryRender);
-#[derive(Serialize, StructuralData, Groupped)]
+#[derive(Serialize, StructuralData, Grouped)]
struct Info {
name: String,
age: i32,
diff --git a/docs/_zh_CN/pages/concepts/3-any-output.md b/docs/_zh_CN/pages/concepts/3-any-output.md
index 9b820da..118e856 100644
--- a/docs/_zh_CN/pages/concepts/3-any-output.md
+++ b/docs/_zh_CN/pages/concepts/3-any-output.md
@@ -20,7 +20,7 @@ AnyOutput<G>
这里的 `G` 就是 `gen_program!()` 生成的程序枚举(也就是你熟知的 `ThisProgram`)。
-每个被 `pack!` 或 `#[derive(Groupped)]` 标记的类型都被分配到这个枚举的一个变体。
+每个被 `pack!` 或 `#[derive(Grouped)]` 标记的类型都被分配到这个枚举的一个变体。
## ChainProcess:数据 + 路由
@@ -38,17 +38,17 @@ ChainProcess<G>
调度器根据 `NextProcess` 决定是继续循环还是退出渲染。
-## Groupped:谁是谁
+## Grouped:谁是谁
-调度器如何知道 `AnyOutput` 里装的是 `ResultName` 还是 `ErrorUserBlocked`?答案是 `Groupped` trait:
+调度器如何知道 `AnyOutput` 里装的是 `ResultName` 还是 `ErrorUserBlocked`?答案是 `Grouped` trait:
```
-trait Groupped<G> {
+trait Grouped<G> {
fn member_id() -> G;
}
```
-当你用 `pack!(ResultName = String)` 时,宏自动为 `ResultName` 实现 `Groupped`,`member_id()` 返回枚举中对应的变体。调度器一看 `member_id`,就去找对应的 Chain 或 Renderer。
+当你用 `pack!(ResultName = String)` 时,宏自动为 `ResultName` 实现 `Grouped`,`member_id()` 返回枚举中对应的变体。调度器一看 `member_id`,就去找对应的 Chain 或 Renderer。
`to_chain()` 和 `to_render()` 本质上是 `AnyOutput` 的快捷方法,分别构造 `ChainProcess::Ok(any, Chain)` 和 `ChainProcess::Ok(any, Renderer)`。
diff --git a/docs/_zh_CN/pages/other/features.md b/docs/_zh_CN/pages/other/features.md
index bfd9efc..8bd386c 100644
--- a/docs/_zh_CN/pages/other/features.md
+++ b/docs/_zh_CN/pages/other/features.md
@@ -24,7 +24,7 @@ pack!(StateFoo = ());
#[chain]
async fn handle_state_foo(foo: StateFoo) -> Next {
- StateFoo::new(())
+ StateFoo::new(()).into()
}
```
@@ -160,7 +160,7 @@ use mingling::macros::entry;
pack!(EntryHello = Vec<String>);
fn main() {
- let result = handle_hello(entry!("--name", "Bob")).into();
+ let result: Next = handle_hello(entry!("--name", "Bob")).into();
// ... 此处为断言逻辑
}
@@ -171,7 +171,7 @@ fn handle_hello(args: EntryHello) {}
### `group!`
将外部类型注册为程序组成员,无需修改原始类型的定义。
-类型名会直接作为枚举变体,与 `pack!` 或 `#[derive(Groupped)]` 一致。
+类型名会直接作为枚举变体,与 `pack!` 或 `#[derive(Grouped)]` 一致。
```rust
// Features: ["extra_macros"]
@@ -274,12 +274,24 @@ analyze_and_build_type_mapping().unwrap();
**介绍:**
-启用解析器模块,提供文本解析和语法分析功能。
+启用参数解析器模块,提供参数解析功能。
-开启后可以使用 `Picker` 进行零成本的参数提取,支持 `pick()` 和 `pick_or()` 等方法。
+开启后可以使用 `Picker` 进行简易的参数提取,支持 `pick()` 和 `pick_or()` 等方法。
详见 [示例](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-argument-parse)
+## 特性 `picker`
+
+**介绍:**
+
+引入依赖 `arg-picker`,为 Mingling 提供更高级的参数解析能力。
+
+它可以与 `parser`、`clap` 特性共存,但建议不要和 `parser` 特性同时启用,因为两者的 API 极为相似。
+
+`picker` 是独立于 Mingling 的参数解析器,不依赖 `mingling_core` 的内置参数提取 API。
+
+详见 [示例](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-argument-picker)
+
## 特性 `repl`
**介绍:**
diff --git a/docs/_zh_CN/pages/other/naming_rule.md b/docs/_zh_CN/pages/other/naming_rule.md
index 5f2ac34..c854ba1 100644
--- a/docs/_zh_CN/pages/other/naming_rule.md
+++ b/docs/_zh_CN/pages/other/naming_rule.md
@@ -96,7 +96,7 @@ Result + 内容
| `ResultGreetSomeone` | 问候结果 |
| `ResultFruitList` | 水果列表结果 |
-结果结构体期望被 Renderer 消费,内部结构应该为了渲染美观而设计。一般用 `#[derive(Groupped)]` 代替 `pack!()` 包装,以获得更灵活的字段控制。
+结果结构体期望被 Renderer 消费,内部结构应该为了渲染美观而设计。一般用 `#[derive(Grouped)]` 代替 `pack!()` 包装,以获得更灵活的字段控制。
### 错误
diff --git a/docs/dev/pages/abouts/ci.md b/docs/dev/pages/abouts/ci.md
index 3a93c1c..8b59b72 100644
--- a/docs/dev/pages/abouts/ci.md
+++ b/docs/dev/pages/abouts/ci.md
@@ -37,11 +37,11 @@ cargo ci
- **Test all examples**: Runs the `test-examples` tool.
- **Verify Markdown code blocks compile**: Runs the `test-all-markdown-code` tool to check code blocks in all `*.md` files. See [ABOUT_CODE_VERIFY](docs/_ABOUT_CODE_VERIFY.md) for details.
- **Check if documentation is up to date**: Runs the following documentation refresh tools in sequence:
- - `docs-code-box-fix`
- - `docsify-sidebar-gen`
- - `refresh-docs`
- - `refresh-feature-mod`
- - `sync-examples`
+ - `docs-code-box-fix`
+ - `docsify-sidebar-gen`
+ - `refresh-docs`
+ - `refresh-feature-mod`
+ - `sync-examples`
- Finally, runs `cargo fmt` to unify code formatting.
### 3. File Normalization
@@ -53,11 +53,11 @@ Runs `git add --renormalize .` to ensure file attributes such as line endings co
To ensure reproducible CI results, `ci.rs` imposes strict requirements on the workspace state:
- If the current workspace is not clean and `--dirty` has not been specified, the script will prompt whether to create a temporary commit:
- - The commit message is `[DO NOT PUSH] CI TEMP [DO NOT PUSH]`.
- - Use `-y` to auto-confirm without interaction.
+ - The commit message is `[DO NOT PUSH] CI TEMP [DO NOT PUSH]`.
+ - Use `-y` to auto-confirm without interaction.
- After CI finishes, the script automatically restores the workspace:
- - First, `git reset --hard` discards all changes.
- - If a temporary commit was created, it then runs `git reset --soft HEAD~1` and unstages everything, restoring the state to before CI started.
+ - First, `git reset --hard` discards all changes.
+ - If a temporary commit was created, it then runs `git reset --soft HEAD~1` and unstages everything, restoring the state to before CI started.
- If `--dirty` is specified, the temporary commit and the final cleanliness check are skipped.
> **Warning**: `git reset --hard` is executed at the end of CI. If you use `--dirty`, ensure you have no unsaved important changes.
@@ -69,3 +69,20 @@ To ensure reproducible CI results, `ci.rs` imposes strict requirements on the wo
- Triggered on `push` to the `main` branch.
- Runs `cargo ci` in parallel on `ubuntu-latest` and `windows-latest`.
- After CI passes, the `unreleased` tag is automatically moved to the latest commit on `main`.
+
+### 4. API Documentation Deployment
+
+After all checks pass, the `Deploy-Github-Pages` job:
+
+- **Runs `deploy-api-docs`**: Executes `cargo run --manifest-path .run/Cargo.toml --bin deploy-api-docs`, which reads the `[package.metadata.docs.rs]` features from `mingling/Cargo.toml` and builds the crate's documentation via `cargo doc --no-deps`. The output is placed at `docs/api-docs/`.
+- **Deploys to GitHub Pages**: The entire repository (including the generated `docs/api-docs/`) is uploaded and published to GitHub Pages.
+
+You can view the published API documentation at:
+
+> [https://mingling-rs.github.io/mingling/docs/api-docs/mingling/](https://mingling-rs.github.io/mingling/docs/api-docs/mingling/)
+
+To generate API docs locally:
+
+```bash
+cargo run --manifest-path .run/Cargo.toml --bin deploy-api-docs
+```
diff --git a/docs/dev/pages/issues/add-picker2.md b/docs/dev/pages/issues/add-picker2.md
index f5c3ca7..6fe4418 100644
--- a/docs/dev/pages/issues/add-picker2.md
+++ b/docs/dev/pages/issues/add-picker2.md
@@ -40,7 +40,7 @@ fn handle_hello(args: EntryHello) {
```rust
#[chain]
fn handle_hello(args: EntryHello) -> Next {
- // requires impl Groupped<_>
+ // requires impl Grouped<_>
// |
let parsed = args // vvvvvvvvvvvvvvvvvvv
.pick_route::<String, _>(positional!(), ErrorNoNameProvided)
diff --git a/docs/example-pages/examples.json b/docs/example-pages/examples.json
index a539011..2a07365 100644
--- a/docs/example-pages/examples.json
+++ b/docs/example-pages/examples.json
@@ -31,6 +31,21 @@
]
},
{
+ "id": "example-argument-picker",
+ "name": "Argument Picker",
+ "icon": "📋",
+ "category": "parsing",
+ "desc": "Demonstrates how to use Mingling's `picker` feature and `Picker` to extract typed arguments from the command line.\n",
+ "tags": [
+ "arg-picker",
+ "SinglePickable"
+ ],
+ "files": [
+ "src/main.rs",
+ "Cargo.toml"
+ ]
+ },
+ {
"id": "example-async-support",
"name": "Async Support",
"icon": "⚡",
diff --git a/docs/pages/11-resource-system.md b/docs/pages/11-resource-system.md
index bc2197f..9491212 100644
--- a/docs/pages/11-resource-system.md
+++ b/docs/pages/11-resource-system.md
@@ -57,7 +57,7 @@ Use `&mut T` to inject a mutable resource:
#[chain]
fn handle_visit(_args: EntryVisit, counter: &mut ResVisitCount) -> Next {
counter.0 += 1;
- ResultDone::default()
+ ResultDone::default().into()
}
#[renderer]
diff --git a/docs/pages/3-define-a-chain.md b/docs/pages/3-define-a-chain.md
index c6d3f8e..450522b 100644
--- a/docs/pages/3-define-a-chain.md
+++ b/docs/pages/3-define-a-chain.md
@@ -24,7 +24,7 @@ fn handle_greet(args: EntryGreet) -> Next {
// args contains the remaining params after matching user input
let name = args.inner.first().cloned().unwrap_or_else(|| "World".to_string());
// Wrap the result into Next, telling the dispatcher where to go next
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -48,7 +48,7 @@ You've probably guessed it — `pack!(ResultName = String)` defines a type that
```rust
// pack!(ResultName = String) generates code roughly like this
-#[derive(Groupped)]
+#[derive(Grouped)]
pub struct ResultName {
pub inner: String,
}
@@ -88,7 +88,7 @@ fn handle_greet(args: EntryGreet) -> Next {
.cloned()
.unwrap_or_else(|| "World".to_string());
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -112,7 +112,7 @@ fn handle_greet(args: EntryGreet) -> Next {
.first()
.cloned()
.unwrap_or_else(|| "World".to_string());
- ResultName::new(name)
+ ResultName::new(name).into()
}
fn main() {
diff --git a/docs/pages/4-render-result.md b/docs/pages/4-render-result.md
index b1365b8..ca1e563 100644
--- a/docs/pages/4-render-result.md
+++ b/docs/pages/4-render-result.md
@@ -51,7 +51,7 @@ fn handle_greet(args: EntryGreet) -> Next {
.first()
.cloned()
.unwrap_or_else(|| "World".to_string());
- ResultName::new(name)
+ ResultName::new(name).into()
}
// 4. Output results with a Renderer
diff --git a/docs/pages/5-multiple-commands.md b/docs/pages/5-multiple-commands.md
index a56f7b0..d9a335a 100644
--- a/docs/pages/5-multiple-commands.md
+++ b/docs/pages/5-multiple-commands.md
@@ -20,13 +20,13 @@ pack!(ResultSum = i32);
#[chain]
fn handle_greet(args: EntryGreet) -> Next {
let name = args.inner.first().cloned().unwrap_or_else(|| "World".to_string());
- ResultGreeting::new(name)
+ ResultGreeting::new(name).into()
}
#[chain]
fn handle_add(args: EntryAdd) -> Next {
let sum: i32 = args.inner.iter().filter_map(|s| s.parse::<i32>().ok()).sum();
- ResultSum::new(sum)
+ ResultSum::new(sum).into()
}
#[renderer]
@@ -70,9 +70,9 @@ Notice `with_dispatchers`? When you need to register multiple dispatchers, just
@@@dispatcher!("add", CMDAdd => EntryAdd);
@@@pack!(ResultGreeting = String);
@@@pack!(ResultSum = i32);
-@@@#[chain] fn handle_greet(_args: EntryGreet) -> Next { ResultGreeting::new("ok".into()) }
+@@@#[chain] fn handle_greet(_args: EntryGreet) -> Next { ResultGreeting::new("ok".into()).into() }
@@@#[renderer] fn render_greet(_greeting: ResultGreeting) -> RenderResult { RenderResult::new() }
-@@@#[chain] fn handle_add(_args: EntryAdd) -> Next { ResultSum::new(0) }
+@@@#[chain] fn handle_add(_args: EntryAdd) -> Next { ResultSum::new(0).into() }
@@@#[renderer] fn render_sum(_sum: ResultSum) -> RenderResult { RenderResult::new() }
fn main() {
let mut program = ThisProgram::new();
diff --git a/docs/pages/6-argument-parse-picker.md b/docs/pages/6-argument-parse-picker.md
index c80c25c..398cd3c 100644
--- a/docs/pages/6-argument-parse-picker.md
+++ b/docs/pages/6-argument-parse-picker.md
@@ -32,7 +32,7 @@ Now let's look at `Picker` in action:
#[chain]
fn handle_greet_entry(prev: EntryGreet) -> Next {
let name = prev.pick_or((), "World").unpack();
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -47,7 +47,7 @@ Breaking down the example above:
@@@#[chain]
@@@fn handle_greet_entry(prev: EntryGreet) -> Next {
let name = prev.pick_or((), "World").unpack();
-@@@ResultName::new(name)
+@@@ResultName::new(name).into()
@@@}
```
@@ -82,7 +82,7 @@ If your program needs to parse flag args (e.g., `greet --name Alice`), do this:
#[chain]
fn handle_greet_entry(prev: EntryGreet) -> Next {
let name = prev.pick_or(["--name", "-n"], "World").unpack();
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -124,7 +124,7 @@ fn handle_test_entry(prev: EntryTest) -> Next {
.pick::<u32>(["--id", "-I"])
.unpack();
- ResultInfo::new((name, age, id))
+ ResultInfo::new((name, age, id)).into()
}
```
@@ -224,7 +224,7 @@ fn handle_greet_entry(prev: EntryGreet) -> Next {
})
.unpack();
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -345,7 +345,7 @@ impl Pickable for Address {
#[chain]
fn handle_connect_entry(prev: EntryConnect) -> Next {
let address: Address = prev.pick("--addr").unpack();
- ResultConnected::new(address)
+ ResultConnected::new(address).into()
}
#[renderer]
@@ -387,7 +387,7 @@ impl PickableEnum for Fruits {}
#[chain]
fn handle_eat_entry(prev: EntryEat) -> Next {
let fruit: Fruits = prev.pick("--fruit").unpack();
- ResultFruit::new(fruit)
+ ResultFruit::new(fruit).into()
}
#[renderer]
diff --git a/docs/pages/7-argument-parse-clap.md b/docs/pages/7-argument-parse-clap.md
index b11e00e..86fce35 100644
--- a/docs/pages/7-argument-parse-clap.md
+++ b/docs/pages/7-argument-parse-clap.md
@@ -25,7 +25,7 @@ Add `#[dispatcher_clap]` on a `clap::Parser` struct to auto-generate a Dispatche
// Dependencies:
// clap = "4"
@@@ use mingling::macros::dispatcher_clap;
-#[derive(Default, clap::Parser, Groupped)]
+#[derive(Default, clap::Parser, Grouped)]
#[dispatcher_clap("greet", CMDGreet, help = true, error = ErrorGreetParsed)]
pub struct EntryGreet {
#[clap(default_value = "World")]
@@ -64,7 +64,7 @@ If you need `--help` support, register `BasicProgramSetup` in main and set the c
// clap = "4"
@@@use mingling::setup::BasicProgramSetup;
@@@use mingling::macros::dispatcher_clap;
-@@@#[derive(Default, clap::Parser, Groupped)]
+@@@#[derive(Default, clap::Parser, Grouped)]
@@@#[dispatcher_clap("greet", CMDGreet)]
@@@pub struct EntryGreet {
@@@ name: String,
diff --git a/docs/pages/advanced/2-structural-renderer.md b/docs/pages/advanced/2-structural-renderer.md
index f31f758..910b197 100644
--- a/docs/pages/advanced/2-structural-renderer.md
+++ b/docs/pages/advanced/2-structural-renderer.md
@@ -37,7 +37,7 @@ pack_structural!(ResultInfo = (String, i32));
fn handle_render(args: EntryRender) -> Next {
let name = args.inner.first().cloned().unwrap_or_default();
let age = args.inner.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
- ResultInfo::new((name, age))
+ ResultInfo::new((name, age)).into()
}
#[renderer]
@@ -62,7 +62,7 @@ When the user passes `--json`, the framework automatically serializes the render
## Customizing Output Structure
-The default output from `pack_structural!` includes an `inner` field. For full control over the output structure, define the type manually with `#[derive(StructuralData, Serialize, Groupped)]`:
+The default output from `pack_structural!` includes an `inner` field. For full control over the output structure, define the type manually with `#[derive(StructuralData, Serialize, Grouped)]`:
```rust
// Features: ["structural_renderer"]
@@ -74,7 +74,7 @@ The default output from `pack_structural!` includes an `inner` field. For full c
@@@use serde::Serialize;
@@@dispatcher!("render", CMDRender => EntryRender);
-#[derive(Serialize, StructuralData, Groupped)]
+#[derive(Serialize, StructuralData, Grouped)]
struct Info {
name: String,
age: i32,
diff --git a/docs/pages/concepts/3-any-output.md b/docs/pages/concepts/3-any-output.md
index f780377..f02805f 100644
--- a/docs/pages/concepts/3-any-output.md
+++ b/docs/pages/concepts/3-any-output.md
@@ -20,7 +20,7 @@ AnyOutput<G>
Here `G` is the program enum generated by `gen_program!()` (i.e., `ThisProgram` as you know it).
-Each type annotated with `pack!` or `#[derive(Groupped)]` is assigned to one variant of this enum.
+Each type annotated with `pack!` or `#[derive(Grouped)]` is assigned to one variant of this enum.
## ChainProcess: Data + Routing
@@ -38,17 +38,17 @@ This is why a Chain function returns `ChainProcess` instead of raw data—it bun
The dispatcher reads `NextProcess` to decide whether to continue the loop or exit to rendering.
-## Groupped: Who Is Who
+## Grouped: Who Is Who
-How does the dispatcher know whether an `AnyOutput` holds a `ResultName` or an `ErrorUserBlocked`? The answer is the `Groupped` trait:
+How does the dispatcher know whether an `AnyOutput` holds a `ResultName` or an `ErrorUserBlocked`? The answer is the `Grouped` trait:
```
-trait Groupped<G> {
+trait Grouped<G> {
fn member_id() -> G;
}
```
-When you use `pack!(ResultName = String)`, the macro automatically implements `Groupped` for `ResultName`, and `member_id()` returns the corresponding enum variant. The dispatcher looks at `member_id` and finds the matching Chain or Renderer.
+When you use `pack!(ResultName = String)`, the macro automatically implements `Grouped` for `ResultName`, and `member_id()` returns the corresponding enum variant. The dispatcher looks at `member_id` and finds the matching Chain or Renderer.
`to_chain()` and `to_render()` are essentially convenience methods on `AnyOutput` that construct `ChainProcess::Ok(any, Chain)` and `ChainProcess::Ok(any, Renderer)` respectively.
diff --git a/docs/pages/other/features.md b/docs/pages/other/features.md
index 813ccdd..7994d4c 100644
--- a/docs/pages/other/features.md
+++ b/docs/pages/other/features.md
@@ -24,7 +24,7 @@ pack!(StateFoo = ());
#[chain]
async fn handle_state_foo(foo: StateFoo) -> Next {
- StateFoo::new(())
+ StateFoo::new(()).into()
}
```
@@ -160,7 +160,7 @@ use mingling::macros::entry;
pack!(EntryHello = Vec<String>);
fn main() {
- let result = handle_hello(entry!("--name", "Bob")).into();
+ let result: Next = handle_hello(entry!("--name", "Bob")).into();
// ... assertion logic here
}
@@ -171,7 +171,7 @@ fn handle_hello(args: EntryHello) {}
### `group!`
Registers an external type as a member of the program group without modifying its definition.
-The type's simple name is used as the enum variant, just like `pack!` or `#[derive(Groupped)]`.
+The type's simple name is used as the enum variant, just like `pack!` or `#[derive(Grouped)]`.
```rust
// Features: ["extra_macros"]
@@ -274,12 +274,24 @@ See [example](https://mingling-rs.github.io/mingling/docs/example-viewer.html?na
**Description:**
-Enables the parser module, providing text parsing and analysis capabilities.
+Enables the argument parser module, providing argument parsing functionality.
-When enabled, you can use `Picker` for zero-cost argument extraction, supporting methods like `pick()` and `pick_or()`.
+When enabled, you can use `Picker` for simple argument extraction, supporting methods like `pick()` and `pick_or()`.
See [example](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-argument-parse)
+## Feature `picker`
+
+**Description:**
+
+Introduces the `arg-picker` dependency, providing more advanced argument parsing capabilities for Mingling.
+
+It can coexist with the `parser` and `clap` features, but it is recommended not to enable it alongside the `parser` feature, as their APIs are very similar.
+
+`picker` is an argument parser independent of Mingling and does not rely on the built-in argument extraction API of `mingling_core`.
+
+See [example](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-argument-picker)
+
## Feature `repl`
**Description:**
diff --git a/docs/pages/other/naming_rule.md b/docs/pages/other/naming_rule.md
index 2ede61f..089a711 100644
--- a/docs/pages/other/naming_rule.md
+++ b/docs/pages/other/naming_rule.md
@@ -96,7 +96,7 @@ Result + Content
| `ResultGreetSomeone` | Greeting result |
| `ResultFruitList` | Fruit list result |
-Result structs are expected to be consumed by the Renderer, and their internal structure should be designed for rendering aesthetics. Generally use `#[derive(Groupped)]` instead of `pack!()` wrapping for more flexible field control.
+Result structs are expected to be consumed by the Renderer, and their internal structure should be designed for rendering aesthetics. Generally use `#[derive(Grouped)]` instead of `pack!()` wrapping for more flexible field control.
### Error