From b1ac9fb8ed90699474e911674f1a60b139563858 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 27 May 2026 12:48:54 +0800 Subject: Add Chinese tutorial for Step 1 of Mingling framework --- docs/.gitignore | 1 + docs/_zh_CN/_sidebar.md | 2 + docs/_zh_CN/pages/1-intro.md | 68 ++++ docs/_zh_CN/pages/2-step1.md | 140 +++++++ docs/play/sources/zh_CN/2-fruit-mgr-expect.md | 104 +++++ docs/play/sources/zh_CN/2-writing.md | 195 ++++++++++ docs/play/sources/zh_CN/2-writing1.md | 208 ++++++++++ docs/play/sources/zh_CN/2-writing2.md | 527 ++++++++++++++++++++++++++ docs/play/sources/zh_CN/2-writing3.md | 317 ++++++++++++++++ docs/res/graph/2-1.drawio | 49 +++ docs/res/graph/2-1.drawio.svg | 4 + 11 files changed, 1615 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/_zh_CN/pages/1-intro.md create mode 100644 docs/_zh_CN/pages/2-step1.md create mode 100644 docs/play/sources/zh_CN/2-fruit-mgr-expect.md create mode 100644 docs/play/sources/zh_CN/2-writing.md create mode 100644 docs/play/sources/zh_CN/2-writing1.md create mode 100644 docs/play/sources/zh_CN/2-writing2.md create mode 100644 docs/play/sources/zh_CN/2-writing3.md create mode 100644 docs/res/graph/2-1.drawio create mode 100644 docs/res/graph/2-1.drawio.svg diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..8d71bf9 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +*.bkp diff --git a/docs/_zh_CN/_sidebar.md b/docs/_zh_CN/_sidebar.md index 40968ba..8c854f9 100644 --- a/docs/_zh_CN/_sidebar.md +++ b/docs/_zh_CN/_sidebar.md @@ -1 +1,3 @@ - [Welcome!](README) +* [介绍](pages/1-intro) +* [初次上手!](pages/2-step1) diff --git a/docs/_zh_CN/pages/1-intro.md b/docs/_zh_CN/pages/1-intro.md new file mode 100644 index 0000000..4e3106c --- /dev/null +++ b/docs/_zh_CN/pages/1-intro.md @@ -0,0 +1,68 @@ +

介绍

+

+ Mingling 能做什么? +

+ +## 前言 + + 首先,非常感谢您愿意尝试和体验 **Mingling** + + 因为这是一个早期框架,所以尚不成熟。 + + 若您在使用过程中遇到任何问题,欢迎提交 [Issue](https://github.com/catilgrass/mingling/issues),我们乐意解决。 + +
+
+ + + +
+
+
+ Mingling - Github +
+
+ A Rust CLI framework for many subcmds & complex workflows, reduces boilerplate via proc macros, focus on biz logic +
+
+
+ +## Mingling 是什么? + + **Mingling** 是一款 Rust 命令行开发框架,更准确地说,它是一款在调度、执行、渲染等方面提供高度抽象的框架。 + + 它的核心逻辑是 **"转换"** —— 您输入的命令行参数(`Vec`)会经过一系列的类型转换,最终变成您想要的结果。用一张图来说明: + +
+ +
+ + **这意味着**,您的执行逻辑和渲染逻辑是完全分离的:所有的状态、数据和结构都是类型,它们都只是转换过程中的一个环节,清晰又灵活。 + +## 它适合什么样的项目? + + 如果您正在开发一个**子命令多、嵌套层次深、横切关注点多**,并且对**执行效率和动态补全**有要求的命令行工具,那么 **Mingling** 会是一个很好的选择。 + + 这些能力得益于它高度抽象的宏系统,以及几乎全部在编译期完成的构建逻辑,让您在运行时能获得出色的性能。 + +## Mingling 能做些什么? + + **Mingling** 专注于命令行流程的调度与编排,为您提供以下能力: + + 1. **核心调度** — 通过类型转换优雅地编排业务逻辑 + 2. **纯函数设计** — 所有行为都是纯函数,可以直接测试 + 3. **无限嵌套** — 支持无限嵌套的子命令系统,再复杂的结构也能驾驭 + 4. **动态补全** — 为任意子命令插入完全动态的补全逻辑 **\[`comp`\]** + 5. **帮助文档** — 为任意子命令插入帮助文档,让用户轻松上手 + +## Mingling 不做些什么? + + **Mingling** 专注于命令行**流程的调度与编排**,因此它不会提供以下功能(您可以自由搭配其他库来实现): + + 1. ❌ 彩色文字、进度条等外观功能 + 2. ❌ 国际化、本地化功能 + 3. ❌ TUI 界面功能 + +

+ Written by @Weicao-CatilGrass +

diff --git a/docs/_zh_CN/pages/2-step1.md b/docs/_zh_CN/pages/2-step1.md new file mode 100644 index 0000000..56f4b3c --- /dev/null +++ b/docs/_zh_CN/pages/2-step1.md @@ -0,0 +1,140 @@ +

初次上手!

+

+ 使用 Mingling 开发简易水果名搜索命令行程序 +

+ +## 前言 + +在本篇示例中,我将介绍如何使用 **Mingling** 开发基本的命令行程序,它包括: + +1. `fruit-mgr list` 命令 +2. `fruit-mgr list --help` 帮助页面 + + + +## 一、导入依赖 + +首先,请确保您的项目依赖 **Mingling** + +若未导入依赖,您可以在 `Cargo.toml` 添加如下内容: + +```toml +[dependencies.mingling] +version = "0.1.9" +features = [""] +``` + +## 二、编写 `main.rs`,创建基本的项目 + +在 `src/main.rs` 中,我们将编写程序的入口函数: + + + +## 三、注册 `list` 子命令 + + + +## 四、实现 `EntryList` 行为 + + + +

+ Written by @Weicao-CatilGrass +

+ +## 五、渲染 `ResultFruits` + +在上一步中,`handle_entry_list` 链接收 `EntryList`,并输出了 `ResultFruits`。 + +接下来我们就要为 `ResultFruits` 渲染出最终的结果,使整个程序像下图这样排列: + +
+ +
+ +让我们开始编写代码吧: + + + +### 💡 关于 `r_println!` 宏 + +`r_println!` 宏并不是对 `println!` 的包装 + +它是为 `#[renderer]` 宏中 **隐式注入** 的 `&mut RenderResult` 值提供。 + +在 `r_println!` 调用时,不会立刻向 stdout 输出信息,而是会被累计到 `&mut RenderResult` 中,在程序结束时整体输出。 + + +## 六、编译并运行 + +现在您已经完成了 `list` 命令,现在可以使用 `cargo run` 运行您的程序: + +```bash +cargo run -- list +``` + +您将会看到如下输出: + +``` +Apple +Banana +Orange +``` + +
+完整代码 + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + let fruits = vec![ + "Apple".to_string(), + "Banana".to_string(), + "Orange".to_string(), + ]; + ResultFruits::new(fruits) +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = &*result; + for fruit in vec { + r_println!("{}", fruit) + } +} + +gen_program!(); + +``` +
+ +

+ Written by @Weicao-CatilGrass +

diff --git a/docs/play/sources/zh_CN/2-fruit-mgr-expect.md b/docs/play/sources/zh_CN/2-fruit-mgr-expect.md new file mode 100644 index 0000000..708dbc7 --- /dev/null +++ b/docs/play/sources/zh_CN/2-fruit-mgr-expect.md @@ -0,0 +1,104 @@ +该命令运行起来应该是这样: + +```bash +~# fruit-mgr <<<<<<<<<< "输入命令" +``` + +--- + +```bash +~# fruit-mgr +Welcome to use FruitManager <<<<<<<<<< "输出欢迎词" +~# +``` + +--- + +```bash +~# fruit-mgr +Welcome to use FruitManager +~# fruit-mgr list --help <<<<<<<<<< "查看 list 命令的帮助" +``` + +--- + +```bash +~# fruit-mgr +Welcome to use FruitManager +~# fruit-mgr list --help +Description: List all fruits +Usage: fruit-mgr list --filter <<<<<<<<<< "输出帮助" +~# +``` +--- + +```bash +~# fruit-mgr +Welcome to use FruitManager +~# fruit-mgr list --help +Description: List all fruits +Usage: fruit-mgr list --filter +~# fruit-mgr list <<<<<<<<<< "输入命令列出水果" +``` + +--- + +```bash +~# fruit-mgr +Welcome to use FruitManager +~# fruit-mgr list --help +Description: List all fruits +Usage: fruit-mgr list --filter +~# fruit-mgr list +Apple +Banana +Orange <<<<<<<<<< "输出水果列表" +~# +``` + +--- + +```bash +~# fruit-mgr +Welcome to use FruitManager +~# fruit-mgr list --help +Description: List all fruits +Usage: fruit-mgr list --filter +~# fruit-mgr list +Apple <<<<<<<<<< "当然,我们可以使用 --filter 来过滤出 Apple" +Banana +Orange +~# +``` + +--- + +```bash +~# fruit-mgr +Welcome to use FruitManager +~# fruit-mgr list --help +Description: List all fruits +Usage: fruit-mgr list --filter +~# fruit-mgr list +Apple +Banana +Orange +~# fruit-mgr list --filter A <<<<<<<<<< "过滤出名字含大写 A 的水果" +``` + +--- + +```bash +~# fruit-mgr +Welcome to use FruitManager +~# fruit-mgr list --help +Description: List all fruits +Usage: fruit-mgr list --filter +~# fruit-mgr list +Apple +Banana +Orange +~# fruit-mgr list --filter A +Apple <<<<<<<<<< "只输出 Apple" +~# +``` diff --git a/docs/play/sources/zh_CN/2-writing.md b/docs/play/sources/zh_CN/2-writing.md new file mode 100644 index 0000000..bdac3b7 --- /dev/null +++ b/docs/play/sources/zh_CN/2-writing.md @@ -0,0 +1,195 @@ +这是 `main.rs` 的默认内容,让我们先删除默认的 `Hello, World!` + +```rust + + +fn main() { + println!("Hello, World!"); +} +``` + +--- + +```rust + + +fn main() { + println!("Hello, World!"); <<<<<<<<<< "删除 Hello, World!" +} +``` + +--- + +```rust + + +fn main() { + <<<<<<<<<< "删除 Hello, World!" +} +``` + +--- + +接下来,让我们构建基本的 **Mingling** 程序入口 + +```rust + + +fn main() { + +} +``` + +--- + +```rust +<<<<<<<<<< "在此处引入 Mingling 的预导入模块" + +fn main() { + +} +``` + +--- +```rust +use mingling::prelude::*; <<<<<<<<<< "编写" + +fn main() { + +} +``` + +--- + +```rust +use mingling::prelude::*; + +fn main() { + +} + +<<<<<<<<<< "在此处引入 gen_program!() 用于生成 ThisProgram" +``` + +--- + + +```rust +use mingling::prelude::*; + +fn main() { + +} + +gen_program!(); <<<<<<<<<< "编写" +``` + +--- + + +```rust +use mingling::prelude::*; <<<<<<<<<< "gen_program!() 由 prelude 提供" + +fn main() { + +} + +gen_program!(); +``` + +--- + + +```rust +use mingling::prelude::*; + +fn main() { + +} + +gen_program!(); <<<<<<<<<< "gen_program!() 必须放在根模块的结尾,这是宏展开的限制" +``` + +--- + + +```rust +use mingling::prelude::*; + +fn main() { + <<<<<<<<<< "在此处使用 ThisProgram 创建程序" +} + +gen_program!(); +``` + +--- + + +```rust +use mingling::prelude::*; + +fn main() { + let mut program = ThisProgram::new(); <<<<<<<<<< "编写" +} + +gen_program!(); +``` + +--- + + +```rust +use mingling::prelude::*; + +fn main() { + let mut program = ThisProgram::new(); +} + +gen_program!(); <<<<<<<<<< "ThisProgram 由 gen_program!() 生成" +``` + +--- + +```rust +use mingling::prelude::*; + +fn main() { + let mut program = ThisProgram::new(); + + <<<<<<<<<< "在此处执行程序并退出" +} + +gen_program!(); +``` + +--- + + +```rust +use mingling::prelude::*; + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); <<<<<<<<<< "编写" +} + +gen_program!(); +``` + +--- + +至此, **Mingling**的基本入口就搭建完成 + +```rust +use mingling::prelude::*; + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` diff --git a/docs/play/sources/zh_CN/2-writing1.md b/docs/play/sources/zh_CN/2-writing1.md new file mode 100644 index 0000000..e416118 --- /dev/null +++ b/docs/play/sources/zh_CN/2-writing1.md @@ -0,0 +1,208 @@ +我们刚刚创建了基本的入口,现在编写子命令: `list` + +```rust +use mingling::prelude::*; + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +fn main() { + let mut program = ThisProgram::new(); + <<<<<<<<<< "所有的资源将在此处注册" + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +<<<<<<<<<< "让我们在此处注册一个分发器,将 list 命令分发到指定的入口" + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!( <<<<<<<<<< "编写" + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", <<<<<<<<<< "编写命令名称" + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList <<<<<<<<<< "编写分发器名称" + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList <<<<<<<<<< "编写入口名称" + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); <<<<<<<<<< "这样,list 命令的分发器 CMDList 就被注册了" + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; <<<<<<<<<< "dispatcher! 宏由 prelude 提供" + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + <<<<<<<<<< "Ok, 现在在此处为程序添加分发器" + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher( <<<<<<<<<< "使用 with_dispatcher 为程序添加分发器" + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); <<<<<<<<<< "添加刚创建的分发器 CMDList" + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +至此,`list` 子命令便已被注册到程序 + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- diff --git a/docs/play/sources/zh_CN/2-writing2.md b/docs/play/sources/zh_CN/2-writing2.md new file mode 100644 index 0000000..4a4d5fb --- /dev/null +++ b/docs/play/sources/zh_CN/2-writing2.md @@ -0,0 +1,527 @@ +现在让我们为其创建行为注册的 `list` 子命令添加入口行为 + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +<<<<<<<<<< "在此处创建链,用于接收 CMDList 传入的 EntryList" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +#[chain] <<<<<<<<<< "编写" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +#[chain] +fn handle_entry_list( <<<<<<<<<< "创建函数体" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +#[chain] +fn handle_entry_list(prev: EntryList <<<<<<<<<< "声明接收 EntryList 类型" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next {} <<<<<<<<<< "返回 Next,这代表下一个类型" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next {} <<<<<<<<<< "Next 是 ChainProcess 的别名" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + +} + +gen_program!(); <<<<<<<<<< "Next 由 gen_program!() 生成" +``` + +--- + +我们需要一个包装类型用来包装 `handle_entry_list` 的结果 + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +<<<<<<<<<< "我们在此处定义一个包装类型" + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits <<<<<<<<<< "使用 pack! 宏快速创建一个包装类型" + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + +} + +gen_program!(); +``` + +--- + + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); <<<<<<<<<< "将 ResultFruits 包装为 Vec" + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; <<<<<<<<<< "pack! 由 prelude 提供" + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + +} + +gen_program!(); +``` + +--- + +现在,继续编辑 `handle_entry_list` 的行为 + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + <<<<<<<<<< "在此处硬编码水果列表" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + let fruits = <<<<<<<<<< "编写" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + let fruits = vec![ <<<<<<<<<< "编写" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + let fruits = vec![ + "Apple".to_string(), + "Banana".to_string(), + "Orange".to_string(), + ]; <<<<<<<<<< "编写" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + let fruits = vec![ + "Apple".to_string(), + "Banana".to_string(), + "Orange".to_string(), + ]; + <<<<<<<<<< "接下来,在此处将 Vec 包装成 ResultFruits 并返回" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(prev: EntryList) -> Next { + let fruits = vec![ + "Apple".to_string(), + "Banana".to_string(), + "Orange".to_string(), + ]; + ResultFruits::new(fruits) <<<<<<<<<< "编写" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] vvvv <<<<<<<<<< "因为没使用 prev 传入的参数,所以将其忽略" +fn handle_entry_list(prev: EntryList) -> Next { + let fruits = vec![ + "Apple".to_string(), + "Banana".to_string(), + "Orange".to_string(), + ]; + ResultFruits::new(fruits) +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + let fruits = vec![ + "Apple".to_string(), + "Banana".to_string(), + "Orange".to_string(), + ]; + ResultFruits::new(fruits) +} + +gen_program!(); +``` + +--- + +好的,现在 `EntryList` 的行为便编写完成 + +```rust +use mingling::prelude::*; + +dispatcher!("list", CMDList => EntryList); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDList); + program.exec_and_exit(); +} + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + let fruits = vec![ + "Apple".to_string(), + "Banana".to_string(), + "Orange".to_string(), + ]; + ResultFruits::new(fruits) +} + +gen_program!(); +``` diff --git a/docs/play/sources/zh_CN/2-writing3.md b/docs/play/sources/zh_CN/2-writing3.md new file mode 100644 index 0000000..e2038e3 --- /dev/null +++ b/docs/play/sources/zh_CN/2-writing3.md @@ -0,0 +1,317 @@ +好的,现在开始编写 `ResultFruits` 的渲染器 + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +<<<<<<<<<< "我们将在此处编写渲染器代码" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] <<<<<<<<<< "和 #[chain] 类似,渲染器函数叫 #[renderer]" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits( <<<<<<<<<< "编写函数体" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits <<<<<<<<<< "声明接收 ResultFruits 类型" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) {} <<<<<<<<<< "一般情况下,渲染器什么都不用返回" + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + <<<<<<<<<< "接下来在此处编写渲染逻辑" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = <<<<<<<<<< "首先我们先解包 ResultFruits" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = <<<<<<<<<< "pack! 宏会自动为 ResultFruits 实现 AsRef trait" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = result.as_ref(); <<<<<<<<<< "所以此处可以使用 as_ref()" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = &*result; <<<<<<<<<< "当然,deref 也可以解包 ResultFruits" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = &*result; + for fruit in vec { <<<<<<<<<< "接下来,循环遍历 ResultFruits 中的水果字符串" +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = &*result; + for fruit in vec { + <<<<<<<<<< "在循环中打印内容" + } +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = &*result; + for fruit in vec { + r_println!("{}", fruit) <<<<<<<<<< "使用 r_println 在循环中打印内容" + } +} + +gen_program!(); +``` + +--- + +```rust +use mingling::prelude::*; <<<<<<<<<< "r_println! 由 prelude 提供" + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = &*result; + for fruit in vec { + r_println!("{}", fruit) + } +} + +gen_program!(); +``` + +--- + +至此 `ResultFruits` 的渲染逻辑便已完成 + +```rust +use mingling::prelude::*; + +pack!(ResultFruits = Vec); + +#[chain] +fn handle_entry_list(_prev: EntryList) -> Next { + // ... +} + +#[renderer] +fn render_fruits(result: ResultFruits) { + let vec: &Vec = &*result; + for fruit in vec { + r_println!("{}", fruit) + } +} + +gen_program!(); +``` diff --git a/docs/res/graph/2-1.drawio b/docs/res/graph/2-1.drawio new file mode 100644 index 0000000..4eadbc3 --- /dev/null +++ b/docs/res/graph/2-1.drawio @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/res/graph/2-1.drawio.svg b/docs/res/graph/2-1.drawio.svg new file mode 100644 index 0000000..e822be0 --- /dev/null +++ b/docs/res/graph/2-1.drawio.svg @@ -0,0 +1,4 @@ + + + +
CMDList
EntryList
ResultFruits
RenderResult
handle_entry_list
render_fruits
\ No newline at end of file -- cgit