diff --git a/src/app/help.rs b/src/app/help.rs index c43d274d..8baac496 100644 --- a/src/app/help.rs +++ b/src/app/help.rs @@ -474,6 +474,7 @@ impl<'a> Help<'a> { Format::None(pv.to_string_lossy()) })); } + // FIXME: add [env::{}: {}] here } if let Some(ref aliases) = a.aliases() { debugln!("Help::spec_vals: Found aliases...{:?}", aliases); diff --git a/src/app/mod.rs b/src/app/mod.rs index e9e26e81..fdf07e65 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1796,6 +1796,7 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> { fn default_vals_ifs(&self) -> Option, &'e OsStr)>> { None } + fn from_env(&self) -> Option<&OsString> { None } fn longest_filter(&self) -> bool { true } fn aliases(&self) -> Option> { if let Some(ref aliases) = self.p.meta.aliases { diff --git a/src/app/parser.rs b/src/app/parser.rs index e4cad819..b0e135cd 100644 --- a/src/app/parser.rs +++ b/src/app/parser.rs @@ -1788,6 +1788,38 @@ impl<'a, 'b> Parser<'a, 'b> } Ok(()) } + + pub fn add_from_env(&mut self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { + macro_rules! add_val { + ($_self:ident, $a:ident, $m:ident) => { + if let Some(ref val) = $a.v.from_env { + if $m.get($a.b.name).map(|ma| ma.vals.len()).map(|len| len == 0).unwrap_or(false) { + $_self.add_val_to_arg($a, OsStr::new(val), $m)?; + + if $_self.cache.map_or(true, |name| name != $a.name()) { + arg_post_processing!($_self, $a, $m); + $_self.cache = Some($a.name()); + } + } else { + $_self.add_val_to_arg($a, OsStr::new(val), $m)?; + + if $_self.cache.map_or(true, |name| name != $a.name()) { + arg_post_processing!($_self, $a, $m); + $_self.cache = Some($a.name()); + } + } + } + }; + } + + for o in &self.opts { + add_val!(self, o, matcher); + } + for p in self.positionals.values() { + add_val!(self, p, matcher); + } + Ok(()) + } pub fn flags(&self) -> Iter> { self.flags.iter() } diff --git a/src/app/validator.rs b/src/app/validator.rs index 6227c060..3077af0b 100644 --- a/src/app/validator.rs +++ b/src/app/validator.rs @@ -28,6 +28,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> { -> ClapResult<()> { debugln!("Validator::validate;"); let mut reqs_validated = false; + self.0.add_from_env(matcher)?; self.0.add_defaults(matcher)?; if let ParseResult::Opt(a) = needs_val_of { debugln!("Validator::validate: needs_val_of={:?}", a); diff --git a/src/args/any_arg.rs b/src/args/any_arg.rs index e1721a70..1767a0ac 100644 --- a/src/args/any_arg.rs +++ b/src/args/any_arg.rs @@ -33,6 +33,7 @@ pub trait AnyArg<'n, 'e>: std_fmt::Display { fn long_help(&self) -> Option<&'e str>; fn default_val(&self) -> Option<&'e OsStr>; fn default_vals_ifs(&self) -> Option, &'e OsStr)>>; + fn from_env(&self) -> Option<&OsString>; fn longest_filter(&self) -> bool; fn val_terminator(&self) -> Option<&'e str>; } diff --git a/src/args/arg.rs b/src/args/arg.rs index f16e20a0..bbfcf505 100644 --- a/src/args/arg.rs +++ b/src/args/arg.rs @@ -6,7 +6,7 @@ use std::ffi::{OsString, OsStr}; use osstringext::OsStrExt3; #[cfg(not(target_os="windows"))] use std::os::unix::ffi::OsStrExt; - +use std::env; #[cfg(feature = "yaml")] use yaml_rust::Yaml; @@ -128,6 +128,7 @@ impl<'a, 'b> Arg<'a, 'b> { "default_value" => yaml_to_str!(a, v, default_value), "default_value_if" => yaml_tuple3!(a, v, default_value_if), "default_value_ifs" => yaml_tuple3!(a, v, default_value_if), + "from_env" => yaml_to_str!(a, v, from_env), "value_names" => yaml_vec_or_str!(v, a, value_name), "groups" => yaml_vec_or_str!(v, a, group), "requires" => yaml_vec_or_str!(v, a, requires), @@ -3311,6 +3312,16 @@ impl<'a, 'b> Arg<'a, 'b> { self } + /// Specifies that if the value is not passed in as an argument, that it should be retrieved + /// from the environment if available. If it is not present in the environment, then default + /// rules will apply. + pub fn from_env>(mut self, name: K) -> Self { + self.setb(ArgSettings::TakesValue); + + self.v.from_env = env::var_os(name); + self + } + /// When set to `true` the help string will be displayed on the line after the argument and /// indented once. This can be helpful for arguments with very long or complex help messages. /// This can also be helpful for arguments with very long flag names, or many/long value names. diff --git a/src/args/arg_builder/flag.rs b/src/args/arg_builder/flag.rs index ec34382c..89b53c7d 100644 --- a/src/args/arg_builder/flag.rs +++ b/src/args/arg_builder/flag.rs @@ -8,20 +8,26 @@ use std::mem; // Internal use Arg; -use args::{ArgSettings, Base, Switched, AnyArg, DispOrder}; +use args::{AnyArg, ArgSettings, Base, DispOrder, Switched}; use map::{self, VecMap}; #[derive(Default, Clone, Debug)] #[doc(hidden)] pub struct FlagBuilder<'n, 'e> - where 'n: 'e +where + 'n: 'e, { pub b: Base<'n, 'e>, pub s: Switched<'e>, } impl<'n, 'e> FlagBuilder<'n, 'e> { - pub fn new(name: &'n str) -> Self { FlagBuilder { b: Base::new(name), ..Default::default() } } + pub fn new(name: &'n str) -> Self { + FlagBuilder { + b: Base::new(name), + ..Default::default() + } + } } impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> { @@ -83,10 +89,12 @@ impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> { fn default_vals_ifs(&self) -> Option, &'e OsStr)>> { None } + fn from_env(&self) -> Option<&OsString> { None } fn longest_filter(&self) -> bool { self.s.long.is_some() } fn aliases(&self) -> Option> { if let Some(ref aliases) = self.s.aliases { - let vis_aliases: Vec<_> = aliases.iter() + let vis_aliases: Vec<_> = aliases + .iter() .filter_map(|&(n, v)| if v { Some(n) } else { None }) .collect(); if vis_aliases.is_empty() { @@ -105,9 +113,7 @@ impl<'n, 'e> DispOrder for FlagBuilder<'n, 'e> { } impl<'n, 'e> PartialEq for FlagBuilder<'n, 'e> { - fn eq(&self, other: &FlagBuilder<'n, 'e>) -> bool { - self.b == other.b - } + fn eq(&self, other: &FlagBuilder<'n, 'e>) -> bool { self.b == other.b } } #[cfg(test)] @@ -142,8 +148,12 @@ mod test { fn flagbuilder_display_multiple_aliases() { let mut f = FlagBuilder::new("flg"); f.s.short = Some('f'); - f.s.aliases = - Some(vec![("alias_not_visible", false), ("f2", true), ("f3", true), ("f4", true)]); + f.s.aliases = Some(vec![ + ("alias_not_visible", false), + ("f2", true), + ("f3", true), + ("f4", true), + ]); assert_eq!(&*format!("{}", f), "-f"); } } diff --git a/src/args/arg_builder/option.rs b/src/args/arg_builder/option.rs index 135feeda..644e43f9 100644 --- a/src/args/arg_builder/option.rs +++ b/src/args/arg_builder/option.rs @@ -6,14 +6,15 @@ use std::ffi::{OsStr, OsString}; use std::mem; // Internal -use args::{ArgSettings, AnyArg, Base, Switched, Valued, Arg, DispOrder}; +use args::{AnyArg, Arg, ArgSettings, Base, DispOrder, Switched, Valued}; use map::{self, VecMap}; #[allow(missing_debug_implementations)] #[doc(hidden)] #[derive(Default, Clone)] pub struct OptBuilder<'n, 'e> - where 'n: 'e +where + 'n: 'e, { pub b: Base<'n, 'e>, pub s: Switched<'e>, @@ -21,7 +22,12 @@ pub struct OptBuilder<'n, 'e> } impl<'n, 'e> OptBuilder<'n, 'e> { - pub fn new(name: &'n str) -> Self { OptBuilder { b: Base::new(name), ..Default::default() } } + pub fn new(name: &'n str) -> Self { + OptBuilder { + b: Base::new(name), + ..Default::default() + } + } } impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for OptBuilder<'n, 'e> { @@ -85,14 +91,16 @@ impl<'n, 'e> Display for OptBuilder<'n, 'e> { write!(f, "...")?; } } else { - write!(f, + write!( + f, "<{}>{}", self.b.name, if self.is_set(ArgSettings::Multiple) { "..." } else { "" - })?; + } + )?; } Ok(()) @@ -132,10 +140,12 @@ impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> { fn default_vals_ifs(&self) -> Option, &'e OsStr)>> { self.v.default_vals_ifs.as_ref().map(|vm| vm.values()) } + fn from_env(&self) -> Option<&OsString> { self.v.from_env.as_ref() } fn longest_filter(&self) -> bool { true } fn aliases(&self) -> Option> { if let Some(ref aliases) = self.s.aliases { - let vis_aliases: Vec<_> = aliases.iter() + let vis_aliases: Vec<_> = aliases + .iter() .filter_map(|&(n, v)| if v { Some(n) } else { None }) .collect(); if vis_aliases.is_empty() { @@ -154,9 +164,7 @@ impl<'n, 'e> DispOrder for OptBuilder<'n, 'e> { } impl<'n, 'e> PartialEq for OptBuilder<'n, 'e> { - fn eq(&self, other: &OptBuilder<'n, 'e>) -> bool { - self.b == other.b - } + fn eq(&self, other: &OptBuilder<'n, 'e>) -> bool { self.b == other.b } } #[cfg(test)] @@ -214,8 +222,12 @@ mod test { fn optbuilder_display_multiple_aliases() { let mut o = OptBuilder::new("opt"); o.s.long = Some("option"); - o.s.aliases = - Some(vec![("als_not_visible", false), ("als2", true), ("als3", true), ("als4", true)]); + o.s.aliases = Some(vec![ + ("als_not_visible", false), + ("als2", true), + ("als3", true), + ("als4", true), + ]); assert_eq!(&*format!("{}", o), "--option "); } } diff --git a/src/args/arg_builder/positional.rs b/src/args/arg_builder/positional.rs index 7ba9d0e6..a6b54bca 100644 --- a/src/args/arg_builder/positional.rs +++ b/src/args/arg_builder/positional.rs @@ -8,7 +8,7 @@ use std::mem; // Internal use Arg; -use args::{ArgSettings, Base, Valued, AnyArg, DispOrder}; +use args::{AnyArg, ArgSettings, Base, DispOrder, Valued}; use INTERNAL_ERROR_MSG; use map::{self, VecMap}; @@ -16,7 +16,8 @@ use map::{self, VecMap}; #[doc(hidden)] #[derive(Clone, Default)] pub struct PosBuilder<'n, 'e> - where 'n: 'e +where + 'n: 'e, { pub b: Base<'n, 'e>, pub v: Valued<'n, 'e>, @@ -39,7 +40,8 @@ impl<'n, 'e> PosBuilder<'n, 'e> { index: idx, }; if a.v.max_vals.is_some() || a.v.min_vals.is_some() || - (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1) { + (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1) + { pb.b.settings.set(ArgSettings::Multiple); } pb @@ -47,7 +49,8 @@ impl<'n, 'e> PosBuilder<'n, 'e> { pub fn from_arg(mut a: Arg<'n, 'e>, idx: u64) -> Self { if a.v.max_vals.is_some() || a.v.min_vals.is_some() || - (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1) { + (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1) + { a.b.settings.set(ArgSettings::Multiple); } PosBuilder { @@ -74,11 +77,13 @@ impl<'n, 'e> PosBuilder<'n, 'e> { if let Some(ref names) = self.v.val_names { debugln!("PosBuilder:name_no_brackets: val_names={:#?}", names); if names.len() > 1 { - Cow::Owned(names - .values() - .map(|n| format!("<{}>", n)) - .collect::>() - .join(" ")) + Cow::Owned( + names + .values() + .map(|n| format!("<{}>", n)) + .collect::>() + .join(" "), + ) } else { Cow::Borrowed(names.values().next().expect(INTERNAL_ERROR_MSG)) } @@ -92,17 +97,21 @@ impl<'n, 'e> PosBuilder<'n, 'e> { impl<'n, 'e> Display for PosBuilder<'n, 'e> { fn fmt(&self, f: &mut Formatter) -> Result { if let Some(ref names) = self.v.val_names { - write!(f, + write!( + f, "{}", names .values() .map(|n| format!("<{}>", n)) .collect::>() - .join(" "))?; + .join(" ") + )?; } else { write!(f, "<{}>", self.b.name)?; } - if self.b.settings.is_set(ArgSettings::Multiple) && (self.v.val_names.is_none() || self.v.val_names.as_ref().unwrap().len() == 1) { + if self.b.settings.is_set(ArgSettings::Multiple) && + (self.v.val_names.is_none() || self.v.val_names.as_ref().unwrap().len() == 1) + { write!(f, "...")?; } @@ -143,6 +152,7 @@ impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> { self.v.default_vals_ifs.as_ref().map(|vm| vm.values()) } fn default_val(&self) -> Option<&'e OsStr> { self.v.default_val } + fn from_env(&self) -> Option<&OsString> { self.v.from_env.as_ref() } fn longest_filter(&self) -> bool { true } fn aliases(&self) -> Option> { None } } diff --git a/src/args/arg_builder/valued.rs b/src/args/arg_builder/valued.rs index 084b6da7..e661b308 100644 --- a/src/args/arg_builder/valued.rs +++ b/src/args/arg_builder/valued.rs @@ -8,7 +8,8 @@ use Arg; #[allow(missing_debug_implementations)] #[derive(Clone)] pub struct Valued<'a, 'b> - where 'a: 'b +where + 'a: 'b, { pub possible_vals: Option>, pub val_names: Option>, @@ -20,6 +21,7 @@ pub struct Valued<'a, 'b> pub val_delim: Option, pub default_val: Option<&'b OsStr>, pub default_vals_ifs: Option, &'b OsStr)>>, + pub from_env: Option, pub terminator: Option<&'b str>, } @@ -36,6 +38,7 @@ impl<'n, 'e> Default for Valued<'n, 'e> { val_delim: None, default_val: None, default_vals_ifs: None, + from_env: None, terminator: None, } } diff --git a/tests/default_vals.rs b/tests/default_vals.rs index 1040b0b7..7f160f34 100644 --- a/tests/default_vals.rs +++ b/tests/default_vals.rs @@ -8,8 +8,9 @@ use clap::{App, Arg, ErrorKind}; #[test] fn opts() { let r = App::new("df") - .arg( Arg::from_usage("-o [opt] 'some opt'") - .default_value("default")) + .arg( + Arg::from_usage("-o [opt] 'some opt'").default_value("default"), + ) .get_matches_from_safe(vec![""]); assert!(r.is_ok()); let m = r.unwrap(); @@ -20,8 +21,9 @@ fn opts() { #[test] fn opt_user_override() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'") - .default_value("default")) + .arg( + Arg::from_usage("--opt [FILE] 'some arg'").default_value("default"), + ) .get_matches_from_safe(vec!["", "--opt", "value"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -32,8 +34,7 @@ fn opt_user_override() { #[test] fn positionals() { let r = App::new("df") - .arg( Arg::from_usage("[arg] 'some opt'") - .default_value("default")) + .arg(Arg::from_usage("[arg] 'some opt'").default_value("default")) .get_matches_from_safe(vec![""]); assert!(r.is_ok()); let m = r.unwrap(); @@ -44,8 +45,7 @@ fn positionals() { #[test] fn positional_user_override() { let r = App::new("df") - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("default")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value("default")) .get_matches_from_safe(vec!["", "value"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -59,10 +59,11 @@ fn positional_user_override() { fn osstr_opts() { use std::ffi::OsStr; let expected = OsStr::new("default"); - + let r = App::new("df") - .arg( Arg::from_usage("-o [opt] 'some opt'") - .default_value_os(expected)) + .arg( + Arg::from_usage("-o [opt] 'some opt'").default_value_os(expected), + ) .get_matches_from_safe(vec![""]); assert!(r.is_ok()); let m = r.unwrap(); @@ -76,8 +77,9 @@ fn osstr_opt_user_override() { let default = OsStr::new("default"); let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'") - .default_value_os(default)) + .arg( + Arg::from_usage("--opt [FILE] 'some arg'").default_value_os(default), + ) .get_matches_from_safe(vec!["", "--opt", "value"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -91,8 +93,9 @@ fn osstr_positionals() { let expected = OsStr::new("default"); let r = App::new("df") - .arg( Arg::from_usage("[arg] 'some opt'") - .default_value_os(expected)) + .arg( + Arg::from_usage("[arg] 'some opt'").default_value_os(expected), + ) .get_matches_from_safe(vec![""]); assert!(r.is_ok()); let m = r.unwrap(); @@ -106,8 +109,9 @@ fn osstr_positional_user_override() { let default = OsStr::new("default"); let r = App::new("df") - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value_os(default)) + .arg( + Arg::from_usage("[arg] 'some arg'").default_value_os(default), + ) .get_matches_from_safe(vec!["", "value"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -115,14 +119,17 @@ fn osstr_positional_user_override() { assert_eq!(m.value_of("arg").unwrap(), "value"); } -// --- Default if arg is present +// --- Default if arg is present #[test] fn default_if_arg_present_no_default() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value_if("opt", None, "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + None, + "default", + )) .get_matches_from_safe(vec!["", "--opt", "some"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -133,9 +140,12 @@ fn default_if_arg_present_no_default() { #[test] fn default_if_arg_present_no_default_user_override() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value_if("opt", None, "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + None, + "default", + )) .get_matches_from_safe(vec!["", "--opt", "some", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -146,10 +156,12 @@ fn default_if_arg_present_no_default_user_override() { #[test] fn default_if_arg_present_no_arg_with_default() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", None, "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", None, "default"), + ) .get_matches_from_safe(vec![""]); assert!(r.is_ok()); let m = r.unwrap(); @@ -160,10 +172,12 @@ fn default_if_arg_present_no_arg_with_default() { #[test] fn default_if_arg_present_with_default() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", None, "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", None, "default"), + ) .get_matches_from_safe(vec!["", "--opt", "some"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -174,10 +188,12 @@ fn default_if_arg_present_with_default() { #[test] fn default_if_arg_present_with_default_user_override() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", None, "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", None, "default"), + ) .get_matches_from_safe(vec!["", "--opt", "some", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -188,10 +204,12 @@ fn default_if_arg_present_with_default_user_override() { #[test] fn default_if_arg_present_no_arg_with_default_user_override() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", None, "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", None, "default"), + ) .get_matches_from_safe(vec!["", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -204,9 +222,12 @@ fn default_if_arg_present_no_arg_with_default_user_override() { #[test] fn default_if_arg_present_with_value_no_default() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value_if("opt", Some("value"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + Some("value"), + "default", + )) .get_matches_from_safe(vec!["", "--opt", "value"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -217,9 +238,12 @@ fn default_if_arg_present_with_value_no_default() { #[test] fn default_if_arg_present_with_value_no_default_fail() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value_if("opt", Some("value"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + Some("value"), + "default", + )) .get_matches_from_safe(vec!["", "--opt", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -230,9 +254,12 @@ fn default_if_arg_present_with_value_no_default_fail() { #[test] fn default_if_arg_present_with_value_no_default_user_override() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value_if("opt", Some("some"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("[arg] 'some arg'").default_value_if( + "opt", + Some("some"), + "default", + )) .get_matches_from_safe(vec!["", "--opt", "some", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -243,10 +270,12 @@ fn default_if_arg_present_with_value_no_default_user_override() { #[test] fn default_if_arg_present_with_value_no_arg_with_default() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", Some("some"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) .get_matches_from_safe(vec![""]); assert!(r.is_ok()); let m = r.unwrap(); @@ -257,10 +286,12 @@ fn default_if_arg_present_with_value_no_arg_with_default() { #[test] fn default_if_arg_present_with_value_no_arg_with_default_fail() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", Some("some"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) .get_matches_from_safe(vec!["", "--opt", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -271,10 +302,12 @@ fn default_if_arg_present_with_value_no_arg_with_default_fail() { #[test] fn default_if_arg_present_with_value_with_default() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", Some("some"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) .get_matches_from_safe(vec!["", "--opt", "some"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -285,10 +318,12 @@ fn default_if_arg_present_with_value_with_default() { #[test] fn default_if_arg_present_with_value_with_default_user_override() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", Some("some"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) .get_matches_from_safe(vec!["", "--opt", "some", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -299,10 +334,12 @@ fn default_if_arg_present_with_value_with_default_user_override() { #[test] fn default_if_arg_present_no_arg_with_value_with_default_user_override() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", Some("some"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) .get_matches_from_safe(vec!["", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -313,10 +350,12 @@ fn default_if_arg_present_no_arg_with_value_with_default_user_override() { #[test] fn default_if_arg_present_no_arg_with_value_with_default_user_override_fail() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_if("opt", Some("some"), "default")) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_if("opt", Some("some"), "default"), + ) .get_matches_from_safe(vec!["", "--opt", "value", "other"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -329,14 +368,13 @@ fn default_if_arg_present_no_arg_with_value_with_default_user_override_fail() { #[test] fn default_ifs_arg_present() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("--flag 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_ifs(&[ - ("opt", Some("some"), "default"), - ("flag", None, "flg"), - ])) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("--flag 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]), + ) .get_matches_from_safe(vec!["", "--flag"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -347,14 +385,13 @@ fn default_ifs_arg_present() { #[test] fn default_ifs_arg_present_user_override() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("--flag 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_ifs(&[ - ("opt", Some("some"), "default"), - ("flag", None, "flg"), - ])) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("--flag 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]), + ) .get_matches_from_safe(vec!["", "--flag", "value"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -365,14 +402,13 @@ fn default_ifs_arg_present_user_override() { #[test] fn default_ifs_arg_present_order() { let r = App::new("df") - .arg( Arg::from_usage("--opt [FILE] 'some arg'")) - .arg( Arg::from_usage("--flag 'some arg'")) - .arg( Arg::from_usage("[arg] 'some arg'") - .default_value("first") - .default_value_ifs(&[ - ("opt", Some("some"), "default"), - ("flag", None, "flg"), - ])) + .arg(Arg::from_usage("--opt [FILE] 'some arg'")) + .arg(Arg::from_usage("--flag 'some arg'")) + .arg( + Arg::from_usage("[arg] 'some arg'") + .default_value("first") + .default_value_ifs(&[("opt", Some("some"), "default"), ("flag", None, "flg")]), + ) .get_matches_from_safe(vec!["", "--opt=some", "--flag"]); assert!(r.is_ok()); let m = r.unwrap(); @@ -386,19 +422,25 @@ fn conditional_reqs_fail() { .version("1.0") .author("F0x06") .about("Arg test") - .arg(Arg::with_name("target") - .takes_value(true) - .default_value("file") - .possible_values(&["file", "stdout"]) - .long("target")) - .arg(Arg::with_name("input") - .takes_value(true) - .required(true) - .long("input")) - .arg(Arg::with_name("output") - .takes_value(true) - .required_if("target", "file") - .long("output")) + .arg( + Arg::with_name("target") + .takes_value(true) + .default_value("file") + .possible_values(&["file", "stdout"]) + .long("target"), + ) + .arg( + Arg::with_name("input") + .takes_value(true) + .required(true) + .long("input"), + ) + .arg( + Arg::with_name("output") + .takes_value(true) + .required_if("target", "file") + .long("output"), + ) .get_matches_from_safe(vec!["test", "--input", "some"]); assert!(m.is_err()); @@ -411,19 +453,25 @@ fn conditional_reqs_pass() { .version("1.0") .author("F0x06") .about("Arg test") - .arg(Arg::with_name("target") - .takes_value(true) - .default_value("file") - .possible_values(&["file", "stdout"]) - .long("target")) - .arg(Arg::with_name("input") - .takes_value(true) - .required(true) - .long("input")) - .arg(Arg::with_name("output") - .takes_value(true) - .required_if("target", "file") - .long("output")) + .arg( + Arg::with_name("target") + .takes_value(true) + .default_value("file") + .possible_values(&["file", "stdout"]) + .long("target"), + ) + .arg( + Arg::with_name("input") + .takes_value(true) + .required(true) + .long("input"), + ) + .arg( + Arg::with_name("output") + .takes_value(true) + .required_if("target", "file") + .long("output"), + ) .get_matches_from_safe(vec!["test", "--input", "some", "--output", "other"]); assert!(m.is_ok()); @@ -431,3 +479,16 @@ fn conditional_reqs_pass() { assert_eq!(m.value_of("output"), Some("other")); assert_eq!(m.value_of("input"), Some("some")); } + +#[test] +fn from_env_no_default() { + std::env::set_var("CLP_TEST_ENV", "from_env"); + + let r = App::new("df") + .arg(Arg::from_usage("[arg] 'some opt'").from_env("CLP_TEST_ENV")) + .get_matches_from_safe(vec![""]); + assert!(r.is_ok()); + let m = r.unwrap(); + // assert!(m.is_present("arg")); // TODO: should this be true? + assert_eq!(m.value_of("arg").unwrap(), "from_env"); +}