flag_completion_demo/
flag_completion_demo.rs

1//! Demonstrates inline flag completion support
2use flag_rs::{CommandBuilder, CompletionResult, Flag};
3
4fn main() {
5    let app = CommandBuilder::new("deploy")
6        .short("Deploy application to various environments")
7        .flag(
8            Flag::choice("environment", &["dev", "staging", "prod"])
9                .short('e')
10                .usage("Target environment")
11                .required()
12                .completion(|_ctx, prefix| {
13                    // Dynamic completion - could check available environments
14                    let environments = vec![
15                        ("dev", "Development environment"),
16                        ("staging", "Staging environment (pre-production)"),
17                        ("prod", "Production environment"),
18                    ];
19
20                    let mut result = CompletionResult::new();
21                    for (env, desc) in environments {
22                        if env.starts_with(prefix) {
23                            result = result.add_with_description(env.to_string(), desc.to_string());
24                        }
25                    }
26
27                    // Add active help if no prefix
28                    if prefix.is_empty() {
29                        result = result.add_help_text("Available environments: dev, staging, prod");
30                    }
31
32                    Ok(result)
33                }),
34        )
35        .flag(
36            Flag::file("config")
37                .short('c')
38                .usage("Configuration file")
39                .default_str("config.yaml")
40                .completion(|_ctx, prefix| {
41                    // In a real app, you might list files in the config directory
42                    let configs = vec![
43                        "config.yaml",
44                        "config.dev.yaml",
45                        "config.staging.yaml",
46                        "config.prod.yaml",
47                        "secrets.yaml",
48                    ];
49
50                    Ok(CompletionResult::new().extend(
51                        configs
52                            .into_iter()
53                            .filter(|c| c.starts_with(prefix))
54                            .map(String::from),
55                    ))
56                }),
57        )
58        .flag(
59            Flag::directory("output")
60                .short('o')
61                .usage("Output directory for deployment artifacts")
62                .completion(|_ctx, prefix| {
63                    // In a real app, you might list actual directories
64                    let dirs = vec!["./build", "./dist", "./output", "/tmp/deploy"];
65
66                    Ok(CompletionResult::new().extend(
67                        dirs.into_iter()
68                            .filter(|d| d.starts_with(prefix))
69                            .map(String::from),
70                    ))
71                }),
72        )
73        .flag(
74            Flag::string_slice("service")
75                .short('s')
76                .usage("Services to deploy (can be specified multiple times)")
77                .completion(|ctx, prefix| {
78                    // Context-aware completion based on environment
79                    let env = ctx.flag_str_or("environment", "dev");
80
81                    let services = match env {
82                        "dev" => vec!["api", "web", "worker", "scheduler", "debug-panel"],
83                        "staging" => vec!["api", "web", "worker", "scheduler"],
84                        "prod" => vec!["api", "web", "worker"],
85                        _ => vec!["api", "web"],
86                    };
87
88                    let mut result = CompletionResult::new().extend(
89                        services
90                            .into_iter()
91                            .filter(|s| s.starts_with(prefix))
92                            .map(String::from),
93                    );
94
95                    // Add context-aware help
96                    if prefix.is_empty() {
97                        result = result
98                            .add_help_text(format!("Available services for {} environment", env));
99                    }
100
101                    Ok(result)
102                }),
103        )
104        .flag(
105            Flag::range("replicas", 1, 10)
106                .short('r')
107                .usage("Number of replicas to deploy")
108                .default_int(2)
109                .completion(|_ctx, _prefix| {
110                    // Suggest common replica counts
111                    Ok(CompletionResult::new()
112                        .add_with_description(
113                            "1".to_string(),
114                            "Single instance (dev/test)".to_string(),
115                        )
116                        .add_with_description("2".to_string(), "Basic redundancy".to_string())
117                        .add_with_description("3".to_string(), "Standard production".to_string())
118                        .add_with_description("5".to_string(), "High availability".to_string()))
119                }),
120        )
121        .run(|ctx| {
122            let env = ctx.flag_str_or("environment", "dev");
123            let config = ctx.flag_str_or("config", "config.yaml");
124            let replicas = ctx.flag_int_or("replicas", 2);
125
126            println!("Deploying to {} environment", env);
127            println!("Using configuration: {}", config);
128            println!("Replica count: {}", replicas);
129
130            if let Some(output) = ctx.flag("output") {
131                println!("Output directory: {}", output);
132            }
133
134            if let Some(services) = ctx.flag("service") {
135                println!("Deploying services: {}", services);
136            } else {
137                println!("Deploying all services");
138            }
139
140            Ok(())
141        })
142        .build();
143
144    let args: Vec<String> = std::env::args().skip(1).collect();
145    if let Err(e) = app.execute(args) {
146        eprintln!("Error: {}", e);
147        std::process::exit(1);
148    }
149}