aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeicao-CatilGrass <1992414357@qq.com>2026-06-12 21:28:41 +0800
committerWeicao-CatilGrass <1992414357@qq.com>2026-06-12 21:30:46 +0800
commitbe74c5f6ae45e528625a3ae6ebe25fd86b8449c0 (patch)
tree2785dcecba2b8f31025d9101e808d0f95f3c1686
parent28dadc7363cbb104935b46dc1b7fb9facdc97568 (diff)
Add naming conventions documentation and update sidebar
-rw-r--r--docs/_sidebar.md2
-rw-r--r--docs/_zh_CN/_sidebar.md2
-rw-r--r--docs/_zh_CN/pages/other/naming_rule.md96
-rw-r--r--docs/pages/other/.name1
-rw-r--r--docs/pages/other/naming_rule.md200
-rw-r--r--docs/play/sources/zh_CN/_template.md4
-rw-r--r--mingling/src/example_docs.rs40
7 files changed, 293 insertions, 52 deletions
diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index 40968ba..e910178 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -1 +1,3 @@
- [Welcome!](README)
+* Other
+ * [Naming Conventions](pages/other/naming_rule)
diff --git a/docs/_zh_CN/_sidebar.md b/docs/_zh_CN/_sidebar.md
index 12e7f94..20615d5 100644
--- a/docs/_zh_CN/_sidebar.md
+++ b/docs/_zh_CN/_sidebar.md
@@ -1,5 +1,3 @@
- [Welcome!](README)
-* [介绍](pages/1-intro)
-* [初次上手!](pages/2-step1)
* 其他
* [命名规范](pages/other/naming_rule)
diff --git a/docs/_zh_CN/pages/other/naming_rule.md b/docs/_zh_CN/pages/other/naming_rule.md
index 59dc9cd..18ebf3f 100644
--- a/docs/_zh_CN/pages/other/naming_rule.md
+++ b/docs/_zh_CN/pages/other/naming_rule.md
@@ -19,11 +19,11 @@
Res + 名称
```
-| 示例 | 说明 |
-|------|------|
+| 示例 | 说明 |
+| --------------- | ------------ |
| `ResCurrentDir` | 当前工作目录 |
-| `ResExitCode` | 进程退出码 |
-| `ResREPL` | REPL 状态 |
+| `ResExitCode` | 进程退出码 |
+| `ResREPL` | REPL 状态 |
### 构建
@@ -33,10 +33,10 @@ Res + 名称
名称 + Setup
```
-| 示例 | 说明 |
-|------|------|
-| `BasicSetup` | 基础初始化(`--quiet`、`--help`、`--confirm`) |
-| `GeneralRendererSetup` | 通用渲染器初始化(`--json`、`--yaml` 等) |
+| 示例 | 说明 |
+| ---------------------- | ---------------------------------------------- |
+| `BasicSetup` | 基础初始化(`--quiet`、`--help`、`--confirm`) |
+| `GeneralRendererSetup` | 通用渲染器初始化(`--json`、`--yaml` 等) |
### 分发器
@@ -46,11 +46,11 @@ Res + 名称
CMD + 命令层级
```
-| 节点 | 分发器 |
-|------|--------|
-| `greet` | `CMDGreet` |
-| `remote.add` | `CMDRemoteAdd` |
-| `remote.rm` | `CMDRemoteRemove` |
+| 节点 | 分发器 |
+| ------------ | ----------------- |
+| `greet` | `CMDGreet` |
+| `remote.add` | `CMDRemoteAdd` |
+| `remote.rm` | `CMDRemoteRemove` |
即使节点是缩写,分发器的名称也要写全名。例如节点是 `remote.rm`,分发器是 `CMDRemoteRemove`,不是 `CMDRemoteRm`。
@@ -62,10 +62,10 @@ CMD + 命令层级
Entry + 命令层级
```
-| 分发器 | 入口 |
-|--------|------|
-| `CMDGreet` | `EntryGreet` |
-| `CMDRemoteAdd` | `EntryRemoteAdd` |
+| 分发器 | 入口 |
+| ----------------- | ------------------- |
+| `CMDGreet` | `EntryGreet` |
+| `CMDRemoteAdd` | `EntryRemoteAdd` |
| `CMDRemoteRemove` | `EntryRemoteRemove` |
### 状态
@@ -76,10 +76,10 @@ Entry + 命令层级
State + 描述
```
-| 示例 | 说明 |
-|------|------|
+| 示例 | 说明 |
+| ----------------------- | -------------------- |
| `StateOperationRemotes` | 正在操作远程仓库列表 |
-| `StateCheckRepository` | 正在检查仓库状态 |
+| `StateCheckRepository` | 正在检查仓库状态 |
典型的管线链:`EntryRemoteAdd → StateOperationRemotes → StateCheckRepository`
@@ -91,10 +91,10 @@ State + 描述
Result + 内容
```
-| 示例 | 说明 |
-|------|------|
-| `ResultGreetSomeone` | 问候结果 |
-| `ResultFruitList` | 水果列表结果 |
+| 示例 | 说明 |
+| -------------------- | ------------ |
+| `ResultGreetSomeone` | 问候结果 |
+| `ResultFruitList` | 水果列表结果 |
结果结构体期望被 Renderer 消费,内部结构应该为了渲染美观而设计。一般用 `#[derive(Groupped)]` 代替 `pack!()` 包装,以获得更灵活的字段控制。
@@ -106,33 +106,31 @@ Result + 内容
Error + 描述
```
-| 示例 | 说明 |
-|------|------|
+| 示例 | 说明 |
+| ------------------------- | ---------- |
| `ErrorRepositoryNotFound` | 仓库未找到 |
`StateOperationRemotes → ErrorRepositoryNotFound`
-
-
## 函数命名
### Chain 函数
-| 处理类型 | 命名模式 | 示例 |
-|----------|----------|------|
-| Entry | `handle_` + entry 名(snake_case) | `handle_remote_add(prev: EntryRemoteAdd)` |
-| State | `handle_state_` + state 名(snake_case) | `handle_state_operation_remotes(prev: StateOperationRemotes)` |
-| Error | `handle_error_` + error 名(snake_case) | `handle_error_repository_not_found(prev: ErrorRepositoryNotFound)` |
-| Result | ❌ 不要为 Result 写 chain | — |
+| 处理类型 | 命名模式 | 示例 |
+| -------- | ---------------------------------------- | ------------------------------------------------------------------ |
+| Entry | `handle_` + entry 名(snake_case) | `handle_remote_add(prev: EntryRemoteAdd)` |
+| State | `handle_state_` + state 名(snake_case) | `handle_state_operation_remotes(prev: StateOperationRemotes)` |
+| Error | `handle_error_` + error 名(snake_case) | `handle_error_repository_not_found(prev: ErrorRepositoryNotFound)` |
+| Result | ❌ 不要为 Result 写 chain | — |
### Renderer 函数
-| 处理类型 | 命名模式 | 示例 |
-|----------|----------|------|
-| Entry | `render_entry_` + entry 名 | `render_entry_remote_add(prev: EntryRemoteAdd)` |
-| State | ❌ 不要为 State 写 renderer | — |
-| Error | `render_error_` + error 名 | `render_error_repository_not_found(prev: ErrorRepositoryNotFound)` |
-| Result | `render_` + result 名 | `render_greet_someone(prev: ResultGreetSomeone)` |
+| 处理类型 | 命名模式 | 示例 |
+| -------- | --------------------------- | ------------------------------------------------------------------ |
+| Entry | `render_entry_` + entry 名 | `render_entry_remote_add(prev: EntryRemoteAdd)` |
+| State | ❌ 不要为 State 写 renderer | — |
+| Error | `render_error_` + error 名 | `render_error_repository_not_found(prev: ErrorRepositoryNotFound)` |
+| Result | `render_` + result 名 | `render_greet_someone(prev: ResultGreetSomeone)` |
**原则**:不要为不会被用户看到或不需要独立渲染的中间类型写 renderer。
@@ -140,16 +138,17 @@ Error + 描述
## 函数签名参数命名
-| 类型 | 推荐参数名 |
-|------|------------|
-| Entry | `args` |
-| State | `prev`(或具名如 `remotes`) |
-| Result | `result`(或具名如 `fruits`) |
-| Error | `err` |
-| 资源(不可变) | `cwd`、`db`、`config` 等 |
-| 资源(可变) | `counter`、`cache`、`session` 等 |
+| 类型 | 推荐参数名 |
+| -------------- | -------------------------------- |
+| Entry | `args` |
+| State | `prev`(或具名如 `remotes`) |
+| Result | `result`(或具名如 `fruits`) |
+| Error | `err` |
+| 资源(不可变) | `cwd`、`db`、`config` 等 |
+| 资源(可变) | `counter`、`cache`、`session` 等 |
```rust
+// NOT VERIFIED
#[chain]
fn handle_remote_add(args: EntryRemoteAdd, cwd: &ResCurrentDir, db: &mut ResDatabase) -> Next {
// args: 入口数据
@@ -163,6 +162,7 @@ fn handle_remote_add(args: EntryRemoteAdd, cwd: &ResCurrentDir, db: &mut ResData
## 完整示例
```rust
+// NOT VERIFIED
// 分发器
dispatcher!("remote.add", CMDRemoteAdd => EntryRemoteAdd);
diff --git a/docs/pages/other/.name b/docs/pages/other/.name
new file mode 100644
index 0000000..01ea8a0
--- /dev/null
+++ b/docs/pages/other/.name
@@ -0,0 +1 @@
+Other
diff --git a/docs/pages/other/naming_rule.md b/docs/pages/other/naming_rule.md
new file mode 100644
index 0000000..9443481
--- /dev/null
+++ b/docs/pages/other/naming_rule.md
@@ -0,0 +1,200 @@
+<h1 align="center">Naming Conventions</h1>
+<p align="center">
+ Keep your <b>Mingling</b> project types and function names organized
+</p>
+
+## Preface
+
+Good naming is the foundation of large CLI projects. Mingling's pipeline pattern introduces several new types (Entry, State, Result, Error, Resource). Without consistent conventions, projects quickly end up with generic names like `Data`, `Info`, or `Context` that make it impossible to tell different responsibilities apart.
+
+The naming conventions below come from real-world usage in production projects. They are not enforced by the framework, but following them is highly recommended.
+
+## Type Naming
+
+### Resource
+
+Resources are global instances shared with all chains and renderers through the resource injection system.
+
+```
+Res + Name
+```
+
+| Example | Description |
+| --------------- | ------------------------- |
+| `ResCurrentDir` | Current working directory |
+| `ResExitCode` | Process exit code |
+| `ResREPL` | REPL state |
+
+### Setup
+
+Setups are initialization steps executed at program startup, registered via `with_setup`.
+
+```
+Name + Setup
+```
+
+| Example | Description |
+| ---------------------- | ---------------------------------------------------------- |
+| `BasicSetup` | Basic initialization (`--quiet`, `--help`, `--confirm`) |
+| `GeneralRendererSetup` | General renderer initialization (`--json`, `--yaml`, etc.) |
+
+### Dispatcher
+
+Dispatchers are the entry points of commands, corresponding one-to-one with `Node` names. Node names use `.` to separate levels, dispatcher names use the `CMD` prefix with PascalCase.
+
+```
+CMD + Command Hierarchy
+```
+
+| Node | Dispatcher |
+| ------------ | ----------------- |
+| `greet` | `CMDGreet` |
+| `remote.add` | `CMDRemoteAdd` |
+| `remote.rm` | `CMDRemoteRemove` |
+
+Even if a node is an abbreviation, the dispatcher name should use the full name. For example, the node is `remote.rm`, but the dispatcher is `CMDRemoteRemove`, not `CMDRemoteRm`.
+
+### Entry
+
+Entries are the pipeline starting types created by dispatchers, wrapping `Vec<String>`.
+
+```
+Entry + Command Hierarchy
+```
+
+| Dispatcher | Entry |
+| ----------------- | ------------------- |
+| `CMDGreet` | `EntryGreet` |
+| `CMDRemoteAdd` | `EntryRemoteAdd` |
+| `CMDRemoteRemove` | `EntryRemoteRemove` |
+
+### State
+
+States are intermediate pipeline types between Entry and Result, representing data after partial processing.
+
+```
+State + Description
+```
+
+| Example | Description |
+| ----------------------- | ----------------------------- |
+| `StateOperationRemotes` | Operating on remote repo list |
+| `StateCheckRepository` | Checking repository status |
+
+Typical pipeline chain: `EntryRemoteAdd → StateOperationRemotes → StateCheckRepository`
+
+### Result
+
+Results are the final types sent to the Renderer via `to_render()` in the pipeline.
+
+```
+Result + Content
+```
+
+| Example | Description |
+| -------------------- | ----------------- |
+| `ResultGreetSomeone` | Greeting result |
+| `ResultFruitList` | Fruit list result |
+
+Result structs are expected to be consumed by the Renderer, and their internal structure should be designed for rendering aesthetics. Generally use `#[derive(Groupped)]` instead of `pack!()` wrapping for more flexible field control.
+
+### Error
+
+Errors are different from Results. Errors can be sent via `to_chain()` or `to_render()` to route execution to the error handling path.
+
+```
+Error + Description
+```
+
+| Example | Description |
+| ------------------------- | -------------------- |
+| `ErrorRepositoryNotFound` | Repository not found |
+
+`StateOperationRemotes → ErrorRepositoryNotFound`
+
+## Function Naming
+
+### Chain Functions
+
+| Processing Type | Naming Pattern | Example |
+| --------------- | ----------------------------------------- | ------------------------------------------------------------------ |
+| Entry | `handle_` + entry name (snake_case) | `handle_remote_add(prev: EntryRemoteAdd)` |
+| State | `handle_state_` + state name (snake_case) | `handle_state_operation_remotes(prev: StateOperationRemotes)` |
+| Error | `handle_error_` + error name (snake_case) | `handle_error_repository_not_found(prev: ErrorRepositoryNotFound)` |
+| Result | ❌ Do not write chains for Result | — |
+
+### Renderer Functions
+
+| Processing Type | Naming Pattern | Example |
+| --------------- | ----------------------------------- | ------------------------------------------------------------------ |
+| Entry | `render_entry_` + entry name | `render_entry_remote_add(prev: EntryRemoteAdd)` |
+| State | ❌ Do not write renderers for State | — |
+| Error | `render_error_` + error name | `render_error_repository_not_found(prev: ErrorRepositoryNotFound)` |
+| Result | `render_` + result name | `render_greet_someone(prev: ResultGreetSomeone)` |
+
+**Principle**: Do not write renderers for intermediate types that users won't see or that don't need independent rendering.
+
+---
+
+## Function Signature Parameter Naming
+
+| Type | Recommended Parameter Name |
+| -------------------- | --------------------------------------- |
+| Entry | `args` |
+| State | `prev` (or descriptive like `remotes`) |
+| Result | `result` (or descriptive like `fruits`) |
+| Error | `err` |
+| Resource (immutable) | `cwd`, `db`, `config`, etc. |
+| Resource (mutable) | `counter`, `cache`, `session`, etc. |
+
+```rust
+// NOT VERIFIED
+#[chain]
+fn handle_remote_add(args: EntryRemoteAdd, cwd: &ResCurrentDir, db: &mut ResDatabase) -> Next {
+ // args: entry data
+ // cwd: injected immutable resource
+ // db: injected mutable resource
+}
+```
+
+---
+
+## Complete Example
+
+```rust
+// NOT VERIFIED
+// Dispatcher
+dispatcher!("remote.add", CMDRemoteAdd => EntryRemoteAdd);
+
+// Entry → State
+#[chain]
+fn handle_remote_add(args: EntryRemoteAdd) -> Next {
+ StateOperationRemotes::new(...).to_chain()
+}
+
+// State → Error or Result
+#[chain]
+fn handle_state_operation_remotes(state: StateOperationRemotes, db: &ResDatabase) -> Next {
+ if db.has_remote(&state.name) {
+ ErrorRepositoryNotFound::new(...).to_render()
+ } else {
+ ResultRemoteAdded::new(...).to_render()
+ }
+}
+
+// Result rendering
+#[renderer]
+fn render_remote_added(result: ResultRemoteAdded) {
+ r_println!("Remote added: {}", result.name);
+}
+
+// Error rendering
+#[renderer]
+fn render_error_repository_not_found(err: ErrorRepositoryNotFound) {
+ r_println!("Error: remote '{}' not found", err.name);
+}
+```
+
+<p align="center" style="font-size: 0.85em; color: gray;">
+ Written by @Weicao-CatilGrass
+</p>
diff --git a/docs/play/sources/zh_CN/_template.md b/docs/play/sources/zh_CN/_template.md
index 29fed62..14e5a1e 100644
--- a/docs/play/sources/zh_CN/_template.md
+++ b/docs/play/sources/zh_CN/_template.md
@@ -3,7 +3,7 @@
```bash
代码 <<<<<<<<<< "提示"
```
-
+
---
消息2
@@ -11,5 +11,5 @@
```bash
代码 <<<<<<<<<< "提示"
```
-
+
---
diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs
index f14aa30..f4a27bd 100644
--- a/mingling/src/example_docs.rs
+++ b/mingling/src/example_docs.rs
@@ -32,6 +32,8 @@
///
/// # Enable `parser` features
/// features = ["parser", "extra_macros"]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -158,6 +160,8 @@ pub mod example_argument_parse {}
/// [dependencies.tokio]
/// version = "1.52.3"
/// features = ["macros", "rt", "rt-multi-thread", "time"]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -230,6 +234,8 @@ pub mod example_async_support {}
///
/// [dependencies]
/// mingling = { path = "../../mingling" }
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -354,6 +360,8 @@ pub mod example_basic {}
/// # Enable `color` feature to support ANSI colors
/// "color",
/// ]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -505,6 +513,8 @@ pub mod example_clap_binding {}
/// # enable `builds` features
/// "builds",
/// ]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -622,6 +632,8 @@ pub mod example_completion {}
/// path = "../../mingling"
///
/// features = ["parser", "extra_macros"]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -773,6 +785,8 @@ pub mod example_custom_pickable {}
/// features = [
/// "dispatch_tree",
/// ]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -848,6 +862,8 @@ pub mod example_dispatch_tree {}
/// "comp",
/// "parser"
/// ]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -973,6 +989,8 @@ pub mod example_enum_tag {}
///
/// [dependencies]
/// mingling = { path = "../../mingling" }
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1084,6 +1102,8 @@ pub mod example_error_handling {}
///
/// [dependencies]
/// mingling = { path = "../../mingling" }
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1173,6 +1193,8 @@ pub mod example_exitcode {}
/// "general_renderer",
/// "parser",
/// ]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1254,6 +1276,8 @@ pub mod example_general_renderer {}
///
/// [dependencies]
/// mingling = { path = "../../mingling" }
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1317,6 +1341,8 @@ pub mod example_help {}
///
/// [dependencies]
/// mingling = { path = "../../mingling" }
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1387,6 +1413,8 @@ pub mod example_hook {}
/// [dependencies.mingling]
/// path = "../../mingling"
/// features = ["extra_macros"]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1445,6 +1473,8 @@ pub mod example_implicit_dispatcher {}
/// [dependencies.mingling]
/// path = "../../mingling"
/// features = []
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1555,6 +1585,8 @@ pub mod example_lazy_resources {}
/// # Enable panic unwinding in dev builds
/// [profile.dev]
/// panic = "unwind"
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1622,6 +1654,8 @@ pub mod example_panic_unwind {}
///
/// [dependencies]
/// just_fmt = "0.1.2"
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1820,6 +1854,8 @@ pub mod example_repl_basic {}
/// [dependencies.mingling]
/// path = "../../mingling"
/// features = ["parser"]
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1888,6 +1924,8 @@ pub mod example_resources {}
///
/// [dependencies]
/// mingling = { path = "../../mingling", features = ["extra_macros"] }
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)
@@ -1940,6 +1978,8 @@ pub mod example_setup {}
///
/// [dependencies]
/// mingling = { path = "../../mingling", features = ["extra_macros"] }
+///
+/// [workspace]
/// ```
///
/// Source code (./src/main.rs)