1use std::env;
2use std::ffi::OsStr;
3use std::fmt;
4use std::process;
5use std::str::FromStr;
6
7mod util;
8mod validation;
9pub use util::Never;
10pub use validation::Invalid;
11
12pub type Matches = getopts::Matches;
13
14#[derive(Hash, PartialEq, Eq, Clone, Debug)]
15pub struct SwitchCommon {
16 pub short: String,
17 pub long: String,
18 pub doc: String,
19}
20
21impl SwitchCommon {
22 fn new(short: &str, long: &str, doc: &str) -> Self {
23 Self {
24 short: short.to_string(),
25 long: long.to_string(),
26 doc: doc.to_string(),
27 }
28 }
29
30 fn key_to_search_in_matches(&self) -> &str {
31 if self.short.len() != 0 {
32 self.short.as_str()
33 } else {
34 self.long.as_str()
35 }
36 }
37}
38
39#[derive(Hash, PartialEq, Eq, Clone, Debug)]
40pub enum SwitchShape {
41 Flag,
42 Opt { hint: String },
43}
44
45pub trait Switches {
46 fn add(&mut self, common: SwitchCommon, shape: SwitchShape);
47}
48
49impl Switches for getopts::Options {
50 fn add(&mut self, common: SwitchCommon, shape: SwitchShape) {
51 match shape {
52 SwitchShape::Flag => {
53 self.optflag(
54 common.short.as_str(),
55 common.long.as_str(),
56 common.doc.as_str(),
57 );
58 }
59 SwitchShape::Opt { hint } => {
60 self.optopt(
61 common.short.as_str(),
62 common.long.as_str(),
63 common.doc.as_str(),
64 hint.as_str(),
65 );
66 }
67 }
68 }
69}
70
71#[derive(Debug)]
72pub enum TopLevelError<E> {
73 Getopts(getopts::Fail),
74 Other(E),
75}
76
77impl<E: fmt::Display> fmt::Display for TopLevelError<E> {
78 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
79 match self {
80 Self::Getopts(fail) => fmt::Display::fmt(&fail, f),
81 Self::Other(other) => fmt::Display::fmt(&other, f),
82 }
83 }
84}
85
86pub struct Usage {
87 opts: getopts::Options,
88 program_name: String,
89}
90
91impl Usage {
92 pub fn render(&self) -> String {
93 let brief = format!("Usage: {} [options]", &self.program_name);
94 self.opts.usage(&brief)
95 }
96}
97
98pub struct ParseResult<I, E> {
99 pub usage: Usage,
100 pub result: Result<I, TopLevelError<E>>,
101}
102
103pub trait Arg: Sized {
104 type Item;
105 type Error: fmt::Debug + fmt::Display;
106 fn update_switches<S: Switches>(&self, switches: &mut S);
107 fn name(&self) -> String;
108 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error>;
109 fn validate(&self) -> Result<(), Invalid> {
110 let mut checker = validation::Checker::default();
111 self.update_switches(&mut checker);
112 if let Some(invalid) = checker.invalid() {
113 Err(invalid)
114 } else {
115 Ok(())
116 }
117 }
118 fn parse_specified_ignoring_validation<I>(
119 self,
120 program_name: String,
121 args: I,
122 ) -> ParseResult<Self::Item, Self::Error>
123 where
124 I: IntoIterator,
125 I::Item: AsRef<OsStr>,
126 {
127 let mut opts = getopts::Options::new();
128 self.update_switches(&mut opts);
129 ParseResult {
130 result: opts
131 .parse(args)
132 .map_err(TopLevelError::Getopts)
133 .and_then(|matches| self.get(&matches).map_err(TopLevelError::Other)),
134 usage: Usage { opts, program_name },
135 }
136 }
137 fn parse_specified<I>(
138 self,
139 program_name: String,
140 args: I,
141 ) -> ParseResult<Self::Item, Self::Error>
142 where
143 I: IntoIterator,
144 I::Item: AsRef<OsStr>,
145 {
146 if let Err(invalid) = self.validate() {
147 panic!("Invalid command spec:\n{}", invalid);
148 }
149 self.parse_specified_ignoring_validation(program_name, args)
150 }
151 fn parse_env(self) -> ParseResult<Self::Item, Self::Error> {
152 let args = env::args().collect::<Vec<_>>();
153 let program_name = args[0].clone();
154 self.parse_specified(program_name, &args[1..])
155 }
156 fn with_help(self, help_flag: Flag) -> WithHelp<Self> {
157 WithHelp {
158 arg: self,
159 help_flag,
160 }
161 }
162 fn with_help_default(self) -> WithHelp<Self> {
163 self.with_help(Flag::new("h", "help", "print this help menu"))
164 }
165 fn option_map<F, T, U>(self, f: F) -> OptionMap<Self, F>
166 where
167 F: FnOnce(T) -> U,
168 {
169 OptionMap { arg: self, f }
170 }
171 fn with_default<T>(self, default_value: T) -> WithDefault<Self, T> {
172 WithDefault {
173 arg: self,
174 default_value,
175 }
176 }
177 fn with_default_lazy<F>(self, default_value_f: F) -> WithDefaultLazy<Self, F> {
178 WithDefaultLazy {
179 arg: self,
180 default_value_f,
181 }
182 }
183 fn choice<O>(self, other: O) -> Choice<Self, O>
184 where
185 O: Arg<Item = Self::Item>,
186 {
187 Choice { a: self, b: other }
188 }
189 fn both<O>(self, other: O) -> Both<Self, O>
190 where
191 O: Arg,
192 {
193 Both { a: self, b: other }
194 }
195 fn map<F, U>(self, f: F) -> Map<Self, F>
196 where
197 F: FnOnce(Self::Item) -> U,
198 {
199 Map { arg: self, f }
200 }
201 fn required(self) -> Required<Self> {
202 Required { arg: self }
203 }
204 fn convert_string<F, T, E>(self, f: F) -> ConvertString<Self, F>
205 where
206 F: FnOnce(&str) -> Result<T, E>,
207 {
208 ConvertString { arg: self, f }
209 }
210 fn option_convert_string<F, T, E>(self, f: F) -> OptionConvertString<Self, F>
211 where
212 F: FnOnce(&str) -> Result<T, E>,
213 {
214 OptionConvertString { arg: self, f }
215 }
216 fn vec_convert_string<F, T, E>(self, f: F) -> VecConvertString<Self, F>
217 where
218 F: FnMut(&str) -> Result<T, E>,
219 {
220 VecConvertString { arg: self, f }
221 }
222 fn vec_singleton(self) -> VecSingleton<Self> {
223 VecSingleton { arg: self }
224 }
225 fn depend<O>(self, other: O) -> Depend<Self, O>
226 where
227 O: Arg,
228 {
229 Depend { a: self, b: other }
230 }
231 fn some_if<T>(self, t: T) -> SomeIf<Self, T> {
232 SomeIf { arg: self, t }
233 }
234}
235
236pub struct Flag {
237 common: SwitchCommon,
238}
239
240impl Flag {
241 pub fn new(short: &str, long: &str, doc: &str) -> Self {
242 Self {
243 common: SwitchCommon::new(short, long, doc),
244 }
245 }
246}
247impl Arg for Flag {
248 type Item = bool;
249 type Error = Never;
250 fn update_switches<S: Switches>(&self, switches: &mut S) {
251 switches.add(self.common.clone(), SwitchShape::Flag);
252 }
253 fn name(&self) -> String {
254 self.common.long.clone()
255 }
256 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
257 Ok(matches.opt_present(self.common.key_to_search_in_matches()))
258 }
259}
260
261pub struct Opt {
262 common: SwitchCommon,
263 hint: String,
264}
265
266impl Opt {
267 pub fn new(short: &str, long: &str, doc: &str, hint: &str) -> Self {
268 Self {
269 common: SwitchCommon::new(short, long, doc),
270 hint: hint.to_string(),
271 }
272 }
273}
274
275impl Arg for Opt {
276 type Item = Option<String>;
277 type Error = Never;
278 fn update_switches<S: Switches>(&self, switches: &mut S) {
279 switches.add(
280 self.common.clone(),
281 SwitchShape::Opt {
282 hint: self.hint.clone(),
283 },
284 );
285 }
286 fn name(&self) -> String {
287 self.common.long.clone()
288 }
289 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
290 Ok(matches.opt_str(self.common.key_to_search_in_matches()))
291 }
292}
293
294pub struct Free;
295
296impl Arg for Free {
297 type Item = Vec<String>;
298 type Error = Never;
299 fn update_switches<S: Switches>(&self, _switches: &mut S) {}
300 fn name(&self) -> String {
301 "ARGS".to_string()
302 }
303 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
304 Ok(matches.free.clone())
305 }
306}
307
308pub struct WithHelp<A> {
309 arg: A,
310 help_flag: Flag,
311}
312
313pub enum OrHelp<T> {
314 Value(T),
315 Help,
316}
317
318impl<A> Arg for WithHelp<A>
319where
320 A: Arg,
321{
322 type Item = OrHelp<A::Item>;
323 type Error = A::Error;
324 fn update_switches<S: Switches>(&self, switches: &mut S) {
325 self.arg.update_switches(switches);
326 self.help_flag.update_switches(switches);
327 }
328 fn name(&self) -> String {
329 format!("({}) with help", self.arg.name())
330 }
331 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
332 if Never::result_ok(self.help_flag.get(matches)) {
333 Ok(OrHelp::Help)
334 } else {
335 self.arg.get(matches).map(OrHelp::Value)
336 }
337 }
338}
339
340impl<A> WithHelp<A>
341where
342 A: Arg,
343{
344 pub fn parse_env_or_exit(self) -> A::Item {
345 let ParseResult { result, usage } = self.parse_env();
346 match result {
347 Ok(OrHelp::Value(a)) => a,
348 Ok(OrHelp::Help) => {
349 print!("{}", usage.render());
350 process::exit(0);
351 }
352 Err(e) => {
353 eprint!("{}\n\n", e);
354 eprint!("{}", usage.render());
355 process::exit(1);
356 }
357 }
358 }
359}
360
361pub struct OptionMap<A, F>
362where
363 A: Arg,
364{
365 arg: A,
366 f: F,
367}
368
369impl<A, F, T, U> Arg for OptionMap<A, F>
370where
371 A: Arg<Item = Option<T>>,
372 F: FnOnce(T) -> U,
373{
374 type Item = Option<U>;
375 type Error = A::Error;
376 fn update_switches<S: Switches>(&self, switches: &mut S) {
377 self.arg.update_switches(switches);
378 }
379 fn name(&self) -> String {
380 self.arg.name()
381 }
382 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
383 let Self { arg, f } = self;
384 arg.get(matches).map(|x| x.map(f))
385 }
386}
387
388pub struct WithDefault<A, T>
389where
390 A: Arg,
391{
392 arg: A,
393 default_value: T,
394}
395
396impl<A, T> Arg for WithDefault<A, T>
397where
398 A: Arg<Item = Option<T>>,
399{
400 type Item = T;
401 type Error = A::Error;
402 fn update_switches<S: Switches>(&self, switches: &mut S) {
403 self.arg.update_switches(switches);
404 }
405 fn name(&self) -> String {
406 self.arg.name()
407 }
408 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
409 let Self { arg, default_value } = self;
410 arg.get(matches).map(|x| x.unwrap_or(default_value))
411 }
412}
413
414pub struct WithDefaultLazy<A, F>
415where
416 A: Arg,
417{
418 arg: A,
419 default_value_f: F,
420}
421
422impl<A, F, T> Arg for WithDefaultLazy<A, F>
423where
424 A: Arg<Item = Option<T>>,
425 F: FnOnce() -> T,
426{
427 type Item = T;
428 type Error = A::Error;
429 fn update_switches<S: Switches>(&self, switches: &mut S) {
430 self.arg.update_switches(switches);
431 }
432 fn name(&self) -> String {
433 self.arg.name()
434 }
435 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
436 let Self {
437 arg,
438 default_value_f,
439 } = self;
440 arg.get(matches).map(|x| x.unwrap_or_else(default_value_f))
441 }
442}
443
444pub struct Choice<A, B>
445where
446 A: Arg,
447 B: Arg,
448{
449 a: A,
450 b: B,
451}
452
453#[derive(Debug)]
454pub enum ChoiceError<A, B> {
455 A(A),
456 B(B),
457 MultipleMutuallyExclusiveArgs { a: String, b: String },
458}
459
460impl<A, B> fmt::Display for ChoiceError<A, B>
461where
462 A: fmt::Display,
463 B: fmt::Display,
464{
465 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
466 match self {
467 Self::A(a) => a.fmt(f),
468 Self::B(b) => b.fmt(f),
469 Self::MultipleMutuallyExclusiveArgs { a, b } => {
470 write!(f, "({}) and ({}) are mutually exclusive", a, b)
471 }
472 }
473 }
474}
475
476impl<A, B, T> Arg for Choice<A, B>
477where
478 A: Arg<Item = Option<T>>,
479 B: Arg<Item = Option<T>>,
480{
481 type Item = Option<T>;
482 type Error = ChoiceError<A::Error, B::Error>;
483
484 fn update_switches<S: Switches>(&self, switches: &mut S) {
485 self.a.update_switches(switches);
486 self.b.update_switches(switches);
487 }
488 fn name(&self) -> String {
489 format!("choose ({}) or ({})", self.a.name(), self.b.name())
490 }
491 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
492 let Self { a, b } = self;
493 let multiple_mutually_exclusive_args =
494 ChoiceError::MultipleMutuallyExclusiveArgs {
495 a: a.name(),
496 b: b.name(),
497 };
498
499 if let Some(a_value) = a.get(matches).map_err(ChoiceError::A)? {
500 if b.get(matches).map_err(ChoiceError::B)?.is_some() {
501 Err(multiple_mutually_exclusive_args)
502 } else {
503 Ok(Some(a_value))
504 }
505 } else {
506 b.get(matches).map_err(ChoiceError::B)
507 }
508 }
509}
510
511#[derive(Debug)]
512pub enum BothError<A, B> {
513 A(A),
514 B(B),
515}
516
517impl<A, B> fmt::Display for BothError<A, B>
518where
519 A: fmt::Display,
520 B: fmt::Display,
521{
522 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
523 match self {
524 Self::A(a) => a.fmt(f),
525 Self::B(b) => b.fmt(f),
526 }
527 }
528}
529
530pub struct Both<A, B>
531where
532 A: Arg,
533 B: Arg,
534{
535 a: A,
536 b: B,
537}
538
539impl<A, B> Arg for Both<A, B>
540where
541 A: Arg,
542 B: Arg,
543{
544 type Item = (A::Item, B::Item);
545 type Error = BothError<A::Error, B::Error>;
546 fn update_switches<S: Switches>(&self, switches: &mut S) {
547 self.a.update_switches(switches);
548 self.b.update_switches(switches);
549 }
550 fn name(&self) -> String {
551 format!("({} and {})", self.a.name(), self.b.name())
552 }
553 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
554 Ok((
555 self.a.get(matches).map_err(BothError::A)?,
556 self.b.get(matches).map_err(BothError::B)?,
557 ))
558 }
559}
560
561pub struct Map<A, F>
562where
563 A: Arg,
564{
565 arg: A,
566 f: F,
567}
568impl<A, U, F> Arg for Map<A, F>
569where
570 A: Arg,
571 F: FnOnce(A::Item) -> U,
572{
573 type Item = U;
574 type Error = A::Error;
575 fn update_switches<S: Switches>(&self, switches: &mut S) {
576 self.arg.update_switches(switches);
577 }
578 fn name(&self) -> String {
579 self.arg.name()
580 }
581 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
582 let Self { arg, f } = self;
583 arg.get(matches).map(f)
584 }
585}
586
587pub struct Value<T> {
588 value: T,
589 name: String,
590}
591
592impl<T> Value<T> {
593 pub fn new(name: &str, value: T) -> Self {
594 Self {
595 name: name.to_string(),
596 value,
597 }
598 }
599}
600
601impl<T> Arg for Value<T> {
602 type Item = T;
603 type Error = Never;
604 fn update_switches<S: Switches>(&self, _switches: &mut S) {}
605 fn name(&self) -> String {
606 self.name.clone()
607 }
608 fn get(self, _matches: &Matches) -> Result<Self::Item, Self::Error> {
609 Ok(self.value)
610 }
611}
612
613pub struct Required<A>
614where
615 A: Arg,
616{
617 arg: A,
618}
619
620#[derive(Debug)]
621pub enum RequiredError<A> {
622 Arg(A),
623 MissingRequiredArg { name: String },
624}
625
626impl<A> fmt::Display for RequiredError<A>
627where
628 A: fmt::Display,
629{
630 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
631 match self {
632 Self::Arg(a) => a.fmt(f),
633 Self::MissingRequiredArg { name } => {
634 write!(f, "missing required argument ({})", name)
635 }
636 }
637 }
638}
639
640impl<A, T> Arg for Required<A>
641where
642 A: Arg<Item = Option<T>>,
643{
644 type Item = T;
645 type Error = RequiredError<A::Error>;
646 fn update_switches<S: Switches>(&self, switches: &mut S) {
647 self.arg.update_switches(switches);
648 }
649 fn name(&self) -> String {
650 self.arg.name()
651 }
652 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
653 let name = self.arg.name();
654 if let Some(x) = self.arg.get(matches).map_err(RequiredError::Arg)? {
655 Ok(x)
656 } else {
657 Err(RequiredError::MissingRequiredArg { name })
658 }
659 }
660}
661
662pub struct ConvertString<A, F>
663where
664 A: Arg,
665{
666 arg: A,
667 f: F,
668}
669
670#[derive(Debug)]
671pub enum ConvertStringError<A, E> {
672 Arg(A),
673 FailedToConvert {
674 name: String,
675 arg_string: String,
676 error: E,
677 },
678}
679
680impl<A, E> fmt::Display for ConvertStringError<A, E>
681where
682 A: fmt::Display,
683 E: fmt::Display,
684{
685 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
686 match self {
687 Self::Arg(a) => a.fmt(f),
688 Self::FailedToConvert {
689 name,
690 arg_string,
691 error,
692 } => write!(
693 f,
694 "failed to convert argument ({}). \"{}\" could not be parsed (error: {})",
695 name, arg_string, error
696 ),
697 }
698 }
699}
700
701impl<A, F, T, E> Arg for ConvertString<A, F>
702where
703 A: Arg<Item = String>,
704 F: FnOnce(&str) -> Result<T, E>,
705 E: fmt::Display + fmt::Debug,
706{
707 type Item = T;
708 type Error = ConvertStringError<A::Error, E>;
709 fn update_switches<S: Switches>(&self, switches: &mut S) {
710 self.arg.update_switches(switches);
711 }
712 fn name(&self) -> String {
713 self.arg.name()
714 }
715 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
716 let name = self.name();
717 let Self { arg, f } = self;
718 let arg_string = arg.get(matches).map_err(ConvertStringError::Arg)?;
719 f(arg_string.as_str()).map_err(|error| ConvertStringError::FailedToConvert {
720 name,
721 arg_string,
722 error,
723 })
724 }
725}
726
727pub struct OptionConvertString<A, F>
728where
729 A: Arg,
730{
731 arg: A,
732 f: F,
733}
734
735#[derive(Debug)]
736pub enum OptionConvertStringError<A, E> {
737 Arg(A),
738 FailedToConvert {
739 name: String,
740 arg_string: String,
741 error: E,
742 },
743}
744
745impl<A, E> fmt::Display for OptionConvertStringError<A, E>
746where
747 A: fmt::Display,
748 E: fmt::Display,
749{
750 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
751 match self {
752 Self::Arg(a) => a.fmt(f),
753 Self::FailedToConvert {
754 name,
755 arg_string,
756 error,
757 } => write!(
758 f,
759 "failed to convert argument ({}). \"{}\" could not be parsed (error: {})",
760 name, arg_string, error
761 ),
762 }
763 }
764}
765
766impl<A, F, T, E> Arg for OptionConvertString<A, F>
767where
768 A: Arg<Item = Option<String>>,
769 F: FnOnce(&str) -> Result<T, E>,
770 E: fmt::Display + fmt::Debug,
771{
772 type Item = Option<T>;
773 type Error = OptionConvertStringError<A::Error, E>;
774 fn update_switches<S: Switches>(&self, switches: &mut S) {
775 self.arg.update_switches(switches);
776 }
777 fn name(&self) -> String {
778 self.arg.name()
779 }
780 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
781 let name = self.name();
782 let Self { arg, f } = self;
783 match arg.get(matches).map_err(OptionConvertStringError::Arg)? {
784 None => Ok(None),
785 Some(arg_string) => f(arg_string.as_str()).map(Some).map_err(|error| {
786 OptionConvertStringError::FailedToConvert {
787 name,
788 arg_string,
789 error,
790 }
791 }),
792 }
793 }
794}
795
796pub struct VecConvertString<A, F>
797where
798 A: Arg,
799{
800 arg: A,
801 f: F,
802}
803
804#[derive(Debug)]
805pub enum VecConvertStringError<A, E> {
806 Arg(A),
807 FailedToConvert {
808 name: String,
809 index: usize,
810 arg_string: String,
811 error: E,
812 },
813}
814
815impl<A, E> fmt::Display for VecConvertStringError<A, E>
816where
817 A: fmt::Display,
818 E: fmt::Display,
819{
820 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
821 match self {
822 Self::Arg(a) => a.fmt(f),
823 Self::FailedToConvert {
824 name,
825 index,
826 arg_string,
827 error,
828 } => write!(
829 f,
830 "failed to convert argument \"{}\" in position ({}). \"{}\" could not be parsed (error: {})",
831 name, index, arg_string, error
832 ),
833 }
834 }
835}
836
837impl<A, F, T, E> Arg for VecConvertString<A, F>
838where
839 A: Arg<Item = Vec<String>>,
840 F: FnMut(&str) -> Result<T, E>,
841 E: fmt::Display + fmt::Debug,
842{
843 type Item = Vec<T>;
844 type Error = VecConvertStringError<A::Error, E>;
845 fn update_switches<S: Switches>(&self, switches: &mut S) {
846 self.arg.update_switches(switches);
847 }
848 fn name(&self) -> String {
849 self.arg.name()
850 }
851 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
852 let name = self.name();
853 let Self { arg, mut f } = self;
854 let mut vec_string = arg.get(matches).map_err(VecConvertStringError::Arg)?;
855 let mut vec_t = Vec::with_capacity(vec_string.len());
856 for (index, arg_string) in vec_string.drain(..).enumerate() {
857 let t = f(arg_string.as_str()).map_err(|error| {
858 VecConvertStringError::FailedToConvert {
859 name: name.clone(),
860 index,
861 error,
862 arg_string,
863 }
864 })?;
865 vec_t.push(t);
866 }
867 Ok(vec_t)
868 }
869}
870
871pub struct VecSingleton<A>
872where
873 A: Arg,
874{
875 arg: A,
876}
877
878#[derive(Debug)]
879pub enum VecSingletonError<A> {
880 Arg(A),
881 IncorrectNumberOfArguments {
882 number_of_arguments: usize,
883 name: String,
884 },
885}
886
887impl<A> fmt::Display for VecSingletonError<A>
888where
889 A: fmt::Display,
890{
891 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
892 match self {
893 Self::Arg(a) => a.fmt(f),
894 Self::IncorrectNumberOfArguments {
895 number_of_arguments,
896 name,
897 } => write!(
898 f,
899 "at most one arguments was expected for {} ({} found)",
900 name, number_of_arguments
901 ),
902 }
903 }
904}
905
906impl<A, T> Arg for VecSingleton<A>
907where
908 A: Arg<Item = Vec<T>>,
909{
910 type Item = Option<T>;
911 type Error = VecSingletonError<A::Error>;
912 fn update_switches<S: Switches>(&self, switches: &mut S) {
913 self.arg.update_switches(switches);
914 }
915 fn name(&self) -> String {
916 self.arg.name()
917 }
918 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
919 let name = self.name();
920 let Self { arg } = self;
921 let mut args: Vec<T> = arg.get(matches).map_err(VecSingletonError::Arg)?;
922 if let Some(item) = args.pop() {
923 match args.len() {
924 0 => Ok(Some(item)),
925 number_of_arguments => {
926 Err(VecSingletonError::IncorrectNumberOfArguments {
927 number_of_arguments: number_of_arguments + 1,
928 name: name.to_string(),
929 })
930 }
931 }
932 } else {
933 Ok(None)
934 }
935 }
936}
937
938pub struct Depend<A, B>
939where
940 A: Arg,
941 B: Arg,
942{
943 a: A,
944 b: B,
945}
946
947#[derive(Debug)]
948pub enum DependError<A, B> {
949 A(A),
950 B(B),
951 MissingDependency { a: String, b: String },
952}
953
954impl<A, B> fmt::Display for DependError<A, B>
955where
956 A: fmt::Display,
957 B: fmt::Display,
958{
959 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
960 match self {
961 Self::A(a) => a.fmt(f),
962 Self::B(b) => b.fmt(f),
963 Self::MissingDependency { a, b } => {
964 write!(f, "({}) and ({}) must be specified together", a, b)
965 }
966 }
967 }
968}
969
970impl<T, U, A, B> Arg for Depend<A, B>
971where
972 A: Arg<Item = Option<T>>,
973 B: Arg<Item = Option<U>>,
974{
975 type Item = Option<(T, U)>;
976 type Error = DependError<A::Error, B::Error>;
977 fn update_switches<S: Switches>(&self, switches: &mut S) {
978 self.a.update_switches(switches);
979 self.b.update_switches(switches);
980 }
981 fn name(&self) -> String {
982 format!("({} and {})", self.a.name(), self.b.name())
983 }
984 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
985 let missing_dependency = DependError::MissingDependency {
986 a: self.a.name(),
987 b: self.b.name(),
988 };
989 let Self { a, b } = self;
990 if let Some(a) = a.get(matches).map_err(DependError::A)? {
991 if let Some(b) = b.get(matches).map_err(DependError::B)? {
992 Ok(Some((a, b)))
993 } else {
994 Err(missing_dependency)
995 }
996 } else if b.get(matches).map_err(DependError::B)?.is_some() {
997 Err(missing_dependency)
998 } else {
999 Ok(None)
1000 }
1001 }
1002}
1003
1004pub struct SomeIf<A, T>
1005where
1006 A: Arg,
1007{
1008 arg: A,
1009 t: T,
1010}
1011
1012impl<A, T> Arg for SomeIf<A, T>
1013where
1014 A: Arg<Item = bool>,
1015{
1016 type Item = Option<T>;
1017 type Error = A::Error;
1018 fn update_switches<S: Switches>(&self, switches: &mut S) {
1019 self.arg.update_switches(switches);
1020 }
1021 fn name(&self) -> String {
1022 self.arg.name()
1023 }
1024 fn get(self, matches: &Matches) -> Result<Self::Item, Self::Error> {
1025 if self.arg.get(matches)? {
1026 Ok(Some(self.t))
1027 } else {
1028 Ok(None)
1029 }
1030 }
1031}
1032
1033pub fn flag(short: &str, long: &str, doc: &str) -> impl Arg<Item = bool> {
1034 Flag::new(short, long, doc)
1035}
1036
1037pub fn opt<T>(
1038 short: &str,
1039 long: &str,
1040 doc: &str,
1041 hint: &str,
1042) -> impl Arg<Item = Option<T>>
1043where
1044 T: FromStr,
1045 <T as FromStr>::Err: fmt::Debug + fmt::Display,
1046{
1047 Opt::new(short, long, doc, hint).option_convert_string(|s| s.parse())
1048}
1049
1050pub fn free<T>() -> impl Arg<Item = Vec<T>>
1051where
1052 T: FromStr,
1053 <T as FromStr>::Err: fmt::Debug + fmt::Display,
1054{
1055 Free.vec_convert_string(|s| s.parse())
1056}
1057
1058#[macro_export]
1059macro_rules! unflatten_closure {
1060 ( $p:pat => $tup:expr ) => {
1061 |$p| $tup
1062 };
1063 ( $p:pat => ( $($tup:tt)* ), $head:expr $(, $tail:expr)* ) => {
1064 $crate::unflatten_closure!( ($p, a) => ( $($tup)*, a) $(, $tail )* )
1065 };
1066}
1067
1068#[macro_export]
1069macro_rules! args_all {
1070 ( $only:expr ) => {
1071 $only
1072 };
1073 ( $head:expr, $($tail:expr),* $(,)* ) => {
1074 $head $( .both($tail) )*
1075 .map(
1076 $crate::unflatten_closure!(a => (a) $(, $tail )*)
1077 )
1078 };
1079}
1080
1081#[macro_export]
1082macro_rules! args_choice {
1083 ( $only:expr ) => {
1084 $only
1085 };
1086 ( $head:expr, $($tail:expr),* $(,)* ) => {
1087 $head $( .choice($tail) )*
1088 };
1089}
1090
1091#[macro_export]
1092macro_rules! args_map {
1093 ( let { $var1:ident = $a1:expr; } in { $b:expr } ) => {
1094 $a1.map(|$var1| $b)
1095 };
1096 ( let { $var1:ident = $a1:expr; $($var:ident = $a:expr;)+ } in { $b:expr } ) => {
1097 { $crate::args_all! {
1098 $a1, $($a),*
1099 } } .map(|($var1, $($var),*)| $b)
1100 };
1101}
1102
1103#[macro_export]
1104macro_rules! args_depend {
1105 ( $only:expr ) => {
1106 $only
1107 };
1108 ( $head:expr, $($tail:expr),* $(,)* ) => {
1109 $head $( .depend($tail) )*
1110 .option_map(
1111 $crate::unflatten_closure!(a => (a) $(, $tail )*)
1112 )
1113 };
1114}
1115
1116#[cfg(test)]
1117mod tests {
1118 use super::*;
1119
1120 #[test]
1121 fn basic() {
1122 assert_eq!(
1123 opt::<u32>("f", "foo", "", "")
1124 .required()
1125 .parse_specified("".to_string(), &["--foo", "42"])
1126 .result
1127 .unwrap(),
1128 42
1129 );
1130 }
1131
1132 #[test]
1133 fn basic_macros() {
1134 assert_eq!(
1135 args_map! {
1136 let {
1137 a = opt::<u32>("f", "foo", "", "").required();
1138 b = opt::<u32>("b", "bar", "", "").required();
1139 } in {
1140 a + b
1141 }
1142 }
1143 .parse_specified("".to_string(), &["--foo", "7", "--bar", "9"])
1144 .result
1145 .unwrap(),
1146 16
1147 );
1148 }
1149
1150 #[test]
1151 fn depend() {
1152 assert_eq!(
1153 args_depend! {
1154 opt::<u32>("f", "foo", "", ""),
1155 opt::<u32>("b", "bar", "", ""),
1156 }
1157 .required()
1158 .map(|(a, b)| a + b)
1159 .parse_specified("".to_string(), &["--foo", "7", "--bar", "9"])
1160 .result
1161 .unwrap(),
1162 16
1163 );
1164 }
1165
1166 #[test]
1167 fn choice() {
1168 #[derive(Debug, Clone, PartialEq, Eq)]
1169 enum E {
1170 A,
1171 B,
1172 C(String),
1173 }
1174 let choice = args_choice! {
1175 flag("a", "", "").some_if(E::A),
1176 flag("b", "", "").some_if(E::B),
1177 opt("c", "", "", "").option_map(|s| E::C(s)),
1178 }
1179 .required()
1180 .parse_specified("".to_string(), &["-c", "foo"])
1181 .result
1182 .unwrap();
1183 assert_eq!(choice, E::C("foo".to_string()));
1184 }
1185
1186 #[test]
1187 fn validate() {
1188 let has_empty_switch = args_all! {
1189 opt::<String>("", "", "doc", "hint"),
1190 opt::<String>("c", "control", "", ""),
1191 };
1192 assert_eq!(
1193 has_empty_switch.validate().unwrap_err(),
1194 Invalid {
1195 has_empty_switch: true,
1196 ..Default::default()
1197 }
1198 );
1199 let duplicate_shorts = args_all! {
1200 opt::<String>("a", "aa", "", ""),
1201 opt::<String>("a", "bb", "", ""),
1202 opt::<String>("c", "control", "", ""),
1203 };
1204 assert_eq!(
1205 duplicate_shorts.validate().unwrap_err(),
1206 Invalid {
1207 duplicate_shorts: vec!["a".to_string()],
1208 duplicate_longs: vec![],
1209 ..Default::default()
1210 }
1211 );
1212 let duplicate_longs = args_all! {
1213 opt::<String>("a", "aa", "", ""),
1214 opt::<String>("b", "aa", "", ""),
1215 opt::<String>("c", "control", "", ""),
1216 };
1217 assert_eq!(
1218 duplicate_longs.validate().unwrap_err(),
1219 Invalid {
1220 duplicate_shorts: vec![],
1221 duplicate_longs: vec!["aa".to_string()],
1222 ..Default::default()
1223 }
1224 );
1225 let invalid_switches = args_all! {
1226 opt::<String>("aa", "", "", ""),
1227 opt::<String>("", "a", "", ""),
1228 opt::<String>("a", "b", "", ""),
1229 opt::<String>("bb", "aa", "", ""),
1230 opt::<String>("c", "control", "", ""),
1231 };
1232 assert_eq!(
1233 invalid_switches.validate().unwrap_err(),
1234 Invalid {
1235 one_char_longs: vec!["a".to_string(), "b".to_string()],
1236 multi_char_shorts: vec!["aa".to_string(), "bb".to_string()],
1237 ..Default::default()
1238 }
1239 );
1240 }
1241}