validator_demo/
validator_demo.rs

1//! Demonstrates argument validation features
2use flag_rs::{ArgValidator, CommandBuilder, Error};
3
4fn main() {
5    let app = CommandBuilder::new("validator-demo")
6        .short("Demonstrates argument validation")
7        .subcommand(
8            CommandBuilder::new("copy")
9                .short("Copy files (requires exactly 2 arguments)")
10                .args(ArgValidator::ExactArgs(2))
11                .run(|ctx| {
12                    let args = ctx.args();
13                    println!("Copying from '{}' to '{}'", args[0], args[1]);
14                    Ok(())
15                })
16                .build(),
17        )
18        .subcommand(
19            CommandBuilder::new("delete")
20                .short("Delete files (requires at least 1 argument)")
21                .args(ArgValidator::MinimumArgs(1))
22                .run(|ctx| {
23                    println!("Deleting {} file(s):", ctx.args().len());
24                    for file in ctx.args() {
25                        println!("  - {}", file);
26                    }
27                    Ok(())
28                })
29                .build(),
30        )
31        .subcommand(
32            CommandBuilder::new("list")
33                .short("List items (accepts 0-3 arguments)")
34                .args(ArgValidator::RangeArgs(0, 3))
35                .run(|ctx| {
36                    if ctx.args().is_empty() {
37                        println!("Listing all items");
38                    } else {
39                        println!("Listing specific items:");
40                        for item in ctx.args() {
41                            println!("  - {}", item);
42                        }
43                    }
44                    Ok(())
45                })
46                .build(),
47        )
48        .subcommand(
49            CommandBuilder::new("action")
50                .short("Perform action (only start/stop/restart allowed)")
51                .args(ArgValidator::OnlyValidArgs(vec![
52                    "start".to_string(),
53                    "stop".to_string(),
54                    "restart".to_string(),
55                ]))
56                .run(|ctx| {
57                    let action = ctx.args().first().map(String::as_str).unwrap_or("start");
58                    println!("Performing action: {}", action);
59                    Ok(())
60                })
61                .build(),
62        )
63        .subcommand(
64            CommandBuilder::new("numbers")
65                .short("Process numbers (custom validator for integers)")
66                .args(ArgValidator::Custom(std::sync::Arc::new(|args| {
67                    if args.is_empty() {
68                        return Err(Error::ArgumentValidation {
69                            message: "at least one number required".to_string(),
70                            expected: "numbers".to_string(),
71                            received: 0,
72                        });
73                    }
74
75                    for (i, arg) in args.iter().enumerate() {
76                        if arg.parse::<i32>().is_err() {
77                            return Err(Error::ArgumentValidation {
78                                message: format!(
79                                    "argument {} ('{}') must be an integer",
80                                    i + 1,
81                                    arg
82                                ),
83                                expected: "integer".to_string(),
84                                received: args.len(),
85                            });
86                        }
87                    }
88                    Ok(())
89                })))
90                .run(|ctx| {
91                    let numbers: Vec<i32> = ctx.args().iter().map(|s| s.parse().unwrap()).collect();
92                    let sum: i32 = numbers.iter().sum();
93                    println!("Sum of {} numbers: {}", numbers.len(), sum);
94                    Ok(())
95                })
96                .build(),
97        )
98        .build();
99
100    let args: Vec<String> = std::env::args().skip(1).collect();
101    if let Err(e) = app.execute(args) {
102        eprintln!("Error: {}", e);
103        std::process::exit(1);
104    }
105}