From 0f7b2a50b05f38d886234ff6b031766c7af1dabb Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Thu, 18 Jun 2026 22:48:16 +0800 Subject: Add `pack_err!` macro for error structs with automatic name field --- examples/example-pack-err/Cargo.lock | 141 ++++++++++++++++++++++++++++++++++ examples/example-pack-err/Cargo.toml | 16 ++++ examples/example-pack-err/page.toml | 10 +++ examples/example-pack-err/src/main.rs | 101 ++++++++++++++++++++++++ 4 files changed, 268 insertions(+) create mode 100644 examples/example-pack-err/Cargo.lock create mode 100644 examples/example-pack-err/Cargo.toml create mode 100644 examples/example-pack-err/page.toml create mode 100644 examples/example-pack-err/src/main.rs (limited to 'examples/example-pack-err') diff --git a/examples/example-pack-err/Cargo.lock b/examples/example-pack-err/Cargo.lock new file mode 100644 index 0000000..36d4b6f --- /dev/null +++ b/examples/example-pack-err/Cargo.lock @@ -0,0 +1,141 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "example-pack-err" +version = "0.1.0" +dependencies = [ + "mingling", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "just_fmt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5454cda0d57db59778608d7a47bff5b16c6705598265869fb052b657f66cf05e" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "mingling" +version = "0.2.0" +dependencies = [ + "mingling_core", + "mingling_macros", + "serde", +] + +[[package]] +name = "mingling_core" +version = "0.2.0" +dependencies = [ + "just_fmt", + "serde", + "serde_json", +] + +[[package]] +name = "mingling_macros" +version = "0.2.0" +dependencies = [ + "just_fmt", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/examples/example-pack-err/Cargo.toml b/examples/example-pack-err/Cargo.toml new file mode 100644 index 0000000..883fc89 --- /dev/null +++ b/examples/example-pack-err/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "example-pack-err" +version = "0.1.0" +edition = "2024" + +[dependencies] +serde = { version = "1.0.228", features = ["derive"] } + +[dependencies.mingling] +path = "../../mingling" +features = [ + "general_renderer", + "extra_macros", +] + +[workspace] diff --git a/examples/example-pack-err/page.toml b/examples/example-pack-err/page.toml new file mode 100644 index 0000000..5534236 --- /dev/null +++ b/examples/example-pack-err/page.toml @@ -0,0 +1,10 @@ +[example] +id = "example-pack-err" +name = "pack_err!" +icon = "🛑" +category = "macros" +desc = """ +Demonstrates how to use the `pack_err!` macro to define error types with automatic `name` field (snake_case at compile time) and optional `info` field. Also shows `--json` serialization when `general_renderer` is enabled. +""" +tags = ["pack_err!", "extra_macros", "general_renderer", "--json"] +files = ["src/main.rs", "Cargo.toml"] diff --git a/examples/example-pack-err/src/main.rs b/examples/example-pack-err/src/main.rs new file mode 100644 index 0000000..72fecd6 --- /dev/null +++ b/examples/example-pack-err/src/main.rs @@ -0,0 +1,101 @@ +//! Example `pack_err!` +//! +//! > This example demonstrates how to use the `pack_err!` macro to define error types +//! > with automatic `name` field (set to snake_case at compile time) and optional `info` field. +//! > Also demonstrates `--json` serialization when `general_renderer` is enabled. +//! +//! Run: +//! ```bash +//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find +//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find --json +//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find Cargo.toml +//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find Cargo.toml --json +//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find src +//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find src --json +//! ``` +//! +//! Output: +//! ```plaintext +//! Search path not provided +//! {"name":"error_not_found"} +//! Not a directory: Cargo.toml +//! {"name":"error_not_dir","info":"Cargo.toml"} +//! Found directory: src +//! {"inner":"src"} +//! ``` + +use mingling::prelude::*; +use mingling::setup::GeneralRendererSetup; +use std::path::PathBuf; + +dispatcher!("find", CMDFind => EntryFind); + +// --------- IMPORTANT --------- +// `pack_err!` is a convenient macro for defining error types. +// +// Simple form: pack_err!(ErrorNotFound); +// Typed form: pack_err!(ErrorNotDir = PathBuf); +// +// The simple form generates a struct with `name: String` and `impl Default`. +// name = "error_not_found" (automatically snake_cased at compile time) +// +// The typed form additionally generates `pub fn new(info)`. +// name = "error_not_dir" +// +// When `general_renderer` is enabled, the struct also gets +// `#[derive(serde::Serialize)]` for --json / --yaml output. +// --------- IMPORTANT --------- + +// Simple form — name = "error_not_found" +pack_err!(ErrorNotFound); + +// Typed form — name = "error_not_dir" +pack_err!(ErrorNotDir = PathBuf); + +// Success type using traditional pack! +pack!(ResultPath = PathBuf); + +#[chain] +fn handle_find(args: EntryFind) -> Next { + let Some(path_str) = args.inner.first().cloned() else { + // No path provided → use the simple error form (Default) + return ErrorNotFound::default().to_render(); + }; + + let path = PathBuf::from(&path_str); + if path.is_dir() { + // Is a directory → success + ResultPath::new(path).to_render() + } else { + // Not a directory (or doesn't exist) → use the typed error form + ErrorNotDir::new(path).to_render() + } +} + +/// Renders the successful result with the found directory path. +#[renderer] +fn render_result_path(path: ResultPath) { + r_println!("Found directory: {}", path.display()); +} + +/// Renders the error when no search path is provided. +#[renderer] +fn render_error_not_found(_: ErrorNotFound) { + r_println!("Search path not provided"); +} + +/// Renders the error when the given path is not a directory. +#[renderer] +fn render_error_not_dir(err: ErrorNotDir) { + r_println!("Not a directory: {}", err.info.display()); +} + +gen_program!(); + +fn main() { + let mut program = ThisProgram::new(); + // Add GeneralRendererSetup to support --json / --yaml flags + program.with_setup(GeneralRendererSetup); + program.with_dispatcher(CMDFind); + let _ = program.exec(); +} -- cgit