diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-08-04 13:26:48 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-08-04 13:26:48 +0800 |
| commit | 4588e17f7ddacd8391a5c881a209735e08d48797 (patch) | |
| tree | 2b513f4d4f8a18ebd3a34cff7c0fb8abf5787321 /examples | |
| parent | f7862affd74ac3b129f9e9791a4cd4e1c7e3e6d1 (diff) | |
feat: add entry metadata system with compile-time typed values
Add `Metadata<B>` trait and `#[metadata(Entry)]` attribute macro
to attach arbitrary, compile-time-typed metadata to entries.
Implement `ProgramCollect::get_metadata<T>()` for runtime retrieval,
backed by a global registry populated by `register_metadata!`.
Extend `pathf` with `MetadataPattern` to resolve metadata types
across modules at build time. Add two examples demonstrating
metadata usage with and without pathf integration.
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/example-combine-pathf-metadata/Cargo.lock | 226 | ||||
| -rw-r--r-- | examples/example-combine-pathf-metadata/Cargo.toml | 24 | ||||
| -rw-r--r-- | examples/example-combine-pathf-metadata/build.rs | 3 | ||||
| -rw-r--r-- | examples/example-combine-pathf-metadata/page.toml | 10 | ||||
| -rw-r--r-- | examples/example-combine-pathf-metadata/src/main.rs | 33 | ||||
| -rw-r--r-- | examples/example-combine-pathf-metadata/src/sub/mod.rs | 71 | ||||
| -rw-r--r-- | examples/example-metadata/Cargo.lock | 216 | ||||
| -rw-r--r-- | examples/example-metadata/Cargo.toml | 9 | ||||
| -rw-r--r-- | examples/example-metadata/page.toml | 10 | ||||
| -rw-r--r-- | examples/example-metadata/src/main.rs | 120 | ||||
| -rw-r--r-- | examples/test-examples.toml | 35 |
11 files changed, 757 insertions, 0 deletions
diff --git a/examples/example-combine-pathf-metadata/Cargo.lock b/examples/example-combine-pathf-metadata/Cargo.lock new file mode 100644 index 0000000..6fb41c4 --- /dev/null +++ b/examples/example-combine-pathf-metadata/Cargo.lock @@ -0,0 +1,226 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "example-combine-pathf-metadata" +version = "0.1.0" +dependencies = [ + "mingling", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "just_fmt" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91b935090fce9a995a79798a22d523f1742b202f57ad2d8fcab6ad3dff528baf" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "might_be_async" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "toml", +] + +[[package]] +name = "mingling" +version = "0.3.0" +dependencies = [ + "mingling_core", + "mingling_macros", +] + +[[package]] +name = "mingling_core" +version = "0.3.0" +dependencies = [ + "just_fmt", + "might_be_async", + "mingling_pathf", +] + +[[package]] +name = "mingling_macros" +version = "0.3.0" +dependencies = [ + "just_fmt", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "mingling_pathf" +version = "0.3.0" +dependencies = [ + "just_fmt", + "proc-macro2", + "syn 2.0.119", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] diff --git a/examples/example-combine-pathf-metadata/Cargo.toml b/examples/example-combine-pathf-metadata/Cargo.toml new file mode 100644 index 0000000..fd14c74 --- /dev/null +++ b/examples/example-combine-pathf-metadata/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "example-combine-pathf-metadata" +version = "0.1.0" +edition = "2024" + +[dependencies.mingling] +path = "../../mingling" +features = [ + # `extras` is required by the implicit `dispatcher!("hello")` form + "extras", + # `pathf` resolves types across modules at build time + "pathf", +] + +[build-dependencies.mingling] +path = "../../mingling" +features = [ + # Enable the `build` feature for build-time support + "build", + # `pathf` must also be enabled in build-dependencies + "pathf", +] + +[workspace] diff --git a/examples/example-combine-pathf-metadata/build.rs b/examples/example-combine-pathf-metadata/build.rs new file mode 100644 index 0000000..d909431 --- /dev/null +++ b/examples/example-combine-pathf-metadata/build.rs @@ -0,0 +1,3 @@ +fn main() { + mingling::build::analyze_and_build_type_mapping().unwrap(); +} diff --git a/examples/example-combine-pathf-metadata/page.toml b/examples/example-combine-pathf-metadata/page.toml new file mode 100644 index 0000000..76c1700 --- /dev/null +++ b/examples/example-combine-pathf-metadata/page.toml @@ -0,0 +1,10 @@ +[example] +id = "example-combine-pathf-metadata" +name = "Pathfinder + Metadata" +icon = "🧭" +category = "advanced" +desc = """ +Combines the `pathf` feature with entry metadata. The metadata `DataType` and the entry `BindType` are defined inside a submodule, and `pathf` resolves them for `gen_program!()` at build time. +""" +tags = ["pathf", "metadata", "build.rs"] +files = ["src/main.rs", "src/sub/mod.rs", "build.rs", "Cargo.toml"] diff --git a/examples/example-combine-pathf-metadata/src/main.rs b/examples/example-combine-pathf-metadata/src/main.rs new file mode 100644 index 0000000..a68eac5 --- /dev/null +++ b/examples/example-combine-pathf-metadata/src/main.rs @@ -0,0 +1,33 @@ +//! Example: Combining pathf + entry metadata +//! +//! > Demonstrates combining the `pathf` feature with entry metadata. The metadata +//! > `DataType` (`Description`) and the dispatchers/entries are defined in the `sub` +//! > module. Thanks to `pathf`, `gen_program!()` resolves these types across +//! > modules automatically, so `main` stays minimal. +//! +//! Run: +//! ```bash +//! cargo run --manifest-path examples/example-combine-pathf-metadata/Cargo.toml --quiet -- hello Alice +//! cargo run --manifest-path examples/example-combine-pathf-metadata/Cargo.toml --quiet -- hello +//! cargo run --manifest-path examples/example-combine-pathf-metadata/Cargo.toml --quiet -- desc +//! ``` +//! +//! Output: +//! ```plaintext +//! Hello, Alice! +//! Hello, World! +//! EntryHello desc = okay +//! ``` + +mod sub; + +use mingling::prelude::*; + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(sub::CMDHello); + program.with_dispatcher(sub::CMDDescription); + program.exec_and_exit(); +} + +gen_program!(); diff --git a/examples/example-combine-pathf-metadata/src/sub/mod.rs b/examples/example-combine-pathf-metadata/src/sub/mod.rs new file mode 100644 index 0000000..2e6776e --- /dev/null +++ b/examples/example-combine-pathf-metadata/src/sub/mod.rs @@ -0,0 +1,71 @@ +use crate::Next; +use crate::ThisProgram; +use mingling::ProgramCollect; +use mingling::macros::metadata; +use mingling::prelude::*; +use std::io::Write; + +// Implicit dispatcher form — creates `CMDHello` / `EntryHello` in this module +dispatcher!("hello"); +// Creates `CMDDescription` / `EntryDescription` in this module +dispatcher!("desc", CMDDescription => EntryDescription); + +/// The metadata type attached to an entry (`DataType`). +#[derive(Debug, PartialEq, Eq)] +pub struct Description { + pub desc: String, +} + +/// Attach a `Description` to `EntryHello`. +/// +/// - `BindType` = `EntryHello` (the enum variant / entry type) +/// - `DataType` = `Description` (the function's return type) +#[metadata(EntryHello)] +pub fn hello_desc() -> Description { + Description { + desc: "okay".to_string(), + } +} + +pack!(ResultName = String); +pack!(DescResult = String); + +/// Chain for `hello` — reads the name and produces a `ResultName`. +#[chain] +pub fn handle_hello(args: EntryHello) -> Next { + let name: ResultName = args + .inner + .first() + .cloned() + .unwrap_or_else(|| "World".to_string()) + .into(); + name.into() +} + +/// Chain for `desc` — looks up the metadata bound to `EntryHello`. +#[chain] +pub fn handle_desc(_args: EntryDescription) -> Next { + // --------- IMPORTANT --------- + let msg = match ThisProgram::get_metadata::<Description>(ThisProgram::EntryHello) { + Some(d) => format!("EntryHello desc = {}", d.desc), + None => "EntryHello has no description".to_string(), + }; + // --------- IMPORTANT --------- + DescResult::new(msg).to_render() +} + +/// Renders the greeting message with the provided name. +#[renderer] +pub fn render_name(name: ResultName) -> RenderResult { + let mut render_result = RenderResult::new(); + writeln!(render_result, "Hello, {}!", *name).ok(); + render_result +} + +/// Renders the metadata query result. +#[renderer] +pub fn render_desc(msg: DescResult) -> RenderResult { + let mut render_result = RenderResult::new(); + writeln!(render_result, "{}", *msg).ok(); + render_result +} diff --git a/examples/example-metadata/Cargo.lock b/examples/example-metadata/Cargo.lock new file mode 100644 index 0000000..ec3d4f2 --- /dev/null +++ b/examples/example-metadata/Cargo.lock @@ -0,0 +1,216 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "example-metadata" +version = "0.1.0" +dependencies = [ + "mingling", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "just_fmt" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91b935090fce9a995a79798a22d523f1742b202f57ad2d8fcab6ad3dff528baf" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "might_be_async" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "toml", +] + +[[package]] +name = "mingling" +version = "0.3.0" +dependencies = [ + "mingling_core", + "mingling_macros", +] + +[[package]] +name = "mingling_core" +version = "0.3.0" +dependencies = [ + "just_fmt", + "might_be_async", +] + +[[package]] +name = "mingling_macros" +version = "0.3.0" +dependencies = [ + "just_fmt", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] diff --git a/examples/example-metadata/Cargo.toml b/examples/example-metadata/Cargo.toml new file mode 100644 index 0000000..eb34960 --- /dev/null +++ b/examples/example-metadata/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "example-metadata" +version = "0.1.0" +edition = "2024" + +[dependencies] +mingling = { path = "../../mingling" } + +[workspace] diff --git a/examples/example-metadata/page.toml b/examples/example-metadata/page.toml new file mode 100644 index 0000000..1a99048 --- /dev/null +++ b/examples/example-metadata/page.toml @@ -0,0 +1,10 @@ +[example] +id = "example-metadata" +name = "Entry Metadata" +icon = "🏷️" +category = "advanced" +desc = """ +Demonstrates attaching arbitrary, compile-time-typed metadata to an entry via `#[metadata(Entry)]` and retrieving it at runtime with `ProgramCollect::get_metadata`. No `pathf` needed here — everything lives in a single module. +""" +tags = ["metadata", "get_metadata", "extras"] +files = ["src/main.rs", "Cargo.toml"] diff --git a/examples/example-metadata/src/main.rs b/examples/example-metadata/src/main.rs new file mode 100644 index 0000000..855241e --- /dev/null +++ b/examples/example-metadata/src/main.rs @@ -0,0 +1,120 @@ +//! Example: Entry Metadata (no `pathf`) +//! +//! > Demonstrates attaching arbitrary, compile-time-typed metadata (`Description`) +//! > to an entry via `#[metadata(Entry)]`, and retrieving it at runtime through +//! > `ProgramCollect::get_metadata`. The `desc` and `nodoc` subcommands dispatch +//! > through the normal chain/render pipeline — exactly like `example-basic`. +//! +//! Run: +//! ```bash +//! cargo run --manifest-path examples/example-metadata/Cargo.toml --quiet -- greet Alice +//! cargo run --manifest-path examples/example-metadata/Cargo.toml --quiet -- greet +//! cargo run --manifest-path examples/example-metadata/Cargo.toml --quiet -- desc +//! cargo run --manifest-path examples/example-metadata/Cargo.toml --quiet -- nodoc +//! ``` +//! +//! Output: +//! ```plaintext +//! Hello, Alice! +//! Hello, World! +//! EntryGreet desc = ok +//! EntryDescription has no description +//! ``` + +use mingling::{macros::metadata, prelude::*}; +use std::io::Write; + +// Define the `greet` subcommand +dispatcher!("greet", CMDGreet => EntryGreet); + +// Define the `desc` subcommand, which queries metadata bound to EntryGreet +dispatcher!("desc", CMDDescription => EntryDescription); + +// Define the `nodoc` subcommand, which queries metadata for an entry that has none +dispatcher!("nodoc", CMDNoDescription => EntryNoDescription); + +fn main() { + let mut program = ThisProgram::new(); + program.with_dispatcher(CMDGreet); + program.with_dispatcher(CMDDescription); + program.with_dispatcher(CMDNoDescription); + program.exec_and_exit(); +} + +/// The metadata type attached to an entry. +#[derive(Debug, PartialEq, Eq)] +pub struct Description { + pub desc: String, +} + +// --------- IMPORTANT --------- +/// Attach a `Description` to `EntryGreet`. +/// +/// - `BindType` = `EntryGreet` (the enum variant / entry type) +/// - `DataType` = `Description` (the function's return type) +#[metadata(EntryGreet)] +pub fn greet_desc() -> Description { + Description { + desc: "ok".to_string(), + } +} +// --------- IMPORTANT --------- + +pack!(ResultName = String); +pack!(DescResult = String); + +/// Chain for `greet` — reads the name and produces a `ResultName`. +#[chain] +fn handle_greet(args: EntryGreet) -> Next { + let name: ResultName = args + .inner + .first() + .cloned() + .unwrap_or_else(|| "World".to_string()) + .into(); + name.into() +} + +/// Chain for `desc` — looks up the metadata bound to `EntryGreet`. +#[chain] +fn handle_desc(_args: EntryDescription) -> Next { + use mingling::ProgramCollect; + // --------- IMPORTANT --------- + let msg = match ThisProgram::get_metadata::<Description>(ThisProgram::EntryGreet) { + Some(d) => format!("EntryGreet desc = {}", d.desc), + None => "EntryGreet has no description".to_string(), + }; + // --------- IMPORTANT --------- + DescResult::new(msg).to_render() +} + +/// Chain for `nodoc` — asks for metadata on an entry that has none. +#[chain] +fn handle_nodoc(_args: EntryNoDescription) -> Next { + use mingling::ProgramCollect; + // --------- IMPORTANT --------- + let msg = match ThisProgram::get_metadata::<Description>(ThisProgram::EntryDescription) { + Some(d) => format!("EntryDescription desc = {}", d.desc), + None => "EntryDescription has no description".to_string(), + }; + // --------- IMPORTANT --------- + DescResult::new(msg).to_render() +} + +/// Renders the greeting message with the provided name. +#[renderer] +fn render_name(name: ResultName) -> RenderResult { + let mut render_result = RenderResult::new(); + writeln!(render_result, "Hello, {}!", *name).ok(); + render_result +} + +/// Renders the metadata query result. +#[renderer] +fn render_desc(msg: DescResult) -> RenderResult { + let mut render_result = RenderResult::new(); + writeln!(render_result, "{}", *msg).ok(); + render_result +} + +gen_program!(); diff --git a/examples/test-examples.toml b/examples/test-examples.toml index b74c9a5..03df5e1 100644 --- a/examples/test-examples.toml +++ b/examples/test-examples.toml @@ -327,3 +327,38 @@ expect.result = "Hello, Alice" command = "goodbye" expect.exit-code = 0 expect.result = "Goodbye!" + +[[test.example-metadata]] +command = "greet" +expect.exit-code = 0 +expect.result = "Hello, World!" + +[[test.example-metadata]] +command = "greet Alice" +expect.exit-code = 0 +expect.result = "Hello, Alice!" + +[[test.example-metadata]] +command = "desc" +expect.exit-code = 0 +expect.result = "EntryGreet desc = ok" + +[[test.example-metadata]] +command = "nodoc" +expect.exit-code = 0 +expect.result = "EntryDescription has no description" + +[[test.example-combine-pathf-metadata]] +command = "hello" +expect.exit-code = 0 +expect.result = "Hello, World!" + +[[test.example-combine-pathf-metadata]] +command = "hello Alice" +expect.exit-code = 0 +expect.result = "Hello, Alice!" + +[[test.example-combine-pathf-metadata]] +command = "desc" +expect.exit-code = 0 +expect.result = "EntryHello desc = okay" |
