diff options
Diffstat (limited to 'docs/_zh_CN/pages')
| -rw-r--r-- | docs/_zh_CN/pages/10-help.md | 26 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/11-resource-system.md | 20 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/14-testing.md | 2 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/3-define-a-chain.md | 8 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/4-render-result.md | 51 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/5-multiple-commands.md | 25 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/6-argument-parse-picker.md | 61 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/7-argument-parse-clap.md | 34 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/9-error-handling.md | 34 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/advanced/2-structural-renderer.md | 24 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/concepts/3-any-output.md | 10 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/other/features.md | 22 | ||||
| -rw-r--r-- | docs/_zh_CN/pages/other/naming_rule.md | 19 |
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); } ``` |
