aboutsummaryrefslogtreecommitdiff
path: root/docs/_zh_CN/pages/5-multiple-commands.md
blob: 9d9d37e8804075aa7a4f020b5d9381a168769dfa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<h1 align="center">多命令程序</h1>
<p align="center">
    在一个程序里添加多个命令
</p>

真实世界的 CLI 很少只有一个命令。这篇我们来扩展之前的 greet 程序,加上第二个命令,看看多命令的程序长什么样。

## 添加第二个命令

继续在同一个项目里操作:

```rust
@@@use mingling::macros::buffer;
// 声明两个命令
dispatcher!("greet", EntryGreet);
dispatcher!("add",   EntryAdd);
 
#[derive(Grouped, Wrap)]
pub struct ResultGreeting(String);
#[derive(Grouped, Wrap)]
pub struct ResultSum(i32);
 
#[chain]
fn handle_greet(args: EntryGreet) -> Next {
    let name = args.0.first().cloned().unwrap_or_else(|| "World".to_string());
    ResultGreeting(name).into()
}
 
#[chain]
fn handle_add(args: EntryAdd) -> Next {
    let sum: i32 = args.0.iter().filter_map(|s| s.parse::<i32>().ok()).sum();
    ResultSum(sum).into()
}
 
#[renderer(buffer)]
fn render_greet(result: ResultGreeting) {
    r_println!("Hello, {}!", *result);
}
 
#[renderer(buffer)]
fn render_sum(result: ResultSum) {
    r_println!("Sum: {}", *result);
}
 
fn main() {
    let mut program = ThisProgram::new();
    program.exec_and_exit();
}
 
gen_program!();
```
 
两个命令共享同一个管线模型,但各走各的:

```text
> my-cli greet Alice
Hello, Alice!
> my-cli add 1 2 3
Sum: 6
```
 
## 子命令

多层级的命令也是同理——每个点号分隔的层级都只是名字的一部分:

```rust
dispatcher!("remote.add", EntryRemoteAdd);
dispatcher!("remote.rm",  EntryRemoteRm);
```
 
每个子命令的 Entry、Chain、Renderer 完全独立,互不干扰。

## 数据类型的独立性

注意我们用了两个不同的类型:

- `#[derive(Grouped, Wrap)] pub struct ResultGreeting(String);`
- `#[derive(Grouped, Wrap)] pub struct ResultSum(i32);`

它们都是独立的类型,`gen_program!()` 会给它们分配不同的枚举变体。

调度器永远不会把 `ResultGreeting` 的数据送到 `render_sum` 去 —— **类型安全从命名那一刻就保证了**。

<p align="center" style="font-size: 0.85em; color: gray;">
    Written by @Weicao-CatilGrass
</p>