diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-06-30 18:05:05 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-06-30 18:05:05 +0800 |
| commit | 13408e79b940e9a33ca593ed30d1b20c54e01234 (patch) | |
| tree | 282549991a3f31791401ca2f3255b9318679d2e9 /docs/_zh_CN/pages/13-hook.md | |
| parent | 29867ab5c0b40378a33318d989c809f90fc7d3aa (diff) | |
feat(docs): add Chinese and English documentation for Mingling tutorials
Add comprehensive documentation covering Declare a Dispatcher, Declare a
Chain, Rendering Results, Multi-Command Program, Argument Parsing with
Picker and Clap, Program Setup, Error Handling, Help Info, Resource
System, Exit Code Control, Hook System, Testing, Completion, Structural
Rendering, and Core Concepts
Diffstat (limited to 'docs/_zh_CN/pages/13-hook.md')
| -rw-r--r-- | docs/_zh_CN/pages/13-hook.md | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/docs/_zh_CN/pages/13-hook.md b/docs/_zh_CN/pages/13-hook.md new file mode 100644 index 0000000..543ee55 --- /dev/null +++ b/docs/_zh_CN/pages/13-hook.md @@ -0,0 +1,107 @@ +<h1 align="center">钩子系统</h1> +<p align="center"> + 如何使用 ProgramHook 向程序内部插入行为 +</p> + +Hook 让你在管线的各个生命周期节点插入自定义逻辑 —— 在 dispatch 之前、chain 之后、render 前后、程序退出时 …… + +你可以把横切关注点(日志、鉴权、指标收集)写在 hook 里,而不是散落在各处的业务代码中。 + +## 基本用法 + +`ProgramHook` 采用 builder 模式构造: + +```rust +@@@use mingling::hook::ProgramHook; +fn main() { + let mut program = ThisProgram::new(); + program.with_hook( + ProgramHook::empty() + .on_pre_chain(|info| { + println!("before chain: {}", info.input); + }) + .on_post_render(|info| { + println!("after render: {}", info.result); + }), + ); + program.exec_and_exit(); +} +``` + +> [!TIP] +> `ProgramHook::empty()` 创建一个空 hook,然后链式调用 `.on_*()` 方法注册你关心的生命周期节点。没有注册的节点不会执行。 + +## 生命周期节点 + +Hook 覆盖了管线的完整生命周期: + +| 阶段 | Hook | 触发时机 | +| ------------ | ------------------ | ------------- | +| **Dispatch** | `on_begin` | 执行开始 | +| | `on_pre_dispatch` | Dispatch 之前 | +| | `on_post_dispatch` | Dispatch 之后 | +| **Chain** | `on_pre_chain` | Chain 执行前 | +| | `on_post_chain` | Chain 执行后 | +| **Render** | `on_pre_render` | Render 执行前 | +| | `on_post_render` | Render 执行后 | +| **Finish** | `on_finish` | 程序退出前 | + +每个 hook 回调接收对应的 `Hook*Info` 结构体,里面包含当前上下文的信息(输入类型、参数、渲染结果等)。 + +## 实际例子:记录操作日志 + +```rust +@@@use mingling::prelude::*; +@@@use mingling::hook::ProgramHook; +@@@ +@@@dispatcher!("greet", CMDGreet => EntryGreet); +@@@pack!(ResultName = String); +@@@ +@@@#[chain] fn handle_greet(args: EntryGreet) -> Next { +@@@ ResultName::new(args.inner.first().cloned().unwrap_or_default()).to_render() +@@@} +@@@#[renderer] fn render_name(r: ResultName) { r_println!("Hello, {}!", *r); } +fn main() { + let mut program = ThisProgram::new(); + + // 记录每次 chain 执行前后的信息 + program.with_hook( + ProgramHook::empty() + .on_pre_chain(|info| { + eprintln!("[hook] executing chain for: {}", info.input); + }) + .on_post_chain(|info| { + eprintln!("[hook] chain output: {}", info.output.member_id); + }), + ); + + program.with_dispatcher(CMDGreet); + program.exec_and_exit(); +} +``` + +运行效果: + +```text +[hook] executing chain for: EntryGreet +[hook] chain output: ResultName +Hello, World! +``` + +## 通过 Hook 控制行为 + +Hook 不仅用来 "看",还可以用 `ProgramControlUnit` 改变程序行为: + +| 变体 | 效果 | +| -------------------------- | ----------------------------------------- | +| `Continue` | 什么都不做,继续执行 | +| `OverrideExitCode(i32)` | 覆盖退出码 | +| `RouteToChain(AnyOutput)` | 将当前数据替换为新的,重新进入 Chain 循环 | +| `RouteToRender(AnyOutput)` | 跳过后续 Chain,直接渲染 | + +> [!NOTE] +> Hook 可以注册多个,按注册顺序执行。 + +<p align="center" style="font-size: 0.85em; color: gray;"> + Written by @Weicao-CatilGrass +</p> |
