aboutsummaryrefslogtreecommitdiff
path: root/examples/example-pack-err/src/main.rs
blob: f859faecae6f95c05b6f7005258c9ee5173d0171 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! 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 Cargo.toml
//! 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-structural --json
//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find-structural Cargo.toml --json
//! cargo run --manifest-path examples/example-pack-err/Cargo.toml --quiet -- find-structural src --json
//! ```
//!
//! Output:
//! ```plaintext
//! Search path not provided
//! Not a directory: Cargo.toml
//! Found directory: src
//! {"name":"error_not_found"}
//! {"name":"error_not_dir","info":"Cargo.toml"}
//! {"inner":"src"}
//! {"name":"error_not_found_structural"}
//! {"name":"error_not_dir_structural","info":"Cargo.toml"}
//! ```

use mingling::prelude::*;
use mingling::setup::GeneralRendererSetup;
use std::path::PathBuf;

dispatcher!("find", CMDFind => EntryFind);
dispatcher!("find-structural", CMDFindStructural => EntryFindStructural);

// --------- 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);

// Simple form — with StructuralData support for --json / --yaml
pack_err_structural!(ErrorNotFoundStructural);

// Typed form — with StructuralData support for --json / --yaml
pack_err_structural!(ErrorNotDirStructural = PathBuf);

// Success type with StructuralData support
pack_structural!(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()
    }
}

#[chain]
fn handle_find_structural(args: EntryFindStructural) -> Next {
    let Some(path_str) = args.inner.first().cloned() else {
        // No path provided → use the simple error form (Default)
        return ErrorNotFoundStructural::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
        ErrorNotDirStructural::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());
}

/// Renders the structural error when no search path is provided.
#[renderer]
fn render_error_not_found_structural(_: ErrorNotFoundStructural) {
    r_println!("Search path not provided");
}

/// Renders the structural error when the given path is not a directory.
#[renderer]
fn render_error_not_dir_structural(err: ErrorNotDirStructural) {
    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);
    program.with_dispatcher(CMDFindStructural);
    let _ = program.exec();
}