mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
Tests on flags passing
This commit is contained in:
parent
f4e19a3193
commit
c501773ed3
6 changed files with 3154 additions and 61 deletions
|
@ -18,7 +18,7 @@ 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 mkeymap::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;
|
||||||
|
@ -639,7 +639,7 @@ impl<'a, 'b> App<'a, 'b> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let arg = a.into().help_heading(help_heading);
|
let arg = a.into().help_heading(help_heading);
|
||||||
self.args.push(arg);
|
self.args.make_entries(arg);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1508,7 +1508,7 @@ impl<'a, 'b> App<'a, 'b> {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
for a in self.args.values().filter(|a| a.is_set(ArgSettings::Global)) {
|
for a in self.args.values().filter(|a| a.is_set(ArgSettings::Global)) {
|
||||||
sc.args.push(a.clone());
|
sc.args.make_entries(a.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// @TODO @deadcode @perf @v3-alpha: Currently we're not propagating
|
// @TODO @deadcode @perf @v3-alpha: Currently we're not propagating
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// Std
|
// Std
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
|
|
|
@ -903,14 +903,14 @@ macro_rules! flags {
|
||||||
use mkeymap::KeyType::*;
|
use mkeymap::KeyType::*;
|
||||||
$app.args
|
$app.args
|
||||||
.$how()
|
.$how()
|
||||||
.filter(|(k, a)| !a.settings.is_set(::build::ArgSettings::TakesValue))
|
.filter(|(_, a)| !a.settings.is_set(::build::ArgSettings::TakesValue))
|
||||||
.filter(|(k, a)| match k {
|
.filter(|(k, _)| match k {
|
||||||
Long(_) => true,
|
Long(_) => true,
|
||||||
Short(_) => true,
|
Short(_) => true,
|
||||||
Position(_) => false,
|
Position(_) => false,
|
||||||
})
|
})
|
||||||
.filter(|(k, a)| !a.help_heading.is_some())
|
.filter(|(_, a)| !a.help_heading.is_some())
|
||||||
.map(|(k, v)| v)
|
.map(|(_, v)| v)
|
||||||
}};
|
}};
|
||||||
($app:expr) => {
|
($app:expr) => {
|
||||||
flags!($app, iter)
|
flags!($app, iter)
|
||||||
|
@ -929,14 +929,14 @@ macro_rules! opts {
|
||||||
use mkeymap::KeyType::*;
|
use mkeymap::KeyType::*;
|
||||||
$app.args
|
$app.args
|
||||||
.$how()
|
.$how()
|
||||||
.filter(|(k, a)| a.settings.is_set(::build::ArgSettings::TakesValue))
|
.filter(|(_, a)| a.settings.is_set(::build::ArgSettings::TakesValue))
|
||||||
.filter(|(k, a)| match k {
|
.filter(|(k, _)| match k {
|
||||||
Long(_) => true,
|
Long(_) => true,
|
||||||
Short(_) => true,
|
Short(_) => true,
|
||||||
Position(_) => false,
|
Position(_) => false,
|
||||||
})
|
})
|
||||||
.filter(|(k, a)| !a.help_heading.is_some())
|
.filter(|(_, a)| !a.help_heading.is_some())
|
||||||
.map(|(k, v)| v)
|
.map(|(_, v)| v)
|
||||||
}};
|
}};
|
||||||
($app:expr) => {
|
($app:expr) => {
|
||||||
opts!($app, iter)
|
opts!($app, iter)
|
||||||
|
|
|
@ -4,7 +4,6 @@ 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
|
||||||
|
|
||||||
|
@ -97,9 +96,9 @@ where
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool { self.keys.is_empty() && self.values.is_empty() }
|
pub fn is_empty(&self) -> bool { self.keys.is_empty() && self.values.is_empty() }
|
||||||
|
|
||||||
pub fn remove_by_name(&mut self, name: &str) -> Option<T> { unimplemented!() }
|
pub fn remove_by_name(&mut self, _name: &str) -> Option<T> { unimplemented!() }
|
||||||
|
|
||||||
pub fn remove(&mut self, key: KeyType) -> Option<T> { unimplemented!() }
|
pub fn remove(&mut self, _key: KeyType) -> Option<T> { unimplemented!() }
|
||||||
//TODO ::remove_many([KeyA, KeyB])
|
//TODO ::remove_many([KeyA, KeyB])
|
||||||
//? 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
|
||||||
|
@ -301,7 +300,6 @@ where
|
||||||
mod tests {
|
mod tests {
|
||||||
use self::KeyType::*;
|
use self::KeyType::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::ffi::OsStr;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_some_value() {
|
fn get_some_value() {
|
||||||
|
|
|
@ -19,9 +19,6 @@ use std::mem;
|
||||||
)]
|
)]
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
// Third party facade
|
|
||||||
use util::VecMap;
|
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
use build::app::Propagation;
|
use build::app::Propagation;
|
||||||
use build::AppSettings as AS;
|
use build::AppSettings as AS;
|
||||||
|
@ -60,9 +57,6 @@ where
|
||||||
pub app: &'c mut App<'a, 'b>,
|
pub app: &'c mut App<'a, 'b>,
|
||||||
pub required: ChildGraph<&'a str>,
|
pub required: ChildGraph<&'a str>,
|
||||||
pub overriden: Vec<&'a str>,
|
pub overriden: Vec<&'a str>,
|
||||||
//cache: Option<&'a str>,
|
|
||||||
num_opts: usize,
|
|
||||||
num_flags: usize,
|
|
||||||
seen: Vec<&'a str>,
|
seen: Vec<&'a str>,
|
||||||
cur_idx: Cell<usize>,
|
cur_idx: Cell<usize>,
|
||||||
}
|
}
|
||||||
|
@ -88,8 +82,6 @@ where
|
||||||
app: app,
|
app: app,
|
||||||
required: ChildGraph::from(reqs),
|
required: ChildGraph::from(reqs),
|
||||||
overriden: Vec::new(),
|
overriden: Vec::new(),
|
||||||
num_opts: 0,
|
|
||||||
num_flags: 0,
|
|
||||||
seen: Vec::new(),
|
seen: Vec::new(),
|
||||||
cur_idx: Cell::new(0),
|
cur_idx: Cell::new(0),
|
||||||
}
|
}
|
||||||
|
@ -157,14 +149,6 @@ where
|
||||||
// * a value terminator
|
// * a value terminator
|
||||||
// * ArgSettings::Last
|
// * ArgSettings::Last
|
||||||
// * The last arg is Required
|
// * The last arg is Required
|
||||||
let mut it = self.app.args.keys().filter(|x| {
|
|
||||||
if let KeyType::Position(_) = x {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//self.positionals.values().rev();
|
|
||||||
|
|
||||||
// We can't pass the closure (it.next()) to the macro directly because each call to
|
// We can't pass the closure (it.next()) to the macro directly because each call to
|
||||||
// find() (iterator, not macro) gets called repeatedly.
|
// find() (iterator, not macro) gets called repeatedly.
|
||||||
|
@ -173,8 +157,7 @@ where
|
||||||
.args
|
.args
|
||||||
.get(KeyType::Position(highest_idx))
|
.get(KeyType::Position(highest_idx))
|
||||||
.expect(INTERNAL_ERROR_MSG);
|
.expect(INTERNAL_ERROR_MSG);
|
||||||
//let second_to_last_name = it.next().expect(INTERNAL_ERROR_MSG);
|
|
||||||
//let last = find!(self.app, last_name).expect(INTERNAL_ERROR_MSG);
|
|
||||||
let second_to_last = self
|
let second_to_last = self
|
||||||
.app
|
.app
|
||||||
.args
|
.args
|
||||||
|
@ -306,6 +289,8 @@ where
|
||||||
// Does all the initializing and prepares the parser
|
// Does all the initializing and prepares the parser
|
||||||
pub(crate) fn _build(&mut self) {
|
pub(crate) fn _build(&mut self) {
|
||||||
debugln!("Parser::_build;");
|
debugln!("Parser::_build;");
|
||||||
|
|
||||||
|
//I wonder whether this part is even needed if we insert all Args using make_entries
|
||||||
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 {
|
||||||
|
@ -530,30 +515,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let low_index_mults = self.is_set(AS::LowIndexMultiplePositional)
|
let positional_count = self
|
||||||
&& pos_counter
|
|
||||||
== (
|
|
||||||
//TODO make a macro for that
|
|
||||||
self
|
|
||||||
.app
|
.app
|
||||||
.args
|
.args
|
||||||
.keys()
|
.keys()
|
||||||
.filter(|x| if let KeyType::Position(_) = x { true } else { false })
|
.filter(|x| if let KeyType::Position(_) = x { true } else { false })
|
||||||
.count() - 1);
|
.count();
|
||||||
let missing_pos = self.is_set(AS::AllowMissingPositional)
|
let is_second_to_last = positional_count > 1
|
||||||
&& (pos_counter
|
&& (pos_counter
|
||||||
== (self
|
== (positional_count - 1));
|
||||||
.app
|
|
||||||
.args
|
let low_index_mults = self.is_set(AS::LowIndexMultiplePositional)
|
||||||
.keys()
|
&& is_second_to_last;
|
||||||
.filter(|x| {
|
let missing_pos = self.is_set(AS::AllowMissingPositional)
|
||||||
if let KeyType::Position(_) = x {
|
&& is_second_to_last && !self.is_set(AS::TrailingValues);
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.count() - 1) && !self.is_set(AS::TrailingValues));
|
|
||||||
debugln!(
|
debugln!(
|
||||||
"Parser::get_matches_with: Positional counter...{}",
|
"Parser::get_matches_with: Positional counter...{}",
|
||||||
pos_counter
|
pos_counter
|
||||||
|
@ -825,7 +800,7 @@ where
|
||||||
}
|
}
|
||||||
sc
|
sc
|
||||||
};
|
};
|
||||||
let mut parser = Parser::new(&mut sc);
|
let parser = Parser::new(&mut sc);
|
||||||
if help_help {
|
if help_help {
|
||||||
let mut pb = Arg::with_name("subcommand")
|
let mut pb = Arg::with_name("subcommand")
|
||||||
.index(1)
|
.index(1)
|
||||||
|
@ -1106,8 +1081,15 @@ where
|
||||||
// Option: -o
|
// Option: -o
|
||||||
// Value: val
|
// Value: val
|
||||||
if let Some(opt) = self.app.args.get(KeyType::Short(c)) {
|
if let Some(opt) = self.app.args.get(KeyType::Short(c)) {
|
||||||
debugln!("Parser::parse_short_arg:iter:{}: Found valid opt", c);
|
debugln!("Parser::parse_short_arg:iter:{}: Found valid opt or flag", c);
|
||||||
self.app.settings.set(AS::ValidArgFound);
|
self.app.settings.set(AS::ValidArgFound);
|
||||||
|
|
||||||
|
if !opt.is_set(ArgSettings::TakesValue) {
|
||||||
|
self.check_for_help_and_version_char(c)?;
|
||||||
|
ret = self.parse_flag(opt, matcher)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for trailing concatenated value
|
// Check for trailing concatenated value
|
||||||
let p: Vec<_> = arg.splitn(2, c).collect();
|
let p: Vec<_> = arg.splitn(2, c).collect();
|
||||||
debugln!(
|
debugln!(
|
||||||
|
@ -1133,12 +1115,6 @@ where
|
||||||
let ret = self.parse_opt(val, opt, false, matcher)?;
|
let ret = self.parse_opt(val, opt, false, matcher)?;
|
||||||
|
|
||||||
return Ok(ret);
|
return Ok(ret);
|
||||||
} else if let Some(flag) = self.app.args.get(KeyType::Short(c)) {
|
|
||||||
debugln!("Parser::parse_short_arg:iter:{}: Found valid flag", c);
|
|
||||||
self.app.settings.set(AS::ValidArgFound);
|
|
||||||
// Only flags can be help or version
|
|
||||||
self.check_for_help_and_version_char(c)?;
|
|
||||||
ret = self.parse_flag(flag, matcher)?;
|
|
||||||
} else {
|
} else {
|
||||||
let arg = format!("-{}", c);
|
let arg = format!("-{}", c);
|
||||||
return Err(ClapError::unknown_argument(
|
return Err(ClapError::unknown_argument(
|
||||||
|
|
3120
tests.test
Normal file
3120
tests.test
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue