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/pages/5-multiple-commands.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/pages/5-multiple-commands.md')
| -rw-r--r-- | docs/pages/5-multiple-commands.md | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/docs/pages/5-multiple-commands.md b/docs/pages/5-multiple-commands.md new file mode 100644 index 0000000..9ad7ef4 --- /dev/null +++ b/docs/pages/5-multiple-commands.md @@ -0,0 +1,109 @@ +<h1 align="center">Multi-Command Program</h1> +<p align="center"> + Adding multiple commands to a single program +</p> + +Real-world CLIs rarely have just one command. Let's extend our previous greet program by adding a second command, and see what a multi-command program looks like. + +## Adding a Second Command + +Work in the same project: + +```rust +// Declare two commands +dispatcher!("greet", CMDGreet => EntryGreet); +dispatcher!("add", CMDAdd => EntryAdd); + +pack!(ResultGreeting = String); +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) +} + +#[chain] +fn handle_add(args: EntryAdd) -> Next { + let sum: i32 = args.inner.iter().filter_map(|s| s.parse::<i32>().ok()).sum(); + ResultSum::new(sum) +} + +#[renderer] +fn render_greet(result: ResultGreeting) { + r_println!("Hello, {}!", *result); +} + +#[renderer] +fn render_sum(result: ResultSum) { + r_println!("Sum: {}", *result); +} + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatchers((CMDGreet, CMDAdd)); + program.exec_and_exit(); +} + +gen_program!(); +``` + +Both commands share the same pipeline model, but each has its own path: + +```text +> my-cli greet Alice +Hello, Alice! +> my-cli add 1 2 3 +Sum: 6 +``` + +## Registering Multiple Dispatchers + +Notice `with_dispatchers`? When you need to register multiple dispatchers, just pass them as a tuple: + +```rust +@@@dispatcher!("greet", CMDGreet => EntryGreet); +@@@dispatcher!("add", CMDAdd => EntryAdd); +@@@pack!(ResultGreeting = String); +@@@pack!(ResultSum = i32); +@@@#[chain] fn handle_greet(_args: EntryGreet) -> Next { ResultGreeting::new("ok".into()) } +@@@#[renderer] fn render_greet(_greeting: ResultGreeting) { r_println!("hi"); } +@@@#[chain] fn handle_add(_args: EntryAdd) -> Next { ResultSum::new(0) } +@@@#[renderer] fn render_sum(_sum: ResultSum) { r_println!("sum"); } +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatchers((CMDGreet, CMDAdd)); + program.exec_and_exit(); +} +``` + +This is equivalent to registering them one by one, same effect. + +> [!TIP] +> The tuple supports up to 7 dispatchers. For more than 7, chain `with_dispatcher` calls instead. + +## Subcommands + +Multi-level commands work the same way—each dot-separated level is just part of the name: + +```rust +dispatcher!("remote.add", CMDRemoteAdd => EntryRemoteAdd); +dispatcher!("remote.rm", CMDRemoteRm => EntryRemoteRm); +``` + +Each subcommand's Entry, Chain, and Renderer are completely independent and don't interfere. + +## Type Independence + +Notice we used two different `pack!` macros: + +- `pack!(ResultGreeting = String)` +- `pack!(ResultSum = i32)` + +They are independent types, and `gen_program!()` assigns them different enum variants. + +The dispatcher will never route `ResultGreeting` data to `render_sum` — **type safety is guaranteed from the naming stage**. + +<p align="center" style="font-size: 0.85em; color: gray;"> + Written by @Weicao-CatilGrass +</p> |
