aboutsummaryrefslogtreecommitdiff
path: root/docs/pages/advanced
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-30 18:05:05 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-30 18:05:05 +0800
commit13408e79b940e9a33ca593ed30d1b20c54e01234 (patch)
tree282549991a3f31791401ca2f3255b9318679d2e9 /docs/pages/advanced
parent29867ab5c0b40378a33318d989c809f90fc7d3aa (diff)
feat(docs): add Chinese and English documentation for Mingling tutorials
Add comprehensive documentation covering Declare a Dispatcher, Declare a Chain, Rendering Results, Multi-Command Program, Argument Parsing with Picker and Clap, Program Setup, Error Handling, Help Info, Resource System, Exit Code Control, Hook System, Testing, Completion, Structural Rendering, and Core Concepts
Diffstat (limited to 'docs/pages/advanced')
-rw-r--r--docs/pages/advanced/.name1
-rw-r--r--docs/pages/advanced/1-completion.md83
-rw-r--r--docs/pages/advanced/2-structural-renderer.md120
3 files changed, 204 insertions, 0 deletions
diff --git a/docs/pages/advanced/.name b/docs/pages/advanced/.name
new file mode 100644
index 0000000..a8a2c7e
--- /dev/null
+++ b/docs/pages/advanced/.name
@@ -0,0 +1 @@
+Advanced
diff --git a/docs/pages/advanced/1-completion.md b/docs/pages/advanced/1-completion.md
new file mode 100644
index 0000000..a90c3ce
--- /dev/null
+++ b/docs/pages/advanced/1-completion.md
@@ -0,0 +1,83 @@
+<h1 align="center">Completion</h1>
+<p align="center">
+ Fully dynamic completion system via the `comp` feature
+</p>
+
+Mingling's completion is **fully dynamic** — no static completion files, suggestions are computed at runtime based on the user's current input.
+
+## Enable `comp`
+
+```toml
+# Cargo.toml
+[dependencies.mingling]
+features = ["comp"]
+
+[build-dependencies.mingling]
+features = [
+ "comp",
+ # Enable `builds` for build-time support
+ "builds"
+]
+```
+
+## How it works
+
+When the user presses `TAB`, the completion script calls the program's hidden subcommand `__comp`, which dynamically queries the best suggestions based on the provided `ShellContext`.
+
+This hidden subcommand is auto-generated by `gen_program!()` when the `comp` feature is enabled. Its dispatcher is `CMDCompletion` — you need to add it to your program via `with_dispatcher`.
+
+Completion flow:
+
+1. Re-match the user's current input to a `Dispatcher`
+2. Call the corresponding `#[completion]` function
+3. The function returns a `Suggest` (file completion or a list of suggestions)
+4. Notify the shell to display the suggestions
+
+## Define completions
+
+Use `#[completion(EntryType)]` to define completion logic for an Entry:
+
+```rust
+// Features: ["comp"]
+@@@use mingling::prelude::*;
+@@@use mingling::{ShellContext, Suggest, SuggestItem};
+@@@use std::collections::BTreeSet;
+@@@dispatcher!("greet", CMDGreet => EntryGreet);
+
+#[completion(EntryGreet)]
+fn complete_greet(ctx: &ShellContext) -> Suggest {
+ if ctx.previous_word == "greet" {
+ let mut items = BTreeSet::new();
+ items.insert(SuggestItem::new_with_desc("Alice".into(), "Likes to receive messages".into()));
+ items.insert(SuggestItem::new("World".into()));
+ Suggest::Suggest(items)
+ } else {
+ Suggest::FileCompletion
+ }
+}
+```
+
+The `suggest!` macro is a more concise way to write the same thing:
+
+```rust
+// Features: ["comp"]
+@@@use mingling::macros::suggest;
+@@@fn example() {
+suggest! {
+ "Alice": "Likes to receive messages",
+ "World"
+};
+@@@}
+```
+
+`ShellContext` holds the user's current input state (`previous_word`, `current_word`, `all_words`, etc.). `Suggest` has two variants: `Suggest::Suggest(list)` returns a suggestion list, `Suggest::FileCompletion` delegates file completion to the shell.
+
+## Generate completion scripts
+
+Call `build_comp_scripts` in `build.rs` to generate completion scripts (requires `builds` + `comp` features).
+
+See [example-completion](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-completion).
+
+<p align="center" style="font-size: 0.85em; color: gray;">
+ Written by @Weicao-CatilGrass
+</p>
diff --git a/docs/pages/advanced/2-structural-renderer.md b/docs/pages/advanced/2-structural-renderer.md
new file mode 100644
index 0000000..09c86d1
--- /dev/null
+++ b/docs/pages/advanced/2-structural-renderer.md
@@ -0,0 +1,120 @@
+<h1 align="center">Structural Rendering</h1>
+<p align="center">
+ Use the <code>structural_renderer</code> feature to render output as serialized text
+</p>
+
+With `structural_renderer` enabled, your program can switch output to a structured format via `--json`, `--yaml`, etc., making it easy to integrate with other tools.
+
+## Enabling the Feature
+
+```toml
+[dependencies.mingling]
+features = ["structural_renderer"]
+```
+
+`structural_renderer` automatically enables `json_serde_fmt`.
+
+For more formats, enable `structural_renderer_full` (includes JSON, YAML, TOML, RON).
+
+> [!NOTE]
+> To customize output types, see [Features](./pages/other/features)
+
+## Basic Usage
+
+After enabling `StructuralRendererSetup`, use `pack_structural!` instead of `pack!` to declare types that support structured output:
+
+```rust
+// Features: ["structural_renderer"]
+// Dependencies:
+// serde = "1"
+@@@use mingling::setup::StructuralRendererSetup;
+@@@dispatcher!("render", CMDRender => EntryRender);
+
+// pack_structural! is equivalent to pack! + StructuralData
+pack_structural!(ResultInfo = (String, i32));
+
+#[chain]
+fn handle_render(args: EntryRender) -> Next {
+ let name = args.inner.first().cloned().unwrap_or_default();
+ let age = args.inner.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
+ ResultInfo::new((name, age))
+}
+
+#[renderer]
+fn render_info(r: ResultInfo) {
+ r_println!("{:?}", *r);
+}
+```
+
+Output:
+
+```text
+~# my-cli render Bob 22
+("Bob", 22)
+
+~# my-cli render Bob 22 --json
+{"inner":["Bob",22]}
+```
+
+When the user passes `--json`, the framework automatically serializes the render result as JSON — no business logic changes needed.
+
+## Customizing Output Structure
+
+The default output from `pack_structural!` includes an `inner` field. For full control over the output structure, define the type manually with `#[derive(StructuralData, Serialize, Groupped)]`:
+
+```rust
+// Features: ["structural_renderer"]
+// Dependencies:
+// serde = "1"
+@@@use mingling::prelude::*;
+@@@use mingling::setup::StructuralRendererSetup;
+@@@use mingling::StructuralData;
+@@@use serde::Serialize;
+@@@dispatcher!("render", CMDRender => EntryRender);
+
+#[derive(Serialize, StructuralData, Groupped)]
+struct Info {
+ name: String,
+ age: i32,
+}
+
+#[chain]
+fn handle_render(args: EntryRender) -> Next {
+ let name = args.inner.first().cloned().unwrap_or_default();
+ let age = args.inner.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
+ Info { name, age }.to_render()
+}
+
+#[renderer]
+fn render_info(info: Info) {
+ r_println!("{} is {} years old", info.name, info.age);
+}
+@@@
+@@@fn main() {
+@@@ let mut program = ThisProgram::new();
+@@@ program.with_setup(StructuralRendererSetup);
+@@@ program.with_dispatcher(CMDRender);
+@@@ program.exec();
+@@@}
+@@@gen_program!();
+```
+
+Now `--json` outputs:
+
+```json
+{ "name": "Bob", "age": 22 }
+```
+
+## Notes
+
+- Supported formats: JSON, YAML, TOML, RON (depends on enabled features)
+- `StructuralRendererSetup` registers global params like `--json`, `--yaml`, `--toml`, `--ron`
+
+> [!NOTE]
+> Each type still needs an **empty Renderer**, otherwise that type **is not considered renderable**
+
+See [example-structural-renderer](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-structural-renderer).
+
+<p align="center" style="font-size: 0.85em; color: gray;">
+ Written by @Weicao-CatilGrass
+</p>