aboutsummaryrefslogtreecommitdiff
path: root/docs/_zh_CN/pages
diff options
context:
space:
mode:
Diffstat (limited to 'docs/_zh_CN/pages')
-rw-r--r--docs/_zh_CN/pages/10-help.md26
-rw-r--r--docs/_zh_CN/pages/11-resource-system.md20
-rw-r--r--docs/_zh_CN/pages/14-testing.md2
-rw-r--r--docs/_zh_CN/pages/3-define-a-chain.md8
-rw-r--r--docs/_zh_CN/pages/4-render-result.md51
-rw-r--r--docs/_zh_CN/pages/5-multiple-commands.md25
-rw-r--r--docs/_zh_CN/pages/6-argument-parse-picker.md61
-rw-r--r--docs/_zh_CN/pages/7-argument-parse-clap.md34
-rw-r--r--docs/_zh_CN/pages/9-error-handling.md34
-rw-r--r--docs/_zh_CN/pages/advanced/2-structural-renderer.md24
-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.md19
13 files changed, 165 insertions, 171 deletions
diff --git a/docs/_zh_CN/pages/10-help.md b/docs/_zh_CN/pages/10-help.md
index 8cee2aa..1c4e410 100644
--- a/docs/_zh_CN/pages/10-help.md
+++ b/docs/_zh_CN/pages/10-help.md
@@ -13,18 +13,17 @@ Mingling 里用 `#[help]` 宏给命令添加帮助文本。
```rust
@@@use mingling::macros::help;
+@@@use mingling::macros::buffer;
@@@dispatcher!("greet", CMDGreet => EntryGreet);
-#[help]
-fn help_greet(_entry: EntryGreet) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Usage: greet [name]").ok();
- writeln!(r, "Say hello to someone.").ok();
- r
+#[help(buffer)]
+fn help_greet(_entry: EntryGreet) {
+ r_println!("Usage: greet [name]");
+ r_println!("Say hello to someone.");
}
```
> [!NOTE]
-> 帮助函数同样通过 `writeln!` 向 `RenderResult` 写入内容,因为 `#[help]` 遵循渲染管线 —— 它是由 `--help` 标志提前触发的短路渲染,而不是管线之外的逻辑。
+> 帮助函数同样通过 `r_println!` 向 `RenderResult` 写入内容,因为 `#[help]` 遵循渲染管线 —— 它是由 `--help` 标志提前触发的短路渲染,而不是管线之外的逻辑。
## 全局帮助
@@ -32,14 +31,13 @@ fn help_greet(_entry: EntryGreet) -> RenderResult {
```rust
@@@use mingling::macros::help;
+@@@use mingling::macros::buffer;
// 用户直接输入 --help 时触发
-#[help]
-fn help_root(entry: ErrorDispatcherNotFound) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Usage: my-cli <command>").ok();
- writeln!(r, "Commands:").ok();
- writeln!(r, " greet Say hello").ok();
- r
+#[help(buffer)]
+fn help_root(entry: ErrorDispatcherNotFound) {
+ r_println!("Usage: my-cli <command>");
+ r_println!("Commands:");
+ r_println!(" greet Say hello");
}
```
diff --git a/docs/_zh_CN/pages/11-resource-system.md b/docs/_zh_CN/pages/11-resource-system.md
index 152e5d6..b127a3a 100644
--- a/docs/_zh_CN/pages/11-resource-system.md
+++ b/docs/_zh_CN/pages/11-resource-system.md
@@ -27,6 +27,7 @@ fn main() {
在 Chain 或 Renderer 中,只需在参数列表里声明你要的资源:
```rust
+@@@use mingling::macros::buffer;
@@@#[derive(Default, Clone)]
@@@struct ResCurrentDir(String);
@@@dispatcher!("pwd", CMDPrintWorkingDir => EntryPrintWorkingDir);
@@ -37,11 +38,9 @@ fn handle_pwd(_args: EntryPrintWorkingDir, cwd: &ResCurrentDir) -> Next {
ResultPath::new(cwd.0.clone()).to_render()
}
-#[renderer]
-fn render_path(result: ResultPath) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "{}", *result).ok();
- r
+#[renderer(buffer)]
+fn render_path(result: ResultPath) {
+ r_println!("{}", *result);
}
```
@@ -50,6 +49,7 @@ fn render_path(result: ResultPath) -> RenderResult {
用 `&mut T` 注入可修改资源:
```rust
+@@@use mingling::macros::buffer;
@@@#[derive(Default, Clone)]
@@@struct ResVisitCount(u32);
@@@dispatcher!("visit", CMDVisit => EntryVisit);
@@ -57,14 +57,12 @@ 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]
-fn render_done(_done: ResultDone, counter: &ResVisitCount) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "visit count is : {}", counter.0).ok();
- r
+#[renderer(buffer)]
+fn render_done(_done: ResultDone, counter: &ResVisitCount) {
+ r_println!("visit count is : {}", counter.0);
}
```
diff --git a/docs/_zh_CN/pages/14-testing.md b/docs/_zh_CN/pages/14-testing.md
index 621d43e..031be59 100644
--- a/docs/_zh_CN/pages/14-testing.md
+++ b/docs/_zh_CN/pages/14-testing.md
@@ -16,7 +16,7 @@ Renderer 是最容易测试的——调用函数,断言返回结果:
#[renderer]
fn render_greet(result: ResultName) -> RenderResult {
let mut r = RenderResult::new();
- writeln!(r, "Hello, {}!", *result).ok();
+ r_println!(r, "Hello, {}!", *result);
r
}
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..8b29fca 100644
--- a/docs/_zh_CN/pages/4-render-result.md
+++ b/docs/_zh_CN/pages/4-render-result.md
@@ -10,18 +10,31 @@
跟 `#[chain]` 类似,`#[renderer]` 用于标记一个输出函数:
```rust
-use std::io::Write;
+@@@use mingling::macros::buffer;
+@@@pack!(ResultName = String);
+#[renderer(buffer)]
+fn render_name(name: ResultName) {
+ r_println!("Hello, {}!", *name);
+}
+```
+
+Renderer 接收 Chain 产出的结果,然后返回一个 `RenderResult`。在函数内部,创建 `RenderResult`,用 `r_print!` / `r_println!` 写入内容,最后返回它。
+
+## `buffer` 拓展
+
+若您觉得显式创建并返回 `RenderResult` 过于繁琐,可以使用 `#[renderer(buffer)]` 在原始函数内植入一个缓冲区。
+
+```rust
+use mingling::macros::buffer;
@@@pack!(ResultName = String);
-#[renderer]
-fn render_name(name: ResultName) -> RenderResult {
- let mut result = RenderResult::new();
- writeln!(result, "Hello, {}!", *name).ok();
- result
+#[renderer(buffer)]
+fn render_name(name: ResultName) {
+ r_println!("Hello, {}!", *name);
}
```
-Renderer 接收 Chain 产出的结果,然后返回一个 `RenderResult`。在函数内部,创建 `RenderResult`,用 `write!` / `writeln!`(来自 [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html))写入内容,最后返回它。
+这样,你的 renderer 函数就获得了更简洁的语法,但也引入了一个隐含机制:它会向函数内注入一个名为 `__render_result_buffer` 的可变 `RenderResult`。当 `r_print!` 宏没有显式指定 `RenderResult` 时,它便会按照约定向该缓冲区追加输出。
## `RenderResult` 类型
@@ -36,7 +49,7 @@ Renderer 接收 Chain 产出的结果,然后返回一个 `RenderResult`。在
把三篇教程的内容合在一起,你的第一个 Mingling 程序就完整了:
```rust
-use std::io::Write;
+use mingling::macros::buffer;
// 1. 用 Dispatcher 声明命令
dispatcher!("greet", CMDGreet => EntryGreet);
@@ -51,15 +64,13 @@ fn handle_greet(args: EntryGreet) -> Next {
.first()
.cloned()
.unwrap_or_else(|| "World".to_string());
- ResultName::new(name)
+ ResultName::new(name).into()
}
// 4. 用 Renderer 输出结果
-#[renderer]
-fn render_name(name: ResultName) -> RenderResult {
- let mut result = RenderResult::new();
- writeln!(result, "Hello, {}!", *name).ok();
- result
+#[renderer(buffer)]
+fn render_name(name: ResultName) {
+ r_println!("Hello, {}!", *name);
}
// 5. 在 main 函数内装配程序并运行
@@ -108,17 +119,15 @@ cargo run -- great
`gen_program!()` 自动生成了一个 `ErrorDispatcherNotFound` 类型,包裹 `Vec<String>`——它存的是用户输入的那些没匹配到的命令。你只需要给它写一个 Renderer:
```rust
-use std::io::Write;
+use mingling::macros::buffer;
-#[renderer]
-fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) -> RenderResult {
- let mut result = RenderResult::new();
+#[renderer(buffer)]
+fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) {
if err.inner.is_empty() {
- writeln!(result, "Unknown command").ok();
+ r_println!("Unknown command");
} else {
- writeln!(result, "Command not found: \"{}\"", err.inner.join(" ")).ok();
+ r_println!("Command not found: \"{}\"", err.inner.join(" "));
}
- result
}
```
diff --git a/docs/_zh_CN/pages/5-multiple-commands.md b/docs/_zh_CN/pages/5-multiple-commands.md
index 7d2617b..ff6596d 100644
--- a/docs/_zh_CN/pages/5-multiple-commands.md
+++ b/docs/_zh_CN/pages/5-multiple-commands.md
@@ -10,6 +10,7 @@
继续在同一个项目里操作:
```rust
+@@@use mingling::macros::buffer;
// 声明两个命令
dispatcher!("greet", CMDGreet => EntryGreet);
dispatcher!("add", CMDAdd => EntryAdd);
@@ -20,27 +21,23 @@ 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]
-fn render_greet(result: ResultGreeting) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Hello, {}!", *result).ok();
- r
+#[renderer(buffer)]
+fn render_greet(result: ResultGreeting) {
+ r_println!("Hello, {}!", *result);
}
-#[renderer]
-fn render_sum(result: ResultSum) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Sum: {}", *result).ok();
- r
+#[renderer(buffer)]
+fn render_sum(result: ResultSum) {
+ r_println!("Sum: {}", *result);
}
fn main() {
@@ -70,9 +67,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..f0609ed 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()
}
```
@@ -139,6 +139,7 @@ fn handle_test_entry(prev: EntryTest) -> Next {
```rust
// Features: ["parser", "extra_macros"]
+@@@use mingling::macros::buffer;
@@@use mingling::macros::route;
@@@dispatcher!("greet", CMDGreet => EntryGreet);
@@@pack!(ResultName = String);
@@ -155,11 +156,9 @@ fn handle_greet_entry(prev: EntryGreet) -> Next {
ResultName::new(name).into()
}
-#[renderer]
-fn render_greet(result: ResultName) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Hello, {}!", *result).ok();
- r
+#[renderer(buffer)]
+fn render_greet(result: ResultName) {
+ r_println!("Hello, {}!", *result);
}
```
@@ -199,7 +198,7 @@ let name = match pick_result {
在您使用 `pick` 提取了用户输入后,可以使用 `after` 立刻处理该参数
-```rust
+````rust
// Features: ["parser"]
@@@dispatcher!("greet", CMDGreet => EntryGreet);
@@@pack!(ResultName = String);
@@ -217,7 +216,7 @@ fn handle_greet_entry(prev: EntryGreet) -> Next {
})
.unpack();
- ResultName::new(name)
+ ResultName::new(name).into()
}
```
@@ -225,6 +224,7 @@ fn handle_greet_entry(prev: EntryGreet) -> Next {
```rust
// Features: ["parser", "extra_macros"]
+@@@use mingling::macros::buffer;
@@@use mingling::macros::route;
@@@dispatcher!("greet", CMDGreet => EntryGreet);
@@@pack!(ResultName = String);
@@ -247,19 +247,15 @@ fn handle_greet_entry(prev: EntryGreet) -> Next {
ResultName::new(name).into()
}
-#[renderer]
-fn render_name_too_long(prev: ErrorNameTooLong) -> RenderResult {
- let mut r = RenderResult::new();
+#[renderer(buffer)]
+fn render_name_too_long(prev: ErrorNameTooLong) {
let len = *prev;
- writeln!(r, "Error: name too long (length: {} > 32)", len).ok();
- r
+ r_println!("Error: name too long (length: {} > 32)", len);
}
-#[renderer]
-fn render_name(prev: ResultName) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Hello, {}!", *prev).ok();
- r
+#[renderer(buffer)]
+fn render_name(prev: ResultName) {
+ r_println!("Hello, {}!", *prev);
}
```
@@ -314,6 +310,7 @@ fn parse_size() {
```rust
// Features: ["parser"]
+@@@use mingling::macros::buffer;
@@@use mingling::parser::{Pickable, Argument};
@@@use mingling::Flag;
#[derive(Default, Clone)]
@@ -338,14 +335,12 @@ 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]
-fn render_connected(addr: ResultConnected) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Connected: IP: {} PORT: {}", addr.ip, addr.port).ok();
- r
+#[renderer(buffer)]
+fn render_connected(addr: ResultConnected) {
+ r_println!("Connected: IP: {} PORT: {}", addr.ip, addr.port);
}
```
@@ -362,6 +357,7 @@ Connected: IP: 127.0.0.1 PORT: 8080
```rust
// Features: ["parser"]
+@@@use mingling::macros::buffer;
@@@use mingling::parser::PickableEnum;
@@@use mingling::EnumTag;
#[derive(Debug, Default, EnumTag)]
@@ -379,14 +375,12 @@ 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]
-fn render_fruit(prev: ResultFruit) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Picked fruit: {:?}", *prev).ok();
- r
+#[renderer(buffer)]
+fn render_fruit(prev: ResultFruit) {
+ r_println!("Picked fruit: {:?}", *prev);
}
```
@@ -395,3 +389,4 @@ fn render_fruit(prev: ResultFruit) -> RenderResult {
<p align="center" style="font-size: 0.85em; color: gray;">
Written by @Weicao-CatilGrass
</p>
+````
diff --git a/docs/_zh_CN/pages/7-argument-parse-clap.md b/docs/_zh_CN/pages/7-argument-parse-clap.md
index 7dce301..fda93f3 100644
--- a/docs/_zh_CN/pages/7-argument-parse-clap.md
+++ b/docs/_zh_CN/pages/7-argument-parse-clap.md
@@ -25,7 +25,8 @@ features = ["derive", "color"]
// Dependencies:
// clap = "4"
@@@ use mingling::macros::dispatcher_clap;
-#[derive(Default, clap::Parser, Groupped)]
+@@@ use mingling::macros::buffer;
+#[derive(Default, clap::Parser, Grouped)]
#[dispatcher_clap("greet", CMDGreet, help = true, error = ErrorGreetParsed)]
pub struct EntryGreet {
#[clap(default_value = "World")]
@@ -34,23 +35,19 @@ pub struct EntryGreet {
repeat: i32,
}
-#[renderer]
-fn render_greet(greet: EntryGreet) -> RenderResult {
- let mut r = RenderResult::new();
+#[renderer(buffer)]
+fn render_greet(greet: EntryGreet) {
let count = greet.repeat.max(0) as usize;
- write!(r, "Hello, ").ok();
+ r_print!("Hello, ");
for _ in 0..count {
- write!(r, "{} ", greet.name).ok();
+ r_print!("{} ", greet.name);
}
- writeln!(r, "!").ok();
- r
+ r_println!("!");
}
-#[renderer]
-fn render_greet_parse_failed(err: ErrorGreetParsed) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "{}", *err).ok();
- r
+#[renderer(buffer)]
+fn render_greet_parse_failed(err: ErrorGreetParsed) {
+ r_println!("{}", *err);
}
```
@@ -62,18 +59,17 @@ fn render_greet_parse_failed(err: ErrorGreetParsed) -> RenderResult {
// Features: ["clap"]
// Dependencies:
// clap = "4"
+@@@use mingling::macros::buffer;
@@@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,
@@@}
-@@@#[renderer]
-@@@fn render_greet(greet: EntryGreet) -> RenderResult {
-@@@ let mut r = RenderResult::new();
-@@@ write!(r, "Hello, {}!", greet.name).ok();
-@@@ r
+@@@#[renderer(buffer)]
+@@@fn render_greet(greet: EntryGreet) {
+@@@ r_println!("Hello, {}!", greet.name);
@@@}
fn main() {
let mut program = ThisProgram::new();
diff --git a/docs/_zh_CN/pages/9-error-handling.md b/docs/_zh_CN/pages/9-error-handling.md
index 07c82da..4ce61ab 100644
--- a/docs/_zh_CN/pages/9-error-handling.md
+++ b/docs/_zh_CN/pages/9-error-handling.md
@@ -38,23 +38,20 @@ fn handle_greet(args: EntryGreet) -> Next {
然后各自写 Renderer:
```rust
+@@@use mingling::macros::buffer;
@@@dispatcher!("greet", CMDGreet => EntryGreet);
@@@pack!(ResultGreeting = String);
@@@pack!(ErrorNameEmpty = String);
@@@#[chain] fn handle_greet(args: EntryGreet) -> Next { ResultGreeting::new(args.inner.first().cloned().unwrap_or_default()).to_render() }
-#[renderer]
-fn render_greet(result: ResultGreeting) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Hello, {}!", *result).ok();
- r
+#[renderer(buffer)]
+fn render_greet(result: ResultGreeting) {
+ r_println!("Hello, {}!", *result);
}
-#[renderer]
-fn render_error_name_empty(err: ErrorNameEmpty) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Error: {}", *err).ok();
- r
+#[renderer(buffer)]
+fn render_error_name_empty(err: ErrorNameEmpty) {
+ r_println!("Error: {}", *err);
}
```
@@ -63,6 +60,7 @@ fn render_error_name_empty(err: ErrorNameEmpty) -> RenderResult {
## 完整的例子
```rust
+@@@use mingling::macros::buffer;
dispatcher!("greet", CMDGreet => EntryGreet);
pack!(ResultGreeting = String);
@@ -78,18 +76,14 @@ fn handle_greet(args: EntryGreet) -> Next {
}
}
-#[renderer]
-fn render_greet(result: ResultGreeting) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Hello, {}!", *result).ok();
- r
+#[renderer(buffer)]
+fn render_greet(result: ResultGreeting) {
+ r_println!("Hello, {}!", *result);
}
-#[renderer]
-fn render_error_name_empty(err: ErrorNameEmpty) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Error: {}", *err).ok();
- r
+#[renderer(buffer)]
+fn render_error_name_empty(err: ErrorNameEmpty) {
+ r_println!("Error: {}", *err);
}
fn main() {
diff --git a/docs/_zh_CN/pages/advanced/2-structural-renderer.md b/docs/_zh_CN/pages/advanced/2-structural-renderer.md
index 9a4f111..a498dac 100644
--- a/docs/_zh_CN/pages/advanced/2-structural-renderer.md
+++ b/docs/_zh_CN/pages/advanced/2-structural-renderer.md
@@ -27,6 +27,7 @@ features = ["structural_renderer"]
// Features: ["structural_renderer"]
// Dependencies:
// serde = "1"
+@@@use mingling::macros::buffer;
@@@use mingling::setup::StructuralRendererSetup;
@@@dispatcher!("render", CMDRender => EntryRender);
@@ -37,14 +38,12 @@ 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]
-fn render_info(r: ResultInfo) -> RenderResult {
- let mut result = RenderResult::new();
- writeln!(result, "{:?}", *r).ok();
- result
+#[renderer(buffer)]
+fn render_info(r: ResultInfo) {
+ r_println!("{:?}", *r);
}
```
@@ -62,19 +61,20 @@ fn render_info(r: ResultInfo) -> RenderResult {
## 自定义输出结构
-`pack_structural!` 的默认输出包含 `inner` 字段。要完全控制输出结构,可以用 `#[derive(StructuralData, Serialize, Groupped)]` 手动定义类型:
+`pack_structural!` 的默认输出包含 `inner` 字段。要完全控制输出结构,可以用 `#[derive(StructuralData, Serialize, Grouped)]` 手动定义类型:
```rust
// Features: ["structural_renderer"]
// Dependencies:
// serde = "1"
+@@@use mingling::macros::buffer;
@@@use mingling::prelude::*;
@@@use mingling::setup::StructuralRendererSetup;
@@@use mingling::StructuralData;
@@@use serde::Serialize;
@@@dispatcher!("render", CMDRender => EntryRender);
-#[derive(Serialize, StructuralData, Groupped)]
+#[derive(Serialize, StructuralData, Grouped)]
struct Info {
name: String,
age: i32,
@@ -87,11 +87,9 @@ fn handle_render(args: EntryRender) -> Next {
Info { name, age }.to_render()
}
-#[renderer]
-fn render_info(info: Info) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "{} is {} years old", info.name, info.age).ok();
- r
+#[renderer(buffer)]
+fn render_info(info: Info) {
+ r_println!("{} is {} years old", info.name, info.age);
}
@@@
@@@fn main() {
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..6e65ee4 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!()` 包装,以获得更灵活的字段控制。
### 错误
@@ -166,6 +166,7 @@ fn handle_remote_add(args: EntryRemoteAdd, cwd: &ResCurrentDir, db: &mut ResData
## 完整示例
```rust
+@@@use mingling::macros::buffer;
@@@ #[derive(Default, Clone)]
@@@ struct ResDatabase { }
@@@ impl ResDatabase { fn has_remote(&self, remote: &String) -> bool { true } }
@@ -192,19 +193,15 @@ fn handle_state_operation_remotes(state: StateOperationRemotes, db: &ResDatabase
}
// 结果渲染
-#[renderer]
-fn render_remote_added(result: ResultRemoteAdded) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Remote added: {}", result.inner).ok();
- r
+#[renderer(buffer)]
+fn render_remote_added(result: ResultRemoteAdded) {
+ r_println!("Remote added: {}", result.inner);
}
// 错误渲染
-#[renderer]
-fn render_error_repository_not_found(err: ErrorRepositoryNotFound) -> RenderResult {
- let mut r = RenderResult::new();
- writeln!(r, "Error: remote '{}' not found", err.inner).ok();
- r
+#[renderer(buffer)]
+fn render_error_repository_not_found(err: ErrorRepositoryNotFound) {
+ r_println!("Error: remote '{}' not found", err.inner);
}
```