1#[macro_export]
53macro_rules! spec_flag {
54 ($short:literal, $long:literal) => {{
56 $crate::SpecFlagBuilder::new()
57 .short($short.chars().nth(1).expect("short flag must be -X format"))
58 .long(&$long[2..])
59 .build()
60 }};
61
62 ($short:literal, $long:literal; $($key:ident = $value:expr),* $(,)?) => {{
64 let mut builder = $crate::SpecFlagBuilder::new()
65 .short($short.chars().nth(1).expect("short flag must be -X format"))
66 .long(&$long[2..]);
67 $(builder = $crate::__spec_flag_attr!(builder, $key, $value);)*
68 builder.build()
69 }};
70
71 ($long:literal) => {{
73 $crate::SpecFlagBuilder::new()
74 .long(&$long[2..])
75 .build()
76 }};
77
78 ($long:literal; $($key:ident = $value:expr),* $(,)?) => {{
80 let mut builder = $crate::SpecFlagBuilder::new()
81 .long(&$long[2..]);
82 $(builder = $crate::__spec_flag_attr!(builder, $key, $value);)*
83 builder.build()
84 }};
85
86 ($long:literal => $arg:literal) => {{
88 let arg: $crate::SpecArg = $arg.parse().expect("invalid arg format");
89 $crate::SpecFlagBuilder::new()
90 .long(&$long[2..])
91 .arg(arg)
92 .build()
93 }};
94
95 ($long:literal => $arg:literal; $($key:ident = $value:expr),* $(,)?) => {{
97 let arg: $crate::SpecArg = $arg.parse().expect("invalid arg format");
98 let mut builder = $crate::SpecFlagBuilder::new()
99 .long(&$long[2..])
100 .arg(arg);
101 $(builder = $crate::__spec_flag_attr!(builder, $key, $value);)*
102 builder.build()
103 }};
104
105 ($short:literal, $long:literal => $arg:literal) => {{
107 let arg: $crate::SpecArg = $arg.parse().expect("invalid arg format");
108 $crate::SpecFlagBuilder::new()
109 .short($short.chars().nth(1).expect("short flag must be -X format"))
110 .long(&$long[2..])
111 .arg(arg)
112 .build()
113 }};
114
115 ($short:literal, $long:literal => $arg:literal; $($key:ident = $value:expr),* $(,)?) => {{
117 let arg: $crate::SpecArg = $arg.parse().expect("invalid arg format");
118 let mut builder = $crate::SpecFlagBuilder::new()
119 .short($short.chars().nth(1).expect("short flag must be -X format"))
120 .long(&$long[2..])
121 .arg(arg);
122 $(builder = $crate::__spec_flag_attr!(builder, $key, $value);)*
123 builder.build()
124 }};
125}
126
127#[macro_export]
129#[doc(hidden)]
130macro_rules! __spec_flag_attr {
131 ($builder:expr, help, $value:expr) => {
132 $builder.help($value)
133 };
134 ($builder:expr, help_long, $value:expr) => {
135 $builder.help_long($value)
136 };
137 ($builder:expr, var, $value:expr) => {
138 $builder.var($value)
139 };
140 ($builder:expr, var_min, $value:expr) => {
141 $builder.var_min($value)
142 };
143 ($builder:expr, var_max, $value:expr) => {
144 $builder.var_max($value)
145 };
146 ($builder:expr, required, $value:expr) => {
147 $builder.required($value)
148 };
149 ($builder:expr, global, $value:expr) => {
150 $builder.global($value)
151 };
152 ($builder:expr, hide, $value:expr) => {
153 $builder.hide($value)
154 };
155 ($builder:expr, count, $value:expr) => {
156 $builder.count($value)
157 };
158 ($builder:expr, env, $value:expr) => {
159 $builder.env($value)
160 };
161}
162
163#[macro_export]
188macro_rules! spec_arg {
189 ($name:literal) => {{
191 $crate::SpecArgBuilder::new()
192 .name($name)
193 .build()
194 }};
195
196 ($name:literal; $($key:ident = $value:expr),* $(,)?) => {{
198 let mut builder = $crate::SpecArgBuilder::new()
199 .name($name);
200 $(builder = $crate::__spec_arg_attr!(builder, $key, $value);)*
201 builder.build()
202 }};
203}
204
205#[macro_export]
207#[doc(hidden)]
208macro_rules! __spec_arg_attr {
209 ($builder:expr, help, $value:expr) => {
210 $builder.help($value)
211 };
212 ($builder:expr, help_long, $value:expr) => {
213 $builder.help_long($value)
214 };
215 ($builder:expr, var, $value:expr) => {
216 $builder.var($value)
217 };
218 ($builder:expr, var_min, $value:expr) => {
219 $builder.var_min($value)
220 };
221 ($builder:expr, var_max, $value:expr) => {
222 $builder.var_max($value)
223 };
224 ($builder:expr, required, $value:expr) => {
225 $builder.required($value)
226 };
227 ($builder:expr, hide, $value:expr) => {
228 $builder.hide($value)
229 };
230 ($builder:expr, env, $value:expr) => {
231 $builder.env($value)
232 };
233}
234
235#[macro_export]
260macro_rules! spec_cmd {
261 ($name:literal) => {{
263 $crate::SpecCommandBuilder::new()
264 .name($name)
265 .build()
266 }};
267
268 ($name:literal; $($key:ident = $value:expr),* $(,)?) => {{
270 let mut builder = $crate::SpecCommandBuilder::new()
271 .name($name);
272 $(builder = $crate::__spec_cmd_attr!(builder, $key, $value);)*
273 builder.build()
274 }};
275}
276
277#[macro_export]
279#[doc(hidden)]
280macro_rules! __spec_cmd_attr {
281 ($builder:expr, help, $value:expr) => {
282 $builder.help($value)
283 };
284 ($builder:expr, help_long, $value:expr) => {
285 $builder.help_long($value)
286 };
287 ($builder:expr, hide, $value:expr) => {
288 $builder.hide($value)
289 };
290 ($builder:expr, subcommand_required, $value:expr) => {
291 $builder.subcommand_required($value)
292 };
293 ($builder:expr, aliases, $value:expr) => {
294 $builder.aliases($value)
295 };
296 ($builder:expr, hidden_aliases, $value:expr) => {
297 $builder.hidden_aliases($value)
298 };
299}
300
301#[macro_export]
312macro_rules! defaults {
313 [$($value:expr),* $(,)?] => {
314 vec![$($value.to_string()),*]
315 };
316}
317
318#[macro_export]
329macro_rules! shorts {
330 [$($char:literal),* $(,)?] => {
331 vec![$($char),*]
332 };
333}
334
335#[macro_export]
346macro_rules! longs {
347 [$($name:literal),* $(,)?] => {
348 vec![$($name.to_string()),*]
349 };
350}
351
352#[macro_export]
363macro_rules! aliases {
364 [$($name:literal),* $(,)?] => {
365 vec![$($name.to_string()),*]
366 };
367}
368
369#[cfg(test)]
370mod tests {
371
372 #[test]
373 fn test_spec_flag_simple() {
374 let f = spec_flag!("-v", "--verbose");
375 assert_eq!(f.short, vec!['v']);
376 assert_eq!(f.long, vec!["verbose".to_string()]);
377 }
378
379 #[test]
380 fn test_spec_flag_with_help() {
381 let f = spec_flag!("-f", "--force"; help = "Force operation");
382 assert_eq!(f.short, vec!['f']);
383 assert_eq!(f.long, vec!["force".to_string()]);
384 assert_eq!(f.help, Some("Force operation".to_string()));
385 }
386
387 #[test]
388 fn test_spec_flag_long_only() {
389 let f = spec_flag!("--all");
390 assert!(f.short.is_empty());
391 assert_eq!(f.long, vec!["all".to_string()]);
392 }
393
394 #[test]
395 fn test_spec_flag_variadic() {
396 let f = spec_flag!("--file"; var = true, var_min = 1, var_max = 10);
397 assert!(f.var);
398 assert_eq!(f.var_min, Some(1));
399 assert_eq!(f.var_max, Some(10));
400 }
401
402 #[test]
403 fn test_spec_flag_with_arg() {
404 let f = spec_flag!("--output" => "<file>"; help = "Output file");
405 assert!(f.arg.is_some());
406 assert_eq!(f.arg.as_ref().unwrap().name, "file");
407 assert_eq!(f.help, Some("Output file".to_string()));
408 }
409
410 #[test]
411 fn test_spec_arg_simple() {
412 let a = spec_arg!("file");
413 assert_eq!(a.name, "file");
414 }
415
416 #[test]
417 fn test_spec_arg_with_options() {
418 let a = spec_arg!("files"; var = true, var_min = 1, help = "Input files");
419 assert_eq!(a.name, "files");
420 assert!(a.var);
421 assert_eq!(a.var_min, Some(1));
422 assert_eq!(a.help, Some("Input files".to_string()));
423 }
424
425 #[test]
426 fn test_spec_cmd_simple() {
427 let c = spec_cmd!("install");
428 assert_eq!(c.name, "install");
429 }
430
431 #[test]
432 fn test_spec_cmd_with_options() {
433 let c = spec_cmd!("install"; help = "Install packages", aliases = ["i", "add"]);
434 assert_eq!(c.name, "install");
435 assert_eq!(c.help, Some("Install packages".to_string()));
436 assert_eq!(c.aliases, vec!["i".to_string(), "add".to_string()]);
437 }
438
439 #[test]
440 fn test_defaults_macro() {
441 let d = defaults!["a", "b", "c"];
442 assert_eq!(d, vec!["a".to_string(), "b".to_string(), "c".to_string()]);
443 }
444
445 #[test]
446 fn test_shorts_macro() {
447 let s = shorts!['a', 'b', 'c'];
448 assert_eq!(s, vec!['a', 'b', 'c']);
449 }
450
451 #[test]
452 fn test_longs_macro() {
453 let l = longs!["verbose", "debug"];
454 assert_eq!(l, vec!["verbose".to_string(), "debug".to_string()]);
455 }
456
457 #[test]
458 fn test_aliases_macro() {
459 let a = aliases!["i", "inst"];
460 assert_eq!(a, vec!["i".to_string(), "inst".to_string()]);
461 }
462}