aboutsummaryrefslogtreecommitdiff
path: root/docs/_zh_CN/pages/5-multiple-commands.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/_zh_CN/pages/5-multiple-commands.md')
-rw-r--r--docs/_zh_CN/pages/5-multiple-commands.md109
1 files changed, 109 insertions, 0 deletions
diff --git a/docs/_zh_CN/pages/5-multiple-commands.md b/docs/_zh_CN/pages/5-multiple-commands.md
new file mode 100644
index 0000000..4a9c72d
--- /dev/null
+++ b/docs/_zh_CN/pages/5-multiple-commands.md
@@ -0,0 +1,109 @@
+<h1 align="center">多命令程序</h1>
+<p align="center">
+ 在一个程序里添加多个命令
+</p>
+
+真实世界的 CLI 很少只有一个命令。这篇我们来扩展之前的 greet 程序,加上第二个命令,看看多命令的程序长什么样。
+
+## 添加第二个命令
+
+继续在同一个项目里操作:
+
+```rust
+// 声明两个命令
+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!();
+```
+
+两个命令共享同一个管线模型,但各走各的:
+
+```text
+> my-cli greet Alice
+Hello, Alice!
+> my-cli add 1 2 3
+Sum: 6
+```
+
+## 注册多个分发器
+
+注意到 `with_dispatchers` 了吗?当你需要注册多个分发器时,一次传一个元组就行:
+
+```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();
+}
+```
+
+等价于一个个注册,效果一样。
+
+> [!TIP]
+> 元组最多支持 7 个分发器。超过 7 个时链式调用 `with_dispatcher` 就行。
+
+## 子命令
+
+多层级的命令也是同理——每个点号分隔的层级都只是名字的一部分:
+
+```rust
+dispatcher!("remote.add", CMDRemoteAdd => EntryRemoteAdd);
+dispatcher!("remote.rm", CMDRemoteRm => EntryRemoteRm);
+```
+
+每个子命令的 Entry、Chain、Renderer 完全独立,互不干扰。
+
+## 数据类型的独立性
+
+注意我们用了两个不同的 `pack!`:
+
+- `pack!(ResultGreeting = String)`
+- `pack!(ResultSum = i32)`
+
+它们都是独立的类型,`gen_program!()` 会给它们分配不同的枚举变体。
+
+调度器永远不会把 `ResultGreeting` 的数据送到 `render_sum` 去 —— **类型安全从命名那一刻就保证了**。
+
+<p align="center" style="font-size: 0.85em; color: gray;">
+ Written by @Weicao-CatilGrass
+</p>