使用 renderer 宏声明渲染器,将结果输出
现在,我们创建了 Dispatcher 和 Chain,也通过 `pack!` 产出了一个 Result 类型。最后一步:**把结果展示给用户**。 ## `#[renderer]` 宏 跟 `#[chain]` 类似,`#[renderer]` 用于标记一个输出函数: ```rust use std::io::Write; @@@pack!(ResultName = String); #[renderer] fn render_name(name: ResultName) -> RenderResult { let mut result = RenderResult::new(); writeln!(result, "Hello, {}!", *name).ok(); result } ``` Renderer 接收 Chain 产出的结果,然后返回一个 `RenderResult`。在函数内部,创建 `RenderResult`,用 `write!` / `writeln!`(来自 [`std::io::Write`](https://doc.rust-lang.org/std/io/trait.Write.html))写入内容,最后返回它。 ## `RenderResult` 类型 `RenderResult` 是一个缓冲区类型,持有渲染后的文本和退出码。它不是直接输出到终端,而是把内容写入缓冲区。这样做的好处是: 1. **持有退出码**——你可以设置程序以特定退出码结束 2. **方便测试**——可以捕获渲染结果做断言 3. **便于后处理**——你可以将结果捕获,统一进行文本后处理 ## 完整的可运行程序 把三篇教程的内容合在一起,你的第一个 Mingling 程序就完整了: ```rust use std::io::Write; // 1. 用 Dispatcher 声明命令 dispatcher!("greet", CMDGreet => EntryGreet); // 2. 用 pack! 声明结果数据 pack!(ResultName = String); // 3. 用 Chain 处理逻辑 #[chain] fn handle_greet(args: EntryGreet) -> Next { let name = args.inner .first() .cloned() .unwrap_or_else(|| "World".to_string()); ResultName::new(name) } // 4. 用 Renderer 输出结果 #[renderer] fn render_name(name: ResultName) -> RenderResult { let mut result = RenderResult::new(); writeln!(result, "Hello, {}!", *name).ok(); result } // 5. 在 main 函数内装配程序并运行 fn main() { let mut program = ThisProgram::new(); program.with_dispatcher(CMDGreet); program.exec_and_exit(); } // 6. 使用 gen_program! 生成完整程序 gen_program!(); ``` ## 跑起来试试 ```bash ~# cargo run -- greet Alice ``` ```text Hello, Alice! ``` 试试不给参数: ```bash ~# cargo run -- greet ``` ```text Hello, World! ``` 试试不存在的命令: ```bash cargo run -- great ``` ```text # 什么也没输出! ``` ## 补上 Fallback `gen_program!()` 自动生成了一个 `ErrorDispatcherNotFound` 类型,包裹 `VecWritten by @Weicao-CatilGrass