RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
1032
zeroidc/vendor/clap/src/app/help.rs
vendored
Normal file
1032
zeroidc/vendor/clap/src/app/help.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
35
zeroidc/vendor/clap/src/app/meta.rs
vendored
Normal file
35
zeroidc/vendor/clap/src/app/meta.rs
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct AppMeta<'b> {
|
||||
pub name: String,
|
||||
pub bin_name: Option<String>,
|
||||
pub author: Option<&'b str>,
|
||||
pub version: Option<&'b str>,
|
||||
pub long_version: Option<&'b str>,
|
||||
pub about: Option<&'b str>,
|
||||
pub long_about: Option<&'b str>,
|
||||
pub more_help: Option<&'b str>,
|
||||
pub pre_help: Option<&'b str>,
|
||||
pub aliases: Option<Vec<(&'b str, bool)>>, // (name, visible)
|
||||
pub usage_str: Option<&'b str>,
|
||||
pub usage: Option<String>,
|
||||
pub help_str: Option<&'b str>,
|
||||
pub disp_ord: usize,
|
||||
pub term_w: Option<usize>,
|
||||
pub max_w: Option<usize>,
|
||||
pub template: Option<&'b str>,
|
||||
}
|
||||
|
||||
impl<'b> AppMeta<'b> {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
pub fn with_name(s: String) -> Self {
|
||||
AppMeta {
|
||||
name: s,
|
||||
disp_ord: 999,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
1909
zeroidc/vendor/clap/src/app/mod.rs
vendored
Normal file
1909
zeroidc/vendor/clap/src/app/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2236
zeroidc/vendor/clap/src/app/parser.rs
vendored
Normal file
2236
zeroidc/vendor/clap/src/app/parser.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1192
zeroidc/vendor/clap/src/app/settings.rs
vendored
Normal file
1192
zeroidc/vendor/clap/src/app/settings.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
493
zeroidc/vendor/clap/src/app/usage.rs
vendored
Normal file
493
zeroidc/vendor/clap/src/app/usage.rs
vendored
Normal file
@@ -0,0 +1,493 @@
|
||||
// std
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
app::{parser::Parser, settings::AppSettings as AS},
|
||||
args::{settings::ArgSettings, AnyArg, ArgMatcher, PosBuilder},
|
||||
INTERNAL_ERROR_MSG,
|
||||
};
|
||||
|
||||
// Creates a usage string for display. This happens just after all arguments were parsed, but before
|
||||
// any subcommands have been parsed (so as to give subcommands their own usage recursively)
|
||||
pub fn create_usage_with_title(p: &Parser, used: &[&str]) -> String {
|
||||
debugln!("usage::create_usage_with_title;");
|
||||
let mut usage = String::with_capacity(75);
|
||||
usage.push_str("USAGE:\n ");
|
||||
usage.push_str(&*create_usage_no_title(p, used));
|
||||
usage
|
||||
}
|
||||
|
||||
// Creates a usage string to be used in error message (i.e. one with currently used args)
|
||||
pub fn create_error_usage<'a, 'b>(
|
||||
p: &Parser<'a, 'b>,
|
||||
matcher: &'b ArgMatcher<'a>,
|
||||
extra: Option<&str>,
|
||||
) -> String {
|
||||
let mut args: Vec<_> = matcher
|
||||
.arg_names()
|
||||
.iter()
|
||||
.filter(|n| {
|
||||
if let Some(o) = find_by_name!(p, **n, opts, iter) {
|
||||
!o.b.is_set(ArgSettings::Required) && !o.b.is_set(ArgSettings::Hidden)
|
||||
} else if let Some(p) = find_by_name!(p, **n, positionals, values) {
|
||||
!p.b.is_set(ArgSettings::Required) && p.b.is_set(ArgSettings::Hidden)
|
||||
} else {
|
||||
true // flags can't be required, so they're always true
|
||||
}
|
||||
})
|
||||
.copied()
|
||||
.collect();
|
||||
if let Some(r) = extra {
|
||||
args.push(r);
|
||||
}
|
||||
create_usage_with_title(p, &*args)
|
||||
}
|
||||
|
||||
// Creates a usage string (*without title*) if one was not provided by the user manually.
|
||||
pub fn create_usage_no_title(p: &Parser, used: &[&str]) -> String {
|
||||
debugln!("usage::create_usage_no_title;");
|
||||
if let Some(u) = p.meta.usage_str {
|
||||
String::from(&*u)
|
||||
} else if used.is_empty() {
|
||||
create_help_usage(p, true)
|
||||
} else {
|
||||
create_smart_usage(p, used)
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a usage string for display in help messages (i.e. not for errors)
|
||||
pub fn create_help_usage(p: &Parser, incl_reqs: bool) -> String {
|
||||
let mut usage = String::with_capacity(75);
|
||||
let name = p
|
||||
.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| p.meta.bin_name.as_ref().unwrap_or(&p.meta.name));
|
||||
usage.push_str(&*name);
|
||||
let req_string = if incl_reqs {
|
||||
let mut reqs: Vec<&str> = p.required().map(|r| &**r).collect();
|
||||
reqs.sort_unstable();
|
||||
reqs.dedup();
|
||||
get_required_usage_from(p, &reqs, None, None, false)
|
||||
.iter()
|
||||
.fold(String::new(), |a, s| a + &format!(" {}", s)[..])
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let flags = needs_flags_tag(p);
|
||||
if flags && !p.is_set(AS::UnifiedHelpMessage) {
|
||||
usage.push_str(" [FLAGS]");
|
||||
} else if flags {
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
if !p.is_set(AS::UnifiedHelpMessage)
|
||||
&& p.opts
|
||||
.iter()
|
||||
.any(|o| !o.is_set(ArgSettings::Required) && !o.is_set(ArgSettings::Hidden))
|
||||
{
|
||||
usage.push_str(" [OPTIONS]");
|
||||
}
|
||||
|
||||
usage.push_str(&req_string[..]);
|
||||
|
||||
let has_last = p.positionals.values().any(|p| p.is_set(ArgSettings::Last));
|
||||
// places a '--' in the usage string if there are args and options
|
||||
// supporting multiple values
|
||||
if p.opts.iter().any(|o| o.is_set(ArgSettings::Multiple))
|
||||
&& p.positionals
|
||||
.values()
|
||||
.any(|p| !p.is_set(ArgSettings::Required))
|
||||
&& !(p.has_visible_subcommands() || p.is_set(AS::AllowExternalSubcommands))
|
||||
&& !has_last
|
||||
{
|
||||
usage.push_str(" [--]");
|
||||
}
|
||||
let not_req_or_hidden = |p: &PosBuilder| {
|
||||
(!p.is_set(ArgSettings::Required) || p.is_set(ArgSettings::Last))
|
||||
&& !p.is_set(ArgSettings::Hidden)
|
||||
};
|
||||
if p.has_positionals() && p.positionals.values().any(not_req_or_hidden) {
|
||||
if let Some(args_tag) = get_args_tag(p, incl_reqs) {
|
||||
usage.push_str(&*args_tag);
|
||||
} else {
|
||||
usage.push_str(" [ARGS]");
|
||||
}
|
||||
if has_last && incl_reqs {
|
||||
let pos = p
|
||||
.positionals
|
||||
.values()
|
||||
.find(|p| p.b.is_set(ArgSettings::Last))
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
debugln!("usage::create_help_usage: '{}' has .last(true)", pos.name());
|
||||
let req = pos.is_set(ArgSettings::Required);
|
||||
if req
|
||||
&& p.positionals
|
||||
.values()
|
||||
.any(|p| !p.is_set(ArgSettings::Required))
|
||||
{
|
||||
usage.push_str(" -- <");
|
||||
} else if req {
|
||||
usage.push_str(" [--] <");
|
||||
} else {
|
||||
usage.push_str(" [-- <");
|
||||
}
|
||||
usage.push_str(&*pos.name_no_brackets());
|
||||
usage.push('>');
|
||||
usage.push_str(pos.multiple_str());
|
||||
if !req {
|
||||
usage.push(']');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// incl_reqs is only false when this function is called recursively
|
||||
if p.has_visible_subcommands() && incl_reqs || p.is_set(AS::AllowExternalSubcommands) {
|
||||
if p.is_set(AS::SubcommandsNegateReqs) || p.is_set(AS::ArgsNegateSubcommands) {
|
||||
usage.push_str("\n ");
|
||||
if !p.is_set(AS::ArgsNegateSubcommands) {
|
||||
usage.push_str(&*create_help_usage(p, false));
|
||||
} else {
|
||||
usage.push_str(&*name);
|
||||
}
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
} else if p.is_set(AS::SubcommandRequired) || p.is_set(AS::SubcommandRequiredElseHelp) {
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
} else {
|
||||
usage.push_str(" [SUBCOMMAND]");
|
||||
}
|
||||
}
|
||||
usage.shrink_to_fit();
|
||||
debugln!("usage::create_help_usage: usage={}", usage);
|
||||
usage
|
||||
}
|
||||
|
||||
// Creates a context aware usage string, or "smart usage" from currently used
|
||||
// args, and requirements
|
||||
fn create_smart_usage(p: &Parser, used: &[&str]) -> String {
|
||||
debugln!("usage::smart_usage;");
|
||||
let mut usage = String::with_capacity(75);
|
||||
let mut hs: Vec<&str> = p.required().map(|s| &**s).collect();
|
||||
hs.extend_from_slice(used);
|
||||
|
||||
let r_string = get_required_usage_from(p, &hs, None, None, false)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| acc + &format!(" {}", s)[..]);
|
||||
|
||||
usage.push_str(
|
||||
&p.meta
|
||||
.usage
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| p.meta.bin_name.as_ref().unwrap_or(&p.meta.name))[..],
|
||||
);
|
||||
usage.push_str(&*r_string);
|
||||
if p.is_set(AS::SubcommandRequired) {
|
||||
usage.push_str(" <SUBCOMMAND>");
|
||||
}
|
||||
usage.shrink_to_fit();
|
||||
usage
|
||||
}
|
||||
|
||||
// Gets the `[ARGS]` tag for the usage string
|
||||
fn get_args_tag(p: &Parser, incl_reqs: bool) -> Option<String> {
|
||||
debugln!("usage::get_args_tag;");
|
||||
let mut count = 0;
|
||||
'outer: for pos in p
|
||||
.positionals
|
||||
.values()
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||
{
|
||||
debugln!("usage::get_args_tag:iter:{}:", pos.b.name);
|
||||
if let Some(g_vec) = p.groups_for_arg(pos.b.name) {
|
||||
for grp_s in &g_vec {
|
||||
debugln!("usage::get_args_tag:iter:{}:iter:{};", pos.b.name, grp_s);
|
||||
// if it's part of a required group we don't want to count it
|
||||
if p.groups.iter().any(|g| g.required && (&g.name == grp_s)) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
count += 1;
|
||||
debugln!(
|
||||
"usage::get_args_tag:iter: {} Args not required or hidden",
|
||||
count
|
||||
);
|
||||
}
|
||||
if !p.is_set(AS::DontCollapseArgsInUsage) && count > 1 {
|
||||
debugln!("usage::get_args_tag:iter: More than one, returning [ARGS]");
|
||||
return None; // [ARGS]
|
||||
} else if count == 1 && incl_reqs {
|
||||
let pos = p
|
||||
.positionals
|
||||
.values()
|
||||
.find(|pos| {
|
||||
!pos.is_set(ArgSettings::Required)
|
||||
&& !pos.is_set(ArgSettings::Hidden)
|
||||
&& !pos.is_set(ArgSettings::Last)
|
||||
})
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
debugln!(
|
||||
"usage::get_args_tag:iter: Exactly one, returning '{}'",
|
||||
pos.name()
|
||||
);
|
||||
return Some(format!(
|
||||
" [{}]{}",
|
||||
pos.name_no_brackets(),
|
||||
pos.multiple_str()
|
||||
));
|
||||
} else if p.is_set(AS::DontCollapseArgsInUsage) && !p.positionals.is_empty() && incl_reqs {
|
||||
debugln!("usage::get_args_tag:iter: Don't collapse returning all");
|
||||
return Some(
|
||||
p.positionals
|
||||
.values()
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||
.map(|pos| format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str()))
|
||||
.collect::<Vec<_>>()
|
||||
.join(""),
|
||||
);
|
||||
} else if !incl_reqs {
|
||||
debugln!("usage::get_args_tag:iter: incl_reqs=false, building secondary usage string");
|
||||
let highest_req_pos = p
|
||||
.positionals
|
||||
.iter()
|
||||
.filter_map(|(idx, pos)| {
|
||||
if pos.b.is_set(ArgSettings::Required) && !pos.b.is_set(ArgSettings::Last) {
|
||||
Some(idx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.max()
|
||||
.unwrap_or_else(|| p.positionals.len());
|
||||
return Some(
|
||||
p.positionals
|
||||
.iter()
|
||||
.filter_map(|(idx, pos)| {
|
||||
if idx <= highest_req_pos {
|
||||
Some(pos)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Required))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Hidden))
|
||||
.filter(|pos| !pos.is_set(ArgSettings::Last))
|
||||
.map(|pos| format!(" [{}]{}", pos.name_no_brackets(), pos.multiple_str()))
|
||||
.collect::<Vec<_>>()
|
||||
.join(""),
|
||||
);
|
||||
}
|
||||
Some("".into())
|
||||
}
|
||||
|
||||
// Determines if we need the `[FLAGS]` tag in the usage string
|
||||
fn needs_flags_tag(p: &Parser) -> bool {
|
||||
debugln!("usage::needs_flags_tag;");
|
||||
'outer: for f in &p.flags {
|
||||
debugln!("usage::needs_flags_tag:iter: f={};", f.b.name);
|
||||
if let Some(l) = f.s.long {
|
||||
if l == "help" || l == "version" {
|
||||
// Don't print `[FLAGS]` just for help or version
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if let Some(g_vec) = p.groups_for_arg(f.b.name) {
|
||||
for grp_s in &g_vec {
|
||||
debugln!("usage::needs_flags_tag:iter:iter: grp_s={};", grp_s);
|
||||
if p.groups.iter().any(|g| &g.name == grp_s && g.required) {
|
||||
debugln!("usage::needs_flags_tag:iter:iter: Group is required");
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if f.is_set(ArgSettings::Hidden) {
|
||||
continue;
|
||||
}
|
||||
debugln!("usage::needs_flags_tag:iter: [FLAGS] required");
|
||||
return true;
|
||||
}
|
||||
|
||||
debugln!("usage::needs_flags_tag: [FLAGS] not required");
|
||||
false
|
||||
}
|
||||
|
||||
// Returns the required args in usage string form by fully unrolling all groups
|
||||
pub fn get_required_usage_from<'a, 'b>(
|
||||
p: &Parser<'a, 'b>,
|
||||
reqs: &[&'a str],
|
||||
matcher: Option<&ArgMatcher<'a>>,
|
||||
extra: Option<&str>,
|
||||
incl_last: bool,
|
||||
) -> VecDeque<String> {
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: reqs={:?}, extra={:?}",
|
||||
reqs,
|
||||
extra
|
||||
);
|
||||
let mut desc_reqs: Vec<&str> = vec![];
|
||||
desc_reqs.extend(extra);
|
||||
let mut new_reqs: Vec<&str> = vec![];
|
||||
macro_rules! get_requires {
|
||||
(@group $a: ident, $v:ident, $p:ident) => {{
|
||||
if let Some(rl) = p
|
||||
.groups
|
||||
.iter()
|
||||
.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
|
||||
);
|
||||
$v.push(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}};
|
||||
($a:ident, $what:ident, $how:ident, $v:ident, $p:ident) => {{
|
||||
if let Some(rl) = p
|
||||
.$what
|
||||
.$how()
|
||||
.filter(|a| a.b.requires.is_some())
|
||||
.find(|arg| &arg.b.name == $a)
|
||||
.map(|a| a.b.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
|
||||
);
|
||||
$v.push(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
// initialize new_reqs
|
||||
for a in reqs {
|
||||
get_requires!(a, flags, iter, new_reqs, reqs);
|
||||
get_requires!(a, opts, iter, new_reqs, reqs);
|
||||
get_requires!(a, positionals, values, new_reqs, reqs);
|
||||
get_requires!(@group a, new_reqs, reqs);
|
||||
}
|
||||
desc_reqs.extend_from_slice(&*new_reqs);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: after init desc_reqs={:?}",
|
||||
desc_reqs
|
||||
);
|
||||
loop {
|
||||
let mut tmp = vec![];
|
||||
for a in &new_reqs {
|
||||
get_requires!(a, flags, iter, tmp, desc_reqs);
|
||||
get_requires!(a, opts, iter, tmp, desc_reqs);
|
||||
get_requires!(a, positionals, values, tmp, desc_reqs);
|
||||
get_requires!(@group a, tmp, desc_reqs);
|
||||
}
|
||||
if tmp.is_empty() {
|
||||
debugln!("usage::get_required_usage_from: no more children");
|
||||
break;
|
||||
} else {
|
||||
debugln!("usage::get_required_usage_from: after iter tmp={:?}", tmp);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: after iter new_reqs={:?}",
|
||||
new_reqs
|
||||
);
|
||||
desc_reqs.extend_from_slice(&*new_reqs);
|
||||
new_reqs.clear();
|
||||
new_reqs.extend_from_slice(&*tmp);
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: after iter desc_reqs={:?}",
|
||||
desc_reqs
|
||||
);
|
||||
}
|
||||
}
|
||||
desc_reqs.extend_from_slice(reqs);
|
||||
desc_reqs.sort_unstable();
|
||||
desc_reqs.dedup();
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: final desc_reqs={:?}",
|
||||
desc_reqs
|
||||
);
|
||||
let mut ret_val = VecDeque::new();
|
||||
let args_in_groups = p
|
||||
.groups
|
||||
.iter()
|
||||
.filter(|gn| desc_reqs.contains(&gn.name))
|
||||
.flat_map(|g| p.arg_names_in_group(g.name))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let pmap = if let Some(m) = matcher {
|
||||
desc_reqs
|
||||
.iter()
|
||||
.filter(|a| p.positionals.values().any(|p| &&p.b.name == a))
|
||||
.filter(|&pos| !m.contains(pos))
|
||||
.filter_map(|pos| p.positionals.values().find(|x| &x.b.name == pos))
|
||||
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
||||
.filter(|pos| !args_in_groups.contains(&pos.b.name))
|
||||
.map(|pos| (pos.index, pos))
|
||||
.collect::<BTreeMap<u64, &PosBuilder>>() // sort by index
|
||||
} else {
|
||||
desc_reqs
|
||||
.iter()
|
||||
.filter(|a| p.positionals.values().any(|pos| &&pos.b.name == a))
|
||||
.filter_map(|pos| p.positionals.values().find(|x| &x.b.name == pos))
|
||||
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
||||
.filter(|pos| !args_in_groups.contains(&pos.b.name))
|
||||
.map(|pos| (pos.index, pos))
|
||||
.collect::<BTreeMap<u64, &PosBuilder>>() // sort by index
|
||||
};
|
||||
debugln!(
|
||||
"usage::get_required_usage_from: args_in_groups={:?}",
|
||||
args_in_groups
|
||||
);
|
||||
for &p in pmap.values() {
|
||||
let s = p.to_string();
|
||||
if args_in_groups.is_empty() || !args_in_groups.contains(&&*s) {
|
||||
ret_val.push_back(s);
|
||||
}
|
||||
}
|
||||
for a in desc_reqs
|
||||
.iter()
|
||||
.filter(|name| !p.positionals.values().any(|p| &&p.b.name == name))
|
||||
.filter(|name| !p.groups.iter().any(|g| &&g.name == name))
|
||||
.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);
|
||||
let arg = find_by_name!(p, *a, flags, iter)
|
||||
.map(|f| f.to_string())
|
||||
.unwrap_or_else(|| {
|
||||
find_by_name!(p, *a, opts, iter)
|
||||
.map(|o| o.to_string())
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
});
|
||||
ret_val.push_back(arg);
|
||||
}
|
||||
let mut g_vec: Vec<String> = vec![];
|
||||
for g in desc_reqs
|
||||
.iter()
|
||||
.filter(|n| p.groups.iter().any(|g| &&g.name == n))
|
||||
{
|
||||
let g_string = p.args_in_group(g).join("|");
|
||||
let elem = format!("<{}>", &g_string[..g_string.len()]);
|
||||
if !g_vec.contains(&elem) {
|
||||
g_vec.push(elem);
|
||||
}
|
||||
}
|
||||
for g in g_vec {
|
||||
ret_val.push_back(g);
|
||||
}
|
||||
|
||||
ret_val
|
||||
}
|
||||
584
zeroidc/vendor/clap/src/app/validator.rs
vendored
Normal file
584
zeroidc/vendor/clap/src/app/validator.rs
vendored
Normal file
@@ -0,0 +1,584 @@
|
||||
// std
|
||||
#[allow(deprecated, unused_imports)]
|
||||
use std::{ascii::AsciiExt, fmt::Display};
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
app::{
|
||||
parser::{ParseResult, Parser},
|
||||
settings::AppSettings as AS,
|
||||
usage,
|
||||
},
|
||||
args::{settings::ArgSettings, AnyArg, ArgMatcher, MatchedArg},
|
||||
errors::{Error, ErrorKind, Result as ClapResult},
|
||||
fmt::{Colorizer, ColorizerOption},
|
||||
INTERNAL_ERROR_MSG, INVALID_UTF8,
|
||||
};
|
||||
|
||||
pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>)
|
||||
where
|
||||
'a: 'b,
|
||||
'b: 'z;
|
||||
|
||||
impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
|
||||
pub fn new(p: &'z mut Parser<'a, 'b>) -> Self {
|
||||
Validator(p)
|
||||
}
|
||||
|
||||
pub fn validate(
|
||||
&mut self,
|
||||
needs_val_of: ParseResult<'a>,
|
||||
subcmd_name: Option<String>,
|
||||
matcher: &mut ArgMatcher<'a>,
|
||||
) -> ClapResult<()> {
|
||||
debugln!("Validator::validate;");
|
||||
let mut reqs_validated = false;
|
||||
self.0.add_env(matcher)?;
|
||||
self.0.add_defaults(matcher)?;
|
||||
if let ParseResult::Opt(a) = needs_val_of {
|
||||
debugln!("Validator::validate: needs_val_of={:?}", a);
|
||||
let o = {
|
||||
self.0
|
||||
.opts
|
||||
.iter()
|
||||
.find(|o| o.b.name == a)
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.clone()
|
||||
};
|
||||
self.validate_required(matcher)?;
|
||||
reqs_validated = true;
|
||||
let should_err = if let Some(v) = matcher.0.args.get(&*o.b.name) {
|
||||
v.vals.is_empty() && !(o.v.min_vals.is_some() && o.v.min_vals.unwrap() == 0)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if should_err {
|
||||
return Err(Error::empty_value(
|
||||
&o,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if matcher.is_empty()
|
||||
&& matcher.subcommand_name().is_none()
|
||||
&& self.0.is_set(AS::ArgRequiredElseHelp)
|
||||
{
|
||||
let mut out = vec![];
|
||||
self.0.write_help_err(&mut out)?;
|
||||
return Err(Error {
|
||||
message: String::from_utf8_lossy(&*out).into_owned(),
|
||||
kind: ErrorKind::MissingArgumentOrSubcommand,
|
||||
info: None,
|
||||
});
|
||||
}
|
||||
self.validate_blacklist(matcher)?;
|
||||
if !(reqs_validated || self.0.is_set(AS::SubcommandsNegateReqs) && subcmd_name.is_some()) {
|
||||
self.validate_required(matcher)?;
|
||||
}
|
||||
self.validate_matched_args(matcher)?;
|
||||
matcher.usage(usage::create_usage_with_title(self.0, &[]));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_values<A>(
|
||||
&self,
|
||||
arg: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher<'a>,
|
||||
) -> ClapResult<()>
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
debugln!("Validator::validate_arg_values: arg={:?}", arg.name());
|
||||
for val in &ma.vals {
|
||||
if self.0.is_set(AS::StrictUtf8) && val.to_str().is_none() {
|
||||
debugln!(
|
||||
"Validator::validate_arg_values: invalid UTF-8 found in val {:?}",
|
||||
val
|
||||
);
|
||||
return Err(Error::invalid_utf8(
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
if let Some(p_vals) = arg.possible_vals() {
|
||||
debugln!("Validator::validate_arg_values: possible_vals={:?}", p_vals);
|
||||
let val_str = val.to_string_lossy();
|
||||
let ok = if arg.is_set(ArgSettings::CaseInsensitive) {
|
||||
p_vals.iter().any(|pv| pv.eq_ignore_ascii_case(&*val_str))
|
||||
} else {
|
||||
p_vals.contains(&&*val_str)
|
||||
};
|
||||
if !ok {
|
||||
return Err(Error::invalid_value(
|
||||
val_str,
|
||||
p_vals,
|
||||
arg,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if !arg.is_set(ArgSettings::EmptyValues)
|
||||
&& val.is_empty()
|
||||
&& matcher.contains(&*arg.name())
|
||||
{
|
||||
debugln!("Validator::validate_arg_values: illegal empty val found");
|
||||
return Err(Error::empty_value(
|
||||
arg,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
if let Some(vtor) = arg.validator() {
|
||||
debug!("Validator::validate_arg_values: checking validator...");
|
||||
if let Err(e) = vtor(val.to_string_lossy().into_owned()) {
|
||||
sdebugln!("error");
|
||||
return Err(Error::value_validation(Some(arg), e, self.0.color()));
|
||||
} else {
|
||||
sdebugln!("good");
|
||||
}
|
||||
}
|
||||
if let Some(vtor) = arg.validator_os() {
|
||||
debug!("Validator::validate_arg_values: checking validator_os...");
|
||||
if let Err(e) = vtor(val) {
|
||||
sdebugln!("error");
|
||||
return Err(Error::value_validation(
|
||||
Some(arg),
|
||||
(*e).to_string_lossy().to_string(),
|
||||
self.0.color(),
|
||||
));
|
||||
} else {
|
||||
sdebugln!("good");
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_err(&self, name: &str, matcher: &ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("build_err!: name={}", name);
|
||||
let mut c_with = find_from!(self.0, &name, blacklist, matcher);
|
||||
c_with = c_with.or_else(|| {
|
||||
self.0
|
||||
.find_any_arg(name)
|
||||
.and_then(|aa| aa.blacklist())
|
||||
.and_then(|bl| bl.iter().find(|arg| matcher.contains(arg)))
|
||||
.and_then(|an| self.0.find_any_arg(an))
|
||||
.map(|aa| format!("{}", aa))
|
||||
});
|
||||
debugln!("build_err!: '{:?}' conflicts with '{}'", c_with, &name);
|
||||
// matcher.remove(&name);
|
||||
let usg = usage::create_error_usage(self.0, matcher, None);
|
||||
if let Some(f) = find_by_name!(self.0, name, flags, iter) {
|
||||
debugln!("build_err!: It was a flag...");
|
||||
Err(Error::argument_conflict(f, c_with, &*usg, self.0.color()))
|
||||
} else if let Some(o) = find_by_name!(self.0, name, opts, iter) {
|
||||
debugln!("build_err!: It was an option...");
|
||||
Err(Error::argument_conflict(o, c_with, &*usg, self.0.color()))
|
||||
} else {
|
||||
match find_by_name!(self.0, name, positionals, values) {
|
||||
Some(p) => {
|
||||
debugln!("build_err!: It was a positional...");
|
||||
Err(Error::argument_conflict(p, c_with, &*usg, self.0.color()))
|
||||
}
|
||||
None => panic!("{}", INTERNAL_ERROR_MSG),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_blacklist;");
|
||||
let mut conflicts: Vec<&str> = vec![];
|
||||
for (&name, _) in matcher.iter() {
|
||||
debugln!("Validator::validate_blacklist:iter:{};", name);
|
||||
if let Some(grps) = self.0.groups_for_arg(name) {
|
||||
for grp in &grps {
|
||||
if let Some(g) = self.0.groups.iter().find(|g| &g.name == grp) {
|
||||
if !g.multiple {
|
||||
for arg in &g.args {
|
||||
if arg == &name {
|
||||
continue;
|
||||
}
|
||||
conflicts.push(arg);
|
||||
}
|
||||
}
|
||||
if let Some(ref gc) = g.conflicts {
|
||||
conflicts.extend(&*gc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(arg) = find_any_by_name!(self.0, name) {
|
||||
if let Some(bl) = arg.blacklist() {
|
||||
for conf in bl {
|
||||
if matcher.get(conf).is_some() {
|
||||
conflicts.push(conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debugln!("Validator::validate_blacklist:iter:{}:group;", name);
|
||||
let args = self.0.arg_names_in_group(name);
|
||||
for arg in &args {
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}:group:iter:{};",
|
||||
name,
|
||||
arg
|
||||
);
|
||||
if let Some(bl) = find_any_by_name!(self.0, *arg).unwrap().blacklist() {
|
||||
for conf in bl {
|
||||
if matcher.get(conf).is_some() {
|
||||
conflicts.push(conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for name in &conflicts {
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}: Checking blacklisted arg",
|
||||
name
|
||||
);
|
||||
let mut should_err = false;
|
||||
if self.0.groups.iter().any(|g| &g.name == name) {
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}: groups contains it...",
|
||||
name
|
||||
);
|
||||
for n in self.0.arg_names_in_group(name) {
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}:iter:{}: looking in group...",
|
||||
name,
|
||||
n
|
||||
);
|
||||
if matcher.contains(n) {
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}:iter:{}: matcher contains it...",
|
||||
name,
|
||||
n
|
||||
);
|
||||
return self.build_err(n, matcher);
|
||||
}
|
||||
}
|
||||
} else if let Some(ma) = matcher.get(name) {
|
||||
debugln!(
|
||||
"Validator::validate_blacklist:iter:{}: matcher contains it...",
|
||||
name
|
||||
);
|
||||
should_err = ma.occurs > 0;
|
||||
}
|
||||
if should_err {
|
||||
return self.build_err(*name, matcher);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_matched_args;");
|
||||
for (name, ma) in matcher.iter() {
|
||||
debugln!(
|
||||
"Validator::validate_matched_args:iter:{}: vals={:#?}",
|
||||
name,
|
||||
ma.vals
|
||||
);
|
||||
if let Some(opt) = find_by_name!(self.0, *name, opts, iter) {
|
||||
self.validate_arg_num_vals(opt, ma, matcher)?;
|
||||
self.validate_arg_values(opt, ma, matcher)?;
|
||||
self.validate_arg_requires(opt, ma, matcher)?;
|
||||
self.validate_arg_num_occurs(opt, ma, matcher)?;
|
||||
} else if let Some(flag) = find_by_name!(self.0, *name, flags, iter) {
|
||||
self.validate_arg_requires(flag, ma, matcher)?;
|
||||
self.validate_arg_num_occurs(flag, ma, matcher)?;
|
||||
} else if let Some(pos) = find_by_name!(self.0, *name, positionals, values) {
|
||||
self.validate_arg_num_vals(pos, ma, matcher)?;
|
||||
self.validate_arg_num_occurs(pos, ma, matcher)?;
|
||||
self.validate_arg_values(pos, ma, matcher)?;
|
||||
self.validate_arg_requires(pos, ma, matcher)?;
|
||||
} else {
|
||||
let grp = self
|
||||
.0
|
||||
.groups
|
||||
.iter()
|
||||
.find(|g| &g.name == name)
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
if let Some(ref g_reqs) = grp.requires {
|
||||
if g_reqs.iter().any(|&n| !matcher.contains(n)) {
|
||||
return self.missing_required_error(matcher, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_num_occurs<A>(
|
||||
&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher,
|
||||
) -> ClapResult<()>
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
debugln!("Validator::validate_arg_num_occurs: a={};", a.name());
|
||||
if ma.occurs > 1 && !a.is_set(ArgSettings::Multiple) {
|
||||
// Not the first time, and we don't allow multiples
|
||||
return Err(Error::unexpected_multiple_usage(
|
||||
a,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_num_vals<A>(
|
||||
&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher,
|
||||
) -> ClapResult<()>
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
debugln!("Validator::validate_arg_num_vals:{}", a.name());
|
||||
if let Some(num) = a.num_vals() {
|
||||
debugln!("Validator::validate_arg_num_vals: num_vals set...{}", num);
|
||||
let should_err = if a.is_set(ArgSettings::Multiple) {
|
||||
((ma.vals.len() as u64) % num) != 0
|
||||
} else {
|
||||
num != (ma.vals.len() as u64)
|
||||
};
|
||||
if should_err {
|
||||
debugln!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
|
||||
return Err(Error::wrong_number_of_values(
|
||||
a,
|
||||
num,
|
||||
if a.is_set(ArgSettings::Multiple) {
|
||||
ma.vals.len() % num as usize
|
||||
} else {
|
||||
ma.vals.len()
|
||||
},
|
||||
if ma.vals.len() == 1
|
||||
|| (a.is_set(ArgSettings::Multiple) && (ma.vals.len() % num as usize) == 1)
|
||||
{
|
||||
"as"
|
||||
} else {
|
||||
"ere"
|
||||
},
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(num) = a.max_vals() {
|
||||
debugln!("Validator::validate_arg_num_vals: max_vals set...{}", num);
|
||||
if (ma.vals.len() as u64) > num {
|
||||
debugln!("Validator::validate_arg_num_vals: Sending error TooManyValues");
|
||||
return Err(Error::too_many_values(
|
||||
ma.vals
|
||||
.iter()
|
||||
.last()
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.to_str()
|
||||
.expect(INVALID_UTF8),
|
||||
a,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let min_vals_zero = if let Some(num) = a.min_vals() {
|
||||
debugln!("Validator::validate_arg_num_vals: min_vals set: {}", num);
|
||||
if (ma.vals.len() as u64) < num && num != 0 {
|
||||
debugln!("Validator::validate_arg_num_vals: Sending error TooFewValues");
|
||||
return Err(Error::too_few_values(
|
||||
a,
|
||||
num,
|
||||
ma.vals.len(),
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
num == 0
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// Issue 665 (https://github.com/clap-rs/clap/issues/665)
|
||||
// Issue 1105 (https://github.com/clap-rs/clap/issues/1105)
|
||||
if a.takes_value() && !min_vals_zero && ma.vals.is_empty() {
|
||||
return Err(Error::empty_value(
|
||||
a,
|
||||
&*usage::create_error_usage(self.0, matcher, None),
|
||||
self.0.color(),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_requires<A>(
|
||||
&self,
|
||||
a: &A,
|
||||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher,
|
||||
) -> ClapResult<()>
|
||||
where
|
||||
A: AnyArg<'a, 'b> + Display,
|
||||
{
|
||||
debugln!("Validator::validate_arg_requires:{};", a.name());
|
||||
if let Some(a_reqs) = a.requires() {
|
||||
for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) {
|
||||
let missing_req =
|
||||
|v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name);
|
||||
if ma.vals.iter().any(missing_req) {
|
||||
return self.missing_required_error(matcher, None);
|
||||
}
|
||||
}
|
||||
for &(_, name) in a_reqs.iter().filter(|&&(val, _)| val.is_none()) {
|
||||
if !matcher.contains(name) {
|
||||
return self.missing_required_error(matcher, Some(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_required(&mut self, matcher: &ArgMatcher) -> ClapResult<()> {
|
||||
debugln!(
|
||||
"Validator::validate_required: required={:?};",
|
||||
self.0.required
|
||||
);
|
||||
|
||||
let mut should_err = false;
|
||||
let mut to_rem = Vec::new();
|
||||
for name in &self.0.required {
|
||||
debugln!("Validator::validate_required:iter:{}:", name);
|
||||
if matcher.contains(name) {
|
||||
continue;
|
||||
}
|
||||
if to_rem.contains(name) {
|
||||
continue;
|
||||
} else if let Some(a) = find_any_by_name!(self.0, *name) {
|
||||
if self.is_missing_required_ok(a, matcher) {
|
||||
to_rem.push(a.name());
|
||||
if let Some(reqs) = a.requires() {
|
||||
for r in reqs
|
||||
.iter()
|
||||
.filter(|&&(val, _)| val.is_none())
|
||||
.map(|&(_, name)| name)
|
||||
{
|
||||
to_rem.push(r);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
should_err = true;
|
||||
break;
|
||||
}
|
||||
if should_err {
|
||||
for r in &to_rem {
|
||||
'inner: for i in (0..self.0.required.len()).rev() {
|
||||
if &self.0.required[i] == r {
|
||||
self.0.required.swap_remove(i);
|
||||
break 'inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self.missing_required_error(matcher, None);
|
||||
}
|
||||
|
||||
// Validate the conditionally required args
|
||||
for &(a, v, r) in &self.0.r_ifs {
|
||||
if let Some(ma) = matcher.get(a) {
|
||||
if matcher.get(r).is_none() && ma.vals.iter().any(|val| val == v) {
|
||||
return self.missing_required_error(matcher, Some(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_arg_conflicts(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> {
|
||||
debugln!("Validator::validate_arg_conflicts: a={:?};", a.name());
|
||||
a.blacklist().map(|bl| {
|
||||
bl.iter().any(|conf| {
|
||||
matcher.contains(conf)
|
||||
|| self
|
||||
.0
|
||||
.groups
|
||||
.iter()
|
||||
.find(|g| &g.name == conf)
|
||||
.map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn validate_required_unless(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> {
|
||||
debugln!("Validator::validate_required_unless: a={:?};", a.name());
|
||||
macro_rules! check {
|
||||
($how:ident, $_self:expr, $a:ident, $m:ident) => {{
|
||||
$a.required_unless().map(|ru| {
|
||||
ru.iter().$how(|n| {
|
||||
$m.contains(n) || {
|
||||
if let Some(grp) = $_self.groups.iter().find(|g| &g.name == n) {
|
||||
grp.args.iter().any(|arg| $m.contains(arg))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}};
|
||||
}
|
||||
if a.is_set(ArgSettings::RequiredUnlessAll) {
|
||||
check!(all, self.0, a, matcher)
|
||||
} else {
|
||||
check!(any, self.0, a, matcher)
|
||||
}
|
||||
}
|
||||
|
||||
fn missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()> {
|
||||
debugln!("Validator::missing_required_error: extra={:?}", extra);
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: self.0.color(),
|
||||
});
|
||||
let mut reqs = self.0.required.iter().map(|&r| &*r).collect::<Vec<_>>();
|
||||
if let Some(r) = extra {
|
||||
reqs.push(r);
|
||||
}
|
||||
reqs.retain(|n| !matcher.contains(n));
|
||||
reqs.dedup();
|
||||
debugln!("Validator::missing_required_error: reqs={:#?}", reqs);
|
||||
let req_args =
|
||||
usage::get_required_usage_from(self.0, &reqs[..], Some(matcher), extra, true)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| {
|
||||
acc + &format!("\n {}", c.error(s))[..]
|
||||
});
|
||||
debugln!(
|
||||
"Validator::missing_required_error: req_args={:#?}",
|
||||
req_args
|
||||
);
|
||||
Err(Error::missing_required_argument(
|
||||
&*req_args,
|
||||
&*usage::create_error_usage(self.0, matcher, extra),
|
||||
self.0.color(),
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_missing_required_ok(&self, a: &AnyArg, matcher: &ArgMatcher) -> bool {
|
||||
debugln!("Validator::is_missing_required_ok: a={}", a.name());
|
||||
self.validate_arg_conflicts(a, matcher).unwrap_or(false)
|
||||
|| self.validate_required_unless(a, matcher).unwrap_or(false)
|
||||
}
|
||||
}
|
||||
139
zeroidc/vendor/clap/src/args/any_arg.rs
vendored
Normal file
139
zeroidc/vendor/clap/src/args/any_arg.rs
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
// Std
|
||||
use std::{
|
||||
ffi::{OsStr, OsString},
|
||||
fmt as std_fmt,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
args::settings::ArgSettings,
|
||||
map::{self, VecMap},
|
||||
INTERNAL_ERROR_MSG,
|
||||
};
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait AnyArg<'n, 'e>: std_fmt::Display {
|
||||
fn name(&self) -> &'n str;
|
||||
fn overrides(&self) -> Option<&[&'e str]>;
|
||||
fn aliases(&self) -> Option<Vec<&'e str>>;
|
||||
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]>;
|
||||
fn blacklist(&self) -> Option<&[&'e str]>;
|
||||
fn required_unless(&self) -> Option<&[&'e str]>;
|
||||
fn is_set(&self, setting: ArgSettings) -> bool;
|
||||
fn set(&mut self, setting: ArgSettings);
|
||||
fn has_switch(&self) -> bool;
|
||||
fn max_vals(&self) -> Option<u64>;
|
||||
fn min_vals(&self) -> Option<u64>;
|
||||
fn num_vals(&self) -> Option<u64>;
|
||||
fn possible_vals(&self) -> Option<&[&'e str]>;
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator(&self) -> Option<&Rc<Fn(String) -> Result<(), String>>>;
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> Result<(), OsString>>>;
|
||||
fn short(&self) -> Option<char>;
|
||||
fn long(&self) -> Option<&'e str>;
|
||||
fn val_delim(&self) -> Option<char>;
|
||||
fn takes_value(&self) -> bool;
|
||||
fn val_names(&self) -> Option<&VecMap<&'e str>>;
|
||||
fn help(&self) -> Option<&'e str>;
|
||||
fn long_help(&self) -> Option<&'e str>;
|
||||
fn default_val(&self) -> Option<&'e OsStr>;
|
||||
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>>;
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)>;
|
||||
fn longest_filter(&self) -> bool;
|
||||
fn val_terminator(&self) -> Option<&'e str>;
|
||||
}
|
||||
|
||||
pub trait DispOrder {
|
||||
fn disp_ord(&self) -> usize;
|
||||
}
|
||||
|
||||
impl<'n, 'e, 'z, T: ?Sized> AnyArg<'n, 'e> for &'z T
|
||||
where
|
||||
T: AnyArg<'n, 'e> + 'z,
|
||||
{
|
||||
fn name(&self) -> &'n str {
|
||||
(*self).name()
|
||||
}
|
||||
fn overrides(&self) -> Option<&[&'e str]> {
|
||||
(*self).overrides()
|
||||
}
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||
(*self).aliases()
|
||||
}
|
||||
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
|
||||
(*self).requires()
|
||||
}
|
||||
fn blacklist(&self) -> Option<&[&'e str]> {
|
||||
(*self).blacklist()
|
||||
}
|
||||
fn required_unless(&self) -> Option<&[&'e str]> {
|
||||
(*self).required_unless()
|
||||
}
|
||||
fn is_set(&self, a: ArgSettings) -> bool {
|
||||
(*self).is_set(a)
|
||||
}
|
||||
fn set(&mut self, _: ArgSettings) {
|
||||
panic!("{}", INTERNAL_ERROR_MSG)
|
||||
}
|
||||
fn has_switch(&self) -> bool {
|
||||
(*self).has_switch()
|
||||
}
|
||||
fn max_vals(&self) -> Option<u64> {
|
||||
(*self).max_vals()
|
||||
}
|
||||
fn min_vals(&self) -> Option<u64> {
|
||||
(*self).min_vals()
|
||||
}
|
||||
fn num_vals(&self) -> Option<u64> {
|
||||
(*self).num_vals()
|
||||
}
|
||||
fn possible_vals(&self) -> Option<&[&'e str]> {
|
||||
(*self).possible_vals()
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator(&self) -> Option<&Rc<Fn(String) -> Result<(), String>>> {
|
||||
(*self).validator()
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> Result<(), OsString>>> {
|
||||
(*self).validator_os()
|
||||
}
|
||||
fn short(&self) -> Option<char> {
|
||||
(*self).short()
|
||||
}
|
||||
fn long(&self) -> Option<&'e str> {
|
||||
(*self).long()
|
||||
}
|
||||
fn val_delim(&self) -> Option<char> {
|
||||
(*self).val_delim()
|
||||
}
|
||||
fn takes_value(&self) -> bool {
|
||||
(*self).takes_value()
|
||||
}
|
||||
fn val_names(&self) -> Option<&VecMap<&'e str>> {
|
||||
(*self).val_names()
|
||||
}
|
||||
fn help(&self) -> Option<&'e str> {
|
||||
(*self).help()
|
||||
}
|
||||
fn long_help(&self) -> Option<&'e str> {
|
||||
(*self).long_help()
|
||||
}
|
||||
fn default_val(&self) -> Option<&'e OsStr> {
|
||||
(*self).default_val()
|
||||
}
|
||||
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
|
||||
(*self).default_vals_ifs()
|
||||
}
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
|
||||
(*self).env()
|
||||
}
|
||||
fn longest_filter(&self) -> bool {
|
||||
(*self).longest_filter()
|
||||
}
|
||||
fn val_terminator(&self) -> Option<&'e str> {
|
||||
(*self).val_terminator()
|
||||
}
|
||||
}
|
||||
3961
zeroidc/vendor/clap/src/args/arg.rs
vendored
Normal file
3961
zeroidc/vendor/clap/src/args/arg.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
48
zeroidc/vendor/clap/src/args/arg_builder/base.rs
vendored
Normal file
48
zeroidc/vendor/clap/src/args/arg_builder/base.rs
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
use crate::args::{Arg, ArgFlags, ArgSettings};
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Base<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
pub name: &'a str,
|
||||
pub help: Option<&'b str>,
|
||||
pub long_help: Option<&'b str>,
|
||||
pub blacklist: Option<Vec<&'a str>>,
|
||||
pub settings: ArgFlags,
|
||||
pub r_unless: Option<Vec<&'a str>>,
|
||||
pub overrides: Option<Vec<&'a str>>,
|
||||
pub groups: Option<Vec<&'a str>>,
|
||||
pub requires: Option<Vec<(Option<&'b str>, &'a str)>>,
|
||||
}
|
||||
|
||||
impl<'n, 'e> Base<'n, 'e> {
|
||||
pub fn new(name: &'n str) -> Self {
|
||||
Base {
|
||||
name,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, s: ArgSettings) {
|
||||
self.settings.set(s);
|
||||
}
|
||||
pub fn unset(&mut self, s: ArgSettings) {
|
||||
self.settings.unset(s);
|
||||
}
|
||||
pub fn is_set(&self, s: ArgSettings) -> bool {
|
||||
self.settings.is_set(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Base<'n, 'e> {
|
||||
fn from(a: &'z Arg<'n, 'e>) -> Self {
|
||||
a.b.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> PartialEq for Base<'n, 'e> {
|
||||
fn eq(&self, other: &Base<'n, 'e>) -> bool {
|
||||
self.name == other.name
|
||||
}
|
||||
}
|
||||
216
zeroidc/vendor/clap/src/args/arg_builder/flag.rs
vendored
Normal file
216
zeroidc/vendor/clap/src/args/arg_builder/flag.rs
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
// Std
|
||||
use std::{
|
||||
convert::From,
|
||||
ffi::{OsStr, OsString},
|
||||
fmt::{Display, Formatter, Result},
|
||||
mem,
|
||||
rc::Rc,
|
||||
result::Result as StdResult,
|
||||
};
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
args::{AnyArg, Arg, ArgSettings, Base, DispOrder, Switched},
|
||||
map::{self, VecMap},
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
#[doc(hidden)]
|
||||
pub struct FlagBuilder<'n, 'e>
|
||||
where
|
||||
'n: 'e,
|
||||
{
|
||||
pub b: Base<'n, 'e>,
|
||||
pub s: Switched<'e>,
|
||||
}
|
||||
|
||||
impl<'n, 'e> FlagBuilder<'n, 'e> {
|
||||
pub fn new(name: &'n str) -> Self {
|
||||
FlagBuilder {
|
||||
b: Base::new(name),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
|
||||
fn from(a: &'z Arg<'a, 'b>) -> Self {
|
||||
FlagBuilder {
|
||||
b: Base::from(a),
|
||||
s: Switched::from(a),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> From<Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
|
||||
fn from(mut a: Arg<'a, 'b>) -> Self {
|
||||
FlagBuilder {
|
||||
b: mem::take(&mut a.b),
|
||||
s: mem::take(&mut a.s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> Display for FlagBuilder<'n, 'e> {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
if let Some(l) = self.s.long {
|
||||
write!(f, "--{}", l)?;
|
||||
} else {
|
||||
write!(f, "-{}", self.s.short.unwrap())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> {
|
||||
fn name(&self) -> &'n str {
|
||||
self.b.name
|
||||
}
|
||||
fn overrides(&self) -> Option<&[&'e str]> {
|
||||
self.b.overrides.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
|
||||
self.b.requires.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn blacklist(&self) -> Option<&[&'e str]> {
|
||||
self.b.blacklist.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn required_unless(&self) -> Option<&[&'e str]> {
|
||||
self.b.r_unless.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn is_set(&self, s: ArgSettings) -> bool {
|
||||
self.b.settings.is_set(s)
|
||||
}
|
||||
fn has_switch(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn takes_value(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn set(&mut self, s: ArgSettings) {
|
||||
self.b.settings.set(s)
|
||||
}
|
||||
fn max_vals(&self) -> Option<u64> {
|
||||
None
|
||||
}
|
||||
fn val_names(&self) -> Option<&VecMap<&'e str>> {
|
||||
None
|
||||
}
|
||||
fn num_vals(&self) -> Option<u64> {
|
||||
None
|
||||
}
|
||||
fn possible_vals(&self) -> Option<&[&'e str]> {
|
||||
None
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> {
|
||||
None
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> {
|
||||
None
|
||||
}
|
||||
fn min_vals(&self) -> Option<u64> {
|
||||
None
|
||||
}
|
||||
fn short(&self) -> Option<char> {
|
||||
self.s.short
|
||||
}
|
||||
fn long(&self) -> Option<&'e str> {
|
||||
self.s.long
|
||||
}
|
||||
fn val_delim(&self) -> Option<char> {
|
||||
None
|
||||
}
|
||||
fn help(&self) -> Option<&'e str> {
|
||||
self.b.help
|
||||
}
|
||||
fn long_help(&self) -> Option<&'e str> {
|
||||
self.b.long_help
|
||||
}
|
||||
fn val_terminator(&self) -> Option<&'e str> {
|
||||
None
|
||||
}
|
||||
fn default_val(&self) -> Option<&'e OsStr> {
|
||||
None
|
||||
}
|
||||
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
|
||||
None
|
||||
}
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
|
||||
None
|
||||
}
|
||||
fn longest_filter(&self) -> bool {
|
||||
self.s.long.is_some()
|
||||
}
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||
if let Some(ref aliases) = self.s.aliases {
|
||||
let vis_aliases: Vec<_> = aliases
|
||||
.iter()
|
||||
.filter_map(|&(n, v)| if v { Some(n) } else { None })
|
||||
.collect();
|
||||
if vis_aliases.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(vis_aliases)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> DispOrder for FlagBuilder<'n, 'e> {
|
||||
fn disp_ord(&self) -> usize {
|
||||
self.s.disp_ord
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> PartialEq for FlagBuilder<'n, 'e> {
|
||||
fn eq(&self, other: &FlagBuilder<'n, 'e>) -> bool {
|
||||
self.b == other.b
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::FlagBuilder;
|
||||
use crate::args::settings::ArgSettings;
|
||||
|
||||
#[test]
|
||||
fn flagbuilder_display() {
|
||||
let mut f = FlagBuilder::new("flg");
|
||||
f.b.settings.set(ArgSettings::Multiple);
|
||||
f.s.long = Some("flag");
|
||||
|
||||
assert_eq!(&*format!("{}", f), "--flag");
|
||||
|
||||
let mut f2 = FlagBuilder::new("flg");
|
||||
f2.s.short = Some('f');
|
||||
|
||||
assert_eq!(&*format!("{}", f2), "-f");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flagbuilder_display_single_alias() {
|
||||
let mut f = FlagBuilder::new("flg");
|
||||
f.s.long = Some("flag");
|
||||
f.s.aliases = Some(vec![("als", true)]);
|
||||
|
||||
assert_eq!(&*format!("{}", f), "--flag");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flagbuilder_display_multiple_aliases() {
|
||||
let mut f = FlagBuilder::new("flg");
|
||||
f.s.short = Some('f');
|
||||
f.s.aliases = Some(vec![
|
||||
("alias_not_visible", false),
|
||||
("f2", true),
|
||||
("f3", true),
|
||||
("f4", true),
|
||||
]);
|
||||
assert_eq!(&*format!("{}", f), "-f");
|
||||
}
|
||||
}
|
||||
13
zeroidc/vendor/clap/src/args/arg_builder/mod.rs
vendored
Normal file
13
zeroidc/vendor/clap/src/args/arg_builder/mod.rs
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
pub use self::base::Base;
|
||||
pub use self::flag::FlagBuilder;
|
||||
pub use self::option::OptBuilder;
|
||||
pub use self::positional::PosBuilder;
|
||||
pub use self::switched::Switched;
|
||||
pub use self::valued::Valued;
|
||||
|
||||
mod base;
|
||||
mod flag;
|
||||
mod option;
|
||||
mod positional;
|
||||
mod switched;
|
||||
mod valued;
|
||||
295
zeroidc/vendor/clap/src/args/arg_builder/option.rs
vendored
Normal file
295
zeroidc/vendor/clap/src/args/arg_builder/option.rs
vendored
Normal file
@@ -0,0 +1,295 @@
|
||||
// Std
|
||||
use std::{
|
||||
ffi::{OsStr, OsString},
|
||||
fmt::{Display, Formatter, Result},
|
||||
mem,
|
||||
rc::Rc,
|
||||
result::Result as StdResult,
|
||||
};
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
args::{AnyArg, Arg, ArgSettings, Base, DispOrder, Switched, Valued},
|
||||
map::{self, VecMap},
|
||||
INTERNAL_ERROR_MSG,
|
||||
};
|
||||
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[doc(hidden)]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct OptBuilder<'n, 'e>
|
||||
where
|
||||
'n: 'e,
|
||||
{
|
||||
pub b: Base<'n, 'e>,
|
||||
pub s: Switched<'e>,
|
||||
pub v: Valued<'n, 'e>,
|
||||
}
|
||||
|
||||
impl<'n, 'e> OptBuilder<'n, 'e> {
|
||||
pub fn new(name: &'n str) -> Self {
|
||||
OptBuilder {
|
||||
b: Base::new(name),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for OptBuilder<'n, 'e> {
|
||||
fn from(a: &'z Arg<'n, 'e>) -> Self {
|
||||
OptBuilder {
|
||||
b: Base::from(a),
|
||||
s: Switched::from(a),
|
||||
v: Valued::from(a),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> From<Arg<'n, 'e>> for OptBuilder<'n, 'e> {
|
||||
fn from(mut a: Arg<'n, 'e>) -> Self {
|
||||
a.v.fill_in();
|
||||
OptBuilder {
|
||||
b: mem::take(&mut a.b),
|
||||
s: mem::take(&mut a.s),
|
||||
v: mem::take(&mut a.v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> Display for OptBuilder<'n, 'e> {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
debugln!("OptBuilder::fmt:{}", self.b.name);
|
||||
let sep = if self.b.is_set(ArgSettings::RequireEquals) {
|
||||
"="
|
||||
} else {
|
||||
" "
|
||||
};
|
||||
// Write the name such --long or -l
|
||||
if let Some(l) = self.s.long {
|
||||
write!(f, "--{}{}", l, sep)?;
|
||||
} else {
|
||||
write!(f, "-{}{}", self.s.short.unwrap(), sep)?;
|
||||
}
|
||||
let delim = if self.is_set(ArgSettings::RequireDelimiter) {
|
||||
self.v.val_delim.expect(INTERNAL_ERROR_MSG)
|
||||
} else {
|
||||
' '
|
||||
};
|
||||
|
||||
// Write the values such as <name1> <name2>
|
||||
if let Some(ref vec) = self.v.val_names {
|
||||
let mut it = vec.iter().peekable();
|
||||
while let Some((_, val)) = it.next() {
|
||||
write!(f, "<{}>", val)?;
|
||||
if it.peek().is_some() {
|
||||
write!(f, "{}", delim)?;
|
||||
}
|
||||
}
|
||||
let num = vec.len();
|
||||
if self.is_set(ArgSettings::Multiple) && num == 1 {
|
||||
write!(f, "...")?;
|
||||
}
|
||||
} else if let Some(num) = self.v.num_vals {
|
||||
let mut it = (0..num).peekable();
|
||||
while let Some(_) = it.next() {
|
||||
write!(f, "<{}>", self.b.name)?;
|
||||
if it.peek().is_some() {
|
||||
write!(f, "{}", delim)?;
|
||||
}
|
||||
}
|
||||
if self.is_set(ArgSettings::Multiple) && num == 1 {
|
||||
write!(f, "...")?;
|
||||
}
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"<{}>{}",
|
||||
self.b.name,
|
||||
if self.is_set(ArgSettings::Multiple) {
|
||||
"..."
|
||||
} else {
|
||||
""
|
||||
}
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> {
|
||||
fn name(&self) -> &'n str {
|
||||
self.b.name
|
||||
}
|
||||
fn overrides(&self) -> Option<&[&'e str]> {
|
||||
self.b.overrides.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
|
||||
self.b.requires.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn blacklist(&self) -> Option<&[&'e str]> {
|
||||
self.b.blacklist.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn required_unless(&self) -> Option<&[&'e str]> {
|
||||
self.b.r_unless.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn val_names(&self) -> Option<&VecMap<&'e str>> {
|
||||
self.v.val_names.as_ref()
|
||||
}
|
||||
fn is_set(&self, s: ArgSettings) -> bool {
|
||||
self.b.settings.is_set(s)
|
||||
}
|
||||
fn has_switch(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn set(&mut self, s: ArgSettings) {
|
||||
self.b.settings.set(s)
|
||||
}
|
||||
fn max_vals(&self) -> Option<u64> {
|
||||
self.v.max_vals
|
||||
}
|
||||
fn val_terminator(&self) -> Option<&'e str> {
|
||||
self.v.terminator
|
||||
}
|
||||
fn num_vals(&self) -> Option<u64> {
|
||||
self.v.num_vals
|
||||
}
|
||||
fn possible_vals(&self) -> Option<&[&'e str]> {
|
||||
self.v.possible_vals.as_ref().map(|o| &o[..])
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> {
|
||||
self.v.validator.as_ref()
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> {
|
||||
self.v.validator_os.as_ref()
|
||||
}
|
||||
fn min_vals(&self) -> Option<u64> {
|
||||
self.v.min_vals
|
||||
}
|
||||
fn short(&self) -> Option<char> {
|
||||
self.s.short
|
||||
}
|
||||
fn long(&self) -> Option<&'e str> {
|
||||
self.s.long
|
||||
}
|
||||
fn val_delim(&self) -> Option<char> {
|
||||
self.v.val_delim
|
||||
}
|
||||
fn takes_value(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn help(&self) -> Option<&'e str> {
|
||||
self.b.help
|
||||
}
|
||||
fn long_help(&self) -> Option<&'e str> {
|
||||
self.b.long_help
|
||||
}
|
||||
fn default_val(&self) -> Option<&'e OsStr> {
|
||||
self.v.default_val
|
||||
}
|
||||
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
|
||||
self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
|
||||
}
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
|
||||
self.v
|
||||
.env
|
||||
.as_ref()
|
||||
.map(|&(key, ref value)| (key, value.as_ref()))
|
||||
}
|
||||
fn longest_filter(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||
if let Some(ref aliases) = self.s.aliases {
|
||||
let vis_aliases: Vec<_> = aliases
|
||||
.iter()
|
||||
.filter_map(|&(n, v)| if v { Some(n) } else { None })
|
||||
.collect();
|
||||
if vis_aliases.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(vis_aliases)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> DispOrder for OptBuilder<'n, 'e> {
|
||||
fn disp_ord(&self) -> usize {
|
||||
self.s.disp_ord
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> PartialEq for OptBuilder<'n, 'e> {
|
||||
fn eq(&self, other: &OptBuilder<'n, 'e>) -> bool {
|
||||
self.b == other.b
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::OptBuilder;
|
||||
use crate::{args::settings::ArgSettings, map::VecMap};
|
||||
|
||||
#[test]
|
||||
fn optbuilder_display1() {
|
||||
let mut o = OptBuilder::new("opt");
|
||||
o.s.long = Some("option");
|
||||
o.b.settings.set(ArgSettings::Multiple);
|
||||
|
||||
assert_eq!(&*format!("{}", o), "--option <opt>...");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optbuilder_display2() {
|
||||
let mut v_names = VecMap::new();
|
||||
v_names.insert(0, "file");
|
||||
v_names.insert(1, "name");
|
||||
|
||||
let mut o2 = OptBuilder::new("opt");
|
||||
o2.s.short = Some('o');
|
||||
o2.v.val_names = Some(v_names);
|
||||
|
||||
assert_eq!(&*format!("{}", o2), "-o <file> <name>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optbuilder_display3() {
|
||||
let mut v_names = VecMap::new();
|
||||
v_names.insert(0, "file");
|
||||
v_names.insert(1, "name");
|
||||
|
||||
let mut o2 = OptBuilder::new("opt");
|
||||
o2.s.short = Some('o');
|
||||
o2.v.val_names = Some(v_names);
|
||||
o2.b.settings.set(ArgSettings::Multiple);
|
||||
|
||||
assert_eq!(&*format!("{}", o2), "-o <file> <name>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optbuilder_display_single_alias() {
|
||||
let mut o = OptBuilder::new("opt");
|
||||
o.s.long = Some("option");
|
||||
o.s.aliases = Some(vec![("als", true)]);
|
||||
|
||||
assert_eq!(&*format!("{}", o), "--option <opt>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optbuilder_display_multiple_aliases() {
|
||||
let mut o = OptBuilder::new("opt");
|
||||
o.s.long = Some("option");
|
||||
o.s.aliases = Some(vec![
|
||||
("als_not_visible", false),
|
||||
("als2", true),
|
||||
("als3", true),
|
||||
("als4", true),
|
||||
]);
|
||||
assert_eq!(&*format!("{}", o), "--option <opt>");
|
||||
}
|
||||
}
|
||||
284
zeroidc/vendor/clap/src/args/arg_builder/positional.rs
vendored
Normal file
284
zeroidc/vendor/clap/src/args/arg_builder/positional.rs
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
// Std
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
ffi::{OsStr, OsString},
|
||||
fmt::{Display, Formatter, Result},
|
||||
mem,
|
||||
rc::Rc,
|
||||
result::Result as StdResult,
|
||||
};
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
args::{AnyArg, Arg, ArgSettings, Base, DispOrder, Valued},
|
||||
map::{self, VecMap},
|
||||
INTERNAL_ERROR_MSG,
|
||||
};
|
||||
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct PosBuilder<'n, 'e>
|
||||
where
|
||||
'n: 'e,
|
||||
{
|
||||
pub b: Base<'n, 'e>,
|
||||
pub v: Valued<'n, 'e>,
|
||||
pub index: u64,
|
||||
}
|
||||
|
||||
impl<'n, 'e> PosBuilder<'n, 'e> {
|
||||
pub fn new(name: &'n str, idx: u64) -> Self {
|
||||
PosBuilder {
|
||||
b: Base::new(name),
|
||||
index: idx,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_arg_ref(a: &Arg<'n, 'e>, idx: u64) -> Self {
|
||||
let mut pb = PosBuilder {
|
||||
b: Base::from(a),
|
||||
v: Valued::from(a),
|
||||
index: idx,
|
||||
};
|
||||
if a.v.max_vals.is_some()
|
||||
|| a.v.min_vals.is_some()
|
||||
|| (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1)
|
||||
{
|
||||
pb.b.settings.set(ArgSettings::Multiple);
|
||||
}
|
||||
pb
|
||||
}
|
||||
|
||||
pub fn from_arg(mut a: Arg<'n, 'e>, idx: u64) -> Self {
|
||||
if a.v.max_vals.is_some()
|
||||
|| a.v.min_vals.is_some()
|
||||
|| (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1)
|
||||
{
|
||||
a.b.settings.set(ArgSettings::Multiple);
|
||||
}
|
||||
PosBuilder {
|
||||
b: mem::take(&mut a.b),
|
||||
v: mem::take(&mut a.v),
|
||||
index: idx,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn multiple_str(&self) -> &str {
|
||||
let mult_vals = self
|
||||
.v
|
||||
.val_names
|
||||
.as_ref()
|
||||
.map_or(true, |names| names.len() < 2);
|
||||
if self.is_set(ArgSettings::Multiple) && mult_vals {
|
||||
"..."
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name_no_brackets(&self) -> Cow<str> {
|
||||
debugln!("PosBuilder::name_no_brackets;");
|
||||
let mut delim = String::new();
|
||||
delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
|
||||
self.v.val_delim.expect(INTERNAL_ERROR_MSG)
|
||||
} else {
|
||||
' '
|
||||
});
|
||||
if let Some(ref names) = self.v.val_names {
|
||||
debugln!("PosBuilder:name_no_brackets: val_names={:#?}", names);
|
||||
if names.len() > 1 {
|
||||
Cow::Owned(
|
||||
names
|
||||
.values()
|
||||
.map(|n| format!("<{}>", n))
|
||||
.collect::<Vec<_>>()
|
||||
.join(&*delim),
|
||||
)
|
||||
} else {
|
||||
Cow::Borrowed(names.values().next().expect(INTERNAL_ERROR_MSG))
|
||||
}
|
||||
} else {
|
||||
debugln!("PosBuilder:name_no_brackets: just name");
|
||||
Cow::Borrowed(self.b.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> Display for PosBuilder<'n, 'e> {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
let mut delim = String::new();
|
||||
delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
|
||||
self.v.val_delim.expect(INTERNAL_ERROR_MSG)
|
||||
} else {
|
||||
' '
|
||||
});
|
||||
if let Some(ref names) = self.v.val_names {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
names
|
||||
.values()
|
||||
.map(|n| format!("<{}>", n))
|
||||
.collect::<Vec<_>>()
|
||||
.join(&*delim)
|
||||
)?;
|
||||
} else {
|
||||
write!(f, "<{}>", self.b.name)?;
|
||||
}
|
||||
if self.b.settings.is_set(ArgSettings::Multiple)
|
||||
&& (self.v.val_names.is_none() || self.v.val_names.as_ref().unwrap().len() == 1)
|
||||
{
|
||||
write!(f, "...")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> {
|
||||
fn name(&self) -> &'n str {
|
||||
self.b.name
|
||||
}
|
||||
fn overrides(&self) -> Option<&[&'e str]> {
|
||||
self.b.overrides.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
|
||||
self.b.requires.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn blacklist(&self) -> Option<&[&'e str]> {
|
||||
self.b.blacklist.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn required_unless(&self) -> Option<&[&'e str]> {
|
||||
self.b.r_unless.as_ref().map(|o| &o[..])
|
||||
}
|
||||
fn val_names(&self) -> Option<&VecMap<&'e str>> {
|
||||
self.v.val_names.as_ref()
|
||||
}
|
||||
fn is_set(&self, s: ArgSettings) -> bool {
|
||||
self.b.settings.is_set(s)
|
||||
}
|
||||
fn set(&mut self, s: ArgSettings) {
|
||||
self.b.settings.set(s)
|
||||
}
|
||||
fn has_switch(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn max_vals(&self) -> Option<u64> {
|
||||
self.v.max_vals
|
||||
}
|
||||
fn val_terminator(&self) -> Option<&'e str> {
|
||||
self.v.terminator
|
||||
}
|
||||
fn num_vals(&self) -> Option<u64> {
|
||||
self.v.num_vals
|
||||
}
|
||||
fn possible_vals(&self) -> Option<&[&'e str]> {
|
||||
self.v.possible_vals.as_ref().map(|o| &o[..])
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> {
|
||||
self.v.validator.as_ref()
|
||||
}
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> {
|
||||
self.v.validator_os.as_ref()
|
||||
}
|
||||
fn min_vals(&self) -> Option<u64> {
|
||||
self.v.min_vals
|
||||
}
|
||||
fn short(&self) -> Option<char> {
|
||||
None
|
||||
}
|
||||
fn long(&self) -> Option<&'e str> {
|
||||
None
|
||||
}
|
||||
fn val_delim(&self) -> Option<char> {
|
||||
self.v.val_delim
|
||||
}
|
||||
fn takes_value(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn help(&self) -> Option<&'e str> {
|
||||
self.b.help
|
||||
}
|
||||
fn long_help(&self) -> Option<&'e str> {
|
||||
self.b.long_help
|
||||
}
|
||||
fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
|
||||
self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
|
||||
}
|
||||
fn default_val(&self) -> Option<&'e OsStr> {
|
||||
self.v.default_val
|
||||
}
|
||||
fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
|
||||
self.v
|
||||
.env
|
||||
.as_ref()
|
||||
.map(|&(key, ref value)| (key, value.as_ref()))
|
||||
}
|
||||
fn longest_filter(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn aliases(&self) -> Option<Vec<&'e str>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> DispOrder for PosBuilder<'n, 'e> {
|
||||
fn disp_ord(&self) -> usize {
|
||||
self.index as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> PartialEq for PosBuilder<'n, 'e> {
|
||||
fn eq(&self, other: &PosBuilder<'n, 'e>) -> bool {
|
||||
self.b == other.b
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::PosBuilder;
|
||||
use crate::{args::settings::ArgSettings, map::VecMap};
|
||||
|
||||
#[test]
|
||||
fn display_mult() {
|
||||
let mut p = PosBuilder::new("pos", 1);
|
||||
p.b.settings.set(ArgSettings::Multiple);
|
||||
|
||||
assert_eq!(&*format!("{}", p), "<pos>...");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_required() {
|
||||
let mut p2 = PosBuilder::new("pos", 1);
|
||||
p2.b.settings.set(ArgSettings::Required);
|
||||
|
||||
assert_eq!(&*format!("{}", p2), "<pos>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_val_names() {
|
||||
let mut p2 = PosBuilder::new("pos", 1);
|
||||
let mut vm = VecMap::new();
|
||||
vm.insert(0, "file1");
|
||||
vm.insert(1, "file2");
|
||||
p2.v.val_names = Some(vm);
|
||||
|
||||
assert_eq!(&*format!("{}", p2), "<file1> <file2>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_val_names_req() {
|
||||
let mut p2 = PosBuilder::new("pos", 1);
|
||||
p2.b.settings.set(ArgSettings::Required);
|
||||
let mut vm = VecMap::new();
|
||||
vm.insert(0, "file1");
|
||||
vm.insert(1, "file2");
|
||||
p2.v.val_names = Some(vm);
|
||||
|
||||
assert_eq!(&*format!("{}", p2), "<file1> <file2>");
|
||||
}
|
||||
}
|
||||
40
zeroidc/vendor/clap/src/args/arg_builder/switched.rs
vendored
Normal file
40
zeroidc/vendor/clap/src/args/arg_builder/switched.rs
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
use crate::Arg;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Switched<'b> {
|
||||
pub short: Option<char>,
|
||||
pub long: Option<&'b str>,
|
||||
pub aliases: Option<Vec<(&'b str, bool)>>, // (name, visible)
|
||||
pub disp_ord: usize,
|
||||
pub unified_ord: usize,
|
||||
}
|
||||
|
||||
impl<'e> Default for Switched<'e> {
|
||||
fn default() -> Self {
|
||||
Switched {
|
||||
short: None,
|
||||
long: None,
|
||||
aliases: None,
|
||||
disp_ord: 999,
|
||||
unified_ord: 999,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Switched<'e> {
|
||||
fn from(a: &'z Arg<'n, 'e>) -> Self {
|
||||
a.s.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'e> Clone for Switched<'e> {
|
||||
fn clone(&self) -> Self {
|
||||
Switched {
|
||||
short: self.short,
|
||||
long: self.long,
|
||||
aliases: self.aliases.clone(),
|
||||
disp_ord: self.disp_ord,
|
||||
unified_ord: self.unified_ord,
|
||||
}
|
||||
}
|
||||
}
|
||||
70
zeroidc/vendor/clap/src/args/arg_builder/valued.rs
vendored
Normal file
70
zeroidc/vendor/clap/src/args/arg_builder/valued.rs
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
use std::{
|
||||
ffi::{OsStr, OsString},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use crate::{map::VecMap, Arg};
|
||||
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Clone)]
|
||||
pub struct Valued<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
pub possible_vals: Option<Vec<&'b str>>,
|
||||
pub val_names: Option<VecMap<&'b str>>,
|
||||
pub num_vals: Option<u64>,
|
||||
pub max_vals: Option<u64>,
|
||||
pub min_vals: Option<u64>,
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
pub validator: Option<Rc<Fn(String) -> Result<(), String>>>,
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
pub validator_os: Option<Rc<Fn(&OsStr) -> Result<(), OsString>>>,
|
||||
pub val_delim: Option<char>,
|
||||
pub default_val: Option<&'b OsStr>,
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
|
||||
pub default_vals_ifs: Option<VecMap<(&'a str, Option<&'b OsStr>, &'b OsStr)>>,
|
||||
pub env: Option<(&'a OsStr, Option<OsString>)>,
|
||||
pub terminator: Option<&'b str>,
|
||||
}
|
||||
|
||||
impl<'n, 'e> Default for Valued<'n, 'e> {
|
||||
fn default() -> Self {
|
||||
Valued {
|
||||
possible_vals: None,
|
||||
num_vals: None,
|
||||
min_vals: None,
|
||||
max_vals: None,
|
||||
val_names: None,
|
||||
validator: None,
|
||||
validator_os: None,
|
||||
val_delim: None,
|
||||
default_val: None,
|
||||
default_vals_ifs: None,
|
||||
env: None,
|
||||
terminator: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e> Valued<'n, 'e> {
|
||||
pub fn fill_in(&mut self) {
|
||||
if let Some(ref vec) = self.val_names {
|
||||
if vec.len() > 1 {
|
||||
self.num_vals = Some(vec.len() as u64);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for Valued<'n, 'e> {
|
||||
fn from(a: &'z Arg<'n, 'e>) -> Self {
|
||||
let mut v = a.v.clone();
|
||||
if let Some(ref vec) = a.v.val_names {
|
||||
if vec.len() > 1 {
|
||||
v.num_vals = Some(vec.len() as u64);
|
||||
}
|
||||
}
|
||||
v
|
||||
}
|
||||
}
|
||||
274
zeroidc/vendor/clap/src/args/arg_matcher.rs
vendored
Normal file
274
zeroidc/vendor/clap/src/args/arg_matcher.rs
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
// Std
|
||||
use std::{
|
||||
collections::{
|
||||
hash_map::{Entry, Iter},
|
||||
HashMap,
|
||||
},
|
||||
ffi::OsStr,
|
||||
mem,
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
// Internal
|
||||
use crate::args::{settings::ArgSettings, AnyArg, ArgMatches, MatchedArg, SubCommand};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct ArgMatcher<'a>(pub ArgMatches<'a>);
|
||||
|
||||
impl<'a> Default for ArgMatcher<'a> {
|
||||
fn default() -> Self {
|
||||
ArgMatcher(ArgMatches::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ArgMatcher<'a> {
|
||||
pub fn new() -> Self {
|
||||
ArgMatcher::default()
|
||||
}
|
||||
|
||||
pub fn process_arg_overrides<'b>(
|
||||
&mut self,
|
||||
a: Option<&AnyArg<'a, 'b>>,
|
||||
overrides: &mut Vec<(&'b str, &'a str)>,
|
||||
required: &mut Vec<&'a str>,
|
||||
check_all: bool,
|
||||
) {
|
||||
debugln!(
|
||||
"ArgMatcher::process_arg_overrides:{:?};",
|
||||
a.map_or(None, |a| Some(a.name()))
|
||||
);
|
||||
if let Some(aa) = a {
|
||||
let mut self_done = false;
|
||||
if let Some(a_overrides) = aa.overrides() {
|
||||
for overr in a_overrides {
|
||||
debugln!("ArgMatcher::process_arg_overrides:iter:{};", overr);
|
||||
if overr == &aa.name() {
|
||||
self_done = true;
|
||||
self.handle_self_overrides(a);
|
||||
} else if self.is_present(overr) {
|
||||
debugln!(
|
||||
"ArgMatcher::process_arg_overrides:iter:{}: removing from matches;",
|
||||
overr
|
||||
);
|
||||
self.remove(overr);
|
||||
for i in (0..required.len()).rev() {
|
||||
if &required[i] == overr {
|
||||
debugln!(
|
||||
"ArgMatcher::process_arg_overrides:iter:{}: removing required;",
|
||||
overr
|
||||
);
|
||||
required.swap_remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
overrides.push((overr, aa.name()));
|
||||
} else {
|
||||
overrides.push((overr, aa.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if check_all && !self_done {
|
||||
self.handle_self_overrides(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_self_overrides<'b>(&mut self, a: Option<&AnyArg<'a, 'b>>) {
|
||||
debugln!(
|
||||
"ArgMatcher::handle_self_overrides:{:?};",
|
||||
a.map_or(None, |a| Some(a.name()))
|
||||
);
|
||||
if let Some(aa) = a {
|
||||
if !aa.has_switch() || aa.is_set(ArgSettings::Multiple) {
|
||||
// positional args can't override self or else we would never advance to the next
|
||||
|
||||
// Also flags with --multiple set are ignored otherwise we could never have more
|
||||
// than one
|
||||
return;
|
||||
}
|
||||
if let Some(ma) = self.get_mut(aa.name()) {
|
||||
if ma.vals.len() > 1 {
|
||||
// swap_remove(0) would be O(1) but does not preserve order, which
|
||||
// we need
|
||||
ma.vals.remove(0);
|
||||
ma.occurs = 1;
|
||||
} else if !aa.takes_value() && ma.occurs > 1 {
|
||||
ma.occurs = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_present(&self, name: &str) -> bool {
|
||||
self.0.is_present(name)
|
||||
}
|
||||
|
||||
pub fn propagate_globals(&mut self, global_arg_vec: &[&'a str]) {
|
||||
debugln!(
|
||||
"ArgMatcher::get_global_values: global_arg_vec={:?}",
|
||||
global_arg_vec
|
||||
);
|
||||
let mut vals_map = HashMap::new();
|
||||
self.fill_in_global_values(global_arg_vec, &mut vals_map);
|
||||
}
|
||||
|
||||
fn fill_in_global_values(
|
||||
&mut self,
|
||||
global_arg_vec: &[&'a str],
|
||||
vals_map: &mut HashMap<&'a str, MatchedArg>,
|
||||
) {
|
||||
for global_arg in global_arg_vec {
|
||||
if let Some(ma) = self.get(global_arg) {
|
||||
// We have to check if the parent's global arg wasn't used but still exists
|
||||
// such as from a default value.
|
||||
//
|
||||
// For example, `myprog subcommand --global-arg=value` where --global-arg defines
|
||||
// a default value of `other` myprog would have an existing MatchedArg for
|
||||
// --global-arg where the value is `other`, however the occurs will be 0.
|
||||
let to_update = if let Some(parent_ma) = vals_map.get(global_arg) {
|
||||
if parent_ma.occurs > 0 && ma.occurs == 0 {
|
||||
parent_ma.clone()
|
||||
} else {
|
||||
ma.clone()
|
||||
}
|
||||
} else {
|
||||
ma.clone()
|
||||
};
|
||||
vals_map.insert(global_arg, to_update);
|
||||
}
|
||||
}
|
||||
if let Some(ref mut sc) = self.0.subcommand {
|
||||
let mut am = ArgMatcher(mem::replace(&mut sc.matches, ArgMatches::new()));
|
||||
am.fill_in_global_values(global_arg_vec, vals_map);
|
||||
mem::swap(&mut am.0, &mut sc.matches);
|
||||
}
|
||||
|
||||
for (name, matched_arg) in vals_map.iter_mut() {
|
||||
self.0.args.insert(name, matched_arg.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, arg: &str) -> Option<&mut MatchedArg> {
|
||||
self.0.args.get_mut(arg)
|
||||
}
|
||||
|
||||
pub fn get(&self, arg: &str) -> Option<&MatchedArg> {
|
||||
self.0.args.get(arg)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, arg: &str) {
|
||||
self.0.args.remove(arg);
|
||||
}
|
||||
|
||||
pub fn remove_all(&mut self, args: &[&str]) {
|
||||
for &arg in args {
|
||||
self.0.args.remove(arg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, name: &'a str) {
|
||||
self.0.args.insert(name, MatchedArg::new());
|
||||
}
|
||||
|
||||
pub fn contains(&self, arg: &str) -> bool {
|
||||
self.0.args.contains_key(arg)
|
||||
}
|
||||
|
||||
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) -> Vec<&'a str> {
|
||||
self.0.args.keys().map(Deref::deref).collect()
|
||||
}
|
||||
|
||||
pub fn entry(&mut self, arg: &'a str) -> Entry<&'a str, MatchedArg> {
|
||||
self.0.args.entry(arg)
|
||||
}
|
||||
|
||||
pub fn subcommand(&mut self, sc: SubCommand<'a>) {
|
||||
self.0.subcommand = Some(Box::new(sc));
|
||||
}
|
||||
|
||||
pub fn subcommand_name(&self) -> Option<&str> {
|
||||
self.0.subcommand_name()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<&str, MatchedArg> {
|
||||
self.0.args.iter()
|
||||
}
|
||||
|
||||
pub fn inc_occurrence_of(&mut self, arg: &'a str) {
|
||||
debugln!("ArgMatcher::inc_occurrence_of: arg={}", arg);
|
||||
if let Some(a) = self.get_mut(arg) {
|
||||
a.occurs += 1;
|
||||
return;
|
||||
}
|
||||
debugln!("ArgMatcher::inc_occurrence_of: first instance");
|
||||
self.insert(arg);
|
||||
}
|
||||
|
||||
pub fn inc_occurrences_of(&mut self, args: &[&'a str]) {
|
||||
debugln!("ArgMatcher::inc_occurrences_of: args={:?}", args);
|
||||
for arg in args {
|
||||
self.inc_occurrence_of(arg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_val_to(&mut self, arg: &'a str, val: &OsStr) {
|
||||
let ma = self.entry(arg).or_insert(MatchedArg {
|
||||
occurs: 0,
|
||||
indices: Vec::with_capacity(1),
|
||||
vals: Vec::with_capacity(1),
|
||||
});
|
||||
ma.vals.push(val.to_owned());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
pub fn needs_more_vals<'b, A>(&self, o: &A) -> bool
|
||||
where
|
||||
A: AnyArg<'a, 'b>,
|
||||
{
|
||||
debugln!("ArgMatcher::needs_more_vals: o={}", o.name());
|
||||
if let Some(ma) = self.get(o.name()) {
|
||||
if let Some(num) = o.num_vals() {
|
||||
debugln!("ArgMatcher::needs_more_vals: num_vals...{}", num);
|
||||
return if o.is_set(ArgSettings::Multiple) {
|
||||
((ma.vals.len() as u64) % num) != 0
|
||||
} else {
|
||||
num != (ma.vals.len() as u64)
|
||||
};
|
||||
} else if let Some(num) = o.max_vals() {
|
||||
debugln!("ArgMatcher::needs_more_vals: max_vals...{}", num);
|
||||
return (ma.vals.len() as u64) <= num;
|
||||
} else if o.min_vals().is_some() {
|
||||
debugln!("ArgMatcher::needs_more_vals: min_vals...true");
|
||||
return true;
|
||||
}
|
||||
return o.is_set(ArgSettings::Multiple);
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// Not changing to From just to not deal with possible breaking changes on v2 since v3 is coming
|
||||
// in the future anyways
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::from_over_into))]
|
||||
impl<'a> Into<ArgMatches<'a>> for ArgMatcher<'a> {
|
||||
fn into(self) -> ArgMatches<'a> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
1001
zeroidc/vendor/clap/src/args/arg_matches.rs
vendored
Normal file
1001
zeroidc/vendor/clap/src/args/arg_matches.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
637
zeroidc/vendor/clap/src/args/group.rs
vendored
Normal file
637
zeroidc/vendor/clap/src/args/group.rs
vendored
Normal file
@@ -0,0 +1,637 @@
|
||||
#[cfg(feature = "yaml")]
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::{Debug, Formatter, Result};
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
use yaml_rust::Yaml;
|
||||
|
||||
/// `ArgGroup`s are a family of related [arguments] and way for you to express, "Any of these
|
||||
/// arguments". By placing arguments in a logical group, you can create easier requirement and
|
||||
/// exclusion rules instead of having to list each argument individually, or when you want a rule
|
||||
/// to apply "any but not all" arguments.
|
||||
///
|
||||
/// For instance, you can make an entire `ArgGroup` required. If [`ArgGroup::multiple(true)`] is
|
||||
/// set, this means that at least one argument from that group must be present. If
|
||||
/// [`ArgGroup::multiple(false)`] is set (the default), one and *only* one must be present.
|
||||
///
|
||||
/// You can also do things such as name an entire `ArgGroup` as a [conflict] or [requirement] for
|
||||
/// another argument, meaning any of the arguments that belong to that group will cause a failure
|
||||
/// if present, or must present respectively.
|
||||
///
|
||||
/// Perhaps the most common use of `ArgGroup`s is to require one and *only* one argument to be
|
||||
/// present out of a given set. Imagine that you had multiple arguments, and you want one of them
|
||||
/// to be required, but making all of them required isn't feasible because perhaps they conflict
|
||||
/// with each other. For example, lets say that you were building an application where one could
|
||||
/// set a given version number by supplying a string with an option argument, i.e.
|
||||
/// `--set-ver v1.2.3`, you also wanted to support automatically using a previous version number
|
||||
/// and simply incrementing one of the three numbers. So you create three flags `--major`,
|
||||
/// `--minor`, and `--patch`. All of these arguments shouldn't be used at one time but you want to
|
||||
/// specify that *at least one* of them is used. For this, you can create a group.
|
||||
///
|
||||
/// Finally, you may use `ArgGroup`s to pull a value from a group of arguments when you don't care
|
||||
/// exactly which argument was actually used at runtime.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// The following example demonstrates using an `ArgGroup` to ensure that one, and only one, of
|
||||
/// the arguments from the specified group is present at runtime.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, ArgGroup, ErrorKind};
|
||||
/// let result = App::new("app")
|
||||
/// .args_from_usage(
|
||||
/// "--set-ver [ver] 'set the version manually'
|
||||
/// --major 'auto increase major'
|
||||
/// --minor 'auto increase minor'
|
||||
/// --patch 'auto increase patch'")
|
||||
/// .group(ArgGroup::with_name("vers")
|
||||
/// .args(&["set-ver", "major", "minor", "patch"])
|
||||
/// .required(true))
|
||||
/// .get_matches_from_safe(vec!["app", "--major", "--patch"]);
|
||||
/// // Because we used two args in the group it's an error
|
||||
/// assert!(result.is_err());
|
||||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind, ErrorKind::ArgumentConflict);
|
||||
/// ```
|
||||
/// This next example shows a passing parse of the same scenario
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, ArgGroup};
|
||||
/// let result = App::new("app")
|
||||
/// .args_from_usage(
|
||||
/// "--set-ver [ver] 'set the version manually'
|
||||
/// --major 'auto increase major'
|
||||
/// --minor 'auto increase minor'
|
||||
/// --patch 'auto increase patch'")
|
||||
/// .group(ArgGroup::with_name("vers")
|
||||
/// .args(&["set-ver", "major", "minor","patch"])
|
||||
/// .required(true))
|
||||
/// .get_matches_from_safe(vec!["app", "--major"]);
|
||||
/// assert!(result.is_ok());
|
||||
/// let matches = result.unwrap();
|
||||
/// // We may not know which of the args was used, so we can test for the group...
|
||||
/// assert!(matches.is_present("vers"));
|
||||
/// // we could also alternatively check each arg individually (not shown here)
|
||||
/// ```
|
||||
/// [`ArgGroup::multiple(true)`]: ./struct.ArgGroup.html#method.multiple
|
||||
/// [arguments]: ./struct.Arg.html
|
||||
/// [conflict]: ./struct.Arg.html#method.conflicts_with
|
||||
/// [requirement]: ./struct.Arg.html#method.requires
|
||||
#[derive(Default)]
|
||||
pub struct ArgGroup<'a> {
|
||||
#[doc(hidden)]
|
||||
pub name: &'a str,
|
||||
#[doc(hidden)]
|
||||
pub args: Vec<&'a str>,
|
||||
#[doc(hidden)]
|
||||
pub required: bool,
|
||||
#[doc(hidden)]
|
||||
pub requires: Option<Vec<&'a str>>,
|
||||
#[doc(hidden)]
|
||||
pub conflicts: Option<Vec<&'a str>>,
|
||||
#[doc(hidden)]
|
||||
pub multiple: bool,
|
||||
}
|
||||
|
||||
impl<'a> ArgGroup<'a> {
|
||||
/// Creates a new instance of `ArgGroup` using a unique string name. The name will be used to
|
||||
/// get values from the group or refer to the group inside of conflict and requirement rules.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, ArgGroup};
|
||||
/// ArgGroup::with_name("config")
|
||||
/// # ;
|
||||
/// ```
|
||||
pub fn with_name(n: &'a str) -> Self {
|
||||
ArgGroup {
|
||||
name: n,
|
||||
required: false,
|
||||
args: vec![],
|
||||
requires: None,
|
||||
conflicts: None,
|
||||
multiple: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new instance of `ArgGroup` from a .yml (YAML) file.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// # #[macro_use]
|
||||
/// # extern crate clap;
|
||||
/// # use clap::ArgGroup;
|
||||
/// # fn main() {
|
||||
/// let yml = load_yaml!("group.yml");
|
||||
/// let ag = ArgGroup::from_yaml(yml);
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(feature = "yaml")]
|
||||
pub fn from_yaml(y: &'a Yaml) -> ArgGroup<'a> {
|
||||
ArgGroup::from(y.as_hash().unwrap())
|
||||
}
|
||||
|
||||
/// Adds an [argument] to this group by name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup};
|
||||
/// let m = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .arg("flag")
|
||||
/// .arg("color"))
|
||||
/// .get_matches_from(vec!["myprog", "-f"]);
|
||||
/// // maybe we don't know which of the two flags was used...
|
||||
/// assert!(m.is_present("req_flags"));
|
||||
/// // but we can also check individually if needed
|
||||
/// assert!(m.is_present("flag"));
|
||||
/// ```
|
||||
/// [argument]: ./struct.Arg.html
|
||||
pub fn arg(mut self, n: &'a str) -> Self {
|
||||
assert!(
|
||||
self.name != n,
|
||||
"ArgGroup '{}' can not have same name as arg inside it",
|
||||
&*self.name
|
||||
);
|
||||
self.args.push(n);
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds multiple [arguments] to this group by name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup};
|
||||
/// let m = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .args(&["flag", "color"]))
|
||||
/// .get_matches_from(vec!["myprog", "-f"]);
|
||||
/// // maybe we don't know which of the two flags was used...
|
||||
/// assert!(m.is_present("req_flags"));
|
||||
/// // but we can also check individually if needed
|
||||
/// assert!(m.is_present("flag"));
|
||||
/// ```
|
||||
/// [arguments]: ./struct.Arg.html
|
||||
pub fn args(mut self, ns: &[&'a str]) -> Self {
|
||||
for n in ns {
|
||||
self = self.arg(n);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Allows more than one of the ['Arg']s in this group to be used. (Default: `false`)
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Notice in this example we use *both* the `-f` and `-c` flags which are both part of the
|
||||
/// group
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup};
|
||||
/// let m = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .args(&["flag", "color"])
|
||||
/// .multiple(true))
|
||||
/// .get_matches_from(vec!["myprog", "-f", "-c"]);
|
||||
/// // maybe we don't know which of the two flags was used...
|
||||
/// assert!(m.is_present("req_flags"));
|
||||
/// ```
|
||||
/// In this next example, we show the default behavior (i.e. `multiple(false)) which will throw
|
||||
/// an error if more than one of the args in the group was used.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .args(&["flag", "color"]))
|
||||
/// .get_matches_from_safe(vec!["myprog", "-f", "-c"]);
|
||||
/// // Because we used both args in the group it's an error
|
||||
/// assert!(result.is_err());
|
||||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind, ErrorKind::ArgumentConflict);
|
||||
/// ```
|
||||
/// ['Arg']: ./struct.Arg.html
|
||||
pub fn multiple(mut self, m: bool) -> Self {
|
||||
self.multiple = m;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the group as required or not. A required group will be displayed in the usage string
|
||||
/// of the application in the format `<arg|arg2|arg3>`. A required `ArgGroup` simply states
|
||||
/// that one argument from this group *must* be present at runtime (unless
|
||||
/// conflicting with another argument).
|
||||
///
|
||||
/// **NOTE:** This setting only applies to the current [`App`] / [`SubCommand`], and not
|
||||
/// globally.
|
||||
///
|
||||
/// **NOTE:** By default, [`ArgGroup::multiple`] is set to `false` which when combined with
|
||||
/// `ArgGroup::required(true)` states, "One and *only one* arg must be used from this group.
|
||||
/// Use of more than one arg is an error." Vice setting `ArgGroup::multiple(true)` which
|
||||
/// states, '*At least* one arg from this group must be used. Using multiple is OK."
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .args(&["flag", "color"])
|
||||
/// .required(true))
|
||||
/// .get_matches_from_safe(vec!["myprog"]);
|
||||
/// // Because we didn't use any of the args in the group, it's an error
|
||||
/// assert!(result.is_err());
|
||||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
|
||||
/// ```
|
||||
/// [`App`]: ./struct.App.html
|
||||
/// [`SubCommand`]: ./struct.SubCommand.html
|
||||
/// [`ArgGroup::multiple`]: ./struct.ArgGroup.html#method.multiple
|
||||
pub fn required(mut self, r: bool) -> Self {
|
||||
self.required = r;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the requirement rules of this group. This is not to be confused with a
|
||||
/// [required group]. Requirement rules function just like [argument requirement rules], you
|
||||
/// can name other arguments or groups that must be present when any one of the arguments from
|
||||
/// this group is used.
|
||||
///
|
||||
/// **NOTE:** The name provided may be an argument, or group name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .short("d"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .args(&["flag", "color"])
|
||||
/// .requires("debug"))
|
||||
/// .get_matches_from_safe(vec!["myprog", "-c"]);
|
||||
/// // because we used an arg from the group, and the group requires "-d" to be used, it's an
|
||||
/// // error
|
||||
/// assert!(result.is_err());
|
||||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
|
||||
/// ```
|
||||
/// [required group]: ./struct.ArgGroup.html#method.required
|
||||
/// [argument requirement rules]: ./struct.Arg.html#method.requires
|
||||
pub fn requires(mut self, n: &'a str) -> Self {
|
||||
if let Some(ref mut reqs) = self.requires {
|
||||
reqs.push(n);
|
||||
} else {
|
||||
self.requires = Some(vec![n]);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the requirement rules of this group. This is not to be confused with a
|
||||
/// [required group]. Requirement rules function just like [argument requirement rules], you
|
||||
/// can name other arguments or groups that must be present when one of the arguments from this
|
||||
/// group is used.
|
||||
///
|
||||
/// **NOTE:** The names provided may be an argument, or group name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .short("d"))
|
||||
/// .arg(Arg::with_name("verb")
|
||||
/// .short("v"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .args(&["flag", "color"])
|
||||
/// .requires_all(&["debug", "verb"]))
|
||||
/// .get_matches_from_safe(vec!["myprog", "-c", "-d"]);
|
||||
/// // because we used an arg from the group, and the group requires "-d" and "-v" to be used,
|
||||
/// // yet we only used "-d" it's an error
|
||||
/// assert!(result.is_err());
|
||||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
|
||||
/// ```
|
||||
/// [required group]: ./struct.ArgGroup.html#method.required
|
||||
/// [argument requirement rules]: ./struct.Arg.html#method.requires_all
|
||||
pub fn requires_all(mut self, ns: &[&'a str]) -> Self {
|
||||
for n in ns {
|
||||
self = self.requires(n);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the exclusion rules of this group. Exclusion (aka conflict) rules function just like
|
||||
/// [argument exclusion rules], you can name other arguments or groups that must *not* be
|
||||
/// present when one of the arguments from this group are used.
|
||||
///
|
||||
/// **NOTE:** The name provided may be an argument, or group name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .short("d"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .args(&["flag", "color"])
|
||||
/// .conflicts_with("debug"))
|
||||
/// .get_matches_from_safe(vec!["myprog", "-c", "-d"]);
|
||||
/// // because we used an arg from the group, and the group conflicts with "-d", it's an error
|
||||
/// assert!(result.is_err());
|
||||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind, ErrorKind::ArgumentConflict);
|
||||
/// ```
|
||||
/// [argument exclusion rules]: ./struct.Arg.html#method.conflicts_with
|
||||
pub fn conflicts_with(mut self, n: &'a str) -> Self {
|
||||
if let Some(ref mut confs) = self.conflicts {
|
||||
confs.push(n);
|
||||
} else {
|
||||
self.conflicts = Some(vec![n]);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the exclusion rules of this group. Exclusion rules function just like
|
||||
/// [argument exclusion rules], you can name other arguments or groups that must *not* be
|
||||
/// present when one of the arguments from this group are used.
|
||||
///
|
||||
/// **NOTE:** The names provided may be an argument, or group name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ArgGroup, ErrorKind};
|
||||
/// let result = App::new("myprog")
|
||||
/// .arg(Arg::with_name("flag")
|
||||
/// .short("f"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .short("c"))
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .short("d"))
|
||||
/// .arg(Arg::with_name("verb")
|
||||
/// .short("v"))
|
||||
/// .group(ArgGroup::with_name("req_flags")
|
||||
/// .args(&["flag", "color"])
|
||||
/// .conflicts_with_all(&["debug", "verb"]))
|
||||
/// .get_matches_from_safe(vec!["myprog", "-c", "-v"]);
|
||||
/// // because we used an arg from the group, and the group conflicts with either "-v" or "-d"
|
||||
/// // it's an error
|
||||
/// assert!(result.is_err());
|
||||
/// let err = result.unwrap_err();
|
||||
/// assert_eq!(err.kind, ErrorKind::ArgumentConflict);
|
||||
/// ```
|
||||
/// [argument exclusion rules]: ./struct.Arg.html#method.conflicts_with_all
|
||||
pub fn conflicts_with_all(mut self, ns: &[&'a str]) -> Self {
|
||||
for n in ns {
|
||||
self = self.conflicts_with(n);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Debug for ArgGroup<'a> {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
write!(
|
||||
f,
|
||||
"{{\n\
|
||||
\tname: {:?},\n\
|
||||
\targs: {:?},\n\
|
||||
\trequired: {:?},\n\
|
||||
\trequires: {:?},\n\
|
||||
\tconflicts: {:?},\n\
|
||||
}}",
|
||||
self.name, self.args, self.required, self.requires, self.conflicts
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'z> From<&'z ArgGroup<'a>> for ArgGroup<'a> {
|
||||
fn from(g: &'z ArgGroup<'a>) -> Self {
|
||||
ArgGroup {
|
||||
name: g.name,
|
||||
required: g.required,
|
||||
args: g.args.clone(),
|
||||
requires: g.requires.clone(),
|
||||
conflicts: g.conflicts.clone(),
|
||||
multiple: g.multiple,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
impl<'a> From<&'a BTreeMap<Yaml, Yaml>> for ArgGroup<'a> {
|
||||
fn from(b: &'a BTreeMap<Yaml, Yaml>) -> Self {
|
||||
// We WANT this to panic on error...so expect() is good.
|
||||
let mut a = ArgGroup::default();
|
||||
let group_settings = if b.len() == 1 {
|
||||
let name_yml = b.keys().nth(0).expect("failed to get name");
|
||||
let name_str = name_yml
|
||||
.as_str()
|
||||
.expect("failed to convert arg YAML name to str");
|
||||
a.name = name_str;
|
||||
b.get(name_yml)
|
||||
.expect("failed to get name_str")
|
||||
.as_hash()
|
||||
.expect("failed to convert to a hash")
|
||||
} else {
|
||||
b
|
||||
};
|
||||
|
||||
for (k, v) in group_settings {
|
||||
a = match k.as_str().unwrap() {
|
||||
"required" => a.required(v.as_bool().unwrap()),
|
||||
"multiple" => a.multiple(v.as_bool().unwrap()),
|
||||
"args" => yaml_vec_or_str!(v, a, arg),
|
||||
"arg" => {
|
||||
if let Some(ys) = v.as_str() {
|
||||
a = a.arg(ys);
|
||||
}
|
||||
a
|
||||
}
|
||||
"requires" => yaml_vec_or_str!(v, a, requires),
|
||||
"conflicts_with" => yaml_vec_or_str!(v, a, conflicts_with),
|
||||
"name" => {
|
||||
if let Some(ys) = v.as_str() {
|
||||
a.name = ys;
|
||||
}
|
||||
a
|
||||
}
|
||||
s => panic!(
|
||||
"Unknown ArgGroup setting '{}' in YAML file for \
|
||||
ArgGroup '{}'",
|
||||
s, a.name
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::ArgGroup;
|
||||
#[cfg(feature = "yaml")]
|
||||
use yaml_rust::YamlLoader;
|
||||
|
||||
#[test]
|
||||
fn groups() {
|
||||
let g = ArgGroup::with_name("test")
|
||||
.arg("a1")
|
||||
.arg("a4")
|
||||
.args(&["a2", "a3"])
|
||||
.required(true)
|
||||
.conflicts_with("c1")
|
||||
.conflicts_with_all(&["c2", "c3"])
|
||||
.conflicts_with("c4")
|
||||
.requires("r1")
|
||||
.requires_all(&["r2", "r3"])
|
||||
.requires("r4");
|
||||
|
||||
let args = vec!["a1", "a4", "a2", "a3"];
|
||||
let reqs = vec!["r1", "r2", "r3", "r4"];
|
||||
let confs = vec!["c1", "c2", "c3", "c4"];
|
||||
|
||||
assert_eq!(g.args, args);
|
||||
assert_eq!(g.requires, Some(reqs));
|
||||
assert_eq!(g.conflicts, Some(confs));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug() {
|
||||
let g = ArgGroup::with_name("test")
|
||||
.arg("a1")
|
||||
.arg("a4")
|
||||
.args(&["a2", "a3"])
|
||||
.required(true)
|
||||
.conflicts_with("c1")
|
||||
.conflicts_with_all(&["c2", "c3"])
|
||||
.conflicts_with("c4")
|
||||
.requires("r1")
|
||||
.requires_all(&["r2", "r3"])
|
||||
.requires("r4");
|
||||
|
||||
let args = vec!["a1", "a4", "a2", "a3"];
|
||||
let reqs = vec!["r1", "r2", "r3", "r4"];
|
||||
let confs = vec!["c1", "c2", "c3", "c4"];
|
||||
|
||||
let debug_str = format!(
|
||||
"{{\n\
|
||||
\tname: \"test\",\n\
|
||||
\targs: {:?},\n\
|
||||
\trequired: {:?},\n\
|
||||
\trequires: {:?},\n\
|
||||
\tconflicts: {:?},\n\
|
||||
}}",
|
||||
args,
|
||||
true,
|
||||
Some(reqs),
|
||||
Some(confs)
|
||||
);
|
||||
assert_eq!(&*format!("{:?}", g), &*debug_str);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from() {
|
||||
let g = ArgGroup::with_name("test")
|
||||
.arg("a1")
|
||||
.arg("a4")
|
||||
.args(&["a2", "a3"])
|
||||
.required(true)
|
||||
.conflicts_with("c1")
|
||||
.conflicts_with_all(&["c2", "c3"])
|
||||
.conflicts_with("c4")
|
||||
.requires("r1")
|
||||
.requires_all(&["r2", "r3"])
|
||||
.requires("r4");
|
||||
|
||||
let args = vec!["a1", "a4", "a2", "a3"];
|
||||
let reqs = vec!["r1", "r2", "r3", "r4"];
|
||||
let confs = vec!["c1", "c2", "c3", "c4"];
|
||||
|
||||
let g2 = ArgGroup::from(&g);
|
||||
assert_eq!(g2.args, args);
|
||||
assert_eq!(g2.requires, Some(reqs));
|
||||
assert_eq!(g2.conflicts, Some(confs));
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
#[cfg_attr(feature = "yaml", test)]
|
||||
fn test_yaml() {
|
||||
let g_yaml = "name: test
|
||||
args:
|
||||
- a1
|
||||
- a4
|
||||
- a2
|
||||
- a3
|
||||
conflicts_with:
|
||||
- c1
|
||||
- c2
|
||||
- c3
|
||||
- c4
|
||||
requires:
|
||||
- r1
|
||||
- r2
|
||||
- r3
|
||||
- r4";
|
||||
let yml = &YamlLoader::load_from_str(g_yaml).expect("failed to load YAML file")[0];
|
||||
let g = ArgGroup::from_yaml(yml);
|
||||
let args = vec!["a1", "a4", "a2", "a3"];
|
||||
let reqs = vec!["r1", "r2", "r3", "r4"];
|
||||
let confs = vec!["c1", "c2", "c3", "c4"];
|
||||
assert_eq!(g.args, args);
|
||||
assert_eq!(g.requires, Some(reqs));
|
||||
assert_eq!(g.conflicts, Some(confs));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Clone for ArgGroup<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
ArgGroup {
|
||||
name: self.name,
|
||||
required: self.required,
|
||||
args: self.args.clone(),
|
||||
requires: self.requires.clone(),
|
||||
conflicts: self.conflicts.clone(),
|
||||
multiple: self.multiple,
|
||||
}
|
||||
}
|
||||
}
|
||||
121
zeroidc/vendor/clap/src/args/macros.rs
vendored
Normal file
121
zeroidc/vendor/clap/src/args/macros.rs
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_tuple2 {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
if let Some(vec) = $v.as_vec() {
|
||||
for ys in vec {
|
||||
if let Some(tup) = ys.as_vec() {
|
||||
debug_assert_eq!(2, tup.len());
|
||||
$a = $a.$c(yaml_str!(tup[0]), yaml_str!(tup[1]));
|
||||
} else {
|
||||
panic!("Failed to convert YAML value to vec");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("Failed to convert YAML value to vec");
|
||||
}
|
||||
$a
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_tuple3 {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
if let Some(vec) = $v.as_vec() {
|
||||
for ys in vec {
|
||||
if let Some(tup) = ys.as_vec() {
|
||||
debug_assert_eq!(3, tup.len());
|
||||
$a = $a.$c(yaml_str!(tup[0]), yaml_opt_str!(tup[1]), yaml_str!(tup[2]));
|
||||
} else {
|
||||
panic!("Failed to convert YAML value to vec");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic!("Failed to convert YAML value to vec");
|
||||
}
|
||||
$a
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_vec_or_str {
|
||||
($v:ident, $a:ident, $c:ident) => {{
|
||||
let maybe_vec = $v.as_vec();
|
||||
if let Some(vec) = maybe_vec {
|
||||
for ys in vec {
|
||||
if let Some(s) = ys.as_str() {
|
||||
$a = $a.$c(s);
|
||||
} else {
|
||||
panic!("Failed to convert YAML value {:?} to a string", ys);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let Some(s) = $v.as_str() {
|
||||
$a = $a.$c(s);
|
||||
} else {
|
||||
panic!(
|
||||
"Failed to convert YAML value {:?} to either a vec or string",
|
||||
$v
|
||||
);
|
||||
}
|
||||
}
|
||||
$a
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_opt_str {
|
||||
($v:expr) => {{
|
||||
if $v.is_null() {
|
||||
Some(
|
||||
$v.as_str()
|
||||
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_str {
|
||||
($v:expr) => {{
|
||||
$v.as_str()
|
||||
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_to_str {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
$a.$c(yaml_str!($v))
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_to_bool {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
$a.$c($v
|
||||
.as_bool()
|
||||
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v)))
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_to_u64 {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
$a.$c($v
|
||||
.as_i64()
|
||||
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))
|
||||
as u64)
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "yaml")]
|
||||
macro_rules! yaml_to_usize {
|
||||
($a:ident, $v:ident, $c:ident) => {{
|
||||
$a.$c($v
|
||||
.as_i64()
|
||||
.unwrap_or_else(|| panic!("failed to convert YAML {:?} value to a string", $v))
|
||||
as usize)
|
||||
}};
|
||||
}
|
||||
29
zeroidc/vendor/clap/src/args/matched_arg.rs
vendored
Normal file
29
zeroidc/vendor/clap/src/args/matched_arg.rs
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// Std
|
||||
use std::ffi::OsString;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MatchedArg {
|
||||
#[doc(hidden)]
|
||||
pub occurs: u64,
|
||||
#[doc(hidden)]
|
||||
pub indices: Vec<usize>,
|
||||
#[doc(hidden)]
|
||||
pub vals: Vec<OsString>,
|
||||
}
|
||||
|
||||
impl Default for MatchedArg {
|
||||
fn default() -> Self {
|
||||
MatchedArg {
|
||||
occurs: 1,
|
||||
indices: Vec::new(),
|
||||
vals: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MatchedArg {
|
||||
pub fn new() -> Self {
|
||||
MatchedArg::default()
|
||||
}
|
||||
}
|
||||
21
zeroidc/vendor/clap/src/args/mod.rs
vendored
Normal file
21
zeroidc/vendor/clap/src/args/mod.rs
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
pub use self::any_arg::{AnyArg, DispOrder};
|
||||
pub use self::arg::Arg;
|
||||
pub use self::arg_builder::{Base, FlagBuilder, OptBuilder, PosBuilder, Switched, Valued};
|
||||
pub use self::arg_matcher::ArgMatcher;
|
||||
pub use self::arg_matches::{ArgMatches, OsValues, Values};
|
||||
pub use self::group::ArgGroup;
|
||||
pub use self::matched_arg::MatchedArg;
|
||||
pub use self::settings::{ArgFlags, ArgSettings};
|
||||
pub use self::subcommand::SubCommand;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
pub mod any_arg;
|
||||
mod arg;
|
||||
mod arg_builder;
|
||||
mod arg_matcher;
|
||||
mod arg_matches;
|
||||
mod group;
|
||||
mod matched_arg;
|
||||
pub mod settings;
|
||||
mod subcommand;
|
||||
237
zeroidc/vendor/clap/src/args/settings.rs
vendored
Normal file
237
zeroidc/vendor/clap/src/args/settings.rs
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
// Std
|
||||
#[allow(deprecated, unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
use std::str::FromStr;
|
||||
|
||||
bitflags! {
|
||||
struct Flags: u32 {
|
||||
const REQUIRED = 1;
|
||||
const MULTIPLE = 1 << 1;
|
||||
const EMPTY_VALS = 1 << 2;
|
||||
const GLOBAL = 1 << 3;
|
||||
const HIDDEN = 1 << 4;
|
||||
const TAKES_VAL = 1 << 5;
|
||||
const USE_DELIM = 1 << 6;
|
||||
const NEXT_LINE_HELP = 1 << 7;
|
||||
const R_UNLESS_ALL = 1 << 8;
|
||||
const REQ_DELIM = 1 << 9;
|
||||
const DELIM_NOT_SET = 1 << 10;
|
||||
const HIDE_POS_VALS = 1 << 11;
|
||||
const ALLOW_TAC_VALS = 1 << 12;
|
||||
const REQUIRE_EQUALS = 1 << 13;
|
||||
const LAST = 1 << 14;
|
||||
const HIDE_DEFAULT_VAL = 1 << 15;
|
||||
const CASE_INSENSITIVE = 1 << 16;
|
||||
const HIDE_ENV_VALS = 1 << 17;
|
||||
const HIDDEN_SHORT_H = 1 << 18;
|
||||
const HIDDEN_LONG_H = 1 << 19;
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ArgFlags(Flags);
|
||||
|
||||
impl ArgFlags {
|
||||
pub fn new() -> Self {
|
||||
ArgFlags::default()
|
||||
}
|
||||
|
||||
impl_settings! {ArgSettings,
|
||||
Required => Flags::REQUIRED,
|
||||
Multiple => Flags::MULTIPLE,
|
||||
EmptyValues => Flags::EMPTY_VALS,
|
||||
Global => Flags::GLOBAL,
|
||||
Hidden => Flags::HIDDEN,
|
||||
TakesValue => Flags::TAKES_VAL,
|
||||
UseValueDelimiter => Flags::USE_DELIM,
|
||||
NextLineHelp => Flags::NEXT_LINE_HELP,
|
||||
RequiredUnlessAll => Flags::R_UNLESS_ALL,
|
||||
RequireDelimiter => Flags::REQ_DELIM,
|
||||
ValueDelimiterNotSet => Flags::DELIM_NOT_SET,
|
||||
HidePossibleValues => Flags::HIDE_POS_VALS,
|
||||
AllowLeadingHyphen => Flags::ALLOW_TAC_VALS,
|
||||
RequireEquals => Flags::REQUIRE_EQUALS,
|
||||
Last => Flags::LAST,
|
||||
CaseInsensitive => Flags::CASE_INSENSITIVE,
|
||||
HideEnvValues => Flags::HIDE_ENV_VALS,
|
||||
HideDefaultValue => Flags::HIDE_DEFAULT_VAL,
|
||||
HiddenShortHelp => Flags::HIDDEN_SHORT_H,
|
||||
HiddenLongHelp => Flags::HIDDEN_LONG_H
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ArgFlags {
|
||||
fn default() -> Self {
|
||||
ArgFlags(Flags::EMPTY_VALS | Flags::DELIM_NOT_SET)
|
||||
}
|
||||
}
|
||||
|
||||
/// Various settings that apply to arguments and may be set, unset, and checked via getter/setter
|
||||
/// methods [`Arg::set`], [`Arg::unset`], and [`Arg::is_set`]
|
||||
///
|
||||
/// [`Arg::set`]: ./struct.Arg.html#method.set
|
||||
/// [`Arg::unset`]: ./struct.Arg.html#method.unset
|
||||
/// [`Arg::is_set`]: ./struct.Arg.html#method.is_set
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum ArgSettings {
|
||||
/// The argument must be used
|
||||
Required,
|
||||
/// The argument may be used multiple times such as `--flag --flag`
|
||||
Multiple,
|
||||
/// The argument allows empty values such as `--option ""`
|
||||
EmptyValues,
|
||||
/// The argument should be propagated down through all child [`SubCommand`]s
|
||||
///
|
||||
/// [`SubCommand`]: ./struct.SubCommand.html
|
||||
Global,
|
||||
/// The argument should **not** be shown in help text
|
||||
Hidden,
|
||||
/// The argument accepts a value, such as `--option <value>`
|
||||
TakesValue,
|
||||
/// Determines if the argument allows values to be grouped via a delimiter
|
||||
UseValueDelimiter,
|
||||
/// Prints the help text on the line after the argument
|
||||
NextLineHelp,
|
||||
/// Requires the use of a value delimiter for all multiple values
|
||||
RequireDelimiter,
|
||||
/// Hides the possible values from the help string
|
||||
HidePossibleValues,
|
||||
/// Allows vals that start with a '-'
|
||||
AllowLeadingHyphen,
|
||||
/// Require options use `--option=val` syntax
|
||||
RequireEquals,
|
||||
/// Specifies that the arg is the last positional argument and may be accessed early via `--`
|
||||
/// syntax
|
||||
Last,
|
||||
/// Hides the default value from the help string
|
||||
HideDefaultValue,
|
||||
/// Makes `Arg::possible_values` case insensitive
|
||||
CaseInsensitive,
|
||||
/// Hides ENV values in the help message
|
||||
HideEnvValues,
|
||||
/// The argument should **not** be shown in short help text
|
||||
HiddenShortHelp,
|
||||
/// The argument should **not** be shown in long help text
|
||||
HiddenLongHelp,
|
||||
#[doc(hidden)]
|
||||
RequiredUnlessAll,
|
||||
#[doc(hidden)]
|
||||
ValueDelimiterNotSet,
|
||||
}
|
||||
|
||||
impl FromStr for ArgSettings {
|
||||
type Err = String;
|
||||
fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
|
||||
match &*s.to_ascii_lowercase() {
|
||||
"required" => Ok(ArgSettings::Required),
|
||||
"multiple" => Ok(ArgSettings::Multiple),
|
||||
"global" => Ok(ArgSettings::Global),
|
||||
"emptyvalues" => Ok(ArgSettings::EmptyValues),
|
||||
"hidden" => Ok(ArgSettings::Hidden),
|
||||
"takesvalue" => Ok(ArgSettings::TakesValue),
|
||||
"usevaluedelimiter" => Ok(ArgSettings::UseValueDelimiter),
|
||||
"nextlinehelp" => Ok(ArgSettings::NextLineHelp),
|
||||
"requiredunlessall" => Ok(ArgSettings::RequiredUnlessAll),
|
||||
"requiredelimiter" => Ok(ArgSettings::RequireDelimiter),
|
||||
"valuedelimiternotset" => Ok(ArgSettings::ValueDelimiterNotSet),
|
||||
"hidepossiblevalues" => Ok(ArgSettings::HidePossibleValues),
|
||||
"allowleadinghyphen" => Ok(ArgSettings::AllowLeadingHyphen),
|
||||
"requireequals" => Ok(ArgSettings::RequireEquals),
|
||||
"last" => Ok(ArgSettings::Last),
|
||||
"hidedefaultvalue" => Ok(ArgSettings::HideDefaultValue),
|
||||
"caseinsensitive" => Ok(ArgSettings::CaseInsensitive),
|
||||
"hideenvvalues" => Ok(ArgSettings::HideEnvValues),
|
||||
"hiddenshorthelp" => Ok(ArgSettings::HiddenShortHelp),
|
||||
"hiddenlonghelp" => Ok(ArgSettings::HiddenLongHelp),
|
||||
_ => Err("unknown ArgSetting, cannot convert from str".to_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::ArgSettings;
|
||||
|
||||
#[test]
|
||||
fn arg_settings_fromstr() {
|
||||
assert_eq!(
|
||||
"allowleadinghyphen".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::AllowLeadingHyphen
|
||||
);
|
||||
assert_eq!(
|
||||
"emptyvalues".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::EmptyValues
|
||||
);
|
||||
assert_eq!(
|
||||
"global".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Global
|
||||
);
|
||||
assert_eq!(
|
||||
"hidepossiblevalues".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HidePossibleValues
|
||||
);
|
||||
assert_eq!(
|
||||
"hidden".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Hidden
|
||||
);
|
||||
assert_eq!(
|
||||
"multiple".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Multiple
|
||||
);
|
||||
assert_eq!(
|
||||
"nextlinehelp".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::NextLineHelp
|
||||
);
|
||||
assert_eq!(
|
||||
"requiredunlessall".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequiredUnlessAll
|
||||
);
|
||||
assert_eq!(
|
||||
"requiredelimiter".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequireDelimiter
|
||||
);
|
||||
assert_eq!(
|
||||
"required".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::Required
|
||||
);
|
||||
assert_eq!(
|
||||
"takesvalue".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::TakesValue
|
||||
);
|
||||
assert_eq!(
|
||||
"usevaluedelimiter".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::UseValueDelimiter
|
||||
);
|
||||
assert_eq!(
|
||||
"valuedelimiternotset".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::ValueDelimiterNotSet
|
||||
);
|
||||
assert_eq!(
|
||||
"requireequals".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::RequireEquals
|
||||
);
|
||||
assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last);
|
||||
assert_eq!(
|
||||
"hidedefaultvalue".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HideDefaultValue
|
||||
);
|
||||
assert_eq!(
|
||||
"caseinsensitive".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::CaseInsensitive
|
||||
);
|
||||
assert_eq!(
|
||||
"hideenvvalues".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HideEnvValues
|
||||
);
|
||||
assert_eq!(
|
||||
"hiddenshorthelp".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HiddenShortHelp
|
||||
);
|
||||
assert_eq!(
|
||||
"hiddenlonghelp".parse::<ArgSettings>().unwrap(),
|
||||
ArgSettings::HiddenLongHelp
|
||||
);
|
||||
assert!("hahahaha".parse::<ArgSettings>().is_err());
|
||||
}
|
||||
}
|
||||
71
zeroidc/vendor/clap/src/args/subcommand.rs
vendored
Normal file
71
zeroidc/vendor/clap/src/args/subcommand.rs
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Third Party
|
||||
#[cfg(feature = "yaml")]
|
||||
use yaml_rust::Yaml;
|
||||
|
||||
// Internal
|
||||
use crate::{App, ArgMatches};
|
||||
|
||||
/// The abstract representation of a command line subcommand.
|
||||
///
|
||||
/// This struct describes all the valid options of the subcommand for the program. Subcommands are
|
||||
/// essentially "sub-[`App`]s" and contain all the same possibilities (such as their own
|
||||
/// [arguments], subcommands, and settings).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, SubCommand};
|
||||
/// App::new("myprog")
|
||||
/// .subcommand(
|
||||
/// SubCommand::with_name("config")
|
||||
/// .about("Used for configuration")
|
||||
/// .arg(Arg::with_name("config_file")
|
||||
/// .help("The configuration file to use")
|
||||
/// .index(1)))
|
||||
/// # ;
|
||||
/// ```
|
||||
/// [`App`]: ./struct.App.html
|
||||
/// [arguments]: ./struct.Arg.html
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SubCommand<'a> {
|
||||
#[doc(hidden)]
|
||||
pub name: String,
|
||||
#[doc(hidden)]
|
||||
pub matches: ArgMatches<'a>,
|
||||
}
|
||||
|
||||
impl<'a> SubCommand<'a> {
|
||||
/// Creates a new instance of a subcommand requiring a name. The name will be displayed
|
||||
/// to the user when they print version or help and usage information.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, SubCommand};
|
||||
/// App::new("myprog")
|
||||
/// .subcommand(
|
||||
/// SubCommand::with_name("config"))
|
||||
/// # ;
|
||||
/// ```
|
||||
pub fn with_name<'b>(name: &str) -> App<'a, 'b> {
|
||||
App::new(name)
|
||||
}
|
||||
|
||||
/// Creates a new instance of a subcommand from a YAML (.yml) document
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// # #[macro_use]
|
||||
/// # extern crate clap;
|
||||
/// # use clap::Subcommand;
|
||||
/// # fn main() {
|
||||
/// let sc_yaml = load_yaml!("test_subcommand.yml");
|
||||
/// let sc = SubCommand::from_yaml(sc_yaml);
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(feature = "yaml")]
|
||||
pub fn from_yaml(yaml: &Yaml) -> App {
|
||||
App::from_yaml(yaml)
|
||||
}
|
||||
}
|
||||
223
zeroidc/vendor/clap/src/completions/bash.rs
vendored
Normal file
223
zeroidc/vendor/clap/src/completions/bash.rs
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
// Std
|
||||
use std::io::Write;
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
app::parser::Parser,
|
||||
args::{AnyArg, OptBuilder},
|
||||
completions,
|
||||
};
|
||||
|
||||
pub struct BashGen<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> BashGen<'a, 'b> {
|
||||
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
|
||||
BashGen { p }
|
||||
}
|
||||
|
||||
pub fn generate_to<W: Write>(&self, buf: &mut W) {
|
||||
w!(
|
||||
buf,
|
||||
format!(
|
||||
r#"_{name}() {{
|
||||
local i cur prev opts cmds
|
||||
COMPREPLY=()
|
||||
cur="${{COMP_WORDS[COMP_CWORD]}}"
|
||||
prev="${{COMP_WORDS[COMP_CWORD-1]}}"
|
||||
cmd=""
|
||||
opts=""
|
||||
|
||||
for i in ${{COMP_WORDS[@]}}
|
||||
do
|
||||
case "${{i}}" in
|
||||
{name})
|
||||
cmd="{name}"
|
||||
;;
|
||||
{subcmds}
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "${{cmd}}" in
|
||||
{name})
|
||||
opts="{name_opts}"
|
||||
if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq 1 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${{opts}}" -- "${{cur}}") )
|
||||
return 0
|
||||
fi
|
||||
case "${{prev}}" in
|
||||
{name_opts_details}
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $(compgen -W "${{opts}}" -- "${{cur}}") )
|
||||
return 0
|
||||
;;
|
||||
{subcmd_details}
|
||||
esac
|
||||
}}
|
||||
|
||||
complete -F _{name} -o bashdefault -o default {name}
|
||||
"#,
|
||||
name = self.p.meta.bin_name.as_ref().unwrap(),
|
||||
name_opts = self.all_options_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
||||
name_opts_details =
|
||||
self.option_details_for_path(self.p.meta.bin_name.as_ref().unwrap()),
|
||||
subcmds = self.all_subcommands(),
|
||||
subcmd_details = self.subcommand_details()
|
||||
)
|
||||
.as_bytes()
|
||||
);
|
||||
}
|
||||
|
||||
fn all_subcommands(&self) -> String {
|
||||
debugln!("BashGen::all_subcommands;");
|
||||
let mut subcmds = String::new();
|
||||
let scs = completions::all_subcommand_names(self.p);
|
||||
|
||||
for sc in &scs {
|
||||
subcmds = format!(
|
||||
r#"{}
|
||||
{name})
|
||||
cmd+="__{fn_name}"
|
||||
;;"#,
|
||||
subcmds,
|
||||
name = sc,
|
||||
fn_name = sc.replace("-", "__")
|
||||
);
|
||||
}
|
||||
|
||||
subcmds
|
||||
}
|
||||
|
||||
fn subcommand_details(&self) -> String {
|
||||
debugln!("BashGen::subcommand_details;");
|
||||
let mut subcmd_dets = String::new();
|
||||
let mut scs = completions::get_all_subcommand_paths(self.p, true);
|
||||
scs.sort();
|
||||
scs.dedup();
|
||||
|
||||
for sc in &scs {
|
||||
subcmd_dets = format!(
|
||||
r#"{}
|
||||
{subcmd})
|
||||
opts="{sc_opts}"
|
||||
if [[ ${{cur}} == -* || ${{COMP_CWORD}} -eq {level} ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${{opts}}" -- "${{cur}}") )
|
||||
return 0
|
||||
fi
|
||||
case "${{prev}}" in
|
||||
{opts_details}
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $(compgen -W "${{opts}}" -- "${{cur}}") )
|
||||
return 0
|
||||
;;"#,
|
||||
subcmd_dets,
|
||||
subcmd = sc.replace("-", "__"),
|
||||
sc_opts = self.all_options_for_path(&*sc),
|
||||
level = sc.split("__").count(),
|
||||
opts_details = self.option_details_for_path(&*sc)
|
||||
);
|
||||
}
|
||||
|
||||
subcmd_dets
|
||||
}
|
||||
|
||||
fn option_details_for_path(&self, path: &str) -> String {
|
||||
debugln!("BashGen::option_details_for_path: path={}", path);
|
||||
let mut p = self.p;
|
||||
for sc in path.split("__").skip(1) {
|
||||
debugln!("BashGen::option_details_for_path:iter: sc={}", sc);
|
||||
p = &find_subcmd!(p, sc).unwrap().p;
|
||||
}
|
||||
let mut opts = String::new();
|
||||
for o in p.opts() {
|
||||
if let Some(l) = o.s.long {
|
||||
opts = format!(
|
||||
"{}
|
||||
--{})
|
||||
COMPREPLY=({})
|
||||
return 0
|
||||
;;",
|
||||
opts,
|
||||
l,
|
||||
self.vals_for(o)
|
||||
);
|
||||
}
|
||||
if let Some(s) = o.s.short {
|
||||
opts = format!(
|
||||
"{}
|
||||
-{})
|
||||
COMPREPLY=({})
|
||||
return 0
|
||||
;;",
|
||||
opts,
|
||||
s,
|
||||
self.vals_for(o)
|
||||
);
|
||||
}
|
||||
}
|
||||
opts
|
||||
}
|
||||
|
||||
fn vals_for(&self, o: &OptBuilder) -> String {
|
||||
debugln!("BashGen::vals_for: o={}", o.b.name);
|
||||
if let Some(vals) = o.possible_vals() {
|
||||
format!(r#"$(compgen -W "{}" -- "${{cur}}")"#, vals.join(" "))
|
||||
} else {
|
||||
String::from(r#"$(compgen -f "${cur}")"#)
|
||||
}
|
||||
}
|
||||
|
||||
fn all_options_for_path(&self, path: &str) -> String {
|
||||
debugln!("BashGen::all_options_for_path: path={}", path);
|
||||
let mut p = self.p;
|
||||
for sc in path.split("__").skip(1) {
|
||||
debugln!("BashGen::all_options_for_path:iter: sc={}", sc);
|
||||
p = &find_subcmd!(p, sc).unwrap().p;
|
||||
}
|
||||
let mut opts = shorts!(p).fold(String::new(), |acc, s| format!("{} -{}", acc, s));
|
||||
opts = format!(
|
||||
"{} {}",
|
||||
opts,
|
||||
longs!(p).fold(String::new(), |acc, l| format!("{} --{}", acc, l))
|
||||
);
|
||||
opts = format!(
|
||||
"{} {}",
|
||||
opts,
|
||||
p.positionals
|
||||
.values()
|
||||
.fold(String::new(), |acc, p| format!("{} {}", acc, p))
|
||||
);
|
||||
opts = format!(
|
||||
"{} {}",
|
||||
opts,
|
||||
p.subcommands
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| format!("{} {}", acc, s.p.meta.name))
|
||||
);
|
||||
for sc in &p.subcommands {
|
||||
if let Some(ref aliases) = sc.p.meta.aliases {
|
||||
opts = format!(
|
||||
"{} {}",
|
||||
opts,
|
||||
aliases
|
||||
.iter()
|
||||
.map(|&(n, _)| n)
|
||||
.fold(String::new(), |acc, a| format!("{} {}", acc, a))
|
||||
);
|
||||
}
|
||||
}
|
||||
opts
|
||||
}
|
||||
}
|
||||
127
zeroidc/vendor/clap/src/completions/elvish.rs
vendored
Normal file
127
zeroidc/vendor/clap/src/completions/elvish.rs
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
// Std
|
||||
use std::io::Write;
|
||||
|
||||
// Internal
|
||||
use crate::{app::parser::Parser, INTERNAL_ERROR_MSG};
|
||||
|
||||
pub struct ElvishGen<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ElvishGen<'a, 'b> {
|
||||
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
|
||||
ElvishGen { p }
|
||||
}
|
||||
|
||||
pub fn generate_to<W: Write>(&self, buf: &mut W) {
|
||||
let bin_name = self.p.meta.bin_name.as_ref().unwrap();
|
||||
|
||||
let mut names = vec![];
|
||||
let subcommands_cases = generate_inner(self.p, "", &mut names);
|
||||
|
||||
let result = format!(
|
||||
r#"
|
||||
edit:completion:arg-completer[{bin_name}] = [@words]{{
|
||||
fn spaces [n]{{
|
||||
repeat $n ' ' | joins ''
|
||||
}}
|
||||
fn cand [text desc]{{
|
||||
edit:complex-candidate $text &display-suffix=' '(spaces (- 14 (wcswidth $text)))$desc
|
||||
}}
|
||||
command = '{bin_name}'
|
||||
for word $words[1:-1] {{
|
||||
if (has-prefix $word '-') {{
|
||||
break
|
||||
}}
|
||||
command = $command';'$word
|
||||
}}
|
||||
completions = [{subcommands_cases}
|
||||
]
|
||||
$completions[$command]
|
||||
}}
|
||||
"#,
|
||||
bin_name = bin_name,
|
||||
subcommands_cases = subcommands_cases
|
||||
);
|
||||
|
||||
w!(buf, result.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
// Escape string inside single quotes
|
||||
fn escape_string(string: &str) -> String {
|
||||
string.replace("'", "''")
|
||||
}
|
||||
|
||||
fn get_tooltip<T: ToString>(help: Option<&str>, data: T) -> String {
|
||||
match help {
|
||||
Some(help) => escape_string(help),
|
||||
_ => data.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_inner<'a, 'b, 'p>(
|
||||
p: &'p Parser<'a, 'b>,
|
||||
previous_command_name: &str,
|
||||
names: &mut Vec<&'p str>,
|
||||
) -> String {
|
||||
debugln!("ElvishGen::generate_inner;");
|
||||
let command_name = if previous_command_name.is_empty() {
|
||||
p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG).clone()
|
||||
} else {
|
||||
format!("{};{}", previous_command_name, &p.meta.name)
|
||||
};
|
||||
|
||||
let mut completions = String::new();
|
||||
let preamble = String::from("\n cand ");
|
||||
|
||||
for option in p.opts() {
|
||||
if let Some(data) = option.s.short {
|
||||
let tooltip = get_tooltip(option.b.help, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
|
||||
}
|
||||
if let Some(data) = option.s.long {
|
||||
let tooltip = get_tooltip(option.b.help, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
|
||||
}
|
||||
}
|
||||
|
||||
for flag in p.flags() {
|
||||
if let Some(data) = flag.s.short {
|
||||
let tooltip = get_tooltip(flag.b.help, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(format!("-{} '{}'", data, tooltip).as_str());
|
||||
}
|
||||
if let Some(data) = flag.s.long {
|
||||
let tooltip = get_tooltip(flag.b.help, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(format!("--{} '{}'", data, tooltip).as_str());
|
||||
}
|
||||
}
|
||||
|
||||
for subcommand in &p.subcommands {
|
||||
let data = &subcommand.p.meta.name;
|
||||
let tooltip = get_tooltip(subcommand.p.meta.about, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(format!("{} '{}'", data, tooltip).as_str());
|
||||
}
|
||||
|
||||
let mut subcommands_cases = format!(
|
||||
r"
|
||||
&'{}'= {{{}
|
||||
}}",
|
||||
&command_name, completions
|
||||
);
|
||||
|
||||
for subcommand in &p.subcommands {
|
||||
let subcommand_subcommands_cases = generate_inner(&subcommand.p, &command_name, names);
|
||||
subcommands_cases.push_str(&subcommand_subcommands_cases);
|
||||
}
|
||||
|
||||
subcommands_cases
|
||||
}
|
||||
103
zeroidc/vendor/clap/src/completions/fish.rs
vendored
Normal file
103
zeroidc/vendor/clap/src/completions/fish.rs
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// Std
|
||||
use std::io::Write;
|
||||
|
||||
// Internal
|
||||
use crate::app::parser::Parser;
|
||||
|
||||
pub struct FishGen<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> FishGen<'a, 'b> {
|
||||
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
|
||||
FishGen { p }
|
||||
}
|
||||
|
||||
pub fn generate_to<W: Write>(&self, buf: &mut W) {
|
||||
let command = self.p.meta.bin_name.as_ref().unwrap();
|
||||
let mut buffer = String::new();
|
||||
gen_fish_inner(command, self, command, &mut buffer);
|
||||
w!(buf, buffer.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
// Escape string inside single quotes
|
||||
fn escape_string(string: &str) -> String {
|
||||
string.replace("\\", "\\\\").replace("'", "\\'")
|
||||
}
|
||||
|
||||
fn gen_fish_inner(root_command: &str, comp_gen: &FishGen, subcommand: &str, buffer: &mut String) {
|
||||
debugln!("FishGen::gen_fish_inner;");
|
||||
// example :
|
||||
//
|
||||
// complete
|
||||
// -c {command}
|
||||
// -d "{description}"
|
||||
// -s {short}
|
||||
// -l {long}
|
||||
// -a "{possible_arguments}"
|
||||
// -r # if require parameter
|
||||
// -f # don't use file completion
|
||||
// -n "__fish_use_subcommand" # complete for command "myprog"
|
||||
// -n "__fish_seen_subcommand_from subcmd1" # complete for command "myprog subcmd1"
|
||||
|
||||
let mut basic_template = format!("complete -c {} -n ", root_command);
|
||||
if root_command == subcommand {
|
||||
basic_template.push_str("\"__fish_use_subcommand\"");
|
||||
} else {
|
||||
basic_template.push_str(format!("\"__fish_seen_subcommand_from {}\"", subcommand).as_str());
|
||||
}
|
||||
|
||||
for option in comp_gen.p.opts() {
|
||||
let mut template = basic_template.clone();
|
||||
if let Some(data) = option.s.short {
|
||||
template.push_str(format!(" -s {}", data).as_str());
|
||||
}
|
||||
if let Some(data) = option.s.long {
|
||||
template.push_str(format!(" -l {}", data).as_str());
|
||||
}
|
||||
if let Some(data) = option.b.help {
|
||||
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
|
||||
}
|
||||
if let Some(ref data) = option.v.possible_vals {
|
||||
template.push_str(format!(" -r -f -a \"{}\"", data.join(" ")).as_str());
|
||||
}
|
||||
buffer.push_str(template.as_str());
|
||||
buffer.push('\n');
|
||||
}
|
||||
|
||||
for flag in comp_gen.p.flags() {
|
||||
let mut template = basic_template.clone();
|
||||
if let Some(data) = flag.s.short {
|
||||
template.push_str(format!(" -s {}", data).as_str());
|
||||
}
|
||||
if let Some(data) = flag.s.long {
|
||||
template.push_str(format!(" -l {}", data).as_str());
|
||||
}
|
||||
if let Some(data) = flag.b.help {
|
||||
template.push_str(format!(" -d '{}'", escape_string(data)).as_str());
|
||||
}
|
||||
buffer.push_str(template.as_str());
|
||||
buffer.push('\n');
|
||||
}
|
||||
|
||||
for subcommand in &comp_gen.p.subcommands {
|
||||
let mut template = basic_template.clone();
|
||||
template.push_str(" -f");
|
||||
template.push_str(format!(" -a \"{}\"", &subcommand.p.meta.name).as_str());
|
||||
if let Some(data) = subcommand.p.meta.about {
|
||||
template.push_str(format!(" -d '{}'", escape_string(data)).as_str())
|
||||
}
|
||||
buffer.push_str(template.as_str());
|
||||
buffer.push('\n');
|
||||
}
|
||||
|
||||
// generate options of subcommands
|
||||
for subcommand in &comp_gen.p.subcommands {
|
||||
let sub_comp_gen = FishGen::new(&subcommand.p);
|
||||
gen_fish_inner(root_command, &sub_comp_gen, &subcommand.to_string(), buffer);
|
||||
}
|
||||
}
|
||||
28
zeroidc/vendor/clap/src/completions/macros.rs
vendored
Normal file
28
zeroidc/vendor/clap/src/completions/macros.rs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
macro_rules! w {
|
||||
($buf:expr, $to_w:expr) => {
|
||||
match $buf.write_all($to_w) {
|
||||
Ok(..) => (),
|
||||
Err(..) => panic!("Failed to write to completions file"),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! get_zsh_arg_conflicts {
|
||||
($p:ident, $arg:ident, $msg:ident) => {
|
||||
if let Some(conf_vec) = $arg.blacklist() {
|
||||
let mut v = vec![];
|
||||
for arg_name in conf_vec {
|
||||
let arg = $p.find_any_arg(arg_name).expect($msg);
|
||||
if let Some(s) = arg.short() {
|
||||
v.push(format!("-{}", s));
|
||||
}
|
||||
if let Some(l) = arg.long() {
|
||||
v.push(format!("--{}", l));
|
||||
}
|
||||
}
|
||||
v.join(" ")
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
};
|
||||
}
|
||||
182
zeroidc/vendor/clap/src/completions/mod.rs
vendored
Normal file
182
zeroidc/vendor/clap/src/completions/mod.rs
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod bash;
|
||||
mod elvish;
|
||||
mod fish;
|
||||
mod powershell;
|
||||
mod shell;
|
||||
mod zsh;
|
||||
|
||||
// Std
|
||||
use std::io::Write;
|
||||
|
||||
// Internal
|
||||
pub use crate::completions::shell::Shell;
|
||||
use crate::{
|
||||
app::parser::Parser,
|
||||
completions::{
|
||||
bash::BashGen, elvish::ElvishGen, fish::FishGen, powershell::PowerShellGen, zsh::ZshGen,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct ComplGen<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ComplGen<'a, 'b> {
|
||||
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
|
||||
ComplGen { p }
|
||||
}
|
||||
|
||||
pub fn generate<W: Write>(&self, for_shell: Shell, buf: &mut W) {
|
||||
match for_shell {
|
||||
Shell::Bash => BashGen::new(self.p).generate_to(buf),
|
||||
Shell::Fish => FishGen::new(self.p).generate_to(buf),
|
||||
Shell::Zsh => ZshGen::new(self.p).generate_to(buf),
|
||||
Shell::PowerShell => PowerShellGen::new(self.p).generate_to(buf),
|
||||
Shell::Elvish => ElvishGen::new(self.p).generate_to(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gets all subcommands including child subcommands in the form of 'name' where the name
|
||||
// is a single word (i.e. "install") of the path to said subcommand (i.e.
|
||||
// "rustup toolchain install")
|
||||
//
|
||||
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're
|
||||
// aliasing.
|
||||
pub fn all_subcommand_names(p: &Parser) -> Vec<String> {
|
||||
debugln!("all_subcommand_names;");
|
||||
let mut subcmds: Vec<_> = subcommands_of(p)
|
||||
.iter()
|
||||
.map(|&(ref n, _)| n.clone())
|
||||
.collect();
|
||||
for sc_v in p.subcommands.iter().map(|s| all_subcommand_names(&s.p)) {
|
||||
subcmds.extend(sc_v);
|
||||
}
|
||||
subcmds.sort();
|
||||
subcmds.dedup();
|
||||
subcmds
|
||||
}
|
||||
|
||||
// Gets all subcommands including child subcommands in the form of ('name', 'bin_name') where the name
|
||||
// is a single word (i.e. "install") of the path and full bin_name of said subcommand (i.e.
|
||||
// "rustup toolchain install")
|
||||
//
|
||||
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're
|
||||
// aliasing.
|
||||
pub fn all_subcommands(p: &Parser) -> Vec<(String, String)> {
|
||||
debugln!("all_subcommands;");
|
||||
let mut subcmds: Vec<_> = subcommands_of(p);
|
||||
for sc_v in p.subcommands.iter().map(|s| all_subcommands(&s.p)) {
|
||||
subcmds.extend(sc_v);
|
||||
}
|
||||
subcmds
|
||||
}
|
||||
|
||||
// Gets all subcommands excluding child subcommands in the form of (name, bin_name) where the name
|
||||
// is a single word (i.e. "install") and the bin_name is a space delineated list of the path to said
|
||||
// subcommand (i.e. "rustup toolchain install")
|
||||
//
|
||||
// Also note, aliases are treated as their own subcommands but duplicates of whatever they're
|
||||
// aliasing.
|
||||
pub fn subcommands_of(p: &Parser) -> Vec<(String, String)> {
|
||||
debugln!(
|
||||
"subcommands_of: name={}, bin_name={}",
|
||||
p.meta.name,
|
||||
p.meta.bin_name.as_ref().unwrap()
|
||||
);
|
||||
let mut subcmds = vec![];
|
||||
|
||||
debugln!(
|
||||
"subcommands_of: Has subcommands...{:?}",
|
||||
p.has_subcommands()
|
||||
);
|
||||
if !p.has_subcommands() {
|
||||
let mut ret = vec![];
|
||||
debugln!("subcommands_of: Looking for aliases...");
|
||||
if let Some(ref aliases) = p.meta.aliases {
|
||||
for &(n, _) in aliases {
|
||||
debugln!("subcommands_of:iter:iter: Found alias...{}", n);
|
||||
let mut als_bin_name: Vec<_> =
|
||||
p.meta.bin_name.as_ref().unwrap().split(' ').collect();
|
||||
als_bin_name.push(n);
|
||||
let old = als_bin_name.len() - 2;
|
||||
als_bin_name.swap_remove(old);
|
||||
ret.push((n.to_owned(), als_bin_name.join(" ")));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
for sc in &p.subcommands {
|
||||
debugln!(
|
||||
"subcommands_of:iter: name={}, bin_name={}",
|
||||
sc.p.meta.name,
|
||||
sc.p.meta.bin_name.as_ref().unwrap()
|
||||
);
|
||||
|
||||
debugln!("subcommands_of:iter: Looking for aliases...");
|
||||
if let Some(ref aliases) = sc.p.meta.aliases {
|
||||
for &(n, _) in aliases {
|
||||
debugln!("subcommands_of:iter:iter: Found alias...{}", n);
|
||||
let mut als_bin_name: Vec<_> =
|
||||
p.meta.bin_name.as_ref().unwrap().split(' ').collect();
|
||||
als_bin_name.push(n);
|
||||
let old = als_bin_name.len() - 2;
|
||||
als_bin_name.swap_remove(old);
|
||||
subcmds.push((n.to_owned(), als_bin_name.join(" ")));
|
||||
}
|
||||
}
|
||||
subcmds.push((
|
||||
sc.p.meta.name.clone(),
|
||||
sc.p.meta.bin_name.as_ref().unwrap().clone(),
|
||||
));
|
||||
}
|
||||
subcmds
|
||||
}
|
||||
|
||||
pub fn get_all_subcommand_paths(p: &Parser, first: bool) -> Vec<String> {
|
||||
debugln!("get_all_subcommand_paths;");
|
||||
let mut subcmds = vec![];
|
||||
if !p.has_subcommands() {
|
||||
if !first {
|
||||
let name = &*p.meta.name;
|
||||
let path = p.meta.bin_name.as_ref().unwrap().clone().replace(" ", "__");
|
||||
let mut ret = vec![path.clone()];
|
||||
if let Some(ref aliases) = p.meta.aliases {
|
||||
for &(n, _) in aliases {
|
||||
ret.push(path.replace(name, n));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return vec![];
|
||||
}
|
||||
for sc in &p.subcommands {
|
||||
let name = &*sc.p.meta.name;
|
||||
let path =
|
||||
sc.p.meta
|
||||
.bin_name
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.replace(" ", "__");
|
||||
subcmds.push(path.clone());
|
||||
if let Some(ref aliases) = sc.p.meta.aliases {
|
||||
for &(n, _) in aliases {
|
||||
subcmds.push(path.replace(name, n));
|
||||
}
|
||||
}
|
||||
}
|
||||
for sc_v in p
|
||||
.subcommands
|
||||
.iter()
|
||||
.map(|s| get_all_subcommand_paths(&s.p, false))
|
||||
{
|
||||
subcmds.extend(sc_v);
|
||||
}
|
||||
subcmds
|
||||
}
|
||||
165
zeroidc/vendor/clap/src/completions/powershell.rs
vendored
Normal file
165
zeroidc/vendor/clap/src/completions/powershell.rs
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
// Std
|
||||
use std::io::Write;
|
||||
|
||||
// Internal
|
||||
use crate::{app::parser::Parser, INTERNAL_ERROR_MSG};
|
||||
|
||||
pub struct PowerShellGen<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> PowerShellGen<'a, 'b> {
|
||||
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
|
||||
PowerShellGen { p }
|
||||
}
|
||||
|
||||
pub fn generate_to<W: Write>(&self, buf: &mut W) {
|
||||
let bin_name = self.p.meta.bin_name.as_ref().unwrap();
|
||||
|
||||
let mut names = vec![];
|
||||
let subcommands_cases = generate_inner(self.p, "", &mut names);
|
||||
|
||||
let result = format!(
|
||||
r#"
|
||||
using namespace System.Management.Automation
|
||||
using namespace System.Management.Automation.Language
|
||||
|
||||
Register-ArgumentCompleter -Native -CommandName '{bin_name}' -ScriptBlock {{
|
||||
param($wordToComplete, $commandAst, $cursorPosition)
|
||||
|
||||
$commandElements = $commandAst.CommandElements
|
||||
$command = @(
|
||||
'{bin_name}'
|
||||
for ($i = 1; $i -lt $commandElements.Count; $i++) {{
|
||||
$element = $commandElements[$i]
|
||||
if ($element -isnot [StringConstantExpressionAst] -or
|
||||
$element.StringConstantType -ne [StringConstantType]::BareWord -or
|
||||
$element.Value.StartsWith('-')) {{
|
||||
break
|
||||
}}
|
||||
$element.Value
|
||||
}}) -join ';'
|
||||
|
||||
$completions = @(switch ($command) {{{subcommands_cases}
|
||||
}})
|
||||
|
||||
$completions.Where{{ $_.CompletionText -like "$wordToComplete*" }} |
|
||||
Sort-Object -Property ListItemText
|
||||
}}
|
||||
"#,
|
||||
bin_name = bin_name,
|
||||
subcommands_cases = subcommands_cases
|
||||
);
|
||||
|
||||
w!(buf, result.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
// Escape string inside single quotes
|
||||
fn escape_string(string: &str) -> String {
|
||||
string.replace("'", "''")
|
||||
}
|
||||
|
||||
fn get_tooltip<T: ToString>(help: Option<&str>, data: T) -> String {
|
||||
match help {
|
||||
Some(help) => escape_string(help),
|
||||
_ => data.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_inner<'a, 'b, 'p>(
|
||||
p: &'p Parser<'a, 'b>,
|
||||
previous_command_name: &str,
|
||||
names: &mut Vec<&'p str>,
|
||||
) -> String {
|
||||
debugln!("PowerShellGen::generate_inner;");
|
||||
let command_name = if previous_command_name.is_empty() {
|
||||
p.meta.bin_name.as_ref().expect(INTERNAL_ERROR_MSG).clone()
|
||||
} else {
|
||||
format!("{};{}", previous_command_name, &p.meta.name)
|
||||
};
|
||||
|
||||
let mut completions = String::new();
|
||||
let preamble = String::from("\n [CompletionResult]::new(");
|
||||
|
||||
for option in p.opts() {
|
||||
if let Some(data) = option.s.short {
|
||||
let tooltip = get_tooltip(option.b.help, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(
|
||||
format!(
|
||||
"'-{}', '{}', {}, '{}')",
|
||||
data, data, "[CompletionResultType]::ParameterName", tooltip
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
if let Some(data) = option.s.long {
|
||||
let tooltip = get_tooltip(option.b.help, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(
|
||||
format!(
|
||||
"'--{}', '{}', {}, '{}')",
|
||||
data, data, "[CompletionResultType]::ParameterName", tooltip
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for flag in p.flags() {
|
||||
if let Some(data) = flag.s.short {
|
||||
let tooltip = get_tooltip(flag.b.help, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(
|
||||
format!(
|
||||
"'-{}', '{}', {}, '{}')",
|
||||
data, data, "[CompletionResultType]::ParameterName", tooltip
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
if let Some(data) = flag.s.long {
|
||||
let tooltip = get_tooltip(flag.b.help, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(
|
||||
format!(
|
||||
"'--{}', '{}', {}, '{}')",
|
||||
data, data, "[CompletionResultType]::ParameterName", tooltip
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for subcommand in &p.subcommands {
|
||||
let data = &subcommand.p.meta.name;
|
||||
let tooltip = get_tooltip(subcommand.p.meta.about, data);
|
||||
completions.push_str(&preamble);
|
||||
completions.push_str(
|
||||
format!(
|
||||
"'{}', '{}', {}, '{}')",
|
||||
data, data, "[CompletionResultType]::ParameterValue", tooltip
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut subcommands_cases = format!(
|
||||
r"
|
||||
'{}' {{{}
|
||||
break
|
||||
}}",
|
||||
&command_name, completions
|
||||
);
|
||||
|
||||
for subcommand in &p.subcommands {
|
||||
let subcommand_subcommands_cases = generate_inner(&subcommand.p, &command_name, names);
|
||||
subcommands_cases.push_str(&subcommand_subcommands_cases);
|
||||
}
|
||||
|
||||
subcommands_cases
|
||||
}
|
||||
56
zeroidc/vendor/clap/src/completions/shell.rs
vendored
Normal file
56
zeroidc/vendor/clap/src/completions/shell.rs
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
#[allow(deprecated, unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// Describes which shell to produce a completions file for
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Shell {
|
||||
/// Generates a .bash completion file for the Bourne Again SHell (BASH)
|
||||
Bash,
|
||||
/// Generates a .fish completion file for the Friendly Interactive SHell (fish)
|
||||
Fish,
|
||||
/// Generates a completion file for the Z SHell (ZSH)
|
||||
Zsh,
|
||||
/// Generates a completion file for PowerShell
|
||||
PowerShell,
|
||||
/// Generates a completion file for Elvish
|
||||
Elvish,
|
||||
}
|
||||
|
||||
impl Shell {
|
||||
/// A list of possible variants in `&'static str` form
|
||||
pub fn variants() -> [&'static str; 5] {
|
||||
["zsh", "bash", "fish", "powershell", "elvish"]
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Shell {
|
||||
type Err = String;
|
||||
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::wildcard_in_or_patterns))]
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"ZSH" | _ if s.eq_ignore_ascii_case("zsh") => Ok(Shell::Zsh),
|
||||
"FISH" | _ if s.eq_ignore_ascii_case("fish") => Ok(Shell::Fish),
|
||||
"BASH" | _ if s.eq_ignore_ascii_case("bash") => Ok(Shell::Bash),
|
||||
"POWERSHELL" | _ if s.eq_ignore_ascii_case("powershell") => Ok(Shell::PowerShell),
|
||||
"ELVISH" | _ if s.eq_ignore_ascii_case("elvish") => Ok(Shell::Elvish),
|
||||
_ => Err(String::from(
|
||||
"[valid values: bash, fish, zsh, powershell, elvish]",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Shell {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Shell::Bash => write!(f, "BASH"),
|
||||
Shell::Fish => write!(f, "FISH"),
|
||||
Shell::Zsh => write!(f, "ZSH"),
|
||||
Shell::PowerShell => write!(f, "POWERSHELL"),
|
||||
Shell::Elvish => write!(f, "ELVISH"),
|
||||
}
|
||||
}
|
||||
}
|
||||
484
zeroidc/vendor/clap/src/completions/zsh.rs
vendored
Normal file
484
zeroidc/vendor/clap/src/completions/zsh.rs
vendored
Normal file
@@ -0,0 +1,484 @@
|
||||
// Std
|
||||
#[allow(deprecated, unused_imports)]
|
||||
use std::{ascii::AsciiExt, io::Write};
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
app::{parser::Parser, App},
|
||||
args::{AnyArg, ArgSettings},
|
||||
completions, INTERNAL_ERROR_MSG,
|
||||
};
|
||||
|
||||
pub struct ZshGen<'a, 'b>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
p: &'b Parser<'a, 'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ZshGen<'a, 'b> {
|
||||
pub fn new(p: &'b Parser<'a, 'b>) -> Self {
|
||||
debugln!("ZshGen::new;");
|
||||
ZshGen { p }
|
||||
}
|
||||
|
||||
pub fn generate_to<W: Write>(&self, buf: &mut W) {
|
||||
debugln!("ZshGen::generate_to;");
|
||||
w!(
|
||||
buf,
|
||||
format!(
|
||||
"\
|
||||
#compdef {name}
|
||||
|
||||
autoload -U is-at-least
|
||||
|
||||
_{name}() {{
|
||||
typeset -A opt_args
|
||||
typeset -a _arguments_options
|
||||
local ret=1
|
||||
|
||||
if is-at-least 5.2; then
|
||||
_arguments_options=(-s -S -C)
|
||||
else
|
||||
_arguments_options=(-s -C)
|
||||
fi
|
||||
|
||||
local context curcontext=\"$curcontext\" state line
|
||||
{initial_args}
|
||||
{subcommands}
|
||||
}}
|
||||
|
||||
{subcommand_details}
|
||||
|
||||
_{name} \"$@\"",
|
||||
name = self.p.meta.bin_name.as_ref().unwrap(),
|
||||
initial_args = get_args_of(self.p),
|
||||
subcommands = get_subcommands_of(self.p),
|
||||
subcommand_details = subcommand_details(self.p)
|
||||
)
|
||||
.as_bytes()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Displays the commands of a subcommand
|
||||
// (( $+functions[_[bin_name_underscore]_commands] )) ||
|
||||
// _[bin_name_underscore]_commands() {
|
||||
// local commands; commands=(
|
||||
// '[arg_name]:[arg_help]'
|
||||
// )
|
||||
// _describe -t commands '[bin_name] commands' commands "$@"
|
||||
//
|
||||
// Where the following variables are present:
|
||||
// [bin_name_underscore]: The full space delineated bin_name, where spaces have been replaced by
|
||||
// underscore characters
|
||||
// [arg_name]: The name of the subcommand
|
||||
// [arg_help]: The help message of the subcommand
|
||||
// [bin_name]: The full space delineated bin_name
|
||||
//
|
||||
// Here's a snippet from rustup:
|
||||
//
|
||||
// (( $+functions[_rustup_commands] )) ||
|
||||
// _rustup_commands() {
|
||||
// local commands; commands=(
|
||||
// 'show:Show the active and installed toolchains'
|
||||
// 'update:Update Rust toolchains'
|
||||
// # ... snip for brevity
|
||||
// 'help:Prints this message or the help of the given subcommand(s)'
|
||||
// )
|
||||
// _describe -t commands 'rustup commands' commands "$@"
|
||||
//
|
||||
fn subcommand_details(p: &Parser) -> String {
|
||||
debugln!("ZshGen::subcommand_details;");
|
||||
// First we do ourself
|
||||
let mut ret = vec![format!(
|
||||
"\
|
||||
(( $+functions[_{bin_name_underscore}_commands] )) ||
|
||||
_{bin_name_underscore}_commands() {{
|
||||
local commands; commands=(
|
||||
{subcommands_and_args}
|
||||
)
|
||||
_describe -t commands '{bin_name} commands' commands \"$@\"
|
||||
}}",
|
||||
bin_name_underscore = p.meta.bin_name.as_ref().unwrap().replace(" ", "__"),
|
||||
bin_name = p.meta.bin_name.as_ref().unwrap(),
|
||||
subcommands_and_args = subcommands_of(p)
|
||||
)];
|
||||
|
||||
// Next we start looping through all the children, grandchildren, etc.
|
||||
let mut all_subcommands = completions::all_subcommands(p);
|
||||
all_subcommands.sort();
|
||||
all_subcommands.dedup();
|
||||
for &(_, ref bin_name) in &all_subcommands {
|
||||
debugln!("ZshGen::subcommand_details:iter: bin_name={}", bin_name);
|
||||
ret.push(format!(
|
||||
"\
|
||||
(( $+functions[_{bin_name_underscore}_commands] )) ||
|
||||
_{bin_name_underscore}_commands() {{
|
||||
local commands; commands=(
|
||||
{subcommands_and_args}
|
||||
)
|
||||
_describe -t commands '{bin_name} commands' commands \"$@\"
|
||||
}}",
|
||||
bin_name_underscore = bin_name.replace(" ", "__"),
|
||||
bin_name = bin_name,
|
||||
subcommands_and_args = subcommands_of(parser_of(p, bin_name))
|
||||
));
|
||||
}
|
||||
|
||||
ret.join("\n")
|
||||
}
|
||||
|
||||
// Generates subcommand completions in form of
|
||||
//
|
||||
// '[arg_name]:[arg_help]'
|
||||
//
|
||||
// Where:
|
||||
// [arg_name]: the subcommand's name
|
||||
// [arg_help]: the help message of the subcommand
|
||||
//
|
||||
// A snippet from rustup:
|
||||
// 'show:Show the active and installed toolchains'
|
||||
// 'update:Update Rust toolchains'
|
||||
fn subcommands_of(p: &Parser) -> String {
|
||||
debugln!("ZshGen::subcommands_of;");
|
||||
let mut ret = vec![];
|
||||
fn add_sc(sc: &App, n: &str, ret: &mut Vec<String>) {
|
||||
debugln!("ZshGen::add_sc;");
|
||||
let s = format!(
|
||||
"\"{name}:{help}\" \\",
|
||||
name = n,
|
||||
help =
|
||||
sc.p.meta
|
||||
.about
|
||||
.unwrap_or("")
|
||||
.replace("[", "\\[")
|
||||
.replace("]", "\\]")
|
||||
);
|
||||
if !s.is_empty() {
|
||||
ret.push(s);
|
||||
}
|
||||
}
|
||||
|
||||
// The subcommands
|
||||
for sc in p.subcommands() {
|
||||
debugln!("ZshGen::subcommands_of:iter: subcommand={}", sc.p.meta.name);
|
||||
add_sc(sc, &sc.p.meta.name, &mut ret);
|
||||
if let Some(ref v) = sc.p.meta.aliases {
|
||||
for alias in v.iter().filter(|&&(_, vis)| vis).map(|&(n, _)| n) {
|
||||
add_sc(sc, alias, &mut ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret.join("\n")
|
||||
}
|
||||
|
||||
// Get's the subcommand section of a completion file
|
||||
// This looks roughly like:
|
||||
//
|
||||
// case $state in
|
||||
// ([bin_name]_args)
|
||||
// curcontext=\"${curcontext%:*:*}:[name_hyphen]-command-$words[1]:\"
|
||||
// case $line[1] in
|
||||
//
|
||||
// ([name])
|
||||
// _arguments -C -s -S \
|
||||
// [subcommand_args]
|
||||
// && ret=0
|
||||
//
|
||||
// [RECURSIVE_CALLS]
|
||||
//
|
||||
// ;;",
|
||||
//
|
||||
// [repeat]
|
||||
//
|
||||
// esac
|
||||
// ;;
|
||||
// esac",
|
||||
//
|
||||
// Where the following variables are present:
|
||||
// [name] = The subcommand name in the form of "install" for "rustup toolchain install"
|
||||
// [bin_name] = The full space delineated bin_name such as "rustup toolchain install"
|
||||
// [name_hyphen] = The full space delineated bin_name, but replace spaces with hyphens
|
||||
// [repeat] = From the same recursive calls, but for all subcommands
|
||||
// [subcommand_args] = The same as zsh::get_args_of
|
||||
fn get_subcommands_of(p: &Parser) -> String {
|
||||
debugln!("get_subcommands_of;");
|
||||
|
||||
debugln!(
|
||||
"get_subcommands_of: Has subcommands...{:?}",
|
||||
p.has_subcommands()
|
||||
);
|
||||
if !p.has_subcommands() {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
let sc_names = completions::subcommands_of(p);
|
||||
|
||||
let mut subcmds = vec![];
|
||||
for &(ref name, ref bin_name) in &sc_names {
|
||||
let mut v = vec![format!("({})", name)];
|
||||
let subcommand_args = get_args_of(parser_of(p, &*bin_name));
|
||||
if !subcommand_args.is_empty() {
|
||||
v.push(subcommand_args);
|
||||
}
|
||||
let subcommands = get_subcommands_of(parser_of(p, &*bin_name));
|
||||
if !subcommands.is_empty() {
|
||||
v.push(subcommands);
|
||||
}
|
||||
v.push(String::from(";;"));
|
||||
subcmds.push(v.join("\n"));
|
||||
}
|
||||
|
||||
format!(
|
||||
"case $state in
|
||||
({name})
|
||||
words=($line[{pos}] \"${{words[@]}}\")
|
||||
(( CURRENT += 1 ))
|
||||
curcontext=\"${{curcontext%:*:*}}:{name_hyphen}-command-$line[{pos}]:\"
|
||||
case $line[{pos}] in
|
||||
{subcommands}
|
||||
esac
|
||||
;;
|
||||
esac",
|
||||
name = p.meta.name,
|
||||
name_hyphen = p.meta.bin_name.as_ref().unwrap().replace(" ", "-"),
|
||||
subcommands = subcmds.join("\n"),
|
||||
pos = p.positionals().len() + 1
|
||||
)
|
||||
}
|
||||
|
||||
fn parser_of<'a, 'b>(p: &'b Parser<'a, 'b>, sc: &str) -> &'b Parser<'a, 'b> {
|
||||
debugln!("parser_of: sc={}", sc);
|
||||
if sc == p.meta.bin_name.as_ref().unwrap_or(&String::new()) {
|
||||
return p;
|
||||
}
|
||||
&p.find_subcommand(sc).expect(INTERNAL_ERROR_MSG).p
|
||||
}
|
||||
|
||||
// Writes out the args section, which ends up being the flags, opts and postionals, and a jump to
|
||||
// another ZSH function if there are subcommands.
|
||||
// The structer works like this:
|
||||
// ([conflicting_args]) [multiple] arg [takes_value] [[help]] [: :(possible_values)]
|
||||
// ^-- list '-v -h' ^--'*' ^--'+' ^-- list 'one two three'
|
||||
//
|
||||
// An example from the rustup command:
|
||||
//
|
||||
// _arguments -C -s -S \
|
||||
// '(-h --help --verbose)-v[Enable verbose output]' \
|
||||
// '(-V -v --version --verbose --help)-h[Prints help information]' \
|
||||
// # ... snip for brevity
|
||||
// ':: :_rustup_commands' \ # <-- displays subcommands
|
||||
// '*::: :->rustup' \ # <-- displays subcommand args and child subcommands
|
||||
// && ret=0
|
||||
//
|
||||
// The args used for _arguments are as follows:
|
||||
// -C: modify the $context internal variable
|
||||
// -s: Allow stacking of short args (i.e. -a -b -c => -abc)
|
||||
// -S: Do not complete anything after '--' and treat those as argument values
|
||||
fn get_args_of(p: &Parser) -> String {
|
||||
debugln!("get_args_of;");
|
||||
let mut ret = vec![String::from("_arguments \"${_arguments_options[@]}\" \\")];
|
||||
let opts = write_opts_of(p);
|
||||
let flags = write_flags_of(p);
|
||||
let positionals = write_positionals_of(p);
|
||||
let sc_or_a = if p.has_subcommands() {
|
||||
format!(
|
||||
"\":: :_{name}_commands\" \\",
|
||||
name = p.meta.bin_name.as_ref().unwrap().replace(" ", "__")
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let sc = if p.has_subcommands() {
|
||||
format!("\"*::: :->{name}\" \\", name = p.meta.name)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
if !opts.is_empty() {
|
||||
ret.push(opts);
|
||||
}
|
||||
if !flags.is_empty() {
|
||||
ret.push(flags);
|
||||
}
|
||||
if !positionals.is_empty() {
|
||||
ret.push(positionals);
|
||||
}
|
||||
if !sc_or_a.is_empty() {
|
||||
ret.push(sc_or_a);
|
||||
}
|
||||
if !sc.is_empty() {
|
||||
ret.push(sc);
|
||||
}
|
||||
ret.push(String::from("&& ret=0"));
|
||||
|
||||
ret.join("\n")
|
||||
}
|
||||
|
||||
// Escape help string inside single quotes and brackets
|
||||
fn escape_help(string: &str) -> String {
|
||||
string
|
||||
.replace("\\", "\\\\")
|
||||
.replace("'", "'\\''")
|
||||
.replace("[", "\\[")
|
||||
.replace("]", "\\]")
|
||||
}
|
||||
|
||||
// Escape value string inside single quotes and parentheses
|
||||
fn escape_value(string: &str) -> String {
|
||||
string
|
||||
.replace("\\", "\\\\")
|
||||
.replace("'", "'\\''")
|
||||
.replace("(", "\\(")
|
||||
.replace(")", "\\)")
|
||||
.replace(" ", "\\ ")
|
||||
}
|
||||
|
||||
fn write_opts_of(p: &Parser) -> String {
|
||||
debugln!("write_opts_of;");
|
||||
let mut ret = vec![];
|
||||
for o in p.opts() {
|
||||
debugln!("write_opts_of:iter: o={}", o.name());
|
||||
let help = o.help().map_or(String::new(), escape_help);
|
||||
let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG);
|
||||
conflicts = if conflicts.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!("({})", conflicts)
|
||||
};
|
||||
|
||||
let multiple = if o.is_set(ArgSettings::Multiple) {
|
||||
"*"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let pv = if let Some(pv_vec) = o.possible_vals() {
|
||||
format!(
|
||||
": :({})",
|
||||
pv_vec
|
||||
.iter()
|
||||
.map(|v| escape_value(*v))
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ")
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
if let Some(short) = o.short() {
|
||||
let s = format!(
|
||||
"'{conflicts}{multiple}-{arg}+[{help}]{possible_values}' \\",
|
||||
conflicts = conflicts,
|
||||
multiple = multiple,
|
||||
arg = short,
|
||||
possible_values = pv,
|
||||
help = help
|
||||
);
|
||||
|
||||
debugln!("write_opts_of:iter: Wrote...{}", &*s);
|
||||
ret.push(s);
|
||||
}
|
||||
if let Some(long) = o.long() {
|
||||
let l = format!(
|
||||
"'{conflicts}{multiple}--{arg}=[{help}]{possible_values}' \\",
|
||||
conflicts = conflicts,
|
||||
multiple = multiple,
|
||||
arg = long,
|
||||
possible_values = pv,
|
||||
help = help
|
||||
);
|
||||
|
||||
debugln!("write_opts_of:iter: Wrote...{}", &*l);
|
||||
ret.push(l);
|
||||
}
|
||||
}
|
||||
|
||||
ret.join("\n")
|
||||
}
|
||||
|
||||
fn write_flags_of(p: &Parser) -> String {
|
||||
debugln!("write_flags_of;");
|
||||
let mut ret = vec![];
|
||||
for f in p.flags() {
|
||||
debugln!("write_flags_of:iter: f={}", f.name());
|
||||
let help = f.help().map_or(String::new(), escape_help);
|
||||
let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG);
|
||||
conflicts = if conflicts.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!("({})", conflicts)
|
||||
};
|
||||
|
||||
let multiple = if f.is_set(ArgSettings::Multiple) {
|
||||
"*"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
if let Some(short) = f.short() {
|
||||
let s = format!(
|
||||
"'{conflicts}{multiple}-{arg}[{help}]' \\",
|
||||
multiple = multiple,
|
||||
conflicts = conflicts,
|
||||
arg = short,
|
||||
help = help
|
||||
);
|
||||
|
||||
debugln!("write_flags_of:iter: Wrote...{}", &*s);
|
||||
ret.push(s);
|
||||
}
|
||||
|
||||
if let Some(long) = f.long() {
|
||||
let l = format!(
|
||||
"'{conflicts}{multiple}--{arg}[{help}]' \\",
|
||||
conflicts = conflicts,
|
||||
multiple = multiple,
|
||||
arg = long,
|
||||
help = help
|
||||
);
|
||||
|
||||
debugln!("write_flags_of:iter: Wrote...{}", &*l);
|
||||
ret.push(l);
|
||||
}
|
||||
}
|
||||
|
||||
ret.join("\n")
|
||||
}
|
||||
|
||||
fn write_positionals_of(p: &Parser) -> String {
|
||||
debugln!("write_positionals_of;");
|
||||
let mut ret = vec![];
|
||||
for arg in p.positionals() {
|
||||
debugln!("write_positionals_of:iter: arg={}", arg.b.name);
|
||||
let a = format!(
|
||||
"'{optional}:{name}{help}:{action}' \\",
|
||||
optional = if !arg.b.is_set(ArgSettings::Required) {
|
||||
":"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
name = arg.b.name,
|
||||
help = arg
|
||||
.b
|
||||
.help
|
||||
.map_or("".to_owned(), |v| " -- ".to_owned() + v)
|
||||
.replace("[", "\\[")
|
||||
.replace("]", "\\]"),
|
||||
action = arg.possible_vals().map_or("_files".to_owned(), |values| {
|
||||
format!(
|
||||
"({})",
|
||||
values
|
||||
.iter()
|
||||
.map(|v| escape_value(*v))
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ")
|
||||
)
|
||||
})
|
||||
);
|
||||
|
||||
debugln!("write_positionals_of:iter: Wrote...{}", a);
|
||||
ret.push(a);
|
||||
}
|
||||
|
||||
ret.join("\n")
|
||||
}
|
||||
933
zeroidc/vendor/clap/src/errors.rs
vendored
Normal file
933
zeroidc/vendor/clap/src/errors.rs
vendored
Normal file
@@ -0,0 +1,933 @@
|
||||
// Std
|
||||
use std::{
|
||||
convert::From,
|
||||
error::Error as StdError,
|
||||
fmt as std_fmt,
|
||||
fmt::Display,
|
||||
io::{self, Write},
|
||||
process,
|
||||
result::Result as StdResult,
|
||||
};
|
||||
|
||||
// Internal
|
||||
use crate::{
|
||||
args::AnyArg,
|
||||
fmt::{ColorWhen, Colorizer, ColorizerOption},
|
||||
suggestions,
|
||||
};
|
||||
|
||||
/// Short hand for [`Result`] type
|
||||
///
|
||||
/// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
|
||||
pub type Result<T> = StdResult<T, Error>;
|
||||
|
||||
/// Command line argument parser kind of error
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum ErrorKind {
|
||||
/// Occurs when an [`Arg`] has a set of possible values,
|
||||
/// and the user provides a value which isn't in that set.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::with_name("speed")
|
||||
/// .possible_value("fast")
|
||||
/// .possible_value("slow"))
|
||||
/// .get_matches_from_safe(vec!["prog", "other"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidValue);
|
||||
/// ```
|
||||
/// [`Arg`]: ./struct.Arg.html
|
||||
InvalidValue,
|
||||
|
||||
/// Occurs when a user provides a flag, option, argument or subcommand which isn't defined.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::from_usage("--flag 'some flag'"))
|
||||
/// .get_matches_from_safe(vec!["prog", "--other"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::UnknownArgument);
|
||||
/// ```
|
||||
UnknownArgument,
|
||||
|
||||
/// Occurs when the user provides an unrecognized [`SubCommand`] which meets the threshold for
|
||||
/// being similar enough to an existing subcommand.
|
||||
/// If it doesn't meet the threshold, or the 'suggestions' feature is disabled,
|
||||
/// the more general [`UnknownArgument`] error is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(feature = "suggestions"), doc = " ```no_run")]
|
||||
#[cfg_attr(feature = "suggestions", doc = " ```")]
|
||||
/// # use clap::{App, Arg, ErrorKind, SubCommand};
|
||||
/// let result = App::new("prog")
|
||||
/// .subcommand(SubCommand::with_name("config")
|
||||
/// .about("Used for configuration")
|
||||
/// .arg(Arg::with_name("config_file")
|
||||
/// .help("The configuration file to use")
|
||||
/// .index(1)))
|
||||
/// .get_matches_from_safe(vec!["prog", "confi"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidSubcommand);
|
||||
/// ```
|
||||
/// [`SubCommand`]: ./struct.SubCommand.html
|
||||
/// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument
|
||||
InvalidSubcommand,
|
||||
|
||||
/// Occurs when the user provides an unrecognized [`SubCommand`] which either
|
||||
/// doesn't meet the threshold for being similar enough to an existing subcommand,
|
||||
/// or the 'suggestions' feature is disabled.
|
||||
/// Otherwise the more detailed [`InvalidSubcommand`] error is returned.
|
||||
///
|
||||
/// This error typically happens when passing additional subcommand names to the `help`
|
||||
/// subcommand. Otherwise, the more general [`UnknownArgument`] error is used.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind, SubCommand};
|
||||
/// let result = App::new("prog")
|
||||
/// .subcommand(SubCommand::with_name("config")
|
||||
/// .about("Used for configuration")
|
||||
/// .arg(Arg::with_name("config_file")
|
||||
/// .help("The configuration file to use")
|
||||
/// .index(1)))
|
||||
/// .get_matches_from_safe(vec!["prog", "help", "nothing"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand);
|
||||
/// ```
|
||||
/// [`SubCommand`]: ./struct.SubCommand.html
|
||||
/// [`InvalidSubcommand`]: ./enum.ErrorKind.html#variant.InvalidSubcommand
|
||||
/// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument
|
||||
UnrecognizedSubcommand,
|
||||
|
||||
/// Occurs when the user provides an empty value for an option that does not allow empty
|
||||
/// values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let res = App::new("prog")
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .long("color")
|
||||
/// .empty_values(false))
|
||||
/// .get_matches_from_safe(vec!["prog", "--color="]);
|
||||
/// assert!(res.is_err());
|
||||
/// assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
|
||||
/// ```
|
||||
EmptyValue,
|
||||
|
||||
/// Occurs when the user provides a value for an argument with a custom validation and the
|
||||
/// value fails that validation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// fn is_numeric(val: String) -> Result<(), String> {
|
||||
/// match val.parse::<i64>() {
|
||||
/// Ok(..) => Ok(()),
|
||||
/// Err(..) => Err(String::from("Value wasn't a number!")),
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::with_name("num")
|
||||
/// .validator(is_numeric))
|
||||
/// .get_matches_from_safe(vec!["prog", "NotANumber"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::ValueValidation);
|
||||
/// ```
|
||||
ValueValidation,
|
||||
|
||||
/// Occurs when a user provides more values for an argument than were defined by setting
|
||||
/// [`Arg::max_values`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::with_name("arg")
|
||||
/// .multiple(true)
|
||||
/// .max_values(2))
|
||||
/// .get_matches_from_safe(vec!["prog", "too", "many", "values"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::TooManyValues);
|
||||
/// ```
|
||||
/// [`Arg::max_values`]: ./struct.Arg.html#method.max_values
|
||||
TooManyValues,
|
||||
|
||||
/// Occurs when the user provides fewer values for an argument than were defined by setting
|
||||
/// [`Arg::min_values`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::with_name("some_opt")
|
||||
/// .long("opt")
|
||||
/// .min_values(3))
|
||||
/// .get_matches_from_safe(vec!["prog", "--opt", "too", "few"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::TooFewValues);
|
||||
/// ```
|
||||
/// [`Arg::min_values`]: ./struct.Arg.html#method.min_values
|
||||
TooFewValues,
|
||||
|
||||
/// Occurs when the user provides a different number of values for an argument than what's
|
||||
/// been defined by setting [`Arg::number_of_values`] or than was implicitly set by
|
||||
/// [`Arg::value_names`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::with_name("some_opt")
|
||||
/// .long("opt")
|
||||
/// .takes_value(true)
|
||||
/// .number_of_values(2))
|
||||
/// .get_matches_from_safe(vec!["prog", "--opt", "wrong"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
|
||||
/// ```
|
||||
///
|
||||
/// [`Arg::number_of_values`]: ./struct.Arg.html#method.number_of_values
|
||||
/// [`Arg::value_names`]: ./struct.Arg.html#method.value_names
|
||||
WrongNumberOfValues,
|
||||
|
||||
/// Occurs when the user provides two values which conflict with each other and can't be used
|
||||
/// together.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .long("debug")
|
||||
/// .conflicts_with("color"))
|
||||
/// .arg(Arg::with_name("color")
|
||||
/// .long("color"))
|
||||
/// .get_matches_from_safe(vec!["prog", "--debug", "--color"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::ArgumentConflict);
|
||||
/// ```
|
||||
ArgumentConflict,
|
||||
|
||||
/// Occurs when the user does not provide one or more required arguments.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .required(true))
|
||||
/// .get_matches_from_safe(vec!["prog"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
|
||||
/// ```
|
||||
MissingRequiredArgument,
|
||||
|
||||
/// Occurs when a subcommand is required (as defined by [`AppSettings::SubcommandRequired`]),
|
||||
/// but the user does not provide one.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, AppSettings, SubCommand, ErrorKind};
|
||||
/// let err = App::new("prog")
|
||||
/// .setting(AppSettings::SubcommandRequired)
|
||||
/// .subcommand(SubCommand::with_name("test"))
|
||||
/// .get_matches_from_safe(vec![
|
||||
/// "myprog",
|
||||
/// ]);
|
||||
/// assert!(err.is_err());
|
||||
/// assert_eq!(err.unwrap_err().kind, ErrorKind::MissingSubcommand);
|
||||
/// # ;
|
||||
/// ```
|
||||
/// [`AppSettings::SubcommandRequired`]: ./enum.AppSettings.html#variant.SubcommandRequired
|
||||
MissingSubcommand,
|
||||
|
||||
/// Occurs when either an argument or [`SubCommand`] is required, as defined by
|
||||
/// [`AppSettings::ArgRequiredElseHelp`], but the user did not provide one.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, AppSettings, ErrorKind, SubCommand};
|
||||
/// let result = App::new("prog")
|
||||
/// .setting(AppSettings::ArgRequiredElseHelp)
|
||||
/// .subcommand(SubCommand::with_name("config")
|
||||
/// .about("Used for configuration")
|
||||
/// .arg(Arg::with_name("config_file")
|
||||
/// .help("The configuration file to use")))
|
||||
/// .get_matches_from_safe(vec!["prog"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingArgumentOrSubcommand);
|
||||
/// ```
|
||||
/// [`SubCommand`]: ./struct.SubCommand.html
|
||||
/// [`AppSettings::ArgRequiredElseHelp`]: ./enum.AppSettings.html#variant.ArgRequiredElseHelp
|
||||
MissingArgumentOrSubcommand,
|
||||
|
||||
/// Occurs when the user provides multiple values to an argument which doesn't allow that.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .arg(Arg::with_name("debug")
|
||||
/// .long("debug")
|
||||
/// .multiple(false))
|
||||
/// .get_matches_from_safe(vec!["prog", "--debug", "--debug"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage);
|
||||
/// ```
|
||||
UnexpectedMultipleUsage,
|
||||
|
||||
/// Occurs when the user provides a value containing invalid UTF-8 for an argument and
|
||||
/// [`AppSettings::StrictUtf8`] is set.
|
||||
///
|
||||
/// # Platform Specific
|
||||
///
|
||||
/// Non-Windows platforms only (such as Linux, Unix, macOS, etc.)
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
#[cfg_attr(not(unix), doc = " ```ignore")]
|
||||
#[cfg_attr(unix, doc = " ```")]
|
||||
/// # use clap::{App, Arg, ErrorKind, AppSettings};
|
||||
/// # use std::os::unix::ffi::OsStringExt;
|
||||
/// # use std::ffi::OsString;
|
||||
/// let result = App::new("prog")
|
||||
/// .setting(AppSettings::StrictUtf8)
|
||||
/// .arg(Arg::with_name("utf8")
|
||||
/// .short("u")
|
||||
/// .takes_value(true))
|
||||
/// .get_matches_from_safe(vec![OsString::from("myprog"),
|
||||
/// OsString::from("-u"),
|
||||
/// OsString::from_vec(vec![0xE9])]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidUtf8);
|
||||
/// ```
|
||||
/// [`AppSettings::StrictUtf8`]: ./enum.AppSettings.html#variant.StrictUtf8
|
||||
InvalidUtf8,
|
||||
|
||||
/// Not a true "error" as it means `--help` or similar was used.
|
||||
/// The help message will be sent to `stdout`.
|
||||
///
|
||||
/// **Note**: If the help is displayed due to an error (such as missing subcommands) it will
|
||||
/// be sent to `stderr` instead of `stdout`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .get_matches_from_safe(vec!["prog", "--help"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::HelpDisplayed);
|
||||
/// ```
|
||||
HelpDisplayed,
|
||||
|
||||
/// Not a true "error" as it means `--version` or similar was used.
|
||||
/// The message will be sent to `stdout`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use clap::{App, Arg, ErrorKind};
|
||||
/// let result = App::new("prog")
|
||||
/// .get_matches_from_safe(vec!["prog", "--version"]);
|
||||
/// assert!(result.is_err());
|
||||
/// assert_eq!(result.unwrap_err().kind, ErrorKind::VersionDisplayed);
|
||||
/// ```
|
||||
VersionDisplayed,
|
||||
|
||||
/// Occurs when using the [`value_t!`] and [`values_t!`] macros to convert an argument value
|
||||
/// into type `T`, but the argument you requested wasn't used. I.e. you asked for an argument
|
||||
/// with name `config` to be converted, but `config` wasn't used by the user.
|
||||
/// [`value_t!`]: ./macro.value_t!.html
|
||||
/// [`values_t!`]: ./macro.values_t!.html
|
||||
ArgumentNotFound,
|
||||
|
||||
/// Represents an [I/O error].
|
||||
/// Can occur when writing to `stderr` or `stdout` or reading a configuration file.
|
||||
/// [I/O error]: https://doc.rust-lang.org/std/io/struct.Error.html
|
||||
Io,
|
||||
|
||||
/// Represents a [Format error] (which is a part of [`Display`]).
|
||||
/// Typically caused by writing to `stderr` or `stdout`.
|
||||
///
|
||||
/// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
|
||||
/// [Format error]: https://doc.rust-lang.org/std/fmt/struct.Error.html
|
||||
Format,
|
||||
}
|
||||
|
||||
/// Command Line Argument Parser Error
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
/// Formatted error message
|
||||
pub message: String,
|
||||
/// The type of error
|
||||
pub kind: ErrorKind,
|
||||
/// Any additional information passed along, such as the argument name that caused the error
|
||||
pub info: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Should the message be written to `stdout` or not
|
||||
pub fn use_stderr(&self) -> bool {
|
||||
!matches!(
|
||||
self.kind,
|
||||
ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed
|
||||
)
|
||||
}
|
||||
|
||||
/// Prints the error message and exits. If `Error::use_stderr` evaluates to `true`, the message
|
||||
/// will be written to `stderr` and exits with a status of `1`. Otherwise, `stdout` is used
|
||||
/// with a status of `0`.
|
||||
pub fn exit(&self) -> ! {
|
||||
if self.use_stderr() {
|
||||
wlnerr!(@nopanic "{}", self.message);
|
||||
process::exit(1);
|
||||
}
|
||||
// We are deliberately dropping errors here. We could match on the error kind, and only
|
||||
// drop things such as `std::io::ErrorKind::BrokenPipe`, however nothing is being bubbled
|
||||
// up or reported back to the caller and we will be exit'ing the process anyways.
|
||||
// Additionally, changing this API to bubble up the result would be a breaking change.
|
||||
//
|
||||
// Another approach could be to try and write to stdout, if that fails due to a broken pipe
|
||||
// then use stderr. However, that would change the semantics in what could be argued is a
|
||||
// breaking change. Simply dropping the error, can always be changed to this "use stderr if
|
||||
// stdout is closed" approach later if desired.
|
||||
//
|
||||
// A good explanation of the types of errors are SIGPIPE where the read side of the pipe
|
||||
// closes before the write side. See the README in `calm_io` for a good explanation:
|
||||
//
|
||||
// https://github.com/myrrlyn/calm_io/blob/a42845575a04cd8b65e92c19d104627f5fcad3d7/README.md
|
||||
let _ = writeln!(&mut io::stdout().lock(), "{}", self.message);
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn write_to<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
write!(w, "{}", self.message)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn argument_conflict<O, U>(
|
||||
arg: &AnyArg,
|
||||
other: Option<O>,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
O: Into<String>,
|
||||
U: Display,
|
||||
{
|
||||
let mut v = vec![arg.name().to_owned()];
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The argument '{}' cannot be used with {}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*arg.to_string()),
|
||||
match other {
|
||||
Some(name) => {
|
||||
let n = name.into();
|
||||
v.push(n.clone());
|
||||
c.warning(format!("'{}'", n))
|
||||
}
|
||||
None => c.none("one or more of the other specified arguments".to_owned()),
|
||||
},
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::ArgumentConflict,
|
||||
info: Some(v),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn empty_value<U>(arg: &AnyArg, usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The argument '{}' requires a value but none was supplied\
|
||||
\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::EmptyValue,
|
||||
info: Some(vec![arg.name().to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn invalid_value<B, G, U>(
|
||||
bad_val: B,
|
||||
good_vals: &[G],
|
||||
arg: &AnyArg,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
B: AsRef<str>,
|
||||
G: AsRef<str> + Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
let suffix = suggestions::did_you_mean_value_suffix(bad_val.as_ref(), good_vals.iter());
|
||||
|
||||
let mut sorted = vec![];
|
||||
for v in good_vals {
|
||||
let val = format!("{}", c.good(v));
|
||||
sorted.push(val);
|
||||
}
|
||||
sorted.sort();
|
||||
let valid_values = sorted.join(", ");
|
||||
Error {
|
||||
message: format!(
|
||||
"{} '{}' isn't a valid value for '{}'\n\t\
|
||||
[possible values: {}]\n\
|
||||
{}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(bad_val.as_ref()),
|
||||
c.warning(arg.to_string()),
|
||||
valid_values,
|
||||
suffix.0,
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::InvalidValue,
|
||||
info: Some(vec![arg.name().to_owned(), bad_val.as_ref().to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn invalid_subcommand<S, D, N, U>(
|
||||
subcmd: S,
|
||||
did_you_mean: D,
|
||||
name: N,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
D: AsRef<str> + Display,
|
||||
N: Display,
|
||||
U: Display,
|
||||
{
|
||||
let s = subcmd.into();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The subcommand '{}' wasn't recognized\n\t\
|
||||
Did you mean '{}'?\n\n\
|
||||
If you believe you received this message in error, try \
|
||||
re-running with '{} {} {}'\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*s),
|
||||
c.good(did_you_mean.as_ref()),
|
||||
name,
|
||||
c.good("--"),
|
||||
&*s,
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::InvalidSubcommand,
|
||||
info: Some(vec![s]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn unrecognized_subcommand<S, N>(subcmd: S, name: N, color: ColorWhen) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
N: Display,
|
||||
{
|
||||
let s = subcmd.into();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The subcommand '{}' wasn't recognized\n\n\
|
||||
{}\n\t\
|
||||
{} help <subcommands>...\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*s),
|
||||
c.warning("USAGE:"),
|
||||
name,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::UnrecognizedSubcommand,
|
||||
info: Some(vec![s]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn missing_required_argument<R, U>(required: R, usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
R: Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The following required arguments were not provided:{}\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
required,
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::MissingRequiredArgument,
|
||||
info: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn missing_subcommand<N, U>(name: N, usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
N: AsRef<str> + Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} '{}' requires a subcommand, but one was not provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(name),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::MissingSubcommand,
|
||||
info: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn invalid_utf8<U>(usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} Invalid UTF-8 was detected in one or more arguments\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::InvalidUtf8,
|
||||
info: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn too_many_values<V, U>(val: V, arg: &AnyArg, usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
V: AsRef<str> + Display + ToOwned,
|
||||
U: Display,
|
||||
{
|
||||
let v = val.as_ref();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The value '{}' was provided to '{}', but it wasn't expecting \
|
||||
any more values\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(v),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::TooManyValues,
|
||||
info: Some(vec![arg.name().to_owned(), v.to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn too_few_values<U>(
|
||||
arg: &AnyArg,
|
||||
min_vals: u64,
|
||||
curr_vals: usize,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The argument '{}' requires at least {} values, but only {} w{} \
|
||||
provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
c.warning(min_vals.to_string()),
|
||||
c.warning(curr_vals.to_string()),
|
||||
if curr_vals > 1 { "ere" } else { "as" },
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::TooFewValues,
|
||||
info: Some(vec![arg.name().to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn value_validation(arg: Option<&AnyArg>, err: String, color: ColorWhen) -> Self {
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} Invalid value{}: {}",
|
||||
c.error("error:"),
|
||||
if let Some(a) = arg {
|
||||
format!(" for '{}'", c.warning(a.to_string()))
|
||||
} else {
|
||||
"".to_string()
|
||||
},
|
||||
err
|
||||
),
|
||||
kind: ErrorKind::ValueValidation,
|
||||
info: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn value_validation_auto(err: String) -> Self {
|
||||
let n: Option<&AnyArg> = None;
|
||||
Error::value_validation(n, err, ColorWhen::Auto)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn wrong_number_of_values<S, U>(
|
||||
arg: &AnyArg,
|
||||
num_vals: u64,
|
||||
curr_vals: usize,
|
||||
suffix: S,
|
||||
usage: U,
|
||||
color: ColorWhen,
|
||||
) -> Self
|
||||
where
|
||||
S: Display,
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The argument '{}' requires {} values, but {} w{} \
|
||||
provided\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
c.warning(num_vals.to_string()),
|
||||
c.warning(curr_vals.to_string()),
|
||||
suffix,
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::WrongNumberOfValues,
|
||||
info: Some(vec![arg.name().to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn unexpected_multiple_usage<U>(arg: &AnyArg, usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
U: Display,
|
||||
{
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} The argument '{}' was provided more than once, but cannot \
|
||||
be used multiple times\n\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(arg.to_string()),
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::UnexpectedMultipleUsage,
|
||||
info: Some(vec![arg.name().to_owned()]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn unknown_argument<A, U>(arg: A, did_you_mean: &str, usage: U, color: ColorWhen) -> Self
|
||||
where
|
||||
A: Into<String>,
|
||||
U: Display,
|
||||
{
|
||||
let a = arg.into();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!(
|
||||
"{} Found argument '{}' which wasn't expected, or isn't valid in \
|
||||
this context{}\n\
|
||||
{}\n\n\
|
||||
For more information try {}",
|
||||
c.error("error:"),
|
||||
c.warning(&*a),
|
||||
if did_you_mean.is_empty() {
|
||||
"\n".to_owned()
|
||||
} else {
|
||||
format!("{}\n", did_you_mean)
|
||||
},
|
||||
usage,
|
||||
c.good("--help")
|
||||
),
|
||||
kind: ErrorKind::UnknownArgument,
|
||||
info: Some(vec![a]),
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn io_error(e: &Error, color: ColorWhen) -> Self {
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: color,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} {}", c.error("error:"), e.description()),
|
||||
kind: ErrorKind::Io,
|
||||
info: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn argument_not_found_auto<A>(arg: A) -> Self
|
||||
where
|
||||
A: Into<String>,
|
||||
{
|
||||
let a = arg.into();
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: ColorWhen::Auto,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} The argument '{}' wasn't found", c.error("error:"), a),
|
||||
kind: ErrorKind::ArgumentNotFound,
|
||||
info: Some(vec![a]),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an error with a custom description.
|
||||
///
|
||||
/// This can be used in combination with `Error::exit` to exit your program
|
||||
/// with a custom error message.
|
||||
pub fn with_description(description: &str, kind: ErrorKind) -> Self {
|
||||
let c = Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: ColorWhen::Auto,
|
||||
});
|
||||
Error {
|
||||
message: format!("{} {}", c.error("error:"), description),
|
||||
kind,
|
||||
info: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for Error {
|
||||
fn description(&self) -> &str {
|
||||
&*self.message
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std_fmt::Formatter) -> std_fmt::Result {
|
||||
writeln!(f, "{}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(e: io::Error) -> Self {
|
||||
Error::with_description(e.description(), ErrorKind::Io)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std_fmt::Error> for Error {
|
||||
fn from(e: std_fmt::Error) -> Self {
|
||||
Error::with_description(e.description(), ErrorKind::Format)
|
||||
}
|
||||
}
|
||||
192
zeroidc/vendor/clap/src/fmt.rs
vendored
Normal file
192
zeroidc/vendor/clap/src/fmt.rs
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
||||
use ansi_term::ANSIString;
|
||||
|
||||
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
||||
use ansi_term::Colour::{Green, Red, Yellow};
|
||||
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum ColorWhen {
|
||||
Auto,
|
||||
Always,
|
||||
Never,
|
||||
}
|
||||
|
||||
#[cfg(feature = "color")]
|
||||
pub fn is_a_tty(stderr: bool) -> bool {
|
||||
debugln!("is_a_tty: stderr={:?}", stderr);
|
||||
let stream = if stderr {
|
||||
atty::Stream::Stderr
|
||||
} else {
|
||||
atty::Stream::Stdout
|
||||
};
|
||||
atty::is(stream)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "color"))]
|
||||
pub fn is_a_tty(_: bool) -> bool {
|
||||
debugln!("is_a_tty;");
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_term_dumb() -> bool {
|
||||
env::var("TERM").ok() == Some(String::from("dumb"))
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct ColorizerOption {
|
||||
pub use_stderr: bool,
|
||||
pub when: ColorWhen,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct Colorizer {
|
||||
when: ColorWhen,
|
||||
}
|
||||
|
||||
macro_rules! color {
|
||||
($_self:ident, $c:ident, $m:expr) => {
|
||||
match $_self.when {
|
||||
ColorWhen::Auto => Format::$c($m),
|
||||
ColorWhen::Always => Format::$c($m),
|
||||
ColorWhen::Never => Format::None($m),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl Colorizer {
|
||||
pub fn new(option: ColorizerOption) -> Colorizer {
|
||||
let is_a_tty = is_a_tty(option.use_stderr);
|
||||
let is_term_dumb = is_term_dumb();
|
||||
Colorizer {
|
||||
when: match option.when {
|
||||
ColorWhen::Auto if is_a_tty && !is_term_dumb => ColorWhen::Auto,
|
||||
ColorWhen::Auto => ColorWhen::Never,
|
||||
when => when,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn good<T>(&self, msg: T) -> Format<T>
|
||||
where
|
||||
T: fmt::Display + AsRef<str>,
|
||||
{
|
||||
debugln!("Colorizer::good;");
|
||||
color!(self, Good, msg)
|
||||
}
|
||||
|
||||
pub fn warning<T>(&self, msg: T) -> Format<T>
|
||||
where
|
||||
T: fmt::Display + AsRef<str>,
|
||||
{
|
||||
debugln!("Colorizer::warning;");
|
||||
color!(self, Warning, msg)
|
||||
}
|
||||
|
||||
pub fn error<T>(&self, msg: T) -> Format<T>
|
||||
where
|
||||
T: fmt::Display + AsRef<str>,
|
||||
{
|
||||
debugln!("Colorizer::error;");
|
||||
color!(self, Error, msg)
|
||||
}
|
||||
|
||||
pub fn none<T>(&self, msg: T) -> Format<T>
|
||||
where
|
||||
T: fmt::Display + AsRef<str>,
|
||||
{
|
||||
debugln!("Colorizer::none;");
|
||||
Format::None(msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Colorizer {
|
||||
fn default() -> Self {
|
||||
Colorizer::new(ColorizerOption {
|
||||
use_stderr: true,
|
||||
when: ColorWhen::Auto,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines styles for different types of error messages. Defaults to Error=Red, Warning=Yellow,
|
||||
/// and Good=Green
|
||||
#[derive(Debug)]
|
||||
#[doc(hidden)]
|
||||
pub enum Format<T> {
|
||||
/// Defines the style used for errors, defaults to Red
|
||||
Error(T),
|
||||
/// Defines the style used for warnings, defaults to Yellow
|
||||
Warning(T),
|
||||
/// Defines the style used for good values, defaults to Green
|
||||
Good(T),
|
||||
/// Defines no formatting style
|
||||
None(T),
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
||||
impl<T: AsRef<str>> Format<T> {
|
||||
fn format(&self) -> ANSIString {
|
||||
match *self {
|
||||
Format::Error(ref e) => Red.bold().paint(e.as_ref()),
|
||||
Format::Warning(ref e) => Yellow.paint(e.as_ref()),
|
||||
Format::Good(ref e) => Green.paint(e.as_ref()),
|
||||
Format::None(ref e) => ANSIString::from(e.as_ref()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(not(feature = "color"), target_os = "windows"))]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::match_same_arms))]
|
||||
impl<T: fmt::Display> Format<T> {
|
||||
fn format(&self) -> &T {
|
||||
match *self {
|
||||
Format::Error(ref e) => e,
|
||||
Format::Warning(ref e) => e,
|
||||
Format::Good(ref e) => e,
|
||||
Format::None(ref e) => e,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
||||
impl<T: AsRef<str>> fmt::Display for Format<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", &self.format())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(not(feature = "color"), target_os = "windows"))]
|
||||
impl<T: fmt::Display> fmt::Display for Format<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", &self.format())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, feature = "color", not(target_os = "windows")))]
|
||||
mod test {
|
||||
use super::Format;
|
||||
use ansi_term::ANSIString;
|
||||
use ansi_term::Colour::{Green, Red, Yellow};
|
||||
|
||||
#[test]
|
||||
fn colored_output() {
|
||||
let err = Format::Error("error");
|
||||
assert_eq!(
|
||||
&*format!("{}", err),
|
||||
&*format!("{}", Red.bold().paint("error"))
|
||||
);
|
||||
let good = Format::Good("good");
|
||||
assert_eq!(&*format!("{}", good), &*format!("{}", Green.paint("good")));
|
||||
let warn = Format::Warning("warn");
|
||||
assert_eq!(&*format!("{}", warn), &*format!("{}", Yellow.paint("warn")));
|
||||
let none = Format::None("none");
|
||||
assert_eq!(
|
||||
&*format!("{}", none),
|
||||
&*format!("{}", ANSIString::from("none"))
|
||||
);
|
||||
}
|
||||
}
|
||||
638
zeroidc/vendor/clap/src/lib.rs
vendored
Normal file
638
zeroidc/vendor/clap/src/lib.rs
vendored
Normal file
@@ -0,0 +1,638 @@
|
||||
// Copyright ⓒ 2015-2016 Kevin B. Knapp and [`clap-rs` contributors](https://github.com/clap-rs/clap/blob/v2.33.1/CONTRIBUTORS.md).
|
||||
// Licensed under the MIT license
|
||||
// (see LICENSE or <http://opensource.org/licenses/MIT>) All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
//! `clap` is a simple-to-use, efficient, and full-featured library for parsing command line
|
||||
//! arguments and subcommands when writing console/terminal applications.
|
||||
//!
|
||||
//! ## About
|
||||
//!
|
||||
//! `clap` is used to parse *and validate* the string of command line arguments provided by the user
|
||||
//! at runtime. You provide the list of valid possibilities, and `clap` handles the rest. This means
|
||||
//! you focus on your *applications* functionality, and less on the parsing and validating of
|
||||
//! arguments.
|
||||
//!
|
||||
//! `clap` also provides the traditional version and help switches (or flags) 'for free' meaning
|
||||
//! automatically with no configuration. It does this by checking the list of valid possibilities you
|
||||
//! supplied and adding only the ones you haven't already defined. If you are using subcommands,
|
||||
//! `clap` will also auto-generate a `help` subcommand for you in addition to the traditional flags.
|
||||
//!
|
||||
//! Once `clap` parses the user provided string of arguments, it returns the matches along with any
|
||||
//! applicable values. If the user made an error or typo, `clap` informs them of the mistake and
|
||||
//! exits gracefully (or returns a `Result` type and allows you to perform any clean up prior to
|
||||
//! exit). Because of this, you can make reasonable assumptions in your code about the validity of
|
||||
//! the arguments.
|
||||
//!
|
||||
//!
|
||||
//! ## Quick Example
|
||||
//!
|
||||
//! The following examples show a quick example of some of the very basic functionality of `clap`.
|
||||
//! For more advanced usage, such as requirements, conflicts, groups, multiple values and
|
||||
//! occurrences see the [documentation](https://docs.rs/clap/), [examples/] directory of
|
||||
//! this repository or the [video tutorials].
|
||||
//!
|
||||
//! **NOTE:** All of these examples are functionally the same, but show different styles in which to
|
||||
//! use `clap`
|
||||
//!
|
||||
//! The first example shows a method that allows more advanced configuration options (not shown in
|
||||
//! this small example), or even dynamically generating arguments when desired. The downside is it's
|
||||
//! more verbose.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! // (Full example with detailed comments in examples/01b_quick_example.rs)
|
||||
//! //
|
||||
//! // This example demonstrates clap's full 'builder pattern' style of creating arguments which is
|
||||
//! // more verbose, but allows easier editing, and at times more advanced options, or the possibility
|
||||
//! // to generate arguments dynamically.
|
||||
//! extern crate clap;
|
||||
//! use clap::{Arg, App, SubCommand};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let matches = App::new("My Super Program")
|
||||
//! .version("1.0")
|
||||
//! .author("Kevin K. <kbknapp@gmail.com>")
|
||||
//! .about("Does awesome things")
|
||||
//! .arg(Arg::with_name("config")
|
||||
//! .short("c")
|
||||
//! .long("config")
|
||||
//! .value_name("FILE")
|
||||
//! .help("Sets a custom config file")
|
||||
//! .takes_value(true))
|
||||
//! .arg(Arg::with_name("INPUT")
|
||||
//! .help("Sets the input file to use")
|
||||
//! .required(true)
|
||||
//! .index(1))
|
||||
//! .arg(Arg::with_name("v")
|
||||
//! .short("v")
|
||||
//! .multiple(true)
|
||||
//! .help("Sets the level of verbosity"))
|
||||
//! .subcommand(SubCommand::with_name("test")
|
||||
//! .about("controls testing features")
|
||||
//! .version("1.3")
|
||||
//! .author("Someone E. <someone_else@other.com>")
|
||||
//! .arg(Arg::with_name("debug")
|
||||
//! .short("d")
|
||||
//! .help("print debug information verbosely")))
|
||||
//! .get_matches();
|
||||
//!
|
||||
//! // Gets a value for config if supplied by user, or defaults to "default.conf"
|
||||
//! let config = matches.value_of("config").unwrap_or("default.conf");
|
||||
//! println!("Value for config: {}", config);
|
||||
//!
|
||||
//! // Calling .unwrap() is safe here because "INPUT" is required (if "INPUT" wasn't
|
||||
//! // required we could have used an 'if let' to conditionally get the value)
|
||||
//! println!("Using input file: {}", matches.value_of("INPUT").unwrap());
|
||||
//!
|
||||
//! // Vary the output based on how many times the user used the "verbose" flag
|
||||
//! // (i.e. 'myprog -v -v -v' or 'myprog -vvv' vs 'myprog -v'
|
||||
//! match matches.occurrences_of("v") {
|
||||
//! 0 => println!("No verbose info"),
|
||||
//! 1 => println!("Some verbose info"),
|
||||
//! 2 => println!("Tons of verbose info"),
|
||||
//! 3 | _ => println!("Don't be crazy"),
|
||||
//! }
|
||||
//!
|
||||
//! // You can handle information about subcommands by requesting their matches by name
|
||||
//! // (as below), requesting just the name used, or both at the same time
|
||||
//! if let Some(matches) = matches.subcommand_matches("test") {
|
||||
//! if matches.is_present("debug") {
|
||||
//! println!("Printing debug info...");
|
||||
//! } else {
|
||||
//! println!("Printing normally...");
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! // more program logic goes here...
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The next example shows a far less verbose method, but sacrifices some of the advanced
|
||||
//! configuration options (not shown in this small example). This method also takes a *very* minor
|
||||
//! runtime penalty.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! // (Full example with detailed comments in examples/01a_quick_example.rs)
|
||||
//! //
|
||||
//! // This example demonstrates clap's "usage strings" method of creating arguments
|
||||
//! // which is less verbose
|
||||
//! extern crate clap;
|
||||
//! use clap::{Arg, App, SubCommand};
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let matches = App::new("myapp")
|
||||
//! .version("1.0")
|
||||
//! .author("Kevin K. <kbknapp@gmail.com>")
|
||||
//! .about("Does awesome things")
|
||||
//! .args_from_usage(
|
||||
//! "-c, --config=[FILE] 'Sets a custom config file'
|
||||
//! <INPUT> 'Sets the input file to use'
|
||||
//! -v... 'Sets the level of verbosity'")
|
||||
//! .subcommand(SubCommand::with_name("test")
|
||||
//! .about("controls testing features")
|
||||
//! .version("1.3")
|
||||
//! .author("Someone E. <someone_else@other.com>")
|
||||
//! .arg_from_usage("-d, --debug 'Print debug information'"))
|
||||
//! .get_matches();
|
||||
//!
|
||||
//! // Same as previous example...
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! This third method shows how you can use a YAML file to build your CLI and keep your Rust source
|
||||
//! tidy or support multiple localized translations by having different YAML files for each
|
||||
//! localization.
|
||||
//!
|
||||
//! First, create the `cli.yml` file to hold your CLI options, but it could be called anything we
|
||||
//! like:
|
||||
//!
|
||||
//! ```yaml
|
||||
//! name: myapp
|
||||
//! version: "1.0"
|
||||
//! author: Kevin K. <kbknapp@gmail.com>
|
||||
//! about: Does awesome things
|
||||
//! args:
|
||||
//! - config:
|
||||
//! short: c
|
||||
//! long: config
|
||||
//! value_name: FILE
|
||||
//! help: Sets a custom config file
|
||||
//! takes_value: true
|
||||
//! - INPUT:
|
||||
//! help: Sets the input file to use
|
||||
//! required: true
|
||||
//! index: 1
|
||||
//! - verbose:
|
||||
//! short: v
|
||||
//! multiple: true
|
||||
//! help: Sets the level of verbosity
|
||||
//! subcommands:
|
||||
//! - test:
|
||||
//! about: controls testing features
|
||||
//! version: "1.3"
|
||||
//! author: Someone E. <someone_else@other.com>
|
||||
//! args:
|
||||
//! - debug:
|
||||
//! short: d
|
||||
//! help: print debug information
|
||||
//! ```
|
||||
//!
|
||||
//! Since this feature requires additional dependencies that not everyone may want, it is *not*
|
||||
//! compiled in by default and we need to enable a feature flag in Cargo.toml:
|
||||
//!
|
||||
//! Simply change your `clap = "~2.27.0"` to `clap = {version = "~2.27.0", features = ["yaml"]}`.
|
||||
//!
|
||||
//! At last we create our `main.rs` file just like we would have with the previous two examples:
|
||||
//!
|
||||
//! ```ignore
|
||||
//! // (Full example with detailed comments in examples/17_yaml.rs)
|
||||
//! //
|
||||
//! // This example demonstrates clap's building from YAML style of creating arguments which is far
|
||||
//! // more clean, but takes a very small performance hit compared to the other two methods.
|
||||
//! #[macro_use]
|
||||
//! extern crate clap;
|
||||
//! use clap::App;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! // The YAML file is found relative to the current file, similar to how modules are found
|
||||
//! let yaml = load_yaml!("cli.yml");
|
||||
//! let matches = App::from_yaml(yaml).get_matches();
|
||||
//!
|
||||
//! // Same as previous examples...
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Finally there is a macro version, which is like a hybrid approach offering the speed of the
|
||||
//! builder pattern (the first example), but without all the verbosity.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! #[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")
|
||||
//! (@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 verbose: -v --verbose "Print test information verbosely")
|
||||
//! )
|
||||
//! ).get_matches();
|
||||
//!
|
||||
//! // Same as before...
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! If you were to compile any of the above programs and run them with the flag `--help` or `-h` (or
|
||||
//! `help` subcommand, since we defined `test` as a subcommand) the following would be output
|
||||
//!
|
||||
//! ```text
|
||||
//! $ myprog --help
|
||||
//! My Super Program 1.0
|
||||
//! Kevin K. <kbknapp@gmail.com>
|
||||
//! Does awesome things
|
||||
//!
|
||||
//! USAGE:
|
||||
//! MyApp [FLAGS] [OPTIONS] <INPUT> [SUBCOMMAND]
|
||||
//!
|
||||
//! FLAGS:
|
||||
//! -h, --help Prints this message
|
||||
//! -v Sets the level of verbosity
|
||||
//! -V, --version Prints version information
|
||||
//!
|
||||
//! OPTIONS:
|
||||
//! -c, --config <FILE> Sets a custom config file
|
||||
//!
|
||||
//! ARGS:
|
||||
//! INPUT The input file to use
|
||||
//!
|
||||
//! SUBCOMMANDS:
|
||||
//! help Prints this message
|
||||
//! test Controls testing features
|
||||
//! ```
|
||||
//!
|
||||
//! **NOTE:** You could also run `myapp test --help` to see similar output and options for the
|
||||
//! `test` subcommand.
|
||||
//!
|
||||
//! ## Try it!
|
||||
//!
|
||||
//! ### Pre-Built Test
|
||||
//!
|
||||
//! To try out the pre-built example, use the following steps:
|
||||
//!
|
||||
//! * Clone the repository `$ git clone https://github.com/clap-rs/clap && cd clap-rs/tests`
|
||||
//! * Compile the example `$ cargo build --release`
|
||||
//! * Run the help info `$ ./target/release/claptests --help`
|
||||
//! * Play with the arguments!
|
||||
//!
|
||||
//! ### BYOB (Build Your Own Binary)
|
||||
//!
|
||||
//! To test out `clap`'s default auto-generated help/version follow these steps:
|
||||
//!
|
||||
//! * Create a new cargo project `$ cargo new fake --bin && cd fake`
|
||||
//! * Add `clap` to your `Cargo.toml`
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! clap = "2"
|
||||
//! ```
|
||||
//!
|
||||
//! * Add the following to your `src/main.rs`
|
||||
//!
|
||||
//! ```no_run
|
||||
//! extern crate clap;
|
||||
//! use clap::App;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! App::new("fake").version("v1.0-beta").get_matches();
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! * Build your program `$ cargo build --release`
|
||||
//! * Run with help or version `$ ./target/release/fake --help` or `$ ./target/release/fake
|
||||
//! --version`
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! For full usage, add `clap` as a dependency in your `Cargo.toml` (it is **highly** recommended to
|
||||
//! use the `~major.minor.patch` style versions in your `Cargo.toml`, for more information see
|
||||
//! [Compatibility Policy](#compatibility-policy)) to use from crates.io:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! clap = "~2.27.0"
|
||||
//! ```
|
||||
//!
|
||||
//! Or get the latest changes from the master branch at github:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.clap]
|
||||
//! git = "https://github.com/clap-rs/clap.git"
|
||||
//! ```
|
||||
//!
|
||||
//! Add `extern crate clap;` to your crate root.
|
||||
//!
|
||||
//! Define a list of valid arguments for your program (see the
|
||||
//! [documentation](https://docs.rs/clap/) or [examples/] directory of this repo)
|
||||
//!
|
||||
//! Then run `cargo build` or `cargo update && cargo build` for your project.
|
||||
//!
|
||||
//! ### Optional Dependencies / Features
|
||||
//!
|
||||
//! #### Features enabled by default
|
||||
//!
|
||||
//! * `suggestions`: Turns on the `Did you mean '--myoption'?` feature for when users make typos. (builds dependency `strsim`)
|
||||
//! * `color`: Turns on colored error messages. This feature only works on non-Windows OSs. (builds dependency `ansi-term` and `atty`)
|
||||
//! * `wrap_help`: Wraps the help at the actual terminal width when
|
||||
//! available, instead of 120 characters. (builds dependency `textwrap`
|
||||
//! with feature `term_size`)
|
||||
//!
|
||||
//! To disable these, add this to your `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.clap]
|
||||
//! version = "~2.27.0"
|
||||
//! default-features = false
|
||||
//! ```
|
||||
//!
|
||||
//! You can also selectively enable only the features you'd like to include, by adding:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.clap]
|
||||
//! version = "~2.27.0"
|
||||
//! default-features = false
|
||||
//!
|
||||
//! # Cherry-pick the features you'd like to use
|
||||
//! features = [ "suggestions", "color" ]
|
||||
//! ```
|
||||
//!
|
||||
//! #### Opt-in features
|
||||
//!
|
||||
//! * **"yaml"**: Enables building CLIs from YAML documents. (builds dependency `yaml-rust`)
|
||||
//! * **"unstable"**: Enables unstable `clap` features that may change from release to release
|
||||
//!
|
||||
//! ### Dependencies Tree
|
||||
//!
|
||||
//! The following graphic depicts `clap`s dependency graph (generated using
|
||||
//! [cargo-graph](https://github.com/kbknapp/cargo-graph)).
|
||||
//!
|
||||
//! * **Dashed** Line: Optional dependency
|
||||
//! * **Red** Color: **NOT** included by default (must use cargo `features` to enable)
|
||||
//! * **Blue** Color: Dev dependency, only used while developing.
|
||||
//!
|
||||
//! 
|
||||
//!
|
||||
//! ### More Information
|
||||
//!
|
||||
//! You can find complete documentation on the [docs.rs](https://docs.rs/clap/) for this project.
|
||||
//!
|
||||
//! You can also find usage examples in the [examples/] directory of this repo.
|
||||
//!
|
||||
//! #### Video Tutorials
|
||||
//!
|
||||
//! There's also the video tutorial series [Argument Parsing with Rust v2][video tutorials].
|
||||
//!
|
||||
//! These videos slowly trickle out as I finish them and currently a work in progress.
|
||||
//!
|
||||
//! ## How to Contribute
|
||||
//!
|
||||
//! Contributions are always welcome! And there is a multitude of ways in which you can help
|
||||
//! depending on what you like to do, or are good at. Anything from documentation, code cleanup,
|
||||
//! issue completion, new features, you name it, even filing issues is contributing and greatly
|
||||
//! appreciated!
|
||||
//!
|
||||
//! Another really great way to help is if you find an interesting, or helpful way in which to use
|
||||
//! `clap`. You can either add it to the [examples/] directory, or file an issue and tell
|
||||
//! me. I'm all about giving credit where credit is due :)
|
||||
//!
|
||||
//! Please read [CONTRIBUTING.md](https://github.com/clap-rs/clap/blob/v2.34.0/.github/CONTRIBUTING.md) before you start contributing.
|
||||
//!
|
||||
//!
|
||||
//! ### Testing Code
|
||||
//!
|
||||
//! To test with all features both enabled and disabled, you can run theese commands:
|
||||
//!
|
||||
//! ```text
|
||||
//! $ cargo test --no-default-features
|
||||
//! $ cargo test --features "yaml unstable"
|
||||
//! ```
|
||||
//!
|
||||
//! Alternatively, if you have [`just`](https://github.com/casey/just) installed you can run the
|
||||
//! prebuilt recipes. *Not* using `just` is perfectly fine as well, it simply bundles commands
|
||||
//! automatically.
|
||||
//!
|
||||
//! For example, to test the code, as above simply run:
|
||||
//!
|
||||
//! ```text
|
||||
//! $ just run-tests
|
||||
//! ```
|
||||
//!
|
||||
//! From here on, I will list the appropriate `cargo` command as well as the `just` command.
|
||||
//!
|
||||
//! Sometimes it's helpful to only run a subset of the tests, which can be done via:
|
||||
//!
|
||||
//! ```text
|
||||
//! $ cargo test --test <test_name>
|
||||
//!
|
||||
//! # Or
|
||||
//!
|
||||
//! $ just run-test <test_name>
|
||||
//! ```
|
||||
//!
|
||||
//! ### Linting Code
|
||||
//!
|
||||
//! During the CI process `clap` runs against many different lints using
|
||||
//! [`clippy`](https://github.com/Manishearth/rust-clippy). In order to check if these lints pass on
|
||||
//! your own computer prior to submitting a PR you'll need a nightly compiler.
|
||||
//!
|
||||
//! In order to check the code for lints run either:
|
||||
//!
|
||||
//! ```text
|
||||
//! $ rustup override add nightly
|
||||
//! $ cargo build --features lints
|
||||
//! $ rustup override remove
|
||||
//!
|
||||
//! # Or
|
||||
//!
|
||||
//! $ just lint
|
||||
//! ```
|
||||
//!
|
||||
//! ### Debugging Code
|
||||
//!
|
||||
//! Another helpful technique is to see the `clap` debug output while developing features. In order
|
||||
//! to see the debug output while running the full test suite or individual tests, run:
|
||||
//!
|
||||
//! ```text
|
||||
//! $ cargo test --features debug
|
||||
//!
|
||||
//! # Or for individual tests
|
||||
//! $ cargo test --test <test_name> --features debug
|
||||
//!
|
||||
//! # The corresponding just command for individual debugging tests is:
|
||||
//! $ just debug <test_name>
|
||||
//! ```
|
||||
//!
|
||||
//! ### Goals
|
||||
//!
|
||||
//! There are a few goals of `clap` that I'd like to maintain throughout contributions. If your
|
||||
//! proposed changes break, or go against any of these goals we'll discuss the changes further
|
||||
//! before merging (but will *not* be ignored, all contributes are welcome!). These are by no means
|
||||
//! hard-and-fast rules, as I'm no expert and break them myself from time to time (even if by
|
||||
//! mistake or ignorance).
|
||||
//!
|
||||
//! * Remain backwards compatible when possible
|
||||
//! - If backwards compatibility *must* be broken, use deprecation warnings if at all possible before
|
||||
//! removing legacy code - This does not apply for security concerns
|
||||
//! * Parse arguments quickly
|
||||
//! - Parsing of arguments shouldn't slow down usage of the main program - This is also true of
|
||||
//! generating help and usage information (although *slightly* less stringent, as the program is about
|
||||
//! to exit)
|
||||
//! * Try to be cognizant of memory usage
|
||||
//! - Once parsing is complete, the memory footprint of `clap` should be low since the main program
|
||||
//! is the star of the show
|
||||
//! * `panic!` on *developer* error, exit gracefully on *end-user* error
|
||||
//!
|
||||
//! ### Compatibility Policy
|
||||
//!
|
||||
//! Because `clap` takes `SemVer` and compatibility seriously, this is the official policy regarding
|
||||
//! breaking changes and previous versions of Rust.
|
||||
//!
|
||||
//! `clap` will pin the minimum required version of Rust to the CI builds. Bumping the minimum
|
||||
//! version of Rust is considered a minor breaking change, meaning *at a minimum* the minor version
|
||||
//! of `clap` will be bumped.
|
||||
//!
|
||||
//! In order to keep from being surprised by breaking changes, it is **highly** recommended to use
|
||||
//! the `~major.minor.patch` style in your `Cargo.toml`:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies] clap = "~2.27.0"
|
||||
//! ```
|
||||
//!
|
||||
//! This will cause *only* the patch version to be updated upon a `cargo update` call, and therefore
|
||||
//! cannot break due to new features, or bumped minimum versions of Rust.
|
||||
//!
|
||||
//! #### Minimum Version of Rust
|
||||
//!
|
||||
//! `clap` will officially support current stable Rust, minus two releases, but may work with prior
|
||||
//! releases as well. For example, current stable Rust at the time of this writing is 1.21.0,
|
||||
//! meaning `clap` is guaranteed to compile with 1.19.0 and beyond. At the 1.22.0 release, `clap`
|
||||
//! will be guaranteed to compile with 1.20.0 and beyond, etc.
|
||||
//!
|
||||
//! Upon bumping the minimum version of Rust (assuming it's within the stable-2 range), it *must* be
|
||||
//! clearly annotated in the `CHANGELOG.md`
|
||||
//!
|
||||
//! ## License
|
||||
//!
|
||||
//! `clap` is licensed under the MIT license. Please read the [LICENSE-MIT][license] file in
|
||||
//! this repository for more information.
|
||||
//!
|
||||
//! [examples/]: https://github.com/clap-rs/clap/tree/v2.34.0/examples
|
||||
//! [video tutorials]: https://www.youtube.com/playlist?list=PLza5oFLQGTl2Z5T8g1pRkIynR3E0_pc7U
|
||||
//! [license]: https://github.com/clap-rs/clap/blob/v2.34.0/LICENSE-MIT
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![doc(html_root_url = "https://docs.rs/clap/2.34.0")]
|
||||
#![deny(
|
||||
missing_docs,
|
||||
missing_debug_implementations,
|
||||
missing_copy_implementations,
|
||||
trivial_casts,
|
||||
unused_import_braces,
|
||||
unused_allocation
|
||||
)]
|
||||
// Lints we'd like to deny but are currently failing for upstream crates
|
||||
// unused_qualifications (bitflags, clippy)
|
||||
// trivial_numeric_casts (bitflags)
|
||||
#![cfg_attr(
|
||||
not(any(feature = "cargo-clippy", feature = "nightly")),
|
||||
forbid(unstable_features)
|
||||
)]
|
||||
//#![cfg_attr(feature = "lints", feature(plugin))]
|
||||
//#![cfg_attr(feature = "lints", plugin(clippy))]
|
||||
// Need to disable deny(warnings) while deprecations are active
|
||||
//#![cfg_attr(feature = "cargo-clippy", deny(warnings))]
|
||||
// Due to our "MSRV for 2.x will remain unchanged" policy, we can't fix these warnings
|
||||
#![allow(bare_trait_objects, deprecated)]
|
||||
|
||||
#[cfg(all(feature = "color", not(target_os = "windows")))]
|
||||
extern crate ansi_term;
|
||||
#[cfg(feature = "color")]
|
||||
extern crate atty;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[cfg(feature = "suggestions")]
|
||||
extern crate strsim;
|
||||
#[cfg(feature = "wrap_help")]
|
||||
extern crate term_size;
|
||||
extern crate textwrap;
|
||||
extern crate unicode_width;
|
||||
#[cfg(feature = "vec_map")]
|
||||
extern crate vec_map;
|
||||
#[cfg(feature = "yaml")]
|
||||
extern crate yaml_rust;
|
||||
|
||||
pub use app::{App, AppSettings};
|
||||
pub use args::{Arg, ArgGroup, ArgMatches, ArgSettings, OsValues, SubCommand, Values};
|
||||
pub use completions::Shell;
|
||||
pub use errors::{Error, ErrorKind, Result};
|
||||
pub use fmt::Format;
|
||||
#[cfg(feature = "yaml")]
|
||||
pub use yaml_rust::YamlLoader;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod app;
|
||||
mod args;
|
||||
mod completions;
|
||||
mod errors;
|
||||
mod fmt;
|
||||
mod map;
|
||||
mod osstringext;
|
||||
mod strext;
|
||||
mod suggestions;
|
||||
mod usage_parser;
|
||||
|
||||
const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
|
||||
report at https://github.com/clap-rs/clap/issues";
|
||||
const INVALID_UTF8: &str = "unexpected invalid UTF-8 code point";
|
||||
|
||||
#[cfg(unstable)]
|
||||
pub use derive::{ArgEnum, ClapApp, FromArgMatches, IntoApp};
|
||||
|
||||
#[cfg(unstable)]
|
||||
mod derive {
|
||||
/// @TODO @release @docs
|
||||
pub trait ClapApp: IntoApp + FromArgMatches + Sized {
|
||||
/// @TODO @release @docs
|
||||
fn parse() -> Self {
|
||||
Self::from_argmatches(Self::into_app().get_matches())
|
||||
}
|
||||
|
||||
/// @TODO @release @docs
|
||||
fn parse_from<I, T>(argv: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
Self::from_argmatches(Self::into_app().get_matches_from(argv))
|
||||
}
|
||||
|
||||
/// @TODO @release @docs
|
||||
fn try_parse() -> Result<Self, clap::Error> {
|
||||
Self::try_from_argmatches(Self::into_app().get_matches_safe()?)
|
||||
}
|
||||
|
||||
/// @TODO @release @docs
|
||||
fn try_parse_from<I, T>(argv: I) -> Result<Self, clap::Error>
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
{
|
||||
Self::try_from_argmatches(Self::into_app().get_matches_from_safe(argv)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// @TODO @release @docs
|
||||
pub trait IntoApp {
|
||||
/// @TODO @release @docs
|
||||
fn into_app<'a, 'b>() -> clap::App<'a, 'b>;
|
||||
}
|
||||
|
||||
/// @TODO @release @docs
|
||||
pub trait FromArgMatches: Sized {
|
||||
/// @TODO @release @docs
|
||||
fn from_argmatches<'a>(matches: clap::ArgMatches<'a>) -> Self;
|
||||
|
||||
/// @TODO @release @docs
|
||||
fn try_from_argmatches<'a>(matches: clap::ArgMatches<'a>) -> Result<Self, clap::Error>;
|
||||
}
|
||||
|
||||
/// @TODO @release @docs
|
||||
pub trait ArgEnum {}
|
||||
}
|
||||
1130
zeroidc/vendor/clap/src/macros.rs
vendored
Normal file
1130
zeroidc/vendor/clap/src/macros.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
88
zeroidc/vendor/clap/src/map.rs
vendored
Normal file
88
zeroidc/vendor/clap/src/map.rs
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
#[cfg(feature = "vec_map")]
|
||||
pub use vec_map::{Values, VecMap};
|
||||
|
||||
#[cfg(not(feature = "vec_map"))]
|
||||
pub use self::vec_map::{Values, VecMap};
|
||||
|
||||
#[cfg(not(feature = "vec_map"))]
|
||||
mod vec_map {
|
||||
use std::collections::btree_map;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct VecMap<V> {
|
||||
inner: BTreeMap<usize, V>,
|
||||
}
|
||||
|
||||
impl<V> VecMap<V> {
|
||||
pub fn new() -> Self {
|
||||
VecMap {
|
||||
inner: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.inner.is_empty()
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: usize, value: V) -> Option<V> {
|
||||
self.inner.insert(key, value)
|
||||
}
|
||||
|
||||
pub fn values(&self) -> Values<V> {
|
||||
self.inner.values()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<V> {
|
||||
Iter {
|
||||
inner: self.inner.iter(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_key(&self, key: usize) -> bool {
|
||||
self.inner.contains_key(&key)
|
||||
}
|
||||
|
||||
pub fn entry(&mut self, key: usize) -> Entry<V> {
|
||||
self.inner.entry(key)
|
||||
}
|
||||
|
||||
pub fn get(&self, key: usize) -> Option<&V> {
|
||||
self.inner.get(&key)
|
||||
}
|
||||
}
|
||||
|
||||
pub type Values<'a, V> = btree_map::Values<'a, usize, V>;
|
||||
|
||||
pub type Entry<'a, V> = btree_map::Entry<'a, usize, V>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Iter<'a, V: 'a> {
|
||||
inner: btree_map::Iter<'a, usize, V>,
|
||||
}
|
||||
|
||||
impl<'a, V: 'a + Debug> Debug for Iter<'a, V> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_list().entries(self.inner.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V: 'a> Iterator for Iter<'a, V> {
|
||||
type Item = (usize, &'a V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next().map(|(k, v)| (*k, v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V: 'a> DoubleEndedIterator for Iter<'a, V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next_back().map(|(k, v)| (*k, v))
|
||||
}
|
||||
}
|
||||
}
|
||||
203
zeroidc/vendor/clap/src/osstringext.rs
vendored
Normal file
203
zeroidc/vendor/clap/src/osstringext.rs
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
use std::ffi::OsStr;
|
||||
#[cfg(not(any(target_os = "windows", target_arch = "wasm32")))]
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
|
||||
use crate::INVALID_UTF8;
|
||||
|
||||
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
|
||||
pub trait OsStrExt3 {
|
||||
fn from_bytes(b: &[u8]) -> &Self;
|
||||
fn as_bytes(&self) -> &[u8];
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait OsStrExt2 {
|
||||
fn starts_with(&self, s: &[u8]) -> bool;
|
||||
fn split_at_byte(&self, b: u8) -> (&OsStr, &OsStr);
|
||||
fn split_at(&self, i: usize) -> (&OsStr, &OsStr);
|
||||
fn trim_left_matches(&self, b: u8) -> &OsStr;
|
||||
fn contains_byte(&self, b: u8) -> bool;
|
||||
fn split(&self, b: u8) -> OsSplit;
|
||||
}
|
||||
|
||||
// A starts-with implementation that does not panic when the OsStr contains
|
||||
// invalid Unicode.
|
||||
//
|
||||
// A Windows OsStr is usually UTF-16. If `prefix` is valid UTF-8, we can
|
||||
// re-encode it as UTF-16, and ask whether `osstr` starts with the same series
|
||||
// of u16 code units. If `prefix` is not valid UTF-8, then this comparison
|
||||
// isn't meaningful, and we just return false.
|
||||
#[cfg(target_os = "windows")]
|
||||
fn windows_osstr_starts_with(osstr: &OsStr, prefix: &[u8]) -> bool {
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
let prefix_str = if let Ok(s) = std::str::from_utf8(prefix) {
|
||||
s
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
let mut osstr_units = osstr.encode_wide();
|
||||
let mut prefix_units = prefix_str.encode_utf16();
|
||||
loop {
|
||||
match (osstr_units.next(), prefix_units.next()) {
|
||||
// These code units match. Keep looping.
|
||||
(Some(o), Some(p)) if o == p => continue,
|
||||
// We've reached the end of the prefix. It's a match.
|
||||
(_, None) => return true,
|
||||
// Otherwise, it's not a match.
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "windows")]
|
||||
fn test_windows_osstr_starts_with() {
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
|
||||
fn from_ascii(ascii: &[u8]) -> OsString {
|
||||
let u16_vec: Vec<u16> = ascii.iter().map(|&c| c as u16).collect();
|
||||
OsString::from_wide(&u16_vec)
|
||||
}
|
||||
|
||||
// Test all the basic cases.
|
||||
assert!(windows_osstr_starts_with(&from_ascii(b"abcdef"), b"abc"));
|
||||
assert!(windows_osstr_starts_with(&from_ascii(b"abcdef"), b"abcdef"));
|
||||
assert!(!windows_osstr_starts_with(&from_ascii(b"abcdef"), b"def"));
|
||||
assert!(!windows_osstr_starts_with(&from_ascii(b"abc"), b"abcd"));
|
||||
|
||||
// Test the case where the candidate prefix is not valid UTF-8. Note that a
|
||||
// standalone \xff byte is valid ASCII but not valid UTF-8. Thus although
|
||||
// these strings look identical, they do not match.
|
||||
assert!(!windows_osstr_starts_with(&from_ascii(b"\xff"), b"\xff"));
|
||||
|
||||
// Test the case where the OsString is not valid UTF-16. It should still be
|
||||
// possible to match the valid characters at the front.
|
||||
//
|
||||
// UTF-16 surrogate characters are only valid in pairs. Including one on
|
||||
// the end by itself makes this invalid UTF-16.
|
||||
let surrogate_char: u16 = 0xDC00;
|
||||
let invalid_unicode =
|
||||
OsString::from_wide(&['a' as u16, 'b' as u16, 'c' as u16, surrogate_char]);
|
||||
assert!(
|
||||
invalid_unicode.to_str().is_none(),
|
||||
"This string is invalid Unicode, and conversion to &str should fail.",
|
||||
);
|
||||
assert!(windows_osstr_starts_with(&invalid_unicode, b"abc"));
|
||||
assert!(!windows_osstr_starts_with(&invalid_unicode, b"abcd"));
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
|
||||
impl OsStrExt3 for OsStr {
|
||||
fn from_bytes(b: &[u8]) -> &Self {
|
||||
use std::mem;
|
||||
unsafe { mem::transmute(b) }
|
||||
}
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
self.to_str().map(|s| s.as_bytes()).expect(INVALID_UTF8)
|
||||
}
|
||||
}
|
||||
|
||||
impl OsStrExt2 for OsStr {
|
||||
fn starts_with(&self, s: &[u8]) -> bool {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
// On Windows, the as_bytes() method will panic if the OsStr
|
||||
// contains invalid Unicode. To avoid this, we use a
|
||||
// Windows-specific starts-with function that doesn't rely on
|
||||
// as_bytes(). This is necessary for Windows command line
|
||||
// applications to handle non-Unicode arguments successfully. This
|
||||
// allows common cases like `clap.exe [invalid]` to succeed, though
|
||||
// cases that require string splitting will still fail, like
|
||||
// `clap.exe --arg=[invalid]`. Note that this entire module is
|
||||
// replaced in Clap 3.x, so this workaround is specific to the 2.x
|
||||
// branch.
|
||||
windows_osstr_starts_with(self, s)
|
||||
}
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
self.as_bytes().starts_with(s)
|
||||
}
|
||||
}
|
||||
|
||||
fn contains_byte(&self, byte: u8) -> bool {
|
||||
for b in self.as_bytes() {
|
||||
if b == &byte {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn split_at_byte(&self, byte: u8) -> (&OsStr, &OsStr) {
|
||||
for (i, b) in self.as_bytes().iter().enumerate() {
|
||||
if b == &byte {
|
||||
return (
|
||||
OsStr::from_bytes(&self.as_bytes()[..i]),
|
||||
OsStr::from_bytes(&self.as_bytes()[i + 1..]),
|
||||
);
|
||||
}
|
||||
}
|
||||
(
|
||||
&*self,
|
||||
OsStr::from_bytes(&self.as_bytes()[self.len()..self.len()]),
|
||||
)
|
||||
}
|
||||
|
||||
fn trim_left_matches(&self, byte: u8) -> &OsStr {
|
||||
let mut found = false;
|
||||
for (i, b) in self.as_bytes().iter().enumerate() {
|
||||
if b != &byte {
|
||||
return OsStr::from_bytes(&self.as_bytes()[i..]);
|
||||
} else {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if found {
|
||||
return OsStr::from_bytes(&self.as_bytes()[self.len()..]);
|
||||
}
|
||||
&*self
|
||||
}
|
||||
|
||||
fn split_at(&self, i: usize) -> (&OsStr, &OsStr) {
|
||||
(
|
||||
OsStr::from_bytes(&self.as_bytes()[..i]),
|
||||
OsStr::from_bytes(&self.as_bytes()[i..]),
|
||||
)
|
||||
}
|
||||
|
||||
fn split(&self, b: u8) -> OsSplit {
|
||||
OsSplit {
|
||||
sep: b,
|
||||
val: self.as_bytes(),
|
||||
pos: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OsSplit<'a> {
|
||||
sep: u8,
|
||||
val: &'a [u8],
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for OsSplit<'a> {
|
||||
type Item = &'a OsStr;
|
||||
|
||||
fn next(&mut self) -> Option<&'a OsStr> {
|
||||
debugln!("OsSplit::next: self={:?}", self);
|
||||
if self.pos == self.val.len() {
|
||||
return None;
|
||||
}
|
||||
let start = self.pos;
|
||||
for b in &self.val[start..] {
|
||||
self.pos += 1;
|
||||
if *b == self.sep {
|
||||
return Some(OsStr::from_bytes(&self.val[start..self.pos - 1]));
|
||||
}
|
||||
}
|
||||
Some(OsStr::from_bytes(&self.val[start..]))
|
||||
}
|
||||
}
|
||||
16
zeroidc/vendor/clap/src/strext.rs
vendored
Normal file
16
zeroidc/vendor/clap/src/strext.rs
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
pub trait _StrExt {
|
||||
fn _is_char_boundary(&self, index: usize) -> bool;
|
||||
}
|
||||
|
||||
impl _StrExt for str {
|
||||
#[inline]
|
||||
fn _is_char_boundary(&self, index: usize) -> bool {
|
||||
if index == self.len() {
|
||||
return true;
|
||||
}
|
||||
match self.as_bytes().get(index) {
|
||||
None => false,
|
||||
Some(&b) => !(128..192).contains(&b),
|
||||
}
|
||||
}
|
||||
}
|
||||
141
zeroidc/vendor/clap/src/suggestions.rs
vendored
Normal file
141
zeroidc/vendor/clap/src/suggestions.rs
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
// Internal
|
||||
use crate::{app::App, fmt::Format};
|
||||
|
||||
/// Produces a string from a given list of possible values which is similar to
|
||||
/// the passed in value `v` with a certain confidence.
|
||||
/// Thus in a list of possible values like ["foo", "bar"], the value "fop" will yield
|
||||
/// `Some("foo")`, whereas "blark" would yield `None`.
|
||||
#[cfg(feature = "suggestions")]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::needless_lifetimes))]
|
||||
pub fn did_you_mean<'a, T: ?Sized, I>(v: &str, possible_values: I) -> Option<&'a str>
|
||||
where
|
||||
T: AsRef<str> + 'a,
|
||||
I: IntoIterator<Item = &'a T>,
|
||||
{
|
||||
let mut candidate: Option<(f64, &str)> = None;
|
||||
for pv in possible_values {
|
||||
let confidence = strsim::jaro_winkler(v, pv.as_ref());
|
||||
if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
|
||||
{
|
||||
candidate = Some((confidence, pv.as_ref()));
|
||||
}
|
||||
}
|
||||
match candidate {
|
||||
None => None,
|
||||
Some((_, candidate)) => Some(candidate),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "suggestions"))]
|
||||
pub fn did_you_mean<'a, T: ?Sized, I>(_: &str, _: I) -> Option<&'a str>
|
||||
where
|
||||
T: AsRef<str> + 'a,
|
||||
I: IntoIterator<Item = &'a T>,
|
||||
{
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
|
||||
pub fn did_you_mean_flag_suffix<'z, T, I>(
|
||||
arg: &str,
|
||||
args_rest: &'z [&str],
|
||||
longs: I,
|
||||
subcommands: &'z [App],
|
||||
) -> (String, Option<&'z str>)
|
||||
where
|
||||
T: AsRef<str> + 'z,
|
||||
I: IntoIterator<Item = &'z T>,
|
||||
{
|
||||
if let Some(candidate) = did_you_mean(arg, longs) {
|
||||
let suffix = format!(
|
||||
"\n\tDid you mean {}{}?",
|
||||
Format::Good("--"),
|
||||
Format::Good(candidate)
|
||||
);
|
||||
return (suffix, Some(candidate));
|
||||
}
|
||||
|
||||
subcommands
|
||||
.iter()
|
||||
.filter_map(|subcommand| {
|
||||
let opts = subcommand
|
||||
.p
|
||||
.flags
|
||||
.iter()
|
||||
.filter_map(|f| f.s.long)
|
||||
.chain(subcommand.p.opts.iter().filter_map(|o| o.s.long));
|
||||
|
||||
let candidate = match did_you_mean(arg, opts) {
|
||||
Some(candidate) => candidate,
|
||||
None => return None,
|
||||
};
|
||||
let score = match args_rest.iter().position(|x| *x == subcommand.get_name()) {
|
||||
Some(score) => score,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let suffix = format!(
|
||||
"\n\tDid you mean to put '{}{}' after the subcommand '{}'?",
|
||||
Format::Good("--"),
|
||||
Format::Good(candidate),
|
||||
Format::Good(subcommand.get_name())
|
||||
);
|
||||
|
||||
Some((score, (suffix, Some(candidate))))
|
||||
})
|
||||
.min_by_key(|&(score, _)| score)
|
||||
.map(|(_, suggestion)| suggestion)
|
||||
.unwrap_or_else(|| (String::new(), None))
|
||||
}
|
||||
|
||||
/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
|
||||
pub fn did_you_mean_value_suffix<'z, T, I>(arg: &str, values: I) -> (String, Option<&'z str>)
|
||||
where
|
||||
T: AsRef<str> + 'z,
|
||||
I: IntoIterator<Item = &'z T>,
|
||||
{
|
||||
match did_you_mean(arg, values) {
|
||||
Some(candidate) => {
|
||||
let suffix = format!("\n\tDid you mean '{}'?", Format::Good(candidate));
|
||||
(suffix, Some(candidate))
|
||||
}
|
||||
None => (String::new(), None),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, features = "suggestions"))]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn possible_values_match() {
|
||||
let p_vals = ["test", "possible", "values"];
|
||||
assert_eq!(did_you_mean("tst", p_vals.iter()), Some("test"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn possible_values_nomatch() {
|
||||
let p_vals = ["test", "possible", "values"];
|
||||
assert!(did_you_mean("hahaahahah", p_vals.iter()).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn suffix_long() {
|
||||
let p_vals = ["test", "possible", "values"];
|
||||
let suffix = "\n\tDid you mean \'--test\'?";
|
||||
assert_eq!(
|
||||
did_you_mean_flag_suffix("tst", p_vals.iter(), []),
|
||||
(suffix, Some("test"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn suffix_enum() {
|
||||
let p_vals = ["test", "possible", "values"];
|
||||
let suffix = "\n\tDid you mean \'test\'?";
|
||||
assert_eq!(
|
||||
did_you_mean_value_suffix("tst", p_vals.iter()),
|
||||
(suffix, Some("test"))
|
||||
);
|
||||
}
|
||||
}
|
||||
1356
zeroidc/vendor/clap/src/usage_parser.rs
vendored
Normal file
1356
zeroidc/vendor/clap/src/usage_parser.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user