aboutsummaryrefslogtreecommitdiff
path: root/docs/pages/13-hook.md
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-30 18:05:05 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-30 18:05:05 +0800
commit13408e79b940e9a33ca593ed30d1b20c54e01234 (patch)
tree282549991a3f31791401ca2f3255b9318679d2e9 /docs/pages/13-hook.md
parent29867ab5c0b40378a33318d989c809f90fc7d3aa (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/pages/13-hook.md')
-rw-r--r--docs/pages/13-hook.md107
1 files changed, 107 insertions, 0 deletions
diff --git a/docs/pages/13-hook.md b/docs/pages/13-hook.md
new file mode 100644
index 0000000..0c5e460
--- /dev/null
+++ b/docs/pages/13-hook.md
@@ -0,0 +1,107 @@
+<h1 align="center">Hook System</h1>
+<p align="center">
+ How to insert custom behavior into a program using ProgramHook
+</p>
+
+Hooks let you insert custom logic at various lifecycle points in the pipeline — before dispatch, after chain, before/after render, on program exit …
+
+You can write cross-cutting concerns (logging, auth, metrics collection) in hooks instead of scattering them across business code.
+
+## Basic Usage
+
+`ProgramHook` uses a builder pattern:
+
+```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()` creates an empty hook, then chain-calls `.on_*()` methods to register the lifecycle nodes you care about. Unregistered nodes won't execute.
+
+## Lifecycle Nodes
+
+Hooks cover the full pipeline lifecycle:
+
+| Stage | Hook | Trigger Point |
+| ------------ | ------------------ | ------------------- |
+| **Dispatch** | `on_begin` | Execution start |
+| | `on_pre_dispatch` | Before dispatch |
+| | `on_post_dispatch` | After dispatch |
+| **Chain** | `on_pre_chain` | Before chain exec |
+| | `on_post_chain` | After chain exec |
+| **Render** | `on_pre_render` | Before render exec |
+| | `on_post_render` | After render exec |
+| **Finish** | `on_finish` | Before program exit |
+
+Each hook callback receives a corresponding `Hook*Info` struct containing context info (input type, params, render results, etc.).
+
+## Real Example: Logging Operations
+
+```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();
+
+ // Log info before and after each chain execution
+ 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();
+}
+```
+
+Run output:
+
+```text
+[hook] executing chain for: EntryGreet
+[hook] chain output: ResultName
+Hello, World!
+```
+
+## Controlling Behavior via Hooks
+
+Hooks aren't just for observation — you can use `ProgramControlUnit` to alter program behavior:
+
+| Variant | Effect |
+| -------------------------- | ----------------------------------------- |
+| `Continue` | Do nothing, continue execution |
+| `OverrideExitCode(i32)` | Override the exit code |
+| `RouteToChain(AnyOutput)` | Replace current data, re-enter Chain loop |
+| `RouteToRender(AnyOutput)` | Skip subsequent Chain, render directly |
+
+> [!NOTE]
+> Multiple hooks can be registered and execute in registration order.
+
+<p align="center" style="font-size: 0.85em; color: gray;">
+ Written by @Weicao-CatilGrass
+</p>