mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 22:32:33 +00:00
perf: refactor to remove unneeded vectors and allocations and checks for significant performance increases
Building an `App` struct with a fair number of args/flags/switches, etc. (used ripgrep as test case) went from taking ~21,000 ns to ~13,000ns.
This commit is contained in:
parent
b55cae5fdb
commit
0efa411963
14 changed files with 971 additions and 872 deletions
|
@ -9,11 +9,12 @@ mod test {
|
|||
|
||||
fn compare<S, S2>(l: S, r: S2) -> bool
|
||||
where S: AsRef<str>,
|
||||
S2: AsRef<str> {
|
||||
S2: AsRef<str>
|
||||
{
|
||||
let re = Regex::new("\x1b[^m]*m").unwrap();
|
||||
// Strip out any mismatching \r character on windows that might sneak in on either side
|
||||
let left = re.replace_all(&l.as_ref().trim().replace("\r", "")[..], "").into_owned();
|
||||
let right = re.replace_all(&r.as_ref().trim().replace("\r", "")[..], "").into_owned();
|
||||
let left = re.replace_all(&l.as_ref().trim().replace("\r", "")[..], "");
|
||||
let right = re.replace_all(&r.as_ref().trim().replace("\r", "")[..], "");
|
||||
let b = left == right;
|
||||
if !b {
|
||||
println!("");
|
||||
|
|
|
@ -19,11 +19,14 @@ macro_rules! remove_overriden {
|
|||
};
|
||||
($_self:ident, $name:expr) => {
|
||||
debugln!("remove_overriden!;");
|
||||
if let Some(ref o) = $_self.opts.iter().filter(|o| o.b.name == *$name).next() {
|
||||
if let Some(o) = $_self.opts.iter() .find(|o| o.b.name == *$name) {
|
||||
remove_overriden!(@arg $_self, o);
|
||||
} else if let Some(ref f) = $_self.flags.iter().filter(|f| f.b.name == *$name).next() {
|
||||
} else if let Some(f) = $_self.flags.iter() .find(|f| f.b.name == *$name) {
|
||||
remove_overriden!(@arg $_self, f);
|
||||
} else if let Some(p) = $_self.positionals.values().filter(|p| p.b.name == *$name).next() {
|
||||
} else {
|
||||
let p = $_self.positionals.values()
|
||||
.find(|p| p.b.name == *$name)
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
remove_overriden!(@arg $_self, p);
|
||||
}
|
||||
};
|
||||
|
@ -69,21 +72,20 @@ macro_rules! arg_post_processing {
|
|||
}
|
||||
}
|
||||
|
||||
$me.blacklist.extend(bl);
|
||||
$me.blacklist.extend_from_slice(bl);
|
||||
vec_remove_all!($me.overrides, bl.iter());
|
||||
vec_remove_all!($me.required, bl.iter());
|
||||
// vec_remove_all!($me.required, bl.iter());
|
||||
} else { sdebugln!("No"); }
|
||||
|
||||
// Add all required args which aren't already found in matcher to the master
|
||||
// list
|
||||
debug!("arg_post_processing!: Does '{}' have requirements...", $arg.to_string());
|
||||
if let Some(reqs) = $arg.requires() {
|
||||
for n in reqs.iter().filter(|&&(val, _)| val.is_none()).map(|&(_, name)| name) {
|
||||
if $matcher.contains(&n) {
|
||||
sdebugln!("\tYes '{}' but it's already met", n);
|
||||
continue;
|
||||
} else { sdebugln!("\tYes '{}'", n); }
|
||||
|
||||
for n in reqs.iter()
|
||||
.filter(|&&(val, _)| val.is_none())
|
||||
.filter(|&&(_, req)| !$matcher.contains(&req))
|
||||
.map(|&(_, name)| name) {
|
||||
|
||||
$me.required.push(n);
|
||||
}
|
||||
} else { sdebugln!("No"); }
|
||||
|
@ -96,9 +98,9 @@ macro_rules! _handle_group_reqs{
|
|||
($me:ident, $arg:ident) => ({
|
||||
use args::AnyArg;
|
||||
debugln!("_handle_group_reqs!;");
|
||||
for grp in $me.groups.values() {
|
||||
for grp in $me.groups.iter() {
|
||||
let found = if grp.args.contains(&$arg.name()) {
|
||||
vec_remove!($me.required, &$arg.name());
|
||||
// vec_remove!($me.required, &$arg.name());
|
||||
if let Some(ref reqs) = grp.requires {
|
||||
debugln!("_handle_group_reqs!: Adding {:?} to the required list", reqs);
|
||||
$me.required.extend(reqs);
|
||||
|
@ -126,18 +128,6 @@ macro_rules! _handle_group_reqs{
|
|||
})
|
||||
}
|
||||
|
||||
macro_rules! validate_multiples {
|
||||
($_self:ident, $a:ident, $m:ident) => {
|
||||
debugln!("validate_multiples!;");
|
||||
if $m.contains(&$a.b.name) && !$a.b.is_set(ArgSettings::Multiple) {
|
||||
// Not the first time, and we don't allow multiples
|
||||
return Err(Error::unexpected_multiple_usage($a,
|
||||
&*$_self.create_current_usage($m, None),
|
||||
$_self.color()))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! parse_positional {
|
||||
(
|
||||
$_self:ident,
|
||||
|
@ -147,12 +137,11 @@ macro_rules! parse_positional {
|
|||
$matcher:ident
|
||||
) => {
|
||||
debugln!("parse_positional!;");
|
||||
validate_multiples!($_self, $p, $matcher);
|
||||
|
||||
if !$_self.is_set(TrailingValues) &&
|
||||
($_self.is_set(TrailingVarArg) &&
|
||||
if !$_self.is_set(AS::TrailingValues) &&
|
||||
($_self.is_set(AS::TrailingVarArg) &&
|
||||
$pos_counter == $_self.positionals.len()) {
|
||||
$_self.settings.set(TrailingValues);
|
||||
$_self.settings.set(AS::TrailingValues);
|
||||
}
|
||||
let _ = try!($_self.add_val_to_arg($p, &$arg_os, $matcher));
|
||||
|
||||
|
@ -166,89 +155,3 @@ macro_rules! parse_positional {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! find_from {
|
||||
($_self:ident, $arg_name:expr, $from:ident, $matcher:expr) => {{
|
||||
let mut ret = None;
|
||||
for k in $matcher.arg_names() {
|
||||
if let Some(f) = find_by_name!($_self, &k, flags, iter) {
|
||||
if let Some(ref v) = f.$from() {
|
||||
if v.contains($arg_name) {
|
||||
ret = Some(f.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(o) = find_by_name!($_self, &k, opts, iter) {
|
||||
if let Some(ref v) = o.$from() {
|
||||
if v.contains(&$arg_name) {
|
||||
ret = Some(o.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(pos) = find_by_name!($_self, &k, positionals, values) {
|
||||
if let Some(ref v) = pos.$from() {
|
||||
if v.contains($arg_name) {
|
||||
ret = Some(pos.b.name.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! find_name_from {
|
||||
($_self:ident, $arg_name:expr, $from:ident, $matcher:expr) => {{
|
||||
let mut ret = None;
|
||||
for k in $matcher.arg_names() {
|
||||
if let Some(f) = find_by_name!($_self, &k, flags, iter) {
|
||||
if let Some(ref v) = f.$from() {
|
||||
if v.contains($arg_name) {
|
||||
ret = Some(f.b.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(o) = find_by_name!($_self, &k, opts, iter) {
|
||||
if let Some(ref v) = o.$from() {
|
||||
if v.contains(&$arg_name) {
|
||||
ret = Some(o.b.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(pos) = find_by_name!($_self, &k, positionals, values) {
|
||||
if let Some(ref v) = pos.$from() {
|
||||
if v.contains($arg_name) {
|
||||
ret = Some(pos.b.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}};
|
||||
}
|
||||
|
||||
// Finds an arg by name
|
||||
macro_rules! find_by_name {
|
||||
($_self:ident, $name:expr, $what:ident, $how:ident) => {
|
||||
$_self.$what.$how().find(|o| &o.b.name == $name)
|
||||
}
|
||||
}
|
||||
|
||||
// Finds an option including if it's aliasesed
|
||||
macro_rules! find_by_long {
|
||||
($_self:ident, $long:expr, $what:ident) => {
|
||||
$_self.$what
|
||||
.iter()
|
||||
.filter(|o| o.s.long.is_some())
|
||||
.find(|o| {
|
||||
&&o.s.long.unwrap() == &$long ||
|
||||
(o.s.aliases.is_some() &&
|
||||
o.s
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&(alias, _)| &&alias == &$long))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1335,7 +1335,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// .long("other")
|
||||
/// .takes_value(true))
|
||||
/// .get_matches_from_safe(vec![
|
||||
/// "prog", "--other", "not-special"
|
||||
/// "prog", "--other", "not-special"
|
||||
/// ]);
|
||||
///
|
||||
/// assert!(res.is_ok()); // We didn't use --other=special, so "cfg" wasn't required
|
||||
|
@ -1355,7 +1355,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// .long("other")
|
||||
/// .takes_value(true))
|
||||
/// .get_matches_from_safe(vec![
|
||||
/// "prog", "--other", "special"
|
||||
/// "prog", "--other", "special"
|
||||
/// ]);
|
||||
///
|
||||
/// assert!(res.is_err());
|
||||
|
@ -1721,7 +1721,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// .short("v"))
|
||||
/// .get_matches_from(vec![
|
||||
/// "prog", "-v", "-v", "-v" // note, -vvv would have same result
|
||||
/// ]);
|
||||
/// ]);
|
||||
///
|
||||
/// assert!(m.is_present("verbose"));
|
||||
/// assert_eq!(m.occurrences_of("verbose"), 3);
|
||||
|
@ -1852,7 +1852,7 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// [`number_of_values`]).
|
||||
///
|
||||
/// **NOTE:** This setting only applies to [options] and [positional arguments]
|
||||
///
|
||||
///
|
||||
/// **NOTE:** When the terminator is passed in on the command line, it is **not** stored as one
|
||||
/// of the vaues
|
||||
///
|
||||
|
@ -2965,12 +2965,10 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// ```
|
||||
/// [`Arg::takes_value(true)`]: ./struct.Arg.html#method.takes_value
|
||||
/// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
|
||||
pub fn default_value_if(self,
|
||||
arg: &'a str,
|
||||
val: Option<&'b str>,
|
||||
default: &'b str)
|
||||
-> Self {
|
||||
self.default_value_if_os(arg, val.map(str::as_bytes).map(OsStr::from_bytes), OsStr::from_bytes(default.as_bytes()))
|
||||
pub fn default_value_if(self, arg: &'a str, val: Option<&'b str>, default: &'b str) -> Self {
|
||||
self.default_value_if_os(arg,
|
||||
val.map(str::as_bytes).map(OsStr::from_bytes),
|
||||
OsStr::from_bytes(default.as_bytes()))
|
||||
}
|
||||
|
||||
/// Provides a conditional default value in the exact same manner as [`Arg::default_value_if`]
|
||||
|
@ -2978,10 +2976,10 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// [`Arg::default_value_if`]: ./struct.Arg.html#method.default_value_if
|
||||
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
|
||||
pub fn default_value_if_os(mut self,
|
||||
arg: &'a str,
|
||||
val: Option<&'b OsStr>,
|
||||
default: &'b OsStr)
|
||||
-> Self {
|
||||
arg: &'a str,
|
||||
val: Option<&'b OsStr>,
|
||||
default: &'b OsStr)
|
||||
-> Self {
|
||||
self.setb(ArgSettings::TakesValue);
|
||||
if let Some(ref mut vm) = self.v.default_vals_ifs {
|
||||
let l = vm.len();
|
||||
|
@ -3080,12 +3078,14 @@ impl<'a, 'b> Arg<'a, 'b> {
|
|||
/// [`Arg::default_value`]: ./struct.Arg.html#method.default_value
|
||||
pub fn default_value_ifs(mut self, ifs: &[(&'a str, Option<&'b str>, &'b str)]) -> Self {
|
||||
for &(arg, val, default) in ifs {
|
||||
self = self.default_value_if_os(arg, val.map(str::as_bytes).map(OsStr::from_bytes), OsStr::from_bytes(default.as_bytes()));
|
||||
self = self.default_value_if_os(arg,
|
||||
val.map(str::as_bytes).map(OsStr::from_bytes),
|
||||
OsStr::from_bytes(default.as_bytes()));
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides multiple conditional default values in the exact same manner as
|
||||
/// Provides multiple conditional default values in the exact same manner as
|
||||
/// [`Arg::default_value_ifs`] only using [`OsStr`]s instead.
|
||||
/// [`Arg::default_value_ifs`]: ./struct.Arg.html#method.default_value_ifs
|
||||
/// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
|
||||
|
|
|
@ -22,9 +22,7 @@ impl<'e> Default for Switched<'e> {
|
|||
}
|
||||
|
||||
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Switched<'e> {
|
||||
fn from(a: &'z Arg<'n, 'e>) -> Self {
|
||||
a.s.clone()
|
||||
}
|
||||
fn from(a: &'z Arg<'n, 'e>) -> Self { a.s.clone() }
|
||||
}
|
||||
|
||||
impl<'e> Clone for Switched<'e> {
|
||||
|
|
|
@ -40,7 +40,7 @@ impl<'a> ArgMatcher<'a> {
|
|||
gma.vals.insert(i, v.clone());
|
||||
}
|
||||
gma
|
||||
});
|
||||
});
|
||||
if sma.vals.is_empty() {
|
||||
for (i, v) in &vals {
|
||||
sma.vals.insert(i, v.clone());
|
||||
|
|
|
@ -125,21 +125,7 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
let mut p = self.p;
|
||||
for sc in path.split("__").skip(1) {
|
||||
debugln!("BashGen::option_details_for_path:iter: sc={}", sc);
|
||||
p = &p.subcommands
|
||||
.iter()
|
||||
.find(|s| {
|
||||
s.p.meta.name == sc ||
|
||||
(s.p.meta.aliases.is_some() &&
|
||||
s.p
|
||||
.meta
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&(n, _)| n == sc))
|
||||
})
|
||||
.unwrap()
|
||||
.p;
|
||||
p = &find_subcmd!(p, sc).unwrap().p;
|
||||
}
|
||||
let mut opts = String::new();
|
||||
for o in p.opts() {
|
||||
|
@ -214,28 +200,12 @@ complete -F _{name} -o bashdefault -o default {name}
|
|||
let mut p = self.p;
|
||||
for sc in path.split("__").skip(1) {
|
||||
debugln!("BashGen::all_options_for_path:iter: sc={}", sc);
|
||||
p = &p.subcommands
|
||||
.iter()
|
||||
.find(|s| {
|
||||
s.p.meta.name == sc ||
|
||||
(s.p.meta.aliases.is_some() &&
|
||||
s.p
|
||||
.meta
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&(n, _)| n == sc))
|
||||
})
|
||||
.unwrap()
|
||||
.p;
|
||||
p = &find_subcmd!(p, sc).unwrap().p;
|
||||
}
|
||||
let mut opts = p.short_list.iter().fold(String::new(), |acc, s| format!("{} -{}", acc, s));
|
||||
let mut opts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s));
|
||||
opts = format!("{} {}",
|
||||
opts,
|
||||
p.long_list
|
||||
.iter()
|
||||
.fold(String::new(), |acc, l| format!("{} --{}", acc, l)));
|
||||
longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l)));
|
||||
opts = format!("{} {}",
|
||||
opts,
|
||||
p.positionals
|
||||
|
|
|
@ -19,10 +19,7 @@ impl<'a, 'b> PowerShellGen<'a, 'b> {
|
|||
|
||||
let (subcommands_detection_cases, subcommands_cases) = generate_inner(self.p, "");
|
||||
|
||||
let mut bin_names = vec![
|
||||
bin_name.to_string(),
|
||||
format!("./{0}", bin_name),
|
||||
];
|
||||
let mut bin_names = vec![bin_name.to_string(), format!("./{0}", bin_name)];
|
||||
if cfg!(windows) {
|
||||
bin_names.push(format!("{0}.exe", bin_name));
|
||||
bin_names.push(format!(r".\{0}", bin_name));
|
||||
|
@ -92,10 +89,10 @@ fn generate_inner<'a, 'b>(p: &Parser<'a, 'b>, previous_command_name: &str) -> (S
|
|||
for subcommand in &p.subcommands {
|
||||
completions.push_str(&format!("'{}', ", &subcommand.p.meta.name));
|
||||
}
|
||||
for short in &p.short_list {
|
||||
for short in shorts!(p) {
|
||||
completions.push_str(&format!("'-{}', ", short));
|
||||
}
|
||||
for long in &p.long_list {
|
||||
for long in longs!(p) {
|
||||
completions.push_str(&format!("'--{}', ", long));
|
||||
}
|
||||
|
||||
|
|
252
src/macros.rs
252
src/macros.rs
|
@ -498,11 +498,11 @@ macro_rules! crate_name {
|
|||
/// Provided separator is for the [`crate_authors!`](macro.crate_authors.html) macro,
|
||||
/// refer to the documentation therefor.
|
||||
///
|
||||
/// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically,
|
||||
/// **NOTE:** Changing the values in your `Cargo.toml` does not trigger a re-build automatically,
|
||||
/// and therefore won't change the generated output until you recompile.
|
||||
///
|
||||
/// **Pro Tip:** In some cases you can "trick" the compiler into triggering a rebuild when your
|
||||
/// `Cargo.toml` is changed by including this in your `src/main.rs` file
|
||||
/// `Cargo.toml` is changed by including this in your `src/main.rs` file
|
||||
/// `include_str!("../Cargo.toml");`
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -542,47 +542,47 @@ macro_rules! app_from_crate {
|
|||
/// # #[macro_use]
|
||||
/// # extern crate clap;
|
||||
/// # fn main() {
|
||||
/// let matches = clap_app!(myapp =>
|
||||
/// (version: "1.0")
|
||||
/// (author: "Kevin K. <kbknapp@gmail.com>")
|
||||
/// (about: "Does awesome things")
|
||||
/// let matches = clap_app!(myapp =>
|
||||
/// (version: "1.0")
|
||||
/// (author: "Kevin K. <kbknapp@gmail.com>")
|
||||
/// (about: "Does awesome things")
|
||||
/// (@arg CONFIG: -c --config +takes_value "Sets a custom config file")
|
||||
/// (@arg INPUT: +required "Sets the input file to use")
|
||||
/// (@arg debug: -d ... "Sets the level of debugging information")
|
||||
/// (@subcommand test =>
|
||||
/// (about: "controls testing features")
|
||||
/// (version: "1.3")
|
||||
/// (author: "Someone E. <someone_else@other.com>")
|
||||
/// (@arg INPUT: +required "Sets the input file to use")
|
||||
/// (@arg debug: -d ... "Sets the level of debugging information")
|
||||
/// (@subcommand test =>
|
||||
/// (about: "controls testing features")
|
||||
/// (version: "1.3")
|
||||
/// (author: "Someone E. <someone_else@other.com>")
|
||||
/// (@arg verbose: -v --verbose "Print test information verbosely")
|
||||
/// )
|
||||
/// )
|
||||
/// );
|
||||
/// # }
|
||||
/// # }
|
||||
/// ```
|
||||
/// # Shorthand Syntax for Args
|
||||
///
|
||||
///
|
||||
/// * A single hyphen followed by a character (such as `-c`) sets the [`Arg::short`]
|
||||
/// * A double hyphen followed by a character or word (such as `--config`) sets [`Arg::long`]
|
||||
/// * Three dots (`...`) sets [`Arg::multiple(true)`]
|
||||
/// * Angled brackets after either a short or long will set [`Arg::value_name`] and
|
||||
/// `Arg::required(true)` such as `--config <FILE>` = `Arg::value_name("FILE")` and
|
||||
/// * Angled brackets after either a short or long will set [`Arg::value_name`] and
|
||||
/// `Arg::required(true)` such as `--config <FILE>` = `Arg::value_name("FILE")` and
|
||||
/// `Arg::required(true)
|
||||
/// * Square brackets after either a short or long will set [`Arg::value_name`] and
|
||||
/// `Arg::required(false)` such as `--config [FILE]` = `Arg::value_name("FILE")` and
|
||||
/// * Square brackets after either a short or long will set [`Arg::value_name`] and
|
||||
/// `Arg::required(false)` such as `--config [FILE]` = `Arg::value_name("FILE")` and
|
||||
/// `Arg::required(false)
|
||||
/// * There are short hand syntaxes for Arg methods that accept booleans
|
||||
/// * There are short hand syntaxes for Arg methods that accept booleans
|
||||
/// * A plus sign will set that method to `true` such as `+required` = `Arg::required(true)`
|
||||
/// * An exclamation will set that method to `false` such as `!required` = `Arg::required(false)`
|
||||
/// * A `#{min, max}` will set [`Arg::min_values(min)`] and [`Arg::max_values(max)`]
|
||||
/// * An asterisk (`*`) will set `Arg::required(true)`
|
||||
/// * Curly brackets around a `fn` will set [`Arg::validator`] as in `{fn}` = `Arg::validator(fn)`
|
||||
/// * An Arg method that accepts a string followed by square brackets will set that method such as
|
||||
/// `conflicts_with[FOO]` will set `Arg::conflicts_with("FOO")` (note the lack of quotes around
|
||||
/// `FOO` in the macro)
|
||||
/// * An Arg method that takes a string and can be set multiple times (such as
|
||||
/// [`Arg::conflicts_with`]) followed by square brackets and a list of values separated by spaces
|
||||
/// will set that method such as `conflicts_with[FOO BAR BAZ]` will set
|
||||
/// * An Arg method that accepts a string followed by square brackets will set that method such as
|
||||
/// `conflicts_with[FOO]` will set `Arg::conflicts_with("FOO")` (note the lack of quotes around
|
||||
/// `FOO` in the macro)
|
||||
/// * An Arg method that takes a string and can be set multiple times (such as
|
||||
/// [`Arg::conflicts_with`]) followed by square brackets and a list of values separated by spaces
|
||||
/// will set that method such as `conflicts_with[FOO BAR BAZ]` will set
|
||||
/// `Arg::conflicts_with("FOO")`, `Arg::conflicts_with("BAR")`, and `Arg::conflicts_with("BAZ")`
|
||||
/// (note the lack of quotes around the values in the macro)
|
||||
/// (note the lack of quotes around the values in the macro)
|
||||
///
|
||||
/// [`Arg::short`]: ./struct.Arg.html#method.short
|
||||
/// [`Arg::long`]: ./struct.Arg.html#method.long
|
||||
|
@ -846,3 +846,201 @@ macro_rules! vec_remove_all {
|
|||
}
|
||||
};
|
||||
}
|
||||
macro_rules! find_from {
|
||||
($_self:ident, $arg_name:expr, $from:ident, $matcher:expr) => {{
|
||||
let mut ret = None;
|
||||
for k in $matcher.arg_names() {
|
||||
if let Some(f) = find_by_name!($_self, &k, flags, iter) {
|
||||
if let Some(ref v) = f.$from() {
|
||||
if v.contains($arg_name) {
|
||||
ret = Some(f.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(o) = find_by_name!($_self, &k, opts, iter) {
|
||||
if let Some(ref v) = o.$from() {
|
||||
if v.contains(&$arg_name) {
|
||||
ret = Some(o.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(pos) = find_by_name!($_self, &k, positionals, values) {
|
||||
if let Some(ref v) = pos.$from() {
|
||||
if v.contains($arg_name) {
|
||||
ret = Some(pos.b.name.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! find_name_from {
|
||||
($_self:ident, $arg_name:expr, $from:ident, $matcher:expr) => {{
|
||||
let mut ret = None;
|
||||
for k in $matcher.arg_names() {
|
||||
if let Some(f) = find_by_name!($_self, &k, flags, iter) {
|
||||
if let Some(ref v) = f.$from() {
|
||||
if v.contains($arg_name) {
|
||||
ret = Some(f.b.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(o) = find_by_name!($_self, &k, opts, iter) {
|
||||
if let Some(ref v) = o.$from() {
|
||||
if v.contains(&$arg_name) {
|
||||
ret = Some(o.b.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(pos) = find_by_name!($_self, &k, positionals, values) {
|
||||
if let Some(ref v) = pos.$from() {
|
||||
if v.contains($arg_name) {
|
||||
ret = Some(pos.b.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret
|
||||
}};
|
||||
}
|
||||
|
||||
// Finds an arg by name
|
||||
macro_rules! find_by_name {
|
||||
($_self:ident, $name:expr, $what:ident, $how:ident) => {
|
||||
$_self.$what.$how().find(|o| &o.b.name == $name)
|
||||
}
|
||||
}
|
||||
|
||||
// Finds an option including if it's aliasesed
|
||||
macro_rules! find_opt_by_long {
|
||||
(@os $_self:ident, $long:expr) => {{
|
||||
_find_by_long!($_self, $long, opts)
|
||||
}};
|
||||
($_self:ident, $long:expr) => {{
|
||||
_find_by_long!($_self, $long, opts)
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! find_flag_by_long {
|
||||
(@os $_self:ident, $long:expr) => {{
|
||||
_find_by_long!($_self, $long, flags)
|
||||
}};
|
||||
($_self:ident, $long:expr) => {{
|
||||
_find_by_long!($_self, $long, flags)
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! find_any_by_long {
|
||||
($_self:ident, $long:expr, $what:ident) => {
|
||||
_find_flag_by_long!($_self, $long).or(_find_opt_by_long!($_self, $long))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! _find_by_long {
|
||||
($_self:ident, $long:expr, $what:ident) => {{
|
||||
$_self.$what
|
||||
.iter()
|
||||
.filter(|a| a.s.long.is_some())
|
||||
.find(|a| {
|
||||
&&a.s.long.unwrap() == &$long ||
|
||||
(a.s.aliases.is_some() &&
|
||||
a.s
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&(alias, _)| &&alias == &$long))
|
||||
})
|
||||
}}
|
||||
}
|
||||
|
||||
// Finds an option
|
||||
macro_rules! find_opt_by_short {
|
||||
($_self:ident, $short:expr) => {{
|
||||
_find_by_short!($_self, $short, opts)
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! find_flag_by_short {
|
||||
($_self:ident, $short:expr) => {{
|
||||
_find_by_short!($_self, $short, flags)
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! find_any_by_short {
|
||||
($_self:ident, $short:expr, $what:ident) => {
|
||||
_find_flag_by_short!($_self, $short).or(_find_opt_by_short!($_self, $short))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! _find_by_short {
|
||||
($_self:ident, $short:expr, $what:ident) => {{
|
||||
$_self.$what
|
||||
.iter()
|
||||
.filter(|a| a.s.short.is_some())
|
||||
.find(|a| a.s.short.unwrap() == $short)
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! find_subcmd {
|
||||
($_self:expr, $sc:expr) => {{
|
||||
$_self.subcommands
|
||||
.iter()
|
||||
.find(|s| {
|
||||
s.p.meta.name == $sc ||
|
||||
(s.p.meta.aliases.is_some() &&
|
||||
s.p
|
||||
.meta
|
||||
.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&(n, _)| n == $sc))
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! shorts {
|
||||
($_self:ident) => {{
|
||||
_shorts_longs!($_self, short)
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
macro_rules! longs {
|
||||
($_self:ident) => {{
|
||||
_shorts_longs!($_self, long)
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! _shorts_longs {
|
||||
($_self:ident, $what:ident) => {{
|
||||
$_self.flags
|
||||
.iter()
|
||||
.filter(|f| f.s.$what.is_some())
|
||||
.map(|f| f.s.$what.as_ref().unwrap())
|
||||
.chain($_self.opts.iter()
|
||||
.filter(|o| o.s.$what.is_some())
|
||||
.map(|o| o.s.$what.as_ref().unwrap()))
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! arg_names {
|
||||
($_self:ident) => {{
|
||||
_names!($_self)
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! _names {
|
||||
($_self:ident) => {{
|
||||
$_self.flags
|
||||
.iter()
|
||||
.map(|f| &*f.b.name)
|
||||
.chain($_self.opts.iter()
|
||||
.map(|o| &*o.b.name)
|
||||
.chain($_self.positionals.values()
|
||||
.map(|p| &*p.b.name)))
|
||||
}};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
extern crate regex;
|
||||
extern crate clap;
|
||||
|
||||
use clap::{App, Arg, SubCommand, Shell};
|
||||
use regex::Regex;
|
||||
|
||||
extern crate regex;
|
||||
extern crate clap;
|
||||
|
||||
use clap::{App, Arg, SubCommand, Shell};
|
||||
use regex::Regex;
|
||||
|
||||
static BASH: &'static str = r#"_myapp() {
|
||||
local i cur prev opts cmds
|
||||
COMPREPLY=()
|
||||
|
@ -63,7 +63,7 @@ static BASH: &'static str = r#"_myapp() {
|
|||
return 0
|
||||
;;
|
||||
myapp__test)
|
||||
opts=" -h -V --case --help --version "
|
||||
opts=" -h -V --help --version --case "
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
|
@ -85,8 +85,8 @@ static BASH: &'static str = r#"_myapp() {
|
|||
}
|
||||
|
||||
complete -F _myapp -o bashdefault -o default myapp
|
||||
"#;
|
||||
|
||||
"#;
|
||||
|
||||
static ZSH: &'static str = r#"#compdef myapp
|
||||
|
||||
_myapp() {
|
||||
|
@ -152,8 +152,8 @@ _myapp__test_commands() {
|
|||
_describe -t commands 'myapp test commands' commands "$@"
|
||||
}
|
||||
|
||||
_myapp "$@""#;
|
||||
|
||||
_myapp "$@""#;
|
||||
|
||||
static FISH: &'static str = r#"function __fish_using_command
|
||||
set cmd (commandline -opc)
|
||||
if [ (count $cmd) -eq (count $argv) ]
|
||||
|
@ -176,9 +176,9 @@ complete -c myapp -n "__fish_using_command myapp test" -s h -l help -d "Prints h
|
|||
complete -c myapp -n "__fish_using_command myapp test" -s V -l version -d "Prints version information"
|
||||
complete -c myapp -n "__fish_using_command myapp help" -s h -l help -d "Prints help information"
|
||||
complete -c myapp -n "__fish_using_command myapp help" -s V -l version -d "Prints version information"
|
||||
"#;
|
||||
|
||||
#[cfg(not(target_os="windows"))]
|
||||
"#;
|
||||
|
||||
#[cfg(not(target_os="windows"))]
|
||||
static POWERSHELL: &'static str = r#"
|
||||
@('myapp', './myapp') | %{
|
||||
Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
|
||||
|
@ -227,9 +227,9 @@ static POWERSHELL: &'static str = r#"
|
|||
%{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
"#;
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
static POWERSHELL: &'static str = r#"
|
||||
@('myapp', './myapp', 'myapp.exe', '.\myapp', '.\myapp.exe', './myapp.exe') | %{
|
||||
Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
|
||||
|
@ -267,9 +267,9 @@ static POWERSHELL: &'static str = r#"
|
|||
%{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
#[cfg(not(target_os="windows"))]
|
||||
"#;
|
||||
|
||||
#[cfg(not(target_os="windows"))]
|
||||
static POWERSHELL_WUS: &'static str = r#"
|
||||
@('my_app', './my_app') | %{
|
||||
Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
|
||||
|
@ -327,9 +327,9 @@ static POWERSHELL_WUS: &'static str = r#"
|
|||
%{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
"#;
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
static POWERSHELL_WUS: &'static str = r#"
|
||||
@('my_app', './my_app', 'my_app.exe', '.\my_app', '.\my_app.exe', './my_app.exe') | %{
|
||||
Register-ArgumentCompleter -Native -CommandName $_ -ScriptBlock {
|
||||
|
@ -374,8 +374,8 @@ static POWERSHELL_WUS: &'static str = r#"
|
|||
%{ New-Object System.Management.Automation.CompletionResult $_, $_, 'ParameterValue', $_ }
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
"#;
|
||||
|
||||
static ZSH_WUS: &'static str = r#"#compdef my_app
|
||||
|
||||
_my_app() {
|
||||
|
@ -458,8 +458,8 @@ _my_app__test_commands() {
|
|||
_describe -t commands 'my_app test commands' commands "$@"
|
||||
}
|
||||
|
||||
_my_app "$@""#;
|
||||
|
||||
_my_app "$@""#;
|
||||
|
||||
static FISH_WUS: &'static str = r#"function __fish_using_command
|
||||
set cmd (commandline -opc)
|
||||
if [ (count $cmd) -eq (count $argv) ]
|
||||
|
@ -486,8 +486,8 @@ complete -c my_app -n "__fish_using_command my_app some_cmd" -s h -l help -d "Pr
|
|||
complete -c my_app -n "__fish_using_command my_app some_cmd" -s V -l version -d "Prints version information"
|
||||
complete -c my_app -n "__fish_using_command my_app help" -s h -l help -d "Prints help information"
|
||||
complete -c my_app -n "__fish_using_command my_app help" -s V -l version -d "Prints version information"
|
||||
"#;
|
||||
|
||||
"#;
|
||||
|
||||
static BASH_WUS: &'static str = r#"_my_app() {
|
||||
local i cur prev opts cmds
|
||||
COMPREPLY=()
|
||||
|
@ -550,7 +550,7 @@ static BASH_WUS: &'static str = r#"_my_app() {
|
|||
return 0
|
||||
;;
|
||||
my_app__some_cmd)
|
||||
opts=" -h -V --config --help --version "
|
||||
opts=" -h -V --help --version --config "
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
|
@ -569,7 +569,7 @@ static BASH_WUS: &'static str = r#"_my_app() {
|
|||
return 0
|
||||
;;
|
||||
my_app__test)
|
||||
opts=" -h -V --case --help --version "
|
||||
opts=" -h -V --help --version --case "
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
|
@ -591,129 +591,125 @@ static BASH_WUS: &'static str = r#"_my_app() {
|
|||
}
|
||||
|
||||
complete -F _my_app -o bashdefault -o default my_app
|
||||
"#;
|
||||
|
||||
fn compare(left: &str, right: &str) -> bool {
|
||||
let b = left == right;
|
||||
if !b {
|
||||
let re = Regex::new(" ").unwrap();
|
||||
println!("");
|
||||
println!("--> left");
|
||||
// println!("{}", left);
|
||||
println!("{}", re.replace_all(left, "\u{2022}"));
|
||||
println!("--> right");
|
||||
println!("{}", re.replace_all(right, "\u{2022}"));
|
||||
// println!("{}", right);
|
||||
println!("--")
|
||||
}
|
||||
b
|
||||
}
|
||||
|
||||
fn build_app() -> App<'static, 'static> {
|
||||
build_app_with_name("myapp")
|
||||
}
|
||||
|
||||
fn build_app_with_name(s: &'static str) -> App<'static, 'static> {
|
||||
App::new(s)
|
||||
.about("Tests completions")
|
||||
.arg(Arg::with_name("file")
|
||||
.help("some input file"))
|
||||
.subcommand(SubCommand::with_name("test")
|
||||
.about("tests things")
|
||||
.arg(Arg::with_name("case")
|
||||
.long("case")
|
||||
.takes_value(true)
|
||||
.help("the case to test")))
|
||||
}
|
||||
|
||||
fn build_app_with_underscore() -> App<'static, 'static> {
|
||||
build_app_with_name("my_app")
|
||||
.subcommand(SubCommand::with_name("some_cmd")
|
||||
.about("tests other things")
|
||||
.arg(Arg::with_name("config")
|
||||
.long("--config")
|
||||
.takes_value(true)
|
||||
.help("the other case to test")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bash() {
|
||||
let mut app = build_app();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("myapp", Shell::Bash, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, BASH));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zsh() {
|
||||
let mut app = build_app();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("myapp", Shell::Zsh, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, ZSH));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish() {
|
||||
let mut app = build_app();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("myapp", Shell::Fish, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, FISH));
|
||||
}
|
||||
|
||||
// Disabled until I figure out this windows line ending and AppVeyor issues
|
||||
//#[test]
|
||||
fn powershell() {
|
||||
let mut app = build_app();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("myapp", Shell::PowerShell, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, POWERSHELL));
|
||||
}
|
||||
|
||||
// Disabled until I figure out this windows line ending and AppVeyor issues
|
||||
//#[test]
|
||||
fn powershell_with_underscore() {
|
||||
let mut app = build_app_with_underscore();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("my_app", Shell::PowerShell, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, POWERSHELL_WUS));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bash_with_underscore() {
|
||||
let mut app = build_app_with_underscore();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("my_app", Shell::Bash, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, BASH_WUS));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish_with_underscore() {
|
||||
let mut app = build_app_with_underscore();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("my_app", Shell::Fish, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, FISH_WUS));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zsh_with_underscore() {
|
||||
let mut app = build_app_with_underscore();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("my_app", Shell::Zsh, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, ZSH_WUS));
|
||||
}
|
||||
"#;
|
||||
|
||||
fn compare(left: &str, right: &str) -> bool {
|
||||
let b = left == right;
|
||||
if !b {
|
||||
let re = Regex::new(" ").unwrap();
|
||||
println!("");
|
||||
println!("--> left");
|
||||
// println!("{}", left);
|
||||
println!("{}", re.replace_all(left, "\u{2022}"));
|
||||
println!("--> right");
|
||||
println!("{}", re.replace_all(right, "\u{2022}"));
|
||||
// println!("{}", right);
|
||||
println!("--")
|
||||
}
|
||||
b
|
||||
}
|
||||
|
||||
fn build_app() -> App<'static, 'static> { build_app_with_name("myapp") }
|
||||
|
||||
fn build_app_with_name(s: &'static str) -> App<'static, 'static> {
|
||||
App::new(s)
|
||||
.about("Tests completions")
|
||||
.arg(Arg::with_name("file").help("some input file"))
|
||||
.subcommand(SubCommand::with_name("test")
|
||||
.about("tests things")
|
||||
.arg(Arg::with_name("case")
|
||||
.long("case")
|
||||
.takes_value(true)
|
||||
.help("the case to test")))
|
||||
}
|
||||
|
||||
fn build_app_with_underscore() -> App<'static, 'static> {
|
||||
build_app_with_name("my_app").subcommand(SubCommand::with_name("some_cmd")
|
||||
.about("tests other things")
|
||||
.arg(Arg::with_name("config")
|
||||
.long("--config")
|
||||
.takes_value(true)
|
||||
.help("the other case to test")))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bash() {
|
||||
let mut app = build_app();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("myapp", Shell::Bash, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, BASH));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zsh() {
|
||||
let mut app = build_app();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("myapp", Shell::Zsh, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, ZSH));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish() {
|
||||
let mut app = build_app();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("myapp", Shell::Fish, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, FISH));
|
||||
}
|
||||
|
||||
// Disabled until I figure out this windows line ending and AppVeyor issues
|
||||
//#[test]
|
||||
// fn powershell() {
|
||||
// let mut app = build_app();
|
||||
// let mut buf = vec![];
|
||||
// app.gen_completions_to("myapp", Shell::PowerShell, &mut buf);
|
||||
// let string = String::from_utf8(buf).unwrap();
|
||||
//
|
||||
// assert!(compare(&*string, POWERSHELL));
|
||||
// }
|
||||
|
||||
// Disabled until I figure out this windows line ending and AppVeyor issues
|
||||
//#[test]
|
||||
// fn powershell_with_underscore() {
|
||||
// let mut app = build_app_with_underscore();
|
||||
// let mut buf = vec![];
|
||||
// app.gen_completions_to("my_app", Shell::PowerShell, &mut buf);
|
||||
// let string = String::from_utf8(buf).unwrap();
|
||||
//
|
||||
// assert!(compare(&*string, POWERSHELL_WUS));
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn bash_with_underscore() {
|
||||
let mut app = build_app_with_underscore();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("my_app", Shell::Bash, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, BASH_WUS));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fish_with_underscore() {
|
||||
let mut app = build_app_with_underscore();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("my_app", Shell::Fish, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, FISH_WUS));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zsh_with_underscore() {
|
||||
let mut app = build_app_with_underscore();
|
||||
let mut buf = vec![];
|
||||
app.gen_completions_to("my_app", Shell::Zsh, &mut buf);
|
||||
let string = String::from_utf8(buf).unwrap();
|
||||
|
||||
assert!(compare(&*string, ZSH_WUS));
|
||||
}
|
||||
|
|
117
tests/help.rs
117
tests/help.rs
|
@ -278,8 +278,7 @@ fn help_subcommand() {
|
|||
|
||||
#[test]
|
||||
fn subcommand_short_help() {
|
||||
let m = test::complex_app()
|
||||
.get_matches_from_safe(vec!["clap-test", "subcmd", "-h"]);
|
||||
let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "subcmd", "-h"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
|
||||
|
@ -287,8 +286,7 @@ fn subcommand_short_help() {
|
|||
|
||||
#[test]
|
||||
fn subcommand_long_help() {
|
||||
let m = test::complex_app()
|
||||
.get_matches_from_safe(vec!["clap-test", "subcmd", "--help"]);
|
||||
let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "subcmd", "--help"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
|
||||
|
@ -296,8 +294,7 @@ fn subcommand_long_help() {
|
|||
|
||||
#[test]
|
||||
fn subcommand_help_rev() {
|
||||
let m = test::complex_app()
|
||||
.get_matches_from_safe(vec!["clap-test", "help", "subcmd"]);
|
||||
let m = test::complex_app().get_matches_from_safe(vec!["clap-test", "help", "subcmd"]);
|
||||
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind, ErrorKind::HelpDisplayed);
|
||||
|
@ -321,12 +318,11 @@ fn after_and_before_help_output() {
|
|||
#[test]
|
||||
fn multi_level_sc_help() {
|
||||
let app = App::new("ctest")
|
||||
.subcommand(SubCommand::with_name("subcmd")
|
||||
.subcommand(SubCommand::with_name("multi")
|
||||
.about("tests subcommands")
|
||||
.author("Kevin K. <kbknapp@gmail.com>")
|
||||
.version("0.1")
|
||||
.args_from_usage("
|
||||
.subcommand(SubCommand::with_name("subcmd").subcommand(SubCommand::with_name("multi")
|
||||
.about("tests subcommands")
|
||||
.author("Kevin K. <kbknapp@gmail.com>")
|
||||
.version("0.1")
|
||||
.args_from_usage("
|
||||
-f, --flag 'tests flags'
|
||||
-o, --option [scoption]... 'tests options'
|
||||
")));
|
||||
|
@ -354,16 +350,16 @@ fn issue_626_unicode_cutoff() {
|
|||
.version("0.1")
|
||||
.set_term_width(70)
|
||||
.arg(Arg::with_name("cafe")
|
||||
.short("c")
|
||||
.long("cafe")
|
||||
.value_name("FILE")
|
||||
.help("A coffeehouse, coffee shop, or café is an establishment \
|
||||
.short("c")
|
||||
.long("cafe")
|
||||
.value_name("FILE")
|
||||
.help("A coffeehouse, coffee shop, or café is an establishment \
|
||||
which primarily serves hot coffee, related coffee beverages \
|
||||
(e.g., café latte, cappuccino, espresso), tea, and other hot \
|
||||
beverages. Some coffeehouses also serve cold beverages such as \
|
||||
iced coffee and iced tea. Many cafés also serve some type of \
|
||||
food, such as light snacks, muffins, or pastries.")
|
||||
.takes_value(true));
|
||||
.takes_value(true));
|
||||
assert!(test::compare_output(app, "ctest --help", ISSUE_626_CUTOFF, false));
|
||||
}
|
||||
|
||||
|
@ -372,20 +368,20 @@ fn hide_possible_vals() {
|
|||
let app = App::new("ctest")
|
||||
.version("0.1")
|
||||
.arg(Arg::with_name("pos")
|
||||
.short("p")
|
||||
.long("pos")
|
||||
.value_name("VAL")
|
||||
.possible_values(&["fast", "slow"])
|
||||
.help("Some vals")
|
||||
.takes_value(true))
|
||||
.short("p")
|
||||
.long("pos")
|
||||
.value_name("VAL")
|
||||
.possible_values(&["fast", "slow"])
|
||||
.help("Some vals")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("cafe")
|
||||
.short("c")
|
||||
.long("cafe")
|
||||
.value_name("FILE")
|
||||
.hide_possible_values(true)
|
||||
.possible_values(&["fast", "slow"])
|
||||
.help("A coffeehouse, coffee shop, or café.")
|
||||
.takes_value(true));
|
||||
.short("c")
|
||||
.long("cafe")
|
||||
.value_name("FILE")
|
||||
.hide_possible_values(true)
|
||||
.possible_values(&["fast", "slow"])
|
||||
.help("A coffeehouse, coffee shop, or café.")
|
||||
.takes_value(true));
|
||||
assert!(test::compare_output(app, "ctest --help", HIDE_POS_VALS, false));
|
||||
}
|
||||
|
||||
|
@ -441,9 +437,9 @@ fn old_newline_chars() {
|
|||
|
||||
#[test]
|
||||
fn issue_688_hidden_pos_vals() {
|
||||
let filter_values = ["Nearest", "Linear", "Cubic", "Gaussian", "Lanczos3"];
|
||||
let filter_values = ["Nearest", "Linear", "Cubic", "Gaussian", "Lanczos3"];
|
||||
|
||||
let app1 = App::new("ctest")
|
||||
let app1 = App::new("ctest")
|
||||
.version("0.1")
|
||||
.set_term_width(120)
|
||||
.setting(AppSettings::HidePossibleValuesInHelp)
|
||||
|
@ -455,7 +451,7 @@ fn issue_688_hidden_pos_vals() {
|
|||
.takes_value(true));
|
||||
assert!(test::compare_output(app1, "ctest --help", ISSUE_688, false));
|
||||
|
||||
let app2 = App::new("ctest")
|
||||
let app2 = App::new("ctest")
|
||||
.version("0.1")
|
||||
.set_term_width(120)
|
||||
.arg(Arg::with_name("filter")
|
||||
|
@ -466,7 +462,7 @@ fn issue_688_hidden_pos_vals() {
|
|||
.takes_value(true));
|
||||
assert!(test::compare_output(app2, "ctest --help", ISSUE_688, false));
|
||||
|
||||
let app3 = App::new("ctest")
|
||||
let app3 = App::new("ctest")
|
||||
.version("0.1")
|
||||
.set_term_width(120)
|
||||
.arg(Arg::with_name("filter")
|
||||
|
@ -483,27 +479,26 @@ fn issue_702_multiple_values() {
|
|||
.version("1.0")
|
||||
.author("foo")
|
||||
.about("bar")
|
||||
.arg(Arg::with_name("arg1")
|
||||
.help("some option"))
|
||||
.arg(Arg::with_name("arg1").help("some option"))
|
||||
.arg(Arg::with_name("arg2")
|
||||
.multiple(true)
|
||||
.help("some option"))
|
||||
.multiple(true)
|
||||
.help("some option"))
|
||||
.arg(Arg::with_name("some")
|
||||
.help("some option")
|
||||
.short("s")
|
||||
.long("some")
|
||||
.takes_value(true))
|
||||
.help("some option")
|
||||
.short("s")
|
||||
.long("some")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("other")
|
||||
.help("some other option")
|
||||
.short("o")
|
||||
.long("other")
|
||||
.takes_value(true))
|
||||
.help("some other option")
|
||||
.short("o")
|
||||
.long("other")
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("label")
|
||||
.help("a label")
|
||||
.short("l")
|
||||
.long("label")
|
||||
.multiple(true)
|
||||
.takes_value(true));
|
||||
.help("a label")
|
||||
.short("l")
|
||||
.long("label")
|
||||
.multiple(true)
|
||||
.takes_value(true));
|
||||
assert!(test::compare_output(app, "myapp --help", ISSUE_702, false));
|
||||
}
|
||||
|
||||
|
@ -512,17 +507,17 @@ fn issue_760() {
|
|||
let app = App::new("ctest")
|
||||
.version("0.1")
|
||||
.arg(Arg::with_name("option")
|
||||
.help("tests options")
|
||||
.short("o")
|
||||
.long("option")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1))
|
||||
.help("tests options")
|
||||
.short("o")
|
||||
.long("option")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.number_of_values(1))
|
||||
.arg(Arg::with_name("opt")
|
||||
.help("tests options")
|
||||
.short("O")
|
||||
.long("opt")
|
||||
.takes_value(true));
|
||||
.help("tests options")
|
||||
.short("O")
|
||||
.long("opt")
|
||||
.takes_value(true));
|
||||
assert!(test::compare_output(app, "ctest --help", ISSUE_760, false));
|
||||
}
|
||||
#[test]
|
||||
|
|
|
@ -106,8 +106,7 @@ fn quoted_arg_long_name() {
|
|||
(@arg scpositional: index(1) "tests positionals"))
|
||||
);
|
||||
|
||||
assert_eq!(app.p.long_list[2], "long-option-2");
|
||||
|
||||
let matches = app.get_matches_from_safe(vec!["bin_name", "value1", "value2", "--long-option-2"]).expect("Expected to successfully match the given args.");
|
||||
let matches = app.get_matches_from_safe(vec!["bin_name", "value1", "value2", "--long-option-2"])
|
||||
.expect("Expected to successfully match the given args.");
|
||||
assert!(matches.is_present("option2"));
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ static COND_REQ_IN_USAGE: &'static str = "error: The following required argument
|
|||
--output <output>
|
||||
|
||||
USAGE:
|
||||
test --target <target> --input <input> --output <output>
|
||||
test --input <input> --output <output> --target <target>
|
||||
|
||||
For more information try --help";
|
||||
|
||||
|
@ -46,7 +46,7 @@ fn flag_required_2() {
|
|||
#[test]
|
||||
fn option_required() {
|
||||
let result = App::new("option_required")
|
||||
.arg(Arg::from_usage("-f [flag] 'some flag'").requires("color"))
|
||||
.arg(Arg::from_usage("-f [flag] 'some flag'").requires("c"))
|
||||
.arg(Arg::from_usage("-c [color] 'third flag'"))
|
||||
.get_matches_from_safe(vec!["", "-f", "val"]);
|
||||
assert!(result.is_err());
|
||||
|
@ -560,4 +560,4 @@ fn required_ifs_wrong_val_mult_fail() {
|
|||
|
||||
assert!(res.is_err());
|
||||
assert_eq!(res.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,30 +2,21 @@ extern crate clap;
|
|||
|
||||
use clap::{App, Arg};
|
||||
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn unique_arg_names() {
|
||||
App::new("some").args(&[
|
||||
Arg::with_name("arg").short("a"),
|
||||
Arg::with_name("arg").short("b")
|
||||
]);
|
||||
App::new("some").args(&[Arg::with_name("arg").short("a"), Arg::with_name("arg").short("b")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn unique_arg_shorts() {
|
||||
App::new("some").args(&[
|
||||
Arg::with_name("arg1").short("a"),
|
||||
Arg::with_name("arg2").short("a")
|
||||
]);
|
||||
App::new("some").args(&[Arg::with_name("arg1").short("a"), Arg::with_name("arg2").short("a")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn unique_arg_longs() {
|
||||
App::new("some").args(&[
|
||||
Arg::with_name("arg1").long("long"),
|
||||
Arg::with_name("arg2").long("long")
|
||||
]);
|
||||
App::new("some")
|
||||
.args(&[Arg::with_name("arg1").long("long"), Arg::with_name("arg2").long("long")]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue