dialogue_macro/
lib.rs

1#![allow(clippy::needless_doctest_main)]
2/*!
3
4# dialogue-macro
5
6[文档教程](https://yexiyue.github.io/dialogue-macro/)
7
8`dialogue-macro` 是一款使用 Rust 语言设计的宏库,致力于无缝对接并增强 `dialoguer` 库的功能表现,采用声明式的编程模式简化命令行提示界面的构建流程。该库在实现结构化、层次化的用户交互体验上表现出色,尤其适应于命令行应用程序中各类复杂信息收集和配置选项设定的需求。
9
10**核心特性概览:**
11
121. **结构体与枚举支持**:
13   dialogue-macro 允许开发者通过派生宏 (`#[derive(Asker)]` 和 `#[derive(EnumAsker)]`) 将自定义结构体及枚举类型转换为功能完备的命令行询问器,从而依据预定义的字段或枚举成员进行高效的数据采集。
14
152. **嵌套式交互逻辑**:
16   提供了对嵌套子询问器的支持,通过在结构体成员上标注 `#[asker(SubAsker)]` 属性,可实现多层次、递进式的用户交互过程,以应对不同场景下的深度信息获取需求。
17
183. **主题定制能力**:
19   支持主题设置,如示例中的 `dialogue_macro::ColorfulTheme`,使得开发者能够根据实际需要选择和应用不同的视觉风格,提升命令行提示界面的用户体验和可读性。
20
21
22
23# 快速开始
24
25首先通过cargo添加`dialogue-macro`依赖:
26
27```bash
28cargo add dialogue-macro
29```
30
31然后在您的Rust代码中导入该crate:
32
33```rust
34use dialogue_macro::Asker;
35```
36
37接下来,使用`#[derive(Asker, Debug)]`宏来为需要交互式输入的结构体派生相关trait:
38
39```rust
40#[derive(Asker, Debug)]
41struct User {
42    #[input(prompt = "请输入您的名字:")]
43    name: String,
44    age: u32,
45}
46```
47
48`#[derive(Asker)]`会自动为结构体实现`asker()`构造器方法。对于带有`#[input(prompt = "...")]`属性的字段,您可以直接调用同名方法(无需再传入提示文本作为参数)。
49
50最后,使用派生的方法链式调用来获取用户输入:
51
52```rust
53fn main() {
54    let user = User::asker()
55        .name()
56        .age("请输入您的年龄:")
57        .finish();
58
59    println!("{:?}", user);
60}
61```
62
63 */
64
65mod theme;
66pub use dialogue_core::{ Asker, EnumAsker };
67#[doc(hidden)]
68pub use dialoguer;
69#[doc(hidden)]
70pub use theme::ColorfulTheme;
71
72/**
73# Build Trait
74
75- 构造方法封装: Build trait 需要在实现了它的结构体或枚举中提供 .build() 方法,这个方法会启动并执行所有需要收集用户输入的操作。
76- 嵌套与递归: 当结构体或枚举中的某个字段使用了 SubAsker 特性时,表明该字段也是一个实现了 Build trait 的类型。通过调用 .build() 方法,可以递归地收集这些嵌套结构中的信息。
77- 简化输入流程: 使用 Build trait 可以避免逐个调用每个字段对应的 .asker() 和 .finish() 方法,而是通过一次 .build() 调用来完成整个对象实例化过程,使得代码更简洁且易于管理。
78- 统一接口: 所有作为子询问器使用的结构体都需要实现 Build trait,这保证了不同层次的对象都能遵循一致的构建逻辑。
79
80# Example
81```rust
82#![allow(unused)]
83
84use dialogue_macro::{Asker, Build, EnumAsker};
85
86#[derive(Debug, Asker)]
87#[asker(theme = "dialogue_macro::ColorfulTheme")]
88struct UserInput {
89    username: String,
90    is_student_status: bool,
91    educational_institution: String,
92
93    #[asker(SubAsker)]
94    detailed_info: DetailedUserInfo,
95    #[asker(SubAsker)]
96    choice: EnumSelection,
97}
98
99#[derive(Debug, Clone, Asker)]
100struct DetailedUserInfo {
101    email_address: String,
102    age: u8,
103}
104
105#[derive(Debug, EnumAsker, Clone)]
106enum EnumSelection {
107    OptionD,
108    OptionE,
109    OptionF,
110}
111
112impl Build for DetailedUserInfo {
113    fn build() -> Self {
114        Self::asker()
115            .email_address("请提供您的邮箱地址")
116            .age("请输入您的年龄")
117            .finish()
118    }
119}
120
121fn main() {
122    let collected_user_input = UserInput::asker()
123        .username("请输入用户名")
124        .is_student_status("您是否是学生身份?")
125        .educational_institution("请输入您的学校名称")
126        .detailed_info()
127        .choice()
128        .finish();
129
130    println!("{:?}", collected_user_input);
131}
132
133```
134*/
135pub trait Build {
136    fn build() -> Self;
137}