mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
depr(ArgMatches::usage): deprecates ArgMatches::usage in favor of App::generage_usage
This commit is contained in:
parent
8715ac268c
commit
a9cbf3e5b9
7 changed files with 204 additions and 160 deletions
|
@ -19,7 +19,7 @@ use yaml_rust::Yaml;
|
|||
use build::{Arg, ArgGroup, ArgSettings};
|
||||
use completions::{ComplGen, Shell};
|
||||
use output::fmt::ColorWhen;
|
||||
use output::Help;
|
||||
use output::{Help, Usage};
|
||||
use parse::errors::Result as ClapResult;
|
||||
use parse::{ArgMatcher, ArgMatches, Parser};
|
||||
|
||||
|
@ -1149,6 +1149,19 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
self._write_version(w, true).map_err(From::from)
|
||||
}
|
||||
|
||||
/// @TODO-v3-alpha @docs @p2: write docs
|
||||
pub fn generate_usage(&mut self) -> String {
|
||||
// If there are global arguments, or settings we need to propgate them down to subcommands
|
||||
// before parsing incase we run into a subcommand
|
||||
if !self.settings.is_set(AppSettings::Propagated) {
|
||||
self._build(Propagation::NextLevel);
|
||||
}
|
||||
|
||||
let mut parser = Parser::new(self);
|
||||
parser._build();
|
||||
Usage::new(&parser).create_usage_with_title(&[])
|
||||
}
|
||||
|
||||
/// Starts the parsing process, upon a failed parse an error will be displayed to the user and
|
||||
/// the process will exit with the appropriate error code. By default this method gets all user
|
||||
/// provided arguments from [`env::args_os`] in order to allow for invalid UTF-8 code points,
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
use std::collections::{BTreeMap, VecDeque};
|
||||
|
||||
// Internal
|
||||
use INTERNAL_ERROR_MSG;
|
||||
use build::{Arg, ArgSettings};
|
||||
use build::AppSettings as AS;
|
||||
use parse::{Parser, ArgMatcher};
|
||||
use build::{Arg, ArgSettings};
|
||||
use parse::{ArgMatcher, Parser};
|
||||
use INTERNAL_ERROR_MSG;
|
||||
|
||||
pub struct Usage<'a, 'b, 'c, 'z>(&'z Parser<'a, 'b, 'c>)
|
||||
where
|
||||
|
@ -59,8 +59,10 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
|
||||
// Creates a usage string for display in help messages (i.e. not for errors)
|
||||
pub fn create_help_usage(&self, incl_reqs: bool) -> String {
|
||||
debugln!("Usage::create_help_usage; incl_reqs={:?}", incl_reqs);
|
||||
let mut usage = String::with_capacity(75);
|
||||
let name = self.0
|
||||
let name = self
|
||||
.0
|
||||
.app
|
||||
.usage
|
||||
.as_ref()
|
||||
|
@ -116,7 +118,7 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
let pos = positionals!(self.0.app)
|
||||
.find(|p| p.is_set(ArgSettings::Last))
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
debugln!("usage::create_help_usage: '{}' has .last(true)", pos.name);
|
||||
debugln!("Usage::create_help_usage: '{}' has .last(true)", pos.name);
|
||||
let req = pos.is_set(ArgSettings::Required);
|
||||
if req && positionals!(self.0.app).any(|p| !p.is_set(ArgSettings::Required)) {
|
||||
usage.push_str(" -- <");
|
||||
|
@ -170,12 +172,14 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
let mut hs: Vec<&str> = self.0.required().map(|s| &**s).collect();
|
||||
hs.extend_from_slice(used);
|
||||
|
||||
let r_string = self.get_required_usage_from(&hs, None, None, false)
|
||||
let r_string = self
|
||||
.get_required_usage_from(&hs, None, None, false)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
|
||||
|
||||
usage.push_str(
|
||||
&self.0
|
||||
&self
|
||||
.0
|
||||
.app
|
||||
.usage
|
||||
.as_ref()
|
||||
|
@ -220,7 +224,8 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
} else if count == 1 && incl_reqs {
|
||||
let pos = positionals!(self.0.app)
|
||||
.find(|pos| {
|
||||
!pos.is_set(ArgSettings::Required) && !pos.is_set(ArgSettings::Hidden)
|
||||
!pos.is_set(ArgSettings::Required)
|
||||
&& !pos.is_set(ArgSettings::Hidden)
|
||||
&& !pos.is_set(ArgSettings::Last)
|
||||
})
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
|
@ -233,7 +238,8 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
pos.name_no_brackets(),
|
||||
pos.multiple_str()
|
||||
));
|
||||
} else if self.0.is_set(AS::DontCollapseArgsInUsage) && self.0.has_positionals()
|
||||
} else if self.0.is_set(AS::DontCollapseArgsInUsage)
|
||||
&& self.0.has_positionals()
|
||||
&& incl_reqs
|
||||
{
|
||||
debugln!("usage::get_args_tag:iter: Don't collapse returning all");
|
||||
|
@ -318,7 +324,7 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
incl_last: bool,
|
||||
) -> VecDeque<String> {
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: reqs={:?}, extra={:?}",
|
||||
"Usage::get_required_usage_from: reqs={:?}, extra={:?}",
|
||||
reqs,
|
||||
extra
|
||||
);
|
||||
|
@ -326,15 +332,19 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
desc_reqs.extend(extra);
|
||||
let mut new_reqs: Vec<&str> = vec![];
|
||||
macro_rules! get_requires {
|
||||
(@group $a: ident, $v:ident, $p:ident) => {{
|
||||
(@group $a:ident, $v:ident, $p:ident) => {{
|
||||
if let Some(rl) = groups!(self.0.app)
|
||||
.filter(|g| g.requires.is_some())
|
||||
.find(|g| &g.name == $a)
|
||||
.map(|g| g.requires.as_ref().unwrap()) {
|
||||
.filter(|g| g.requires.is_some())
|
||||
.find(|g| &g.name == $a)
|
||||
.map(|g| g.requires.as_ref().unwrap())
|
||||
{
|
||||
for r in rl {
|
||||
if !$p.contains(&r) {
|
||||
debugln!("usage::get_required_usage_from:iter:{}: adding group req={:?}",
|
||||
$a, r);
|
||||
debugln!(
|
||||
"Usage::get_required_usage_from:iter:{}: adding group req={:?}",
|
||||
$a,
|
||||
r
|
||||
);
|
||||
$v.push(r);
|
||||
}
|
||||
}
|
||||
|
@ -342,13 +352,17 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
}};
|
||||
($a:ident, $what:ident, $how:ident, $v:ident, $p:ident) => {{
|
||||
if let Some(rl) = $what!(self.0.app)
|
||||
.filter(|a| a.requires.is_some())
|
||||
.find(|arg| &arg.name == $a)
|
||||
.map(|a| a.requires.as_ref().unwrap()) {
|
||||
.filter(|a| a.requires.is_some())
|
||||
.find(|arg| &arg.name == $a)
|
||||
.map(|a| a.requires.as_ref().unwrap())
|
||||
{
|
||||
for &(_, r) in rl.iter() {
|
||||
if !$p.contains(&r) {
|
||||
debugln!("usage::get_required_usage_from:iter:{}: adding arg req={:?}",
|
||||
$a, r);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from:iter:{}: adding arg req={:?}",
|
||||
$a,
|
||||
r
|
||||
);
|
||||
$v.push(r);
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +402,7 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
new_reqs.clear();
|
||||
new_reqs.extend_from_slice(&*tmp);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: after iter desc_reqs={:?}",
|
||||
"Usage::get_required_usage_from: after iter desc_reqs={:?}",
|
||||
desc_reqs
|
||||
);
|
||||
}
|
||||
|
@ -397,7 +411,7 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
desc_reqs.sort();
|
||||
desc_reqs.dedup();
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: final desc_reqs={:?}",
|
||||
"Usage::get_required_usage_from: final desc_reqs={:?}",
|
||||
desc_reqs
|
||||
);
|
||||
let mut ret_val = VecDeque::new();
|
||||
|
@ -427,10 +441,11 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
.collect::<BTreeMap<u64, &Arg>>() // sort by index
|
||||
};
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: args_in_groups={:?}",
|
||||
"Usage::get_required_usage_from: args_in_groups={:?}",
|
||||
args_in_groups
|
||||
);
|
||||
for &p in pmap.values() {
|
||||
debugln!("Usage::get_required_usage_from:iter:{}", p.to_string());
|
||||
let s = p.to_string();
|
||||
if args_in_groups.is_empty() || !args_in_groups.contains(&&*s) {
|
||||
ret_val.push_back(s);
|
||||
|
@ -443,7 +458,7 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
.filter(|name| !args_in_groups.contains(name))
|
||||
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name)))
|
||||
{
|
||||
debugln!("usage::get_required_usage_from:iter:{}:", a);
|
||||
debugln!("Usage::get_required_usage_from:iter:{}:", a);
|
||||
let arg = find!(self.0.app, a)
|
||||
.map(|f| f.to_string())
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
|
@ -464,6 +479,7 @@ impl<'a, 'b, 'c, 'z> Usage<'a, 'b, 'c, 'z> {
|
|||
ret_val.push_back(g);
|
||||
}
|
||||
|
||||
debugln!("Usage::get_required_usage_from: ret_val={:?}", ret_val);
|
||||
ret_val
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Std
|
||||
use std::ffi::OsStr;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::mem;
|
||||
|
||||
// Third Party
|
||||
|
@ -88,8 +88,6 @@ impl<'a> ArgMatcher<'a> {
|
|||
|
||||
pub fn is_empty(&self) -> bool { self.0.args.is_empty() }
|
||||
|
||||
pub fn usage(&mut self, usage: String) { self.0.usage = Some(usage); }
|
||||
|
||||
pub fn arg_names(&'a self) -> indexmap::map::Keys<&'a str, MatchedArg> { self.0.args.keys() }
|
||||
|
||||
pub fn entry(&mut self, arg: &'a str) -> indexmap::map::Entry<&'a str, MatchedArg> {
|
||||
|
@ -130,14 +128,14 @@ impl<'a> ArgMatcher<'a> {
|
|||
}
|
||||
|
||||
pub fn add_index_to(&mut self, arg: &'a str, idx: usize) {
|
||||
let ma = self.entry(arg).or_insert(MatchedArg {
|
||||
occurs: 0,
|
||||
indices: Vec::with_capacity(1),
|
||||
vals: Vec::new(),
|
||||
});
|
||||
ma.indices.push(idx);
|
||||
let ma = self.entry(arg).or_insert(MatchedArg {
|
||||
occurs: 0,
|
||||
indices: Vec::with_capacity(1),
|
||||
vals: Vec::new(),
|
||||
});
|
||||
ma.indices.push(idx);
|
||||
}
|
||||
|
||||
|
||||
pub fn needs_more_vals<'b>(&self, o: &Arg) -> bool {
|
||||
debugln!("ArgMatcher::needs_more_vals: o={}", o.name);
|
||||
if let Some(ma) = self.get(o.name) {
|
||||
|
|
|
@ -8,8 +8,8 @@ use std::slice::Iter;
|
|||
use indexmap::IndexMap;
|
||||
|
||||
// Internal
|
||||
use INVALID_UTF8;
|
||||
use parse::{MatchedArg, SubCommand};
|
||||
use INVALID_UTF8;
|
||||
|
||||
/// Used to get information about the arguments that where supplied to the program at runtime by
|
||||
/// the user. New instances of this struct are obtained by using the [`App::get_matches`] family of
|
||||
|
@ -64,8 +64,6 @@ pub struct ArgMatches<'a> {
|
|||
pub args: IndexMap<&'a str, MatchedArg>,
|
||||
#[doc(hidden)]
|
||||
pub subcommand: Option<Box<SubCommand<'a>>>,
|
||||
#[doc(hidden)]
|
||||
pub usage: Option<String>,
|
||||
}
|
||||
|
||||
impl<'a> Default for ArgMatches<'a> {
|
||||
|
@ -73,7 +71,6 @@ impl<'a> Default for ArgMatches<'a> {
|
|||
ArgMatches {
|
||||
args: IndexMap::new(),
|
||||
subcommand: None,
|
||||
usage: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -746,21 +743,13 @@ impl<'a> ArgMatches<'a> {
|
|||
.map_or(("", None), |sc| (&sc.name[..], Some(&sc.matches)))
|
||||
}
|
||||
|
||||
/// Returns a string slice of the usage statement for the [`App`] or [`SubCommand`]
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg, SubCommand};
|
||||
/// let app_m = App::new("myprog")
|
||||
/// .subcommand(SubCommand::with_name("test"))
|
||||
/// .get_matches();
|
||||
///
|
||||
/// println!("{}", app_m.usage());
|
||||
/// ```
|
||||
/// [`Subcommand`]: ./struct.SubCommand.html
|
||||
/// [`App`]: ./struct.App.html
|
||||
pub fn usage(&self) -> &str { self.usage.as_ref().map_or("", |u| &u[..]) }
|
||||
// @TODO @v3-beta: remove
|
||||
/// **Deprecated**
|
||||
#[deprecated(
|
||||
since = "2.32.0",
|
||||
note = "Use App::usage instead. Will be removed in v3-beta"
|
||||
)]
|
||||
pub fn usage(&self) -> &str { panic!("Use App::usage instead. Will be removed in v3-beta") }
|
||||
}
|
||||
|
||||
// The following were taken and adapated from vec_map source
|
||||
|
@ -895,7 +884,8 @@ impl<'a> Default for OsValues<'a> {
|
|||
/// [`ArgMatches::indices_of`]: ./struct.ArgMatches.html#method.indices_of
|
||||
#[derive(Clone)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct Indices<'a> { // would rather use '_, but: https://github.com/rust-lang/rust/issues/48469
|
||||
pub struct Indices<'a> {
|
||||
// would rather use '_, but: https://github.com/rust-lang/rust/issues/48469
|
||||
iter: Map<Iter<'a, usize>, fn(&'a usize) -> usize>,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,43 @@
|
|||
// Std
|
||||
#[cfg(
|
||||
all(
|
||||
feature = "debug",
|
||||
any(target_os = "windows", target_arch = "wasm32")
|
||||
)
|
||||
)]
|
||||
use osstringext::OsStrExt3;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::io::{self, BufWriter, Write};
|
||||
#[cfg(all(feature = "debug", not(any(target_os = "windows", target_arch = "wasm32"))))]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
#[cfg(all(feature = "debug", any(target_os = "windows", target_arch = "wasm32")))]
|
||||
use osstringext::OsStrExt3;
|
||||
use std::slice::Iter;
|
||||
use std::iter::Peekable;
|
||||
use std::mem;
|
||||
use std::cell::Cell;
|
||||
#[cfg(
|
||||
all(
|
||||
feature = "debug",
|
||||
not(any(target_os = "windows", target_arch = "wasm32"))
|
||||
)
|
||||
)]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::slice::Iter;
|
||||
|
||||
// Third party facade
|
||||
use util::VecMap;
|
||||
|
||||
// Internal
|
||||
use INTERNAL_ERROR_MSG;
|
||||
use INVALID_UTF8;
|
||||
use build::{App, Arg, ArgSettings};
|
||||
use build::app::Propagation;
|
||||
use build::AppSettings as AS;
|
||||
use parse::{ArgMatcher, SubCommand};
|
||||
use build::{App, Arg, ArgSettings};
|
||||
use output::Help;
|
||||
use parse::errors::ErrorKind;
|
||||
use parse::errors::Error as ClapError;
|
||||
use parse::errors::Result as ClapResult;
|
||||
use parse::Validator;
|
||||
use util::OsStrExt2;
|
||||
use parse::features::suggestions;
|
||||
use output::Usage;
|
||||
use parse::errors::Error as ClapError;
|
||||
use parse::errors::ErrorKind;
|
||||
use parse::errors::Result as ClapResult;
|
||||
use parse::features::suggestions;
|
||||
use parse::Validator;
|
||||
use parse::{ArgMatcher, SubCommand};
|
||||
use util::OsStrExt2;
|
||||
use INVALID_UTF8;
|
||||
use INTERNAL_ERROR_MSG;
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
#[doc(hidden)]
|
||||
|
@ -92,7 +102,8 @@ where
|
|||
'b: 'c,
|
||||
{
|
||||
pub fn new(app: &'c mut App<'a, 'b>) -> Self {
|
||||
let reqs = app.args
|
||||
let reqs = app
|
||||
.args
|
||||
.iter()
|
||||
.filter(|a| a.settings.is_set(ArgSettings::Required))
|
||||
.map(|a| a.name)
|
||||
|
@ -112,7 +123,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg_attr(feature = "lints", allow(block_in_if_condition_stmt))]
|
||||
fn _verify_positionals(&mut self) -> bool {
|
||||
debugln!("Parser::_verify_positionals;");
|
||||
|
@ -123,14 +133,10 @@ where
|
|||
// positional arguments to verify there are no gaps (i.e. supplying an index of 1 and 3
|
||||
// but no 2)
|
||||
#[cfg(feature = "vec_map")]
|
||||
fn _highest_idx(map: &VecMap<&str>) -> usize {
|
||||
map.keys().last().unwrap_or(0)
|
||||
}
|
||||
fn _highest_idx(map: &VecMap<&str>) -> usize { map.keys().last().unwrap_or(0) }
|
||||
|
||||
#[cfg(not(feature = "vec_map"))]
|
||||
fn _highest_idx(map: &VecMap<&str>) -> usize {
|
||||
*map.keys().last().unwrap_or(&0)
|
||||
}
|
||||
fn _highest_idx(map: &VecMap<&str>) -> usize { *map.keys().last().unwrap_or(&0) }
|
||||
|
||||
let highest_idx = _highest_idx(&self.positionals);
|
||||
|
||||
|
@ -192,7 +198,8 @@ where
|
|||
}
|
||||
});
|
||||
let ok = count <= 1
|
||||
|| (last.is_set(ArgSettings::Last) && last.is_set(ArgSettings::MultipleValues)
|
||||
|| (last.is_set(ArgSettings::Last)
|
||||
&& last.is_set(ArgSettings::MultipleValues)
|
||||
&& second_to_last.is_set(ArgSettings::MultipleValues)
|
||||
&& count == 2);
|
||||
assert!(
|
||||
|
@ -207,7 +214,8 @@ where
|
|||
// index are also required.
|
||||
let mut found = false;
|
||||
let mut foundx2 = false;
|
||||
for p in self.positionals
|
||||
for p in self
|
||||
.positionals
|
||||
.values()
|
||||
.rev()
|
||||
.map(|p_name| find!(self.app, p_name).expect(INTERNAL_ERROR_MSG))
|
||||
|
@ -242,7 +250,8 @@ where
|
|||
// Check that if a required positional argument is found, all positions with a lower
|
||||
// index are also required
|
||||
let mut found = false;
|
||||
for p in self.positionals
|
||||
for p in self
|
||||
.positionals
|
||||
.values()
|
||||
.rev()
|
||||
.map(|p_name| find!(self.app, p_name).expect(INTERNAL_ERROR_MSG))
|
||||
|
@ -268,10 +277,12 @@ where
|
|||
}
|
||||
}
|
||||
assert!(
|
||||
positionals!(self.app).fold(0, |acc, p| if p.is_set(ArgSettings::Last) {
|
||||
acc + 1
|
||||
} else {
|
||||
acc
|
||||
positionals!(self.app).fold(0, |acc, p| {
|
||||
if p.is_set(ArgSettings::Last) {
|
||||
acc + 1
|
||||
} else {
|
||||
acc
|
||||
}
|
||||
}) < 2,
|
||||
"Only one positional argument may have last(true) set. Found two."
|
||||
);
|
||||
|
@ -289,7 +300,7 @@ where
|
|||
}
|
||||
|
||||
// Does all the initializing and prepares the parser
|
||||
fn _build(&mut self) {
|
||||
pub(crate) fn _build(&mut self) {
|
||||
debugln!("Parser::_build;");
|
||||
|
||||
for a in &mut self.app.args {
|
||||
|
@ -354,7 +365,10 @@ where
|
|||
'b: 'c,
|
||||
{
|
||||
// The actual parsing function
|
||||
#[cfg_attr(feature = "lints", allow(while_let_on_iterator, collapsible_if))]
|
||||
#[cfg_attr(
|
||||
feature = "lints",
|
||||
allow(while_let_on_iterator, collapsible_if)
|
||||
)]
|
||||
pub fn get_matches_with<I, T>(
|
||||
&mut self,
|
||||
matcher: &mut ArgMatcher<'a>,
|
||||
|
@ -384,7 +398,9 @@ where
|
|||
self.unset(AS::ValidNegNumFound);
|
||||
// Is this a new argument, or values from a previous option?
|
||||
let starts_new_arg = self.is_new_arg(&arg_os, needs_val_of);
|
||||
if !self.is_set(AS::TrailingValues) && arg_os.starts_with(b"--") && arg_os.len() == 2
|
||||
if !self.is_set(AS::TrailingValues)
|
||||
&& arg_os.starts_with(b"--")
|
||||
&& arg_os.len() == 2
|
||||
&& starts_new_arg
|
||||
{
|
||||
debugln!("Parser::get_matches_with: setting TrailingVals=true");
|
||||
|
@ -473,7 +489,8 @@ where
|
|||
}
|
||||
|
||||
if !(self.is_set(AS::ArgsNegateSubcommands) && self.is_set(AS::ValidArgFound))
|
||||
&& !self.is_set(AS::InferSubcommands) && !self.is_set(AS::AllowExternalSubcommands)
|
||||
&& !self.is_set(AS::InferSubcommands)
|
||||
&& !self.is_set(AS::AllowExternalSubcommands)
|
||||
{
|
||||
if let Some(cdate) =
|
||||
suggestions::did_you_mean(&*arg_os.to_string_lossy(), sc_names!(self.app))
|
||||
|
@ -555,7 +572,8 @@ where
|
|||
let _ = self.add_val_to_arg(p, &arg_os, matcher)?;
|
||||
|
||||
matcher.inc_occurrence_of(p.name);
|
||||
let _ = self.groups_for_arg(p.name)
|
||||
let _ = self
|
||||
.groups_for_arg(p.name)
|
||||
.and_then(|vec| Some(matcher.inc_occurrences_of(&*vec)));
|
||||
|
||||
self.app.settings.set(AS::ValidArgFound);
|
||||
|
@ -673,10 +691,10 @@ where
|
|||
fn possible_subcommand(&self, arg_os: &OsStr) -> (bool, Option<&str>) {
|
||||
debugln!("Parser::possible_subcommand: arg={:?}", arg_os);
|
||||
fn starts(h: &str, n: &OsStr) -> bool {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
#[cfg(target_os = "windows")]
|
||||
use osstringext::OsStrExt3;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
let n_bytes = n.as_bytes();
|
||||
let h_bytes = OsStr::new(h).as_bytes();
|
||||
|
@ -934,9 +952,9 @@ where
|
|||
// specified by the user is sent through. If HiddenShortHelp is not included,
|
||||
// then items specified with hidden_short_help will also be hidden.
|
||||
let should_long = |v: &Arg| {
|
||||
v.long_help.is_some() ||
|
||||
v.is_set(ArgSettings::HiddenLongHelp) ||
|
||||
v.is_set(ArgSettings::HiddenShortHelp)
|
||||
v.long_help.is_some()
|
||||
|| v.is_set(ArgSettings::HiddenLongHelp)
|
||||
|| v.is_set(ArgSettings::HiddenShortHelp)
|
||||
};
|
||||
|
||||
self.app.long_about.is_some()
|
||||
|
@ -944,33 +962,33 @@ where
|
|||
|| subcommands!(self.app).any(|s| s.long_about.is_some())
|
||||
}
|
||||
|
||||
// fn _help(&self, mut use_long: bool) -> ClapError {
|
||||
// debugln!("Parser::_help: use_long={:?}", use_long && self.use_long_help());
|
||||
// use_long = use_long && self.use_long_help();
|
||||
// let mut buf = vec![];
|
||||
// match Help::write_parser_help(&mut buf, self, use_long) {
|
||||
// Err(e) => e,
|
||||
// _ => ClapError {
|
||||
// message: String::from_utf8(buf).unwrap_or_default(),
|
||||
// kind: ErrorKind::HelpDisplayed,
|
||||
// info: None,
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn _version(&self, use_long: bool) -> ClapError {
|
||||
// debugln!("Parser::_version: ");
|
||||
// let out = io::stdout();
|
||||
// let mut buf_w = BufWriter::new(out.lock());
|
||||
// match self.print_version(&mut buf_w, use_long) {
|
||||
// Err(e) => e,
|
||||
// _ => ClapError {
|
||||
// message: String::new(),
|
||||
// kind: ErrorKind::VersionDisplayed,
|
||||
// info: None,
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
// fn _help(&self, mut use_long: bool) -> ClapError {
|
||||
// debugln!("Parser::_help: use_long={:?}", use_long && self.use_long_help());
|
||||
// use_long = use_long && self.use_long_help();
|
||||
// let mut buf = vec![];
|
||||
// match Help::write_parser_help(&mut buf, self, use_long) {
|
||||
// Err(e) => e,
|
||||
// _ => ClapError {
|
||||
// message: String::from_utf8(buf).unwrap_or_default(),
|
||||
// kind: ErrorKind::HelpDisplayed,
|
||||
// info: None,
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn _version(&self, use_long: bool) -> ClapError {
|
||||
// debugln!("Parser::_version: ");
|
||||
// let out = io::stdout();
|
||||
// let mut buf_w = BufWriter::new(out.lock());
|
||||
// match self.print_version(&mut buf_w, use_long) {
|
||||
// Err(e) => e,
|
||||
// _ => ClapError {
|
||||
// message: String::new(),
|
||||
// kind: ErrorKind::VersionDisplayed,
|
||||
// info: None,
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
|
||||
fn parse_long_arg(
|
||||
&mut self,
|
||||
|
@ -1365,16 +1383,26 @@ where
|
|||
(@default $_self:ident, $a:ident, $m:ident) => {
|
||||
if let Some(ref val) = $a.default_val {
|
||||
debugln!("Parser::add_defaults:iter:{}: has default vals", $a.name);
|
||||
if $m.get($a.name).map(|ma| ma.vals.len())
|
||||
.map(|len| len == 0).unwrap_or(false) {
|
||||
debugln!("Parser::add_defaults:iter:{}: has no user defined vals", $a.name);
|
||||
if $m
|
||||
.get($a.name)
|
||||
.map(|ma| ma.vals.len())
|
||||
.map(|len| len == 0)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
debugln!(
|
||||
"Parser::add_defaults:iter:{}: has no user defined vals",
|
||||
$a.name
|
||||
);
|
||||
$_self.add_val_to_arg($a, OsStr::new(val), $m)?;
|
||||
|
||||
if $_self.cache.map_or(true, |name| name != $a.name) {
|
||||
$_self.cache = Some($a.name);
|
||||
}
|
||||
} else if $m.get($a.name).is_some() {
|
||||
debugln!("Parser::add_defaults:iter:{}: has user defined vals", $a.name);
|
||||
debugln!(
|
||||
"Parser::add_defaults:iter:{}: has user defined vals",
|
||||
$a.name
|
||||
);
|
||||
} else {
|
||||
debugln!("Parser::add_defaults:iter:{}: wasn't used", $a.name);
|
||||
|
||||
|
@ -1385,7 +1413,10 @@ where
|
|||
}
|
||||
}
|
||||
} else {
|
||||
debugln!("Parser::add_defaults:iter:{}: doesn't have default vals", $a.name);
|
||||
debugln!(
|
||||
"Parser::add_defaults:iter:{}: doesn't have default vals",
|
||||
$a.name
|
||||
);
|
||||
}
|
||||
};
|
||||
($_self:ident, $a:ident, $m:ident) => {
|
||||
|
@ -1510,7 +1541,10 @@ where
|
|||
}
|
||||
|
||||
fn help_err(&self, mut use_long: bool) -> ClapError {
|
||||
debugln!("Parser::help_err: use_long={:?}", use_long && self.use_long_help());
|
||||
debugln!(
|
||||
"Parser::help_err: use_long={:?}",
|
||||
use_long && self.use_long_help()
|
||||
);
|
||||
use_long = use_long && self.use_long_help();
|
||||
let mut buf = vec![];
|
||||
match Help::write_parser_help(&mut buf, self, use_long) {
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
use std::ascii::AsciiExt;
|
||||
|
||||
// Internal
|
||||
use INTERNAL_ERROR_MSG;
|
||||
use INVALID_UTF8;
|
||||
use build::{Arg, ArgSettings};
|
||||
use build::app::AppSettings as AS;
|
||||
use parse::{ArgMatcher, MatchedArg, ParseResult, Parser};
|
||||
use parse::errors::{Error, ErrorKind};
|
||||
use parse::errors::Result as ClapResult;
|
||||
use build::{Arg, ArgSettings};
|
||||
use output::fmt::{Colorizer, ColorizerOption};
|
||||
use output::Usage;
|
||||
use parse::errors::Result as ClapResult;
|
||||
use parse::errors::{Error, ErrorKind};
|
||||
use parse::{ArgMatcher, MatchedArg, ParseResult, Parser};
|
||||
use INVALID_UTF8;
|
||||
use INTERNAL_ERROR_MSG;
|
||||
|
||||
pub struct Validator<'a, 'b, 'c, 'z>(&'z mut Parser<'a, 'b, 'c>)
|
||||
where
|
||||
|
@ -51,7 +51,8 @@ impl<'a, 'b, 'c, 'z> Validator<'a, 'b, 'c, 'z> {
|
|||
}
|
||||
}
|
||||
|
||||
if matcher.is_empty() && matcher.subcommand_name().is_none()
|
||||
if matcher.is_empty()
|
||||
&& matcher.subcommand_name().is_none()
|
||||
&& self.0.is_set(AS::ArgRequiredElseHelp)
|
||||
{
|
||||
let mut out = vec![];
|
||||
|
@ -67,7 +68,6 @@ impl<'a, 'b, 'c, 'z> Validator<'a, 'b, 'c, 'z> {
|
|||
self.validate_required(matcher)?;
|
||||
}
|
||||
self.validate_matched_args(matcher)?;
|
||||
matcher.usage(Usage::new(self.0).create_usage_with_title(&[]));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -108,7 +108,8 @@ impl<'a, 'b, 'c, 'z> Validator<'a, 'b, 'c, 'z> {
|
|||
));
|
||||
}
|
||||
}
|
||||
if !arg.is_set(ArgSettings::AllowEmptyValues) && val.is_empty()
|
||||
if !arg.is_set(ArgSettings::AllowEmptyValues)
|
||||
&& val.is_empty()
|
||||
&& matcher.contains(&*arg.name)
|
||||
{
|
||||
debugln!("Validator::validate_arg_values: illegal empty val found");
|
||||
|
@ -463,7 +464,7 @@ impl<'a, 'b, 'c, 'z> Validator<'a, 'b, 'c, 'z> {
|
|||
ru.iter().$how(|n| {
|
||||
$m.contains(n) || {
|
||||
if let Some(grp) = find!($_self.app, n, groups) {
|
||||
grp.args.iter().any(|arg| $m.contains(arg))
|
||||
grp.args.iter().any(|arg| $m.contains(arg))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
|
@ -186,44 +186,36 @@ fn positional_hyphen_does_not_panic() {
|
|||
|
||||
#[test]
|
||||
fn single_positional_usage_string() {
|
||||
let m = App::new("test")
|
||||
.arg_from_usage("[FILE] 'some file'")
|
||||
.get_matches_from(vec!["test"]);
|
||||
assert_eq!(m.usage(), "USAGE:\n test [FILE]");
|
||||
let mut app = App::new("test").arg_from_usage("[FILE] 'some file'");
|
||||
assert_eq!(app.generate_usage(), "USAGE:\n test [FILE]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_positional_multiple_usage_string() {
|
||||
let m = App::new("test")
|
||||
.arg_from_usage("[FILE]... 'some file'")
|
||||
.get_matches_from(vec!["test"]);
|
||||
assert_eq!(m.usage(), "USAGE:\n test [FILE]...");
|
||||
let mut app = App::new("test").arg_from_usage("[FILE]... 'some file'");
|
||||
assert_eq!(app.generate_usage(), "USAGE:\n test [FILE]...");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_positional_usage_string() {
|
||||
let m = App::new("test")
|
||||
let mut app = App::new("test")
|
||||
.arg_from_usage("[FILE] 'some file'")
|
||||
.arg_from_usage("[FILES]... 'some file'")
|
||||
.get_matches_from(vec!["test"]);
|
||||
assert_eq!(m.usage(), "USAGE:\n test [ARGS]");
|
||||
.arg_from_usage("[FILES]... 'some file'");
|
||||
assert_eq!(app.generate_usage(), "USAGE:\n test [ARGS]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_positional_one_required_usage_string() {
|
||||
let m = App::new("test")
|
||||
let mut app = App::new("test")
|
||||
.arg_from_usage("<FILE> 'some file'")
|
||||
.arg_from_usage("[FILES]... 'some file'")
|
||||
.get_matches_from(vec!["test", "file"]);
|
||||
assert_eq!(m.usage(), "USAGE:\n test <FILE> [FILES]...");
|
||||
.arg_from_usage("[FILES]... 'some file'");
|
||||
assert_eq!(app.generate_usage(), "USAGE:\n test <FILE> [FILES]...");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_positional_required_usage_string() {
|
||||
let m = App::new("test")
|
||||
.arg_from_usage("<FILE> 'some file'")
|
||||
.get_matches_from(vec!["test", "file"]);
|
||||
assert_eq!(m.usage(), "USAGE:\n test <FILE>");
|
||||
let mut app = App::new("test").arg_from_usage("<FILE> 'some file'");
|
||||
assert_eq!(app.generate_usage(), "USAGE:\n test <FILE>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue