Arg-specific API for MKeyMap

This commit is contained in:
Alena Yuryeva 2018-08-01 20:33:55 +05:00
parent be23ec9701
commit eb01627463
8 changed files with 341 additions and 170 deletions

3
.gitignore vendored
View file

@ -26,3 +26,6 @@ Cargo.lock
.vscode/* .vscode/*
.idea/* .idea/*
clap-rs.iml clap-rs.iml
# Auxiliary files
test-results.test

View file

@ -18,11 +18,11 @@ use yaml_rust::Yaml;
// Internal // Internal
use build::{Arg, ArgGroup, ArgSettings}; use build::{Arg, ArgGroup, ArgSettings};
use completions::{ComplGen, Shell}; use completions::{ComplGen, Shell};
use mkeymap::{KeyType, MKeyMap};
use output::fmt::ColorWhen; use output::fmt::ColorWhen;
use output::{Help, Usage}; use output::{Help, Usage};
use parse::errors::Result as ClapResult; use parse::errors::Result as ClapResult;
use parse::{ArgMatcher, ArgMatches, Parser}; use parse::{ArgMatcher, ArgMatches, Parser};
use mkeymap::{MKeyMap, KeyType};
#[doc(hidden)] #[doc(hidden)]
#[allow(dead_code)] #[allow(dead_code)]
@ -638,7 +638,6 @@ impl<'a, 'b> App<'a, 'b> {
None None
}; };
let arg = a.into().help_heading(help_heading); let arg = a.into().help_heading(help_heading);
//TODO add push functionality to MKeyMap
self.args.push(arg); self.args.push(arg);
self self
} }
@ -679,7 +678,7 @@ impl<'a, 'b> App<'a, 'b> {
// @TODO @perf @p4 @v3-beta: maybe extend_from_slice would be possible and perform better? // @TODO @perf @p4 @v3-beta: maybe extend_from_slice would be possible and perform better?
// But that may also not let us do `&["-a 'some'", "-b 'other']` because of not Into<Arg> // But that may also not let us do `&["-a 'some'", "-b 'other']` because of not Into<Arg>
for arg in args.into_iter() { for arg in args.into_iter() {
self.args.push(arg.into()); self.args.make_entries(arg.into());
} }
self self
} }
@ -988,19 +987,8 @@ impl<'a, 'b> App<'a, 'b> {
where where
F: FnOnce(Arg<'a, 'b>) -> Arg<'a, 'b>, F: FnOnce(Arg<'a, 'b>) -> Arg<'a, 'b>,
{ {
// let i = self self.args.mut_arg(arg, f);
// .args
// .values()
// .enumerate()
// .filter_map(|(i, a)| if a.name == arg { Some(i) } else { None })
// .next();
let a = if let Some(x) = self.args.remove_by_name(arg) {
f(x)
} else {
let mut x = Arg::with_name(arg);
f(x)
};
self.args.push(a);
self self
} }
@ -1545,7 +1533,7 @@ impl<'a, 'b> App<'a, 'b> {
// we have to set short manually because we're dealing with char's // we have to set short manually because we're dealing with char's
arg.short = self.help_short; arg.short = self.help_short;
self.args.push(arg); self.args.make_entries(arg);
} else { } else {
self.settings.unset(AppSettings::NeedsLongHelp); self.settings.unset(AppSettings::NeedsLongHelp);
} }
@ -1560,7 +1548,7 @@ impl<'a, 'b> App<'a, 'b> {
.help(self.version_message.unwrap_or("Prints version information")); .help(self.version_message.unwrap_or("Prints version information"));
// we have to set short manually because we're dealing with char's // we have to set short manually because we're dealing with char's
arg.short = self.version_short; arg.short = self.version_short;
self.args.push(arg); self.args.make_entries(arg);
} else { } else {
self.settings.unset(AppSettings::NeedsLongVersion); self.settings.unset(AppSettings::NeedsLongVersion);
} }
@ -1773,13 +1761,9 @@ impl<'a, 'b> App<'a, 'b> {
pub fn has_positionals(&self) -> bool { positionals!(self).count() > 0 } pub fn has_positionals(&self) -> bool { positionals!(self).count() > 0 }
pub fn has_visible_opts(&self) -> bool { pub fn has_visible_opts(&self) -> bool { opts!(self).any(|o| !o.is_set(ArgSettings::Hidden)) }
opts!(self).any(|o| !o.is_set(ArgSettings::Hidden))
}
pub fn has_visible_flags(&self) -> bool { pub fn has_visible_flags(&self) -> bool { flags!(self).any(|o| !o.is_set(ArgSettings::Hidden)) }
flags!(self).any(|o| !o.is_set(ArgSettings::Hidden))
}
pub fn has_visible_positionals(&self) -> bool { pub fn has_visible_positionals(&self) -> bool {
positionals!(self).any(|o| !o.is_set(ArgSettings::Hidden)) positionals!(self).any(|o| !o.is_set(ArgSettings::Hidden))
@ -1944,7 +1928,7 @@ impl<'a, 'b> App<'a, 'b> {
note = "Use `App::arg(Arg::from(&str)` instead. Will be removed in v3.0-beta" note = "Use `App::arg(Arg::from(&str)` instead. Will be removed in v3.0-beta"
)] )]
pub fn arg_from_usage(mut self, usage: &'a str) -> Self { pub fn arg_from_usage(mut self, usage: &'a str) -> Self {
self.args.push(Arg::from(usage)); self.args.make_entries(Arg::from(usage));
self self
} }
@ -1959,7 +1943,7 @@ impl<'a, 'b> App<'a, 'b> {
if l.is_empty() { if l.is_empty() {
continue; continue;
} }
self.args.push(Arg::from(l)); self.args.make_entries(Arg::from(l));
} }
self self
} }

View file

@ -1,6 +1,6 @@
// Std // Std
use std::io::Write;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::io::Write;
// Internal // Internal
use build::{App, Arg}; use build::{App, Arg};
@ -182,7 +182,9 @@ complete -F _{name} -o bashdefault -o default {name}
shorts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s)), shorts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s)),
// Handles aliases too // Handles aliases too
// error-handling? // error-handling?
longs = longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l.to_str().unwrap())), longs = longs!(p).fold(String::new(), |acc, l| {
format!("{} --{}", acc, l.to_str().unwrap())
}),
pos = positionals!(p).fold(String::new(), |acc, p| format!("{} {}", acc, p)), pos = positionals!(p).fold(String::new(), |acc, p| format!("{} {}", acc, p)),
// Handles aliases too // Handles aliases too
subcmds = sc_names!(p).fold(String::new(), |acc, s| format!("{} {}", acc, s)) subcmds = sc_names!(p).fold(String::new(), |acc, s| format!("{} {}", acc, s))

View file

@ -4,6 +4,7 @@ use std::collections::hash_map::DefaultHasher;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::ffi::OsString; use std::ffi::OsString;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::mem;
use std::slice; use std::slice;
// ! rustdoc // ! rustdoc
@ -18,7 +19,7 @@ pub struct MKeyMap<T> {
pub enum KeyType { pub enum KeyType {
Short(char), Short(char),
Long(OsString), Long(OsString),
Position(usize), Position(u64),
} }
impl<T> MKeyMap<T> impl<T> MKeyMap<T>
@ -77,16 +78,6 @@ where
} }
//TODO ::insert_keyset([Long, Key2]) //TODO ::insert_keyset([Long, Key2])
// pub fn insert_key_by_name(&mut self, key: KeyType, name: &str) {
// let index = self
// .value_index
// .iter()
// .position(|x| x.name == name)
// .expect("No such name found");
// self.keys.insert(key, index);
// }
// ! Arg mutation functionality // ! Arg mutation functionality
pub fn get(&self, key: KeyType) -> Option<&T> { pub fn get(&self, key: KeyType) -> Option<&T> {
@ -113,7 +104,7 @@ where
//? probably shouldn't add a possibility for removal? //? probably shouldn't add a possibility for removal?
//? or remove by replacement by some dummy object, so the order is preserved //? or remove by replacement by some dummy object, so the order is preserved
pub fn remove_key(&mut self, key: KeyType) { unimplemented!() } pub fn remove_key(&mut self, key: KeyType) { self.keys.remove(&key); }
//TODO ::remove_keys([KeyA, KeyB]) //TODO ::remove_keys([KeyA, KeyB])
pub fn keys(&self) -> Keys<usize> { pub fn keys(&self) -> Keys<usize> {
@ -142,6 +133,113 @@ where
} }
} }
impl<'a, 'b> MKeyMap<Arg<'a, 'b>> {
pub fn insert_key_by_name(&mut self, key: KeyType, name: &str) {
let index = self.find_by_name(name);
self.keys.insert(key, index);
}
pub fn make_entries(&mut self, arg: Arg<'a, 'b>) -> usize {
let short = arg.short.map(|c| KeyType::Short(c));
let positional = arg.index.map(|n| KeyType::Position(n));
let mut longs = arg
.aliases
.clone()
.map(|v| {
v.iter()
.map(|(n, _)| KeyType::Long(OsString::from(n)))
.collect()
})
.unwrap_or(Vec::new());
longs.extend(arg.long.map(|l| KeyType::Long(OsString::from(l))));
let index = self.push(arg);
short.map(|s| self.insert_key(s, index));
positional.map(|p| self.insert_key(p, index));
longs.into_iter().map(|l| self.insert_key(l, index)).count();
index
}
pub fn make_entries_by_index(&mut self, index: usize) {
let short;
let positional;
let mut longs;
{
let arg = &self.value_index[index];
short = arg.short.map(|c| KeyType::Short(c));
positional = arg.index.map(|n| KeyType::Position(n));
longs = arg
.aliases
.clone()
.map(|v| {
v.iter()
.map(|(n, _)| KeyType::Long(OsString::from(n)))
.collect()
})
.unwrap_or(Vec::new());
longs.extend(arg.long.map(|l| KeyType::Long(OsString::from(l))));
}
short.map(|s| self.insert_key(s, index));
positional.map(|p| self.insert_key(p, index));
longs.into_iter().map(|l| self.insert_key(l, index)).count();
}
pub fn mut_arg<F>(&mut self, name: &str, f: F)
where
F: FnOnce(Arg<'a, 'b>) -> Arg<'a, 'b>,
{
let index = self.find_by_name(name);
let new_arg = f(self.value_index[index].clone());
let value_key = self
.values
.iter()
.filter(|(_, v)| v.contains(&index))
.map(|(k, _)| k)
.next()
.map(|&x| x);
value_key.map(|k| {
self.values.entry(k).and_modify(|v| {
v.remove(&index);
})
});
let mut hasher = DefaultHasher::new();
new_arg.hash(&mut hasher);
let hash = hasher.finish();
self.values
.entry(hash)
.and_modify(|x| {
x.insert(index);
})
.or_insert({
let mut set = HashSet::new();
set.insert(index);
set
});
self.value_index.push(new_arg);
self.value_index.swap_remove(index);
self.make_entries_by_index(index);
}
pub fn find_by_name(&mut self, name: &str) -> usize {
self.value_index
.iter()
.position(|x| x.name == name)
.expect("No such name found")
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Keys<'a, V: 'a> { pub struct Keys<'a, V: 'a> {
iter: hash_map::Keys<'a, KeyType, V>, iter: hash_map::Keys<'a, KeyType, V>,
@ -218,7 +316,6 @@ mod tests {
} }
#[test] #[test]
#[should_panic]
fn get_none_value() { fn get_none_value() {
let mut map: MKeyMap<Arg> = MKeyMap::new(); let mut map: MKeyMap<Arg> = MKeyMap::new();

View file

@ -142,7 +142,7 @@ where
.count(); .count();
assert!( assert!(
highest_idx == num_p, highest_idx == num_p as u64,
"Found positional argument whose index is {} but there \ "Found positional argument whose index is {} but there \
are only {} positional arguments defined", are only {} positional arguments defined",
highest_idx, highest_idx,
@ -310,7 +310,7 @@ where
let mut key: Vec<(KeyType, usize)> = Vec::new(); let mut key: Vec<(KeyType, usize)> = Vec::new();
for (i, a) in self.app.args.values().enumerate() { for (i, a) in self.app.args.values().enumerate() {
if let Some(ref index) = a.index { if let Some(ref index) = a.index {
key.push((KeyType::Position((*index) as usize), i)); key.push((KeyType::Position(*index), i));
} else { } else {
if let Some(ref c) = a.short { if let Some(ref c) = a.short {
key.push((KeyType::Short(*c), i)); key.push((KeyType::Short(*c), i));
@ -367,7 +367,6 @@ where
} }
}) })
.count()) .count())
//? what is happening below?
}) })
&& self && self
.app .app
@ -641,6 +640,8 @@ where
{ {
self.app.settings.set(AS::TrailingValues); self.app.settings.set(AS::TrailingValues);
} }
//not sure
self.seen.push(p.name);
let _ = self.add_val_to_arg(p, &arg_os, matcher)?; let _ = self.add_val_to_arg(p, &arg_os, matcher)?;
matcher.inc_occurrence_of(p.name); matcher.inc_occurrence_of(p.name);
@ -1084,7 +1085,6 @@ where
sdebugln!("No"); sdebugln!("No");
full_arg.trim_left_matches(b'-') full_arg.trim_left_matches(b'-')
}; };
// opts?? Should probably now check once, then check whether it's opt or flag, or sth else
if let Some(opt) = self.app.args.get(KeyType::Long(arg.into())) { if let Some(opt) = self.app.args.get(KeyType::Long(arg.into())) {
debugln!( debugln!(
"Parser::parse_long_arg: Found valid opt '{}'", "Parser::parse_long_arg: Found valid opt '{}'",
@ -1094,6 +1094,9 @@ where
if opt.is_set(ArgSettings::TakesValue) { if opt.is_set(ArgSettings::TakesValue) {
let ret = self.parse_opt(val, opt, val.is_some(), matcher)?; let ret = self.parse_opt(val, opt, val.is_some(), matcher)?;
//not sure
self.seen.push(opt.name);
// if self.cache.map_or(true, |name| name != opt.name) { // if self.cache.map_or(true, |name| name != opt.name) {
// self.cache = Some(opt.name); // self.cache = Some(opt.name);
// } // }
@ -1106,6 +1109,7 @@ where
self.parse_flag(opt, matcher)?; self.parse_flag(opt, matcher)?;
self.seen.push(opt.name);
// if self.cache.map_or(true, |name| name != opt.name) { // if self.cache.map_or(true, |name| name != opt.name) {
// self.cache = Some(opt.name); // self.cache = Some(opt.name);
// } // }
@ -1188,6 +1192,9 @@ where
// Default to "we're expecting a value later" // Default to "we're expecting a value later"
let ret = self.parse_opt(val, opt, false, matcher)?; let ret = self.parse_opt(val, opt, false, matcher)?;
//not sure
self.seen.push(opt.name);
return Ok(ret); return Ok(ret);
} else if let Some(flag) = self.app.args.get(KeyType::Short(c)) { } else if let Some(flag) = self.app.args.get(KeyType::Short(c)) {
debugln!("Parser::parse_short_arg:iter:{}: Found valid flag", c); debugln!("Parser::parse_short_arg:iter:{}: Found valid flag", c);
@ -1195,6 +1202,9 @@ where
// Only flags can be help or version // Only flags can be help or version
self.check_for_help_and_version_char(c)?; self.check_for_help_and_version_char(c)?;
ret = self.parse_flag(flag, matcher)?; ret = self.parse_flag(flag, matcher)?;
//not sure
self.seen.push(flag.name);
} else { } else {
let arg = format!("-{}", c); let arg = format!("-{}", c);
return Err(ClapError::unknown_argument( return Err(ClapError::unknown_argument(
@ -1453,6 +1463,9 @@ where
$a.name $a.name
); );
$_self.add_val_to_arg($a, OsStr::new(val), $m)?; $_self.add_val_to_arg($a, OsStr::new(val), $m)?;
//not sure
$_self.seen.push($a.name);
} else if $m.get($a.name).is_some() { } else if $m.get($a.name).is_some() {
debugln!( debugln!(
"Parser::add_defaults:iter:{}: has user defined vals", "Parser::add_defaults:iter:{}: has user defined vals",
@ -1462,6 +1475,9 @@ where
debugln!("Parser::add_defaults:iter:{}: wasn't used", $a.name); debugln!("Parser::add_defaults:iter:{}: wasn't used", $a.name);
$_self.add_val_to_arg($a, OsStr::new(val), $m)?; $_self.add_val_to_arg($a, OsStr::new(val), $m)?;
//not sure
$_self.seen.push($a.name);
} }
} else { } else {
debugln!( debugln!(
@ -1487,6 +1503,10 @@ where
}; };
if add { if add {
$_self.add_val_to_arg($a, OsStr::new(default), $m)?; $_self.add_val_to_arg($a, OsStr::new(default), $m)?;
//not sure
$_self.seen.push($a.name);
done = true; done = true;
break; break;
} }
@ -1526,10 +1546,16 @@ where
if let Some(ref val) = val.1 { if let Some(ref val) = val.1 {
self.add_val_to_arg(a, OsStr::new(val), matcher)?; self.add_val_to_arg(a, OsStr::new(val), matcher)?;
} }
//not sure
self.seen.push(a.name);
} else { } else {
if let Some(ref val) = val.1 { if let Some(ref val) = val.1 {
self.add_val_to_arg(a, OsStr::new(val), matcher)?; self.add_val_to_arg(a, OsStr::new(val), matcher)?;
} }
//not sure
self.seen.push(a.name);
} }
} }
} }

View file

@ -8,31 +8,45 @@ use clap::{App, Arg};
#[test] #[test]
fn indices_mult_opts() { fn indices_mult_opts() {
let m = App::new("ind") let m = App::new("ind")
.arg(Arg::with_name("exclude") .arg(
Arg::with_name("exclude")
.short('e') .short('e')
.takes_value(true) .takes_value(true)
.multiple(true)) .multiple(true),
.arg(Arg::with_name("include") )
.arg(
Arg::with_name("include")
.short('i') .short('i')
.takes_value(true) .takes_value(true)
.multiple(true)) .multiple(true),
)
.get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]); .get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]);
assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[2, 3, 8]); assert_eq!(
assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[5, 6]); m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[2, 3, 8]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[5, 6]
);
} }
#[test] #[test]
fn index_mult_opts() { fn index_mult_opts() {
let m = App::new("ind") let m = App::new("ind")
.arg(Arg::with_name("exclude") .arg(
Arg::with_name("exclude")
.short('e') .short('e')
.takes_value(true) .takes_value(true)
.multiple(true)) .multiple(true),
.arg(Arg::with_name("include") )
.arg(
Arg::with_name("include")
.short('i') .short('i')
.takes_value(true) .takes_value(true)
.multiple(true)) .multiple(true),
)
.get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]); .get_matches_from(vec!["ind", "-e", "A", "B", "-i", "B", "C", "-e", "C"]);
assert_eq!(m.index_of("exclude"), Some(2)); assert_eq!(m.index_of("exclude"), Some(2));
@ -42,10 +56,8 @@ fn index_mult_opts() {
#[test] #[test]
fn index_flag() { fn index_flag() {
let m = App::new("ind") let m = App::new("ind")
.arg(Arg::with_name("exclude") .arg(Arg::with_name("exclude").short('e'))
.short('e')) .arg(Arg::with_name("include").short('i'))
.arg(Arg::with_name("include")
.short('i'))
.get_matches_from(vec!["ind", "-e", "-i"]); .get_matches_from(vec!["ind", "-e", "-i"]);
assert_eq!(m.index_of("exclude"), Some(1)); assert_eq!(m.index_of("exclude"), Some(1));
@ -55,12 +67,16 @@ fn index_flag() {
#[test] #[test]
fn index_flags() { fn index_flags() {
let m = App::new("ind") let m = App::new("ind")
.arg(Arg::with_name("exclude") .arg(
Arg::with_name("exclude")
.short('e') .short('e')
.multiple_occurrences(true)) .multiple_occurrences(true),
.arg(Arg::with_name("include") )
.arg(
Arg::with_name("include")
.short('i') .short('i')
.multiple_occurrences(true)) .multiple_occurrences(true),
)
.get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"]); .get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"]);
assert_eq!(m.index_of("exclude"), Some(1)); assert_eq!(m.index_of("exclude"), Some(1));
@ -70,90 +86,133 @@ fn index_flags() {
#[test] #[test]
fn indices_mult_flags() { fn indices_mult_flags() {
let m = App::new("ind") let m = App::new("ind")
.arg(Arg::with_name("exclude") .arg(
Arg::with_name("exclude")
.short('e') .short('e')
.multiple_occurrences(true)) .multiple_occurrences(true),
.arg(Arg::with_name("include") )
.arg(
Arg::with_name("include")
.short('i') .short('i')
.multiple_occurrences(true)) .multiple_occurrences(true),
)
.get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"]); .get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"]);
assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[1, 3, 4]); assert_eq!(
assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[2, 5]); m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[1, 3, 4]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[2, 5]
);
} }
#[test] #[test]
fn indices_mult_flags_combined() { fn indices_mult_flags_combined() {
let m = App::new("ind") let m = App::new("ind")
.arg(Arg::with_name("exclude") .arg(
Arg::with_name("exclude")
.short('e') .short('e')
.multiple_occurrences(true)) .multiple_occurrences(true),
.arg(Arg::with_name("include") )
.arg(
Arg::with_name("include")
.short('i') .short('i')
.multiple_occurrences(true)) .multiple_occurrences(true),
)
.get_matches_from(vec!["ind", "-eieei"]); .get_matches_from(vec!["ind", "-eieei"]);
assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[1, 3, 4]); assert_eq!(
assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[2, 5]); m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[1, 3, 4]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[2, 5]
);
} }
#[test] #[test]
fn indices_mult_flags_opt_combined() { fn indices_mult_flags_opt_combined() {
let m = App::new("ind") let m = App::new("ind")
.arg(Arg::with_name("exclude") .arg(
Arg::with_name("exclude")
.short('e') .short('e')
.multiple_occurrences(true)) .multiple_occurrences(true),
.arg(Arg::with_name("include") )
.arg(
Arg::with_name("include")
.short('i') .short('i')
.multiple_occurrences(true)) .multiple_occurrences(true),
.arg(Arg::with_name("option") )
.short('o') .arg(Arg::with_name("option").short('o').takes_value(true))
.takes_value(true))
.get_matches_from(vec!["ind", "-eieeio", "val"]); .get_matches_from(vec!["ind", "-eieeio", "val"]);
assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[1, 3, 4]); assert_eq!(
assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[2, 5]); m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[1, 3, 4]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[2, 5]
);
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[7]); assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[7]);
} }
#[test] #[test]
fn indices_mult_flags_opt_combined_eq() { fn indices_mult_flags_opt_combined_eq() {
let m = App::new("ind") let m = App::new("ind")
.arg(Arg::with_name("exclude") .arg(
Arg::with_name("exclude")
.short('e') .short('e')
.multiple_occurrences(true)) .multiple_occurrences(true),
.arg(Arg::with_name("include") )
.arg(
Arg::with_name("include")
.short('i') .short('i')
.multiple_occurrences(true)) .multiple_occurrences(true),
.arg(Arg::with_name("option") )
.short('o') .arg(Arg::with_name("option").short('o').takes_value(true))
.takes_value(true))
.get_matches_from(vec!["ind", "-eieeio=val"]); .get_matches_from(vec!["ind", "-eieeio=val"]);
assert_eq!(m.indices_of("exclude").unwrap().collect::<Vec<_>>(), &[1, 3, 4]); assert_eq!(
assert_eq!(m.indices_of("include").unwrap().collect::<Vec<_>>(), &[2, 5]); m.indices_of("exclude").unwrap().collect::<Vec<_>>(),
&[1, 3, 4]
);
assert_eq!(
m.indices_of("include").unwrap().collect::<Vec<_>>(),
&[2, 5]
);
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[7]); assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[7]);
} }
#[test] #[test]
fn indices_mult_opt_value_delim_eq() { fn indices_mult_opt_value_delim_eq() {
let m = App::new("myapp") let m = App::new("myapp")
.arg(Arg::with_name("option") .arg(
Arg::with_name("option")
.short('o') .short('o')
.takes_value(true) .takes_value(true)
.use_delimiter(true) .use_delimiter(true)
.multiple(true)) .multiple(true),
)
.get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 3, 4]); assert_eq!(
m.indices_of("option").unwrap().collect::<Vec<_>>(),
&[2, 3, 4]
);
} }
#[test] #[test]
fn indices_mult_opt_value_no_delim_eq() { fn indices_mult_opt_value_no_delim_eq() {
let m = App::new("myapp") let m = App::new("myapp")
.arg(Arg::with_name("option") .arg(
Arg::with_name("option")
.short('o') .short('o')
.takes_value(true) .takes_value(true)
.multiple(true)) .multiple(true),
)
.get_matches_from(vec!["myapp", "-o=val1,val2,val3"]); .get_matches_from(vec!["myapp", "-o=val1,val2,val3"]);
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]); assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2]);
} }
@ -161,13 +220,13 @@ fn indices_mult_opt_value_no_delim_eq() {
#[test] #[test]
fn indices_mult_opt_mult_flag() { fn indices_mult_opt_mult_flag() {
let m = App::new("myapp") let m = App::new("myapp")
.arg(Arg::with_name("option") .arg(
Arg::with_name("option")
.short('o') .short('o')
.takes_value(true) .takes_value(true)
.multiple_occurrences(true)) .multiple_occurrences(true),
.arg(Arg::with_name("flag") )
.short('f') .arg(Arg::with_name("flag").short('f').multiple_occurrences(true))
.multiple_occurrences(true))
.get_matches_from(vec!["myapp", "-o", "val1", "-f", "-o", "val2", "-f"]); .get_matches_from(vec!["myapp", "-o", "val1", "-f", "-o", "val2", "-f"]);
assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 5]); assert_eq!(m.indices_of("option").unwrap().collect::<Vec<_>>(), &[2, 5]);