Skip to content

Commit 286b2c9

Browse files
authored
Merge pull request #89 from t-rapp/opts-general
Generalize opts_present() and opts_str() for any iterator over strings
2 parents ded6c8e + c71c347 commit 286b2c9

File tree

2 files changed

+119
-2
lines changed

2 files changed

+119
-2
lines changed

src/lib.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,41 @@ impl Matches {
828828
})
829829
}
830830

831+
/// Returns true if any of several options were matched.
832+
///
833+
/// Similar to `opts_present` but accepts any argument that can be converted
834+
/// into an iterator over string references.
835+
///
836+
/// # Panics
837+
///
838+
/// This function might panic if some option name is not defined.
839+
///
840+
/// # Example
841+
///
842+
/// ```
843+
/// # use getopts::Options;
844+
/// let mut opts = Options::new();
845+
/// opts.optopt("a", "alpha", "first option", "STR");
846+
/// opts.optopt("b", "beta", "second option", "STR");
847+
///
848+
/// let args = vec!["-a", "foo"];
849+
/// let matches = &match opts.parse(&args) {
850+
/// Ok(m) => m,
851+
/// _ => panic!(),
852+
/// };
853+
///
854+
/// assert!(matches.opts_present_any(&["alpha"]));
855+
/// assert!(!matches.opts_present_any(&["beta"]));
856+
/// ```
857+
pub fn opts_present_any<C: IntoIterator>(&self, names: C) -> bool
858+
where
859+
C::Item: AsRef<str>,
860+
{
861+
names
862+
.into_iter()
863+
.any(|nm| !self.opt_vals(nm.as_ref()).is_empty())
864+
}
865+
831866
/// Returns the string argument supplied to one of several matching options or `None`.
832867
pub fn opts_str(&self, names: &[String]) -> Option<String> {
833868
names
@@ -839,6 +874,46 @@ impl Matches {
839874
.next()
840875
}
841876

877+
/// Returns the string argument supplied to the first matching option of
878+
/// several options or `None`.
879+
///
880+
/// Similar to `opts_str` but accepts any argument that can be converted
881+
/// into an iterator over string references.
882+
///
883+
/// # Panics
884+
///
885+
/// This function might panic if some option name is not defined.
886+
///
887+
/// # Example
888+
///
889+
/// ```
890+
/// # use getopts::Options;
891+
/// let mut opts = Options::new();
892+
/// opts.optopt("a", "alpha", "first option", "STR");
893+
/// opts.optopt("b", "beta", "second option", "STR");
894+
///
895+
/// let args = vec!["-a", "foo", "--beta", "bar"];
896+
/// let matches = &match opts.parse(&args) {
897+
/// Ok(m) => m,
898+
/// _ => panic!(),
899+
/// };
900+
///
901+
/// assert_eq!(Some("foo".to_string()), matches.opts_str_first(&["alpha", "beta"]));
902+
/// assert_eq!(Some("bar".to_string()), matches.opts_str_first(&["beta", "alpha"]));
903+
/// ```
904+
pub fn opts_str_first<C: IntoIterator>(&self, names: C) -> Option<String>
905+
where
906+
C::Item: AsRef<str>,
907+
{
908+
names
909+
.into_iter()
910+
.filter_map(|nm| match self.opt_val(nm.as_ref()) {
911+
Some(Val(s)) => Some(s),
912+
_ => None,
913+
})
914+
.next()
915+
}
916+
842917
/// Returns a vector of the arguments provided to all matches of the given
843918
/// option.
844919
///

src/tests/mod.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ fn test_multi() {
626626
opts.optopt("e", "", "encrypt", "ENCRYPT");
627627
opts.optopt("", "encrypt", "encrypt", "ENCRYPT");
628628
opts.optopt("f", "", "flag", "FLAG");
629+
let no_opts: &[&str] = &[];
629630

630631
let args_single = vec!["-e".to_string(), "foo".to_string()];
631632
let matches_single = &match opts.parse(&args_single) {
@@ -639,6 +640,12 @@ fn test_multi() {
639640
assert!(!matches_single.opts_present(&["thing".to_string()]));
640641
assert!(!matches_single.opts_present(&[]));
641642

643+
assert!(matches_single.opts_present_any(&["e"]));
644+
assert!(matches_single.opts_present_any(&["encrypt", "e"]));
645+
assert!(matches_single.opts_present_any(&["e", "encrypt"]));
646+
assert!(!matches_single.opts_present_any(&["encrypt"]));
647+
assert!(!matches_single.opts_present_any(no_opts));
648+
642649
assert_eq!(matches_single.opts_str(&["e".to_string()]).unwrap(), "foo");
643650
assert_eq!(
644651
matches_single
@@ -653,11 +660,23 @@ fn test_multi() {
653660
"foo"
654661
);
655662

663+
assert_eq!(matches_single.opts_str_first(&["e"]).unwrap(), "foo");
664+
assert_eq!(
665+
matches_single.opts_str_first(&["e", "encrypt"]).unwrap(),
666+
"foo"
667+
);
668+
assert_eq!(
669+
matches_single.opts_str_first(&["encrypt", "e"]).unwrap(),
670+
"foo"
671+
);
672+
assert_eq!(matches_single.opts_str_first(&["encrypt"]), None);
673+
assert_eq!(matches_single.opts_str_first(no_opts), None);
674+
656675
let args_both = vec![
657676
"-e".to_string(),
658677
"foo".to_string(),
659678
"--encrypt".to_string(),
660-
"foo".to_string(),
679+
"bar".to_string(),
661680
];
662681
let matches_both = &match opts.parse(&args_both) {
663682
Ok(m) => m,
@@ -671,10 +690,17 @@ fn test_multi() {
671690
assert!(!matches_both.opts_present(&["thing".to_string()]));
672691
assert!(!matches_both.opts_present(&[]));
673692

693+
assert!(matches_both.opts_present_any(&["e"]));
694+
assert!(matches_both.opts_present_any(&["encrypt"]));
695+
assert!(matches_both.opts_present_any(&["encrypt", "e"]));
696+
assert!(matches_both.opts_present_any(&["e", "encrypt"]));
697+
assert!(!matches_both.opts_present_any(&["f"]));
698+
assert!(!matches_both.opts_present_any(no_opts));
699+
674700
assert_eq!(matches_both.opts_str(&["e".to_string()]).unwrap(), "foo");
675701
assert_eq!(
676702
matches_both.opts_str(&["encrypt".to_string()]).unwrap(),
677-
"foo"
703+
"bar"
678704
);
679705
assert_eq!(
680706
matches_both
@@ -686,8 +712,24 @@ fn test_multi() {
686712
matches_both
687713
.opts_str(&["encrypt".to_string(), "e".to_string()])
688714
.unwrap(),
715+
"bar"
716+
);
717+
718+
assert_eq!(matches_both.opts_str_first(&["e"]).unwrap(), "foo");
719+
assert_eq!(
720+
matches_both.opts_str_first(&["encrypt"]).unwrap(),
721+
"bar"
722+
);
723+
assert_eq!(
724+
matches_both.opts_str_first(&["e", "encrypt"]).unwrap(),
689725
"foo"
690726
);
727+
assert_eq!(
728+
matches_both.opts_str_first(&["encrypt", "e"]).unwrap(),
729+
"bar"
730+
);
731+
assert_eq!(matches_both.opts_str_first(&["f"]), None);
732+
assert_eq!(matches_both.opts_str_first(no_opts), None);
691733
}
692734

693735
#[test]

0 commit comments

Comments
 (0)