mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
Merge branch 'from_env' of https://github.com/bluejekyll/clap-rs into bluejekyll-from_env
This commit is contained in:
commit
2acd9b23f5
12 changed files with 844 additions and 290 deletions
316
src/app/help.rs
316
src/app/help.rs
|
@ -10,22 +10,19 @@ use app::{App, AppSettings};
|
|||
use app::parser::Parser;
|
||||
use args::{AnyArg, ArgSettings, DispOrder};
|
||||
use errors::{Error, Result as ClapResult};
|
||||
use fmt::{Format, Colorizer, ColorizerOption};
|
||||
use fmt::{Colorizer, ColorizerOption, Format};
|
||||
use app::usage;
|
||||
use map::VecMap;
|
||||
|
||||
// Third Party
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
#[cfg(feature = "wrap_help")]
|
||||
use term_size;
|
||||
use textwrap;
|
||||
|
||||
#[cfg(feature = "wrap_help")]
|
||||
fn term_width() -> usize {
|
||||
textwrap::termwidth()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "wrap_help"))]
|
||||
fn term_width() -> usize {
|
||||
120
|
||||
mod term_size {
|
||||
pub fn dimensions() -> Option<(usize, usize)> { None }
|
||||
}
|
||||
|
||||
fn str_width(s: &str) -> usize { UnicodeWidthStr::width(s) }
|
||||
|
@ -34,13 +31,18 @@ const TAB: &'static str = " ";
|
|||
|
||||
// These are just convenient traits to make the code easier to read.
|
||||
trait ArgWithDisplay<'b, 'c>: AnyArg<'b, 'c> + Display {}
|
||||
impl<'b, 'c, T> ArgWithDisplay<'b, 'c> for T where T: AnyArg<'b, 'c> + Display {}
|
||||
impl<'b, 'c, T> ArgWithDisplay<'b, 'c> for T
|
||||
where
|
||||
T: AnyArg<'b, 'c> + Display,
|
||||
{
|
||||
}
|
||||
|
||||
trait ArgWithOrder<'b, 'c>: ArgWithDisplay<'b, 'c> + DispOrder {
|
||||
fn as_base(&self) -> &ArgWithDisplay<'b, 'c>;
|
||||
}
|
||||
impl<'b, 'c, T> ArgWithOrder<'b, 'c> for T
|
||||
where T: ArgWithDisplay<'b, 'c> + DispOrder
|
||||
where
|
||||
T: ArgWithDisplay<'b, 'c> + DispOrder,
|
||||
{
|
||||
fn as_base(&self) -> &ArgWithDisplay<'b, 'c> { self }
|
||||
}
|
||||
|
@ -87,29 +89,34 @@ pub struct Help<'a> {
|
|||
impl<'a> Help<'a> {
|
||||
/// Create a new `Help` instance.
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
pub fn new(w: &'a mut Write,
|
||||
next_line_help: bool,
|
||||
hide_pv: bool,
|
||||
color: bool,
|
||||
cizer: Colorizer,
|
||||
term_w: Option<usize>,
|
||||
max_w: Option<usize>,
|
||||
use_long: bool)
|
||||
-> Self {
|
||||
pub fn new(
|
||||
w: &'a mut Write,
|
||||
next_line_help: bool,
|
||||
hide_pv: bool,
|
||||
color: bool,
|
||||
cizer: Colorizer,
|
||||
term_w: Option<usize>,
|
||||
max_w: Option<usize>,
|
||||
use_long: bool,
|
||||
) -> Self {
|
||||
debugln!("Help::new;");
|
||||
Help {
|
||||
writer: w,
|
||||
next_line_help: next_line_help,
|
||||
hide_pv: hide_pv,
|
||||
term_w: match term_w {
|
||||
Some(width) => if width == 0 { usize::MAX } else { width },
|
||||
None => {
|
||||
cmp::min(term_width(),
|
||||
match max_w {
|
||||
None | Some(0) => usize::MAX,
|
||||
Some(mw) => mw,
|
||||
})
|
||||
}
|
||||
Some(width) => if width == 0 {
|
||||
usize::MAX
|
||||
} else {
|
||||
width
|
||||
},
|
||||
None => cmp::min(
|
||||
term_size::dimensions().map_or(120, |(w, _)| w),
|
||||
match max_w {
|
||||
None | Some(0) => usize::MAX,
|
||||
Some(mw) => mw,
|
||||
},
|
||||
),
|
||||
},
|
||||
color: color,
|
||||
cizer: cizer,
|
||||
|
@ -142,7 +149,12 @@ impl<'a> Help<'a> {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn _write_parser_help(w: &'a mut Write, parser: &Parser, stderr: bool, use_long: bool) -> ClapResult<()> {
|
||||
pub fn _write_parser_help(
|
||||
w: &'a mut Write,
|
||||
parser: &Parser,
|
||||
stderr: bool,
|
||||
use_long: bool,
|
||||
) -> ClapResult<()> {
|
||||
debugln!("Help::write_parser_help;");
|
||||
let nlh = parser.is_set(AppSettings::NextLineHelp);
|
||||
let hide_v = parser.is_set(AppSettings::HidePossibleValuesInHelp);
|
||||
|
@ -151,15 +163,16 @@ impl<'a> Help<'a> {
|
|||
use_stderr: stderr,
|
||||
when: parser.color(),
|
||||
});
|
||||
Self::new(w,
|
||||
nlh,
|
||||
hide_v,
|
||||
color,
|
||||
cizer,
|
||||
parser.meta.term_w,
|
||||
parser.meta.max_w,
|
||||
use_long)
|
||||
.write_help(parser)
|
||||
Self::new(
|
||||
w,
|
||||
nlh,
|
||||
hide_v,
|
||||
color,
|
||||
cizer,
|
||||
parser.meta.term_w,
|
||||
parser.meta.max_w,
|
||||
use_long,
|
||||
).write_help(parser)
|
||||
}
|
||||
|
||||
/// Writes the parser help to the wrapped stream.
|
||||
|
@ -180,16 +193,16 @@ impl<'a> Help<'a> {
|
|||
impl<'a> Help<'a> {
|
||||
/// Writes help for each argument in the order they were declared to the wrapped stream.
|
||||
fn write_args_unsorted<'b: 'd, 'c: 'd, 'd, I: 'd>(&mut self, args: I) -> io::Result<()>
|
||||
where I: Iterator<Item = &'d ArgWithOrder<'b, 'c>>
|
||||
where
|
||||
I: Iterator<Item = &'d ArgWithOrder<'b, 'c>>,
|
||||
{
|
||||
debugln!("Help::write_args_unsorted;");
|
||||
// The shortest an arg can legally be is 2 (i.e. '-x')
|
||||
self.longest = 2;
|
||||
let mut arg_v = Vec::with_capacity(10);
|
||||
for arg in args.filter(|arg| {
|
||||
!(arg.is_set(ArgSettings::Hidden)) ||
|
||||
arg.is_set(ArgSettings::NextLineHelp)
|
||||
}) {
|
||||
!(arg.is_set(ArgSettings::Hidden)) || arg.is_set(ArgSettings::NextLineHelp)
|
||||
}) {
|
||||
if arg.longest_filter() {
|
||||
self.longest = cmp::max(self.longest, str_width(arg.to_string().as_str()));
|
||||
}
|
||||
|
@ -209,7 +222,8 @@ impl<'a> Help<'a> {
|
|||
|
||||
/// Sorts arguments by length and display order and write their help to the wrapped stream.
|
||||
fn write_args<'b: 'd, 'c: 'd, 'd, I: 'd>(&mut self, args: I) -> io::Result<()>
|
||||
where I: Iterator<Item = &'d ArgWithOrder<'b, 'c>>
|
||||
where
|
||||
I: Iterator<Item = &'d ArgWithOrder<'b, 'c>>,
|
||||
{
|
||||
debugln!("Help::write_args;");
|
||||
// The shortest an arg can legally be is 2 (i.e. '-x')
|
||||
|
@ -338,9 +352,9 @@ impl<'a> Help<'a> {
|
|||
let h_w = str_width(h) + str_width(&*spec_vals);
|
||||
let nlh = self.next_line_help || arg.is_set(ArgSettings::NextLineHelp);
|
||||
let taken = self.longest + 12;
|
||||
self.force_next_line = !nlh && self.term_w >= taken &&
|
||||
(taken as f32 / self.term_w as f32) > 0.40 &&
|
||||
h_w > (self.term_w - taken);
|
||||
self.force_next_line = !nlh && self.term_w >= taken
|
||||
&& (taken as f32 / self.term_w as f32) > 0.40
|
||||
&& h_w > (self.term_w - taken);
|
||||
|
||||
debug!("Help::val: Has switch...");
|
||||
if arg.has_switch() {
|
||||
|
@ -348,10 +362,12 @@ impl<'a> Help<'a> {
|
|||
debugln!("Help::val: force_next_line...{:?}", self.force_next_line);
|
||||
debugln!("Help::val: nlh...{:?}", nlh);
|
||||
debugln!("Help::val: taken...{}", taken);
|
||||
debugln!("Help::val: help_width > (width - taken)...{} > ({} - {})",
|
||||
h_w,
|
||||
self.term_w,
|
||||
taken);
|
||||
debugln!(
|
||||
"Help::val: help_width > (width - taken)...{} > ({} - {})",
|
||||
h_w,
|
||||
self.term_w,
|
||||
taken
|
||||
);
|
||||
debugln!("Help::val: longest...{}", self.longest);
|
||||
debug!("Help::val: next_line...");
|
||||
if !(nlh || self.force_next_line) {
|
||||
|
@ -375,7 +391,10 @@ impl<'a> Help<'a> {
|
|||
}
|
||||
} else if !(nlh || self.force_next_line) {
|
||||
sdebugln!("No, and not next_line");
|
||||
write_nspaces!(self.writer, self.longest + 4 - (str_width(arg.to_string().as_str())));
|
||||
write_nspaces!(
|
||||
self.writer,
|
||||
self.longest + 4 - (str_width(arg.to_string().as_str()))
|
||||
);
|
||||
} else {
|
||||
sdebugln!("No");
|
||||
}
|
||||
|
@ -386,19 +405,25 @@ impl<'a> Help<'a> {
|
|||
debugln!("Help::write_before_after_help;");
|
||||
let mut help = String::from(h);
|
||||
// determine if our help fits or needs to wrap
|
||||
debugln!("Help::write_before_after_help: Term width...{}",
|
||||
self.term_w);
|
||||
debugln!(
|
||||
"Help::write_before_after_help: Term width...{}",
|
||||
self.term_w
|
||||
);
|
||||
let too_long = str_width(h) >= self.term_w;
|
||||
|
||||
debug!("Help::write_before_after_help: Too long...");
|
||||
if too_long || h.contains("{n}") {
|
||||
sdebugln!("Yes");
|
||||
debugln!("Help::write_before_after_help: help: {}", help);
|
||||
debugln!("Help::write_before_after_help: help width: {}",
|
||||
str_width(&*help));
|
||||
debugln!(
|
||||
"Help::write_before_after_help: help width: {}",
|
||||
str_width(&*help)
|
||||
);
|
||||
// Determine how many newlines we need to insert
|
||||
debugln!("Help::write_before_after_help: Usable space: {}",
|
||||
self.term_w);
|
||||
debugln!(
|
||||
"Help::write_before_after_help: Usable space: {}",
|
||||
self.term_w
|
||||
);
|
||||
help = wrap_help(&help.replace("{n}", "\n"), self.term_w);
|
||||
} else {
|
||||
sdebugln!("No");
|
||||
|
@ -467,42 +492,60 @@ impl<'a> Help<'a> {
|
|||
fn spec_vals(&self, a: &ArgWithDisplay) -> String {
|
||||
debugln!("Help::spec_vals: a={}", a);
|
||||
let mut spec_vals = vec![];
|
||||
if let Some(ref env) = a.env() {
|
||||
debugln!(
|
||||
"Help::spec_vals: Found environment variable...[{:?}:{:?}]",
|
||||
env.0,
|
||||
env.1
|
||||
);
|
||||
spec_vals.push(format!(
|
||||
" [env:{}: {}]",
|
||||
env.0.to_string_lossy(),
|
||||
env.1.to_string_lossy()
|
||||
));
|
||||
}
|
||||
if !a.is_set(ArgSettings::HideDefaultValue) {
|
||||
if let Some(pv) = a.default_val() {
|
||||
debugln!("Help::spec_vals: Found default value...[{:?}]", pv);
|
||||
spec_vals.push(format!(" [default: {}]",
|
||||
if self.color {
|
||||
self.cizer.good(pv.to_string_lossy())
|
||||
} else {
|
||||
Format::None(pv.to_string_lossy())
|
||||
}));
|
||||
spec_vals.push(format!(
|
||||
" [default: {}]",
|
||||
if self.color {
|
||||
self.cizer.good(pv.to_string_lossy())
|
||||
} else {
|
||||
Format::None(pv.to_string_lossy())
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(ref aliases) = a.aliases() {
|
||||
debugln!("Help::spec_vals: Found aliases...{:?}", aliases);
|
||||
spec_vals.push(format!(" [aliases: {}]",
|
||||
if self.color {
|
||||
aliases
|
||||
.iter()
|
||||
.map(|v| format!("{}", self.cizer.good(v)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
} else {
|
||||
aliases.join(", ")
|
||||
}));
|
||||
spec_vals.push(format!(
|
||||
" [aliases: {}]",
|
||||
if self.color {
|
||||
aliases
|
||||
.iter()
|
||||
.map(|v| format!("{}", self.cizer.good(v)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
} else {
|
||||
aliases.join(", ")
|
||||
}
|
||||
));
|
||||
}
|
||||
if !self.hide_pv && !a.is_set(ArgSettings::HidePossibleValues) {
|
||||
if let Some(pv) = a.possible_vals() {
|
||||
debugln!("Help::spec_vals: Found possible vals...{:?}", pv);
|
||||
spec_vals.push(if self.color {
|
||||
format!(" [values: {}]",
|
||||
pv.iter()
|
||||
.map(|v| format!("{}", self.cizer.good(v)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "))
|
||||
} else {
|
||||
format!(" [values: {}]", pv.join(", "))
|
||||
});
|
||||
format!(
|
||||
" [values: {}]",
|
||||
pv.iter()
|
||||
.map(|v| format!("{}", self.cizer.good(v)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
} else {
|
||||
format!(" [values: {}]", pv.join(", "))
|
||||
});
|
||||
}
|
||||
}
|
||||
spec_vals.join(" ")
|
||||
|
@ -581,12 +624,11 @@ impl<'a> Help<'a> {
|
|||
self.longest = 2;
|
||||
let mut ord_m = VecMap::new();
|
||||
for sc in parser
|
||||
.subcommands
|
||||
.iter()
|
||||
.filter(|s| !s.p.is_set(AppSettings::Hidden)) {
|
||||
let btm = ord_m
|
||||
.entry(sc.p.meta.disp_ord)
|
||||
.or_insert(BTreeMap::new());
|
||||
.subcommands
|
||||
.iter()
|
||||
.filter(|s| !s.p.is_set(AppSettings::Hidden))
|
||||
{
|
||||
let btm = ord_m.entry(sc.p.meta.disp_ord).or_insert(BTreeMap::new());
|
||||
self.longest = cmp::max(self.longest, str_width(sc.p.meta.name.as_str()));
|
||||
//self.longest = cmp::max(self.longest, sc.p.meta.name.len());
|
||||
btm.insert(sc.p.meta.name.clone(), sc.clone());
|
||||
|
@ -679,10 +721,12 @@ impl<'a> Help<'a> {
|
|||
}
|
||||
|
||||
color!(self, "\nUSAGE:", warning)?;
|
||||
write!(self.writer,
|
||||
"\n{}{}\n\n",
|
||||
TAB,
|
||||
usage::create_usage_no_title(parser, &[]))?;
|
||||
write!(
|
||||
self.writer,
|
||||
"\n{}{}\n\n",
|
||||
TAB,
|
||||
usage::create_usage_no_title(parser, &[])
|
||||
)?;
|
||||
|
||||
let flags = parser.has_flags();
|
||||
let pos = parser.has_positionals();
|
||||
|
@ -748,21 +792,20 @@ fn copy_until<R: Read, W: Write>(r: &mut R, w: &mut W, delimiter_byte: u8) -> Co
|
|||
/// - `None`: The reader was consumed.
|
||||
/// - `Some(Ok(0))`: No tag was captured but the reader still contains data.
|
||||
/// - `Some(Ok(length>0))`: a tag with `length` was captured to the `tag_buffer`.
|
||||
fn copy_and_capture<R: Read, W: Write>(r: &mut R,
|
||||
w: &mut W,
|
||||
tag_buffer: &mut Cursor<Vec<u8>>)
|
||||
-> Option<io::Result<usize>> {
|
||||
fn copy_and_capture<R: Read, W: Write>(
|
||||
r: &mut R,
|
||||
w: &mut W,
|
||||
tag_buffer: &mut Cursor<Vec<u8>>,
|
||||
) -> Option<io::Result<usize>> {
|
||||
use self::CopyUntilResult::*;
|
||||
debugln!("copy_and_capture;");
|
||||
|
||||
// Find the opening byte.
|
||||
match copy_until(r, w, b'{') {
|
||||
|
||||
// The end of the reader was reached without finding the opening tag.
|
||||
// (either with or without having copied data to the writer)
|
||||
// Return None indicating that we are done.
|
||||
ReaderEmpty |
|
||||
DelimiterNotFound(_) => None,
|
||||
ReaderEmpty | DelimiterNotFound(_) => None,
|
||||
|
||||
// Something went wrong.
|
||||
ReadError(e) | WriteError(e) => Some(Err(e)),
|
||||
|
@ -770,7 +813,6 @@ fn copy_and_capture<R: Read, W: Write>(r: &mut R,
|
|||
// The opening byte was found.
|
||||
// (either with or without having copied data to the writer)
|
||||
DelimiterFound(_) => {
|
||||
|
||||
// Lets reset the buffer first and find out how long it is.
|
||||
tag_buffer.set_position(0);
|
||||
let buffer_size = tag_buffer.get_ref().len();
|
||||
|
@ -778,7 +820,6 @@ fn copy_and_capture<R: Read, W: Write>(r: &mut R,
|
|||
// Find the closing byte,limiting the reader to the length of the buffer.
|
||||
let mut rb = r.take(buffer_size as u64);
|
||||
match copy_until(&mut rb, tag_buffer, b'}') {
|
||||
|
||||
// We were already at the end of the reader.
|
||||
// Return None indicating that we are done.
|
||||
ReaderEmpty => None,
|
||||
|
@ -790,17 +831,13 @@ fn copy_and_capture<R: Read, W: Write>(r: &mut R,
|
|||
// The end of the reader was found without finding the closing tag.
|
||||
// Write the opening byte and captured text to the writer.
|
||||
// Return 0 indicating that nothing was caputred but the reader still contains data.
|
||||
DelimiterNotFound(not_tag_length) => {
|
||||
match w.write(b"{") {
|
||||
DelimiterNotFound(not_tag_length) => match w.write(b"{") {
|
||||
Err(e) => Some(Err(e)),
|
||||
_ => match w.write(&tag_buffer.get_ref()[0..not_tag_length]) {
|
||||
Err(e) => Some(Err(e)),
|
||||
_ => {
|
||||
match w.write(&tag_buffer.get_ref()[0..not_tag_length]) {
|
||||
Err(e) => Some(Err(e)),
|
||||
_ => Some(Ok(0)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => Some(Ok(0)),
|
||||
},
|
||||
},
|
||||
|
||||
ReadError(e) | WriteError(e) => Some(Err(e)),
|
||||
}
|
||||
|
@ -850,11 +887,14 @@ impl<'a> Help<'a> {
|
|||
_ => continue,
|
||||
};
|
||||
|
||||
debugln!(
|
||||
"Help::write_template_help:iter: tag_buf={};",
|
||||
str::from_utf8(&tag_buf.get_ref()[..tag_length])
|
||||
.unwrap_or_default()
|
||||
);
|
||||
debugln!("Help::write_template_help:iter: tag_buf={};", unsafe {
|
||||
String::from_utf8_unchecked(
|
||||
tag_buf.get_ref()[0..tag_length]
|
||||
.iter()
|
||||
.map(|&i| i)
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
});
|
||||
match &tag_buf.get_ref()[0..tag_length] {
|
||||
b"?" => {
|
||||
self.writer.write_all(b"Could not decode tag name")?;
|
||||
|
@ -863,24 +903,32 @@ impl<'a> Help<'a> {
|
|||
self.write_bin_name(parser)?;
|
||||
}
|
||||
b"version" => {
|
||||
write!(self.writer,
|
||||
"{}",
|
||||
parser.meta.version.unwrap_or("unknown version"))?;
|
||||
write!(
|
||||
self.writer,
|
||||
"{}",
|
||||
parser.meta.version.unwrap_or("unknown version")
|
||||
)?;
|
||||
}
|
||||
b"author" => {
|
||||
write!(self.writer,
|
||||
"{}",
|
||||
parser.meta.author.unwrap_or("unknown author"))?;
|
||||
write!(
|
||||
self.writer,
|
||||
"{}",
|
||||
parser.meta.author.unwrap_or("unknown author")
|
||||
)?;
|
||||
}
|
||||
b"about" => {
|
||||
write!(self.writer,
|
||||
"{}",
|
||||
parser.meta.about.unwrap_or("unknown about"))?;
|
||||
write!(
|
||||
self.writer,
|
||||
"{}",
|
||||
parser.meta.about.unwrap_or("unknown about")
|
||||
)?;
|
||||
}
|
||||
b"long-about" => {
|
||||
write!(self.writer,
|
||||
"{}",
|
||||
parser.meta.long_about.unwrap_or("unknown about"))?;
|
||||
write!(
|
||||
self.writer,
|
||||
"{}",
|
||||
parser.meta.long_about.unwrap_or("unknown about")
|
||||
)?;
|
||||
}
|
||||
b"usage" => {
|
||||
write!(self.writer, "{}", usage::create_usage_no_title(parser, &[]))?;
|
||||
|
@ -908,14 +956,18 @@ impl<'a> Help<'a> {
|
|||
self.write_subcommands(parser)?;
|
||||
}
|
||||
b"after-help" => {
|
||||
write!(self.writer,
|
||||
"{}",
|
||||
parser.meta.more_help.unwrap_or("unknown after-help"))?;
|
||||
write!(
|
||||
self.writer,
|
||||
"{}",
|
||||
parser.meta.more_help.unwrap_or("unknown after-help")
|
||||
)?;
|
||||
}
|
||||
b"before-help" => {
|
||||
write!(self.writer,
|
||||
"{}",
|
||||
parser.meta.pre_help.unwrap_or("unknown before-help"))?;
|
||||
write!(
|
||||
self.writer,
|
||||
"{}",
|
||||
parser.meta.pre_help.unwrap_or("unknown before-help")
|
||||
)?;
|
||||
}
|
||||
// Unknown tag, write it back.
|
||||
r => {
|
||||
|
|
|
@ -1796,6 +1796,7 @@ impl<'n, 'e> AnyArg<'n, 'e> for App<'n, 'e> {
|
|||
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
|
||||
None
|
||||
}
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, &'s OsString)> { None }
|
||||
fn longest_filter(&self) -> bool { true }
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||
if let Some(ref aliases) = self.p.meta.aliases {
|
||||
|
|
|
@ -1788,6 +1788,38 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_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.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.1), $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.1), $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<FlagBuilder<'a, 'b>> { self.flags.iter() }
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
|||
-> ClapResult<()> {
|
||||
debugln!("Validator::validate;");
|
||||
let mut reqs_validated = false;
|
||||
self.0.add_env(matcher)?;
|
||||
self.0.add_defaults(matcher)?;
|
||||
if let ParseResult::Opt(a) = needs_val_of {
|
||||
debugln!("Validator::validate: needs_val_of={:?}", a);
|
||||
|
|
|
@ -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<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>>;
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, &'s OsString)>;
|
||||
fn longest_filter(&self) -> bool;
|
||||
fn val_terminator(&self) -> Option<&'e str>;
|
||||
}
|
||||
|
|
118
src/args/arg.rs
118
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),
|
||||
"env" => yaml_to_str!(a, v, 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),
|
||||
|
@ -3014,7 +3015,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// **NOTE:** If the user *does not* use this argument at runtime [`ArgMatches::is_present`] will
|
||||
/// still return `true`. If you wish to determine whether the argument was used at runtime or
|
||||
/// not, consider [`ArgMatches::occurrences_of`] which will return `0` if the argument was *not*
|
||||
/// used at runtmie.
|
||||
/// used at runtime.
|
||||
///
|
||||
/// **NOTE:** This setting is perfectly compatible with [`Arg::default_value_if`] but slightly
|
||||
/// different. `Arg::default_value` *only* takes affect when the user has not provided this arg
|
||||
|
@ -3311,6 +3312,119 @@ 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.
|
||||
///
|
||||
/// **NOTE:** If the user *does not* use this argument at runtime, [`ArgMatches::occurrences_of`]
|
||||
/// will return `0` even though the [`ArgMatches::value_of`] will return the default specified.
|
||||
///
|
||||
/// **NOTE:** If the user *does not* use this argument at runtime [`ArgMatches::is_present`] will
|
||||
/// return `true` if the variable is present in the environemnt . If you wish to determine whether
|
||||
/// the argument was used at runtime or not, consider [`ArgMatches::occurrences_of`] which will
|
||||
/// return `0` if the argument was *not* used at runtime.
|
||||
///
|
||||
/// **NOTE:** This implicitly sets [`Arg::takes_value(true)`].
|
||||
///
|
||||
/// **NOTE:** If [`Arg::multiple(true)`] is set then [`Arg::use_delimiter(true)`] should also be
|
||||
/// set. Otherwise, only a single argument will be returned from the environment variable. The
|
||||
/// default delimiter is `,` and follows all the other delimiter rules.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// In this example, we show the variable coming from the environment:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::env;
|
||||
/// # use clap::{App, Arg};
|
||||
///
|
||||
/// env::set_var("MY_FLAG", "env");
|
||||
///
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .long("flag")
|
||||
/// .env("MY_FLAG"))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog"
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(m.value_of("flag"), Some("env"));
|
||||
/// ```
|
||||
///
|
||||
/// In this example, we show the variable coming from an option on the CLI:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::env;
|
||||
/// # use clap::{App, Arg};
|
||||
///
|
||||
/// env::set_var("MY_FLAG", "env");
|
||||
///
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .long("flag")
|
||||
/// .env("MY_FLAG"))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog", "--flag", "opt"
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(m.value_of("flag"), Some("opt"));
|
||||
/// ```
|
||||
///
|
||||
/// In this example, we show the variable coming from the environment even with the
|
||||
/// presence of a default:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::env;
|
||||
/// # use clap::{App, Arg};
|
||||
///
|
||||
/// env::set_var("MY_FLAG", "env");
|
||||
///
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .long("flag")
|
||||
/// .env("MY_FLAG")
|
||||
/// .default_value("default"))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog"
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(m.value_of("flag"), Some("env"));
|
||||
/// ```
|
||||
///
|
||||
/// In this example, we show the use of multiple values in a single environment variable:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::env;
|
||||
/// # use clap::{App, Arg};
|
||||
///
|
||||
/// env::set_var("MY_FLAG_MULTI", "env1,env2");
|
||||
///
|
||||
/// let m = App::new("prog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .long("flag")
|
||||
/// .env("MY_FLAG_MULTI")
|
||||
/// .multiple(true)
|
||||
/// .use_delimiter(true))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog"
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(m.values_of("flag").unwrap().collect::<Vec<_>>(), vec!["env1", "env2"]);
|
||||
/// ```
|
||||
pub fn env(self, name: &'a str) -> Self {
|
||||
self.env_os(OsStr::new(name))
|
||||
}
|
||||
|
||||
/// Specifies that if the value is not passed in as an argument, that it should be retrieved
|
||||
/// from the environment if available in the exact same manner as [`Arg::env`] only using
|
||||
/// [`OsStr`]s instead.
|
||||
pub fn env_os(mut self, name: &'a OsStr) -> Self {
|
||||
self.setb(ArgSettings::TakesValue);
|
||||
|
||||
self.v.env = env::var_os(name).map(|value| (name, value));
|
||||
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.
|
||||
|
|
|
@ -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<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
|
||||
None
|
||||
}
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, &'s OsString)> { None }
|
||||
fn longest_filter(&self) -> bool { self.s.long.is_some() }
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,14 @@ impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> {
|
|||
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
|
||||
self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
|
||||
}
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, &'s OsString)> {
|
||||
self.v.env.as_ref().map(|&(key, ref value)| (key, value))
|
||||
}
|
||||
fn longest_filter(&self) -> bool { true }
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||
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 +166,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 +224,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 <opt>");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<Vec<_>>()
|
||||
.join(" "))
|
||||
Cow::Owned(
|
||||
names
|
||||
.values()
|
||||
.map(|n| format!("<{}>", n))
|
||||
.collect::<Vec<_>>()
|
||||
.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::<Vec<_>>()
|
||||
.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,12 @@ 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 env<'s>(&'s self) -> Option<(&'n OsStr, &'s OsString)> {
|
||||
self.v
|
||||
.env
|
||||
.as_ref()
|
||||
.map(|&(key, ref value)| (key, value))
|
||||
}
|
||||
fn longest_filter(&self) -> bool { true }
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> { None }
|
||||
}
|
||||
|
|
|
@ -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<Vec<&'b str>>,
|
||||
pub val_names: Option<VecMap<&'b str>>,
|
||||
|
@ -20,6 +21,7 @@ pub struct Valued<'a, 'b>
|
|||
pub val_delim: Option<char>,
|
||||
pub default_val: Option<&'b OsStr>,
|
||||
pub default_vals_ifs: Option<VecMap<(&'a str, Option<&'b OsStr>, &'b OsStr)>>,
|
||||
pub env: Option<(&'a OsStr, OsString)>,
|
||||
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,
|
||||
env: None,
|
||||
terminator: None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
263
tests/env.rs
Normal file
263
tests/env.rs
Normal file
|
@ -0,0 +1,263 @@
|
|||
extern crate clap;
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
|
||||
use clap::{App, Arg};
|
||||
|
||||
#[test]
|
||||
fn env() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from_usage("[arg] 'some opt'").env("CLP_TEST_ENV"))
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(m.value_of("arg").unwrap(), "env");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn env_os() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'").env_os(OsStr::new("CLP_TEST_ENV")),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(m.value_of("arg").unwrap(), "env");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_env() {
|
||||
// All the other tests use the presence of the Environment variable...
|
||||
// we need another variable just in case one of the others is running at the same time...
|
||||
env::remove_var("CLP_TEST_ENV_NONE");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from_usage("[arg] 'some opt'").env("CLP_TEST_ENV_NONE"))
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(!m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(m.value_of("arg"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn with_default() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'")
|
||||
.env("CLP_TEST_ENV")
|
||||
.default_value("default"),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(m.value_of("arg").unwrap(), "env");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opt_user_override() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("--arg [FILE] 'some arg'").env("CLP_TEST_ENV"),
|
||||
)
|
||||
.get_matches_from_safe(vec!["", "--arg", "opt"]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 1);
|
||||
assert_eq!(m.value_of("arg").unwrap(), "opt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn positionals() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from_usage("[arg] 'some opt'").env("CLP_TEST_ENV"))
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(m.value_of("arg").unwrap(), "env");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn positionals_user_override() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(Arg::from_usage("[arg] 'some opt'").env("CLP_TEST_ENV"))
|
||||
.get_matches_from_safe(vec!["", "opt"]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 1);
|
||||
assert_eq!(m.value_of("arg").unwrap(), "opt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_one() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'")
|
||||
.env("CLP_TEST_ENV")
|
||||
.use_delimiter(true)
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(m.values_of("arg").unwrap().collect::<Vec<_>>(), vec!["env"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_three() {
|
||||
env::set_var("CLP_TEST_ENV_MULTI1", "env1,env2,env3");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'")
|
||||
.env("CLP_TEST_ENV_MULTI1")
|
||||
.use_delimiter(true)
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(
|
||||
m.values_of("arg").unwrap().collect::<Vec<_>>(),
|
||||
vec!["env1", "env2", "env3"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_no_delimiter() {
|
||||
env::set_var("CLP_TEST_ENV_MULTI2", "env1 env2 env3");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'")
|
||||
.env("CLP_TEST_ENV_MULTI2")
|
||||
.multiple(true),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(
|
||||
m.values_of("arg").unwrap().collect::<Vec<_>>(),
|
||||
vec!["env1 env2 env3"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn possible_value() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'")
|
||||
.env("CLP_TEST_ENV")
|
||||
.possible_value("env"),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(m.value_of("arg").unwrap(), "env");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn not_possible_value() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'")
|
||||
.env("CLP_TEST_ENV")
|
||||
.possible_value("never"),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validator() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'")
|
||||
.env("CLP_TEST_ENV")
|
||||
.validator(|s| if s == "env" {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("not equal".to_string())
|
||||
}),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_ok());
|
||||
let m = r.unwrap();
|
||||
assert!(m.is_present("arg"));
|
||||
assert_eq!(m.occurrences_of("arg"), 0);
|
||||
assert_eq!(m.value_of("arg").unwrap(), "env");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validator_invalid() {
|
||||
env::set_var("CLP_TEST_ENV", "env");
|
||||
|
||||
let r = App::new("df")
|
||||
.arg(
|
||||
Arg::from_usage("[arg] 'some opt'")
|
||||
.env("CLP_TEST_ENV")
|
||||
.validator(|s| if s != "env" {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("is equal".to_string())
|
||||
}),
|
||||
)
|
||||
.get_matches_from_safe(vec![""]);
|
||||
|
||||
assert!(r.is_err());
|
||||
}
|
Loading…
Reference in a new issue