使用 renderer 宏声明渲染器,将结果输出
现在,我们创建了 Dispatcher 和 Chain,也通过 `pack!` 产出了一个 Result 类型。最后一步:**把结果展示给用户**。 ## `#[renderer]` 宏 跟 `#[chain]` 类似,`#[renderer]` 用于标记一个输出函数: ```rust @@@pack!(ResultName = String); #[renderer] fn render_name(name: ResultName) { r_println!("Hello, {}!", *name); } ``` Renderer 接收 Chain 产出的结果,然后用 `r_println!` 输出。这个 `r_println!` 跟我们平常用的 `println!` 有什么区别? ## `r_println!` 和 `r_print!` 宏 `r_println!` 和 `r_print!` 是 Mingling 提供的打印宏,它们把内容写入 `RenderResult` 而不是直接输出到终端。这样做的好处是: 1. **RenderResult 持有退出码**——你可以设置程序以特定退出码结束 2. **方便测试**——可以捕获渲染结果做断言 3. **便于后处理**——你可以将结果捕获,统一进行文本后处理 > [!TIP] > 如果只是简单打印,你可以先把它理解为 `println!` 的平替。用 `r_println!` 替换 `println!` 不会错。 ## 完整的可运行程序 把三篇教程的内容合在一起,你的第一个 Mingling 程序就完整了: ```rust // 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) { r_println!("Hello, {}!", *name); } // 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