Structural Rendering

Use the structural_renderer feature to render output as serialized text

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).

Written by @Weicao-CatilGrass