mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
Merge #1821
1821: Make debug output show names of args along with hashes r=pksunkara a=CreepySkeleton Co-authored-by: CreepySkeleton <creepy-skeleton@yandex.ru>
This commit is contained in:
commit
d210b9fced
16 changed files with 411 additions and 325 deletions
|
@ -24,13 +24,11 @@ use crate::output::fmt::ColorWhen;
|
|||
use crate::output::{Help, Usage};
|
||||
use crate::parse::errors::Result as ClapResult;
|
||||
use crate::parse::{ArgMatcher, ArgMatches, Input, Parser};
|
||||
use crate::util::{Key, HELP_HASH, VERSION_HASH};
|
||||
use crate::util::{Id, Key};
|
||||
use crate::INTERNAL_ERROR_MSG;
|
||||
|
||||
type Id = u64;
|
||||
|
||||
// FIXME (@CreepySkeleton): some of this variants are never constructed
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[allow(unused)]
|
||||
pub(crate) enum Propagation {
|
||||
To(Id),
|
||||
|
@ -195,9 +193,8 @@ impl<'b> App<'b> {
|
|||
/// ```
|
||||
pub fn new<S: Into<String>>(n: S) -> Self {
|
||||
let name = n.into();
|
||||
let id = name.key();
|
||||
App {
|
||||
id,
|
||||
id: Id::from(&*name),
|
||||
name,
|
||||
disp_ord: 999,
|
||||
..Default::default()
|
||||
|
@ -1060,10 +1057,11 @@ impl<'b> App<'b> {
|
|||
F: FnOnce(Arg<'b>) -> Arg<'b>,
|
||||
T: Key + Into<&'b str>,
|
||||
{
|
||||
let id = arg_id.key();
|
||||
let a = self.args.remove_by_name(id).unwrap_or_else(|| Arg {
|
||||
let arg_id: &str = arg_id.into();
|
||||
let id = Id::from(arg_id);
|
||||
let a = self.args.remove_by_name(&id).unwrap_or_else(|| Arg {
|
||||
id,
|
||||
name: arg_id.into(),
|
||||
name: arg_id,
|
||||
..Arg::default()
|
||||
});
|
||||
self.args.push(f(a));
|
||||
|
@ -1470,7 +1468,7 @@ impl<'b> App<'b> {
|
|||
.args
|
||||
.iter()
|
||||
.filter(|a| a.global)
|
||||
.map(|ga| ga.id)
|
||||
.map(|ga| ga.id.clone())
|
||||
.collect();
|
||||
|
||||
matcher.propagate_globals(&global_arg_vec);
|
||||
|
@ -1484,7 +1482,7 @@ impl<'b> App<'b> {
|
|||
debugln!("App::_build;");
|
||||
|
||||
#[cfg(all(feature = "color", windows))]
|
||||
ansi_term::enable_ansi_support();
|
||||
let _ = ansi_term::enable_ansi_support();
|
||||
|
||||
// Make sure all the globally set flags apply to us as well
|
||||
self.settings = self.settings | self.g_settings;
|
||||
|
@ -1496,15 +1494,15 @@ impl<'b> App<'b> {
|
|||
for a in self.args.args.iter_mut() {
|
||||
// Fill in the groups
|
||||
if let Some(ref grps) = a.groups {
|
||||
for &g in grps {
|
||||
for g in grps {
|
||||
let mut found = false;
|
||||
if let Some(ag) = self.groups.iter_mut().find(|grp| grp.id == g) {
|
||||
ag.args.push(a.id);
|
||||
if let Some(ag) = self.groups.iter_mut().find(|grp| grp.id == *g) {
|
||||
ag.args.push(a.id.clone());
|
||||
found = true;
|
||||
}
|
||||
if !found {
|
||||
let mut ag = ArgGroup::_with_id(g);
|
||||
ag.args.push(a.id);
|
||||
let mut ag = ArgGroup::_with_id(g.clone());
|
||||
ag.args.push(a.id.clone());
|
||||
self.groups.push(ag);
|
||||
}
|
||||
}
|
||||
|
@ -1732,7 +1730,7 @@ impl<'b> App<'b> {
|
|||
for sc in &mut self.subcommands {
|
||||
propagate_subcmd!(self, sc);
|
||||
if prop == Propagation::Full {
|
||||
sc._propagate(prop);
|
||||
sc._propagate(prop.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1754,7 +1752,7 @@ impl<'b> App<'b> {
|
|||
.args
|
||||
.args
|
||||
.iter()
|
||||
.any(|x| x.long == Some("help") || x.id == HELP_HASH))
|
||||
.any(|x| x.long == Some("help") || x.id == Id::help_hash()))
|
||||
{
|
||||
debugln!("App::_create_help_and_version: Building --help");
|
||||
let mut help = Arg::with_name("help")
|
||||
|
@ -1770,7 +1768,7 @@ impl<'b> App<'b> {
|
|||
.args
|
||||
.args
|
||||
.iter()
|
||||
.any(|x| x.long == Some("version") || x.id == VERSION_HASH)
|
||||
.any(|x| x.long == Some("version") || x.id == Id::version_hash())
|
||||
|| self.is_set(AppSettings::DisableVersion))
|
||||
{
|
||||
debugln!("App::_create_help_and_version: Building --version");
|
||||
|
@ -1785,7 +1783,7 @@ impl<'b> App<'b> {
|
|||
}
|
||||
if self.has_subcommands()
|
||||
&& !self.is_set(AppSettings::DisableHelpSubcommand)
|
||||
&& !self.subcommands.iter().any(|s| s.id == HELP_HASH)
|
||||
&& !self.subcommands.iter().any(|s| s.id == Id::help_hash())
|
||||
{
|
||||
debugln!("App::_create_help_and_version: Building help");
|
||||
self.subcommands.push(
|
||||
|
@ -1874,11 +1872,11 @@ impl<'b> App<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn format_group(&self, g: Id) -> String {
|
||||
pub(crate) fn format_group(&self, g: &Id) -> String {
|
||||
let g_string = self
|
||||
.unroll_args_in_group(g)
|
||||
.iter()
|
||||
.filter_map(|&x| self.find(x))
|
||||
.filter_map(|x| self.find(x))
|
||||
.map(|x| {
|
||||
if x.index.is_some() {
|
||||
x.name.to_owned()
|
||||
|
@ -1894,8 +1892,8 @@ impl<'b> App<'b> {
|
|||
|
||||
// Internal Query Methods
|
||||
impl<'b> App<'b> {
|
||||
pub(crate) fn find(&self, arg_id: Id) -> Option<&Arg<'b>> {
|
||||
self.args.args.iter().find(|a| a.id == arg_id)
|
||||
pub(crate) fn find(&self, arg_id: &Id) -> Option<&Arg<'b>> {
|
||||
self.args.args.iter().find(|a| a.id == *arg_id)
|
||||
}
|
||||
|
||||
// Should we color the output? None=determined by output location, true=yes, false=no
|
||||
|
@ -1949,22 +1947,22 @@ impl<'b> App<'b> {
|
|||
.any(|sc| !sc.is_set(AppSettings::Hidden))
|
||||
}
|
||||
|
||||
pub(crate) fn unroll_args_in_group(&self, group: Id) -> Vec<Id> {
|
||||
pub(crate) fn unroll_args_in_group(&self, group: &Id) -> Vec<Id> {
|
||||
let mut g_vec = vec![group];
|
||||
let mut args = vec![];
|
||||
|
||||
while let Some(ref g) = g_vec.pop() {
|
||||
for &n in self
|
||||
for n in self
|
||||
.groups
|
||||
.iter()
|
||||
.find(|grp| &grp.id == g)
|
||||
.find(|grp| grp.id == **g)
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.args
|
||||
.iter()
|
||||
{
|
||||
if !args.contains(&n) {
|
||||
if !args.contains(n) {
|
||||
if self.find(n).is_some() {
|
||||
args.push(n)
|
||||
args.push(n.clone())
|
||||
} else {
|
||||
g_vec.push(n);
|
||||
}
|
||||
|
@ -1975,20 +1973,20 @@ impl<'b> App<'b> {
|
|||
args
|
||||
}
|
||||
|
||||
pub(crate) fn unroll_requirements_for_arg(&self, arg: Id, matcher: &ArgMatcher) -> Vec<Id> {
|
||||
let requires_if_or_not = |&(val, req_arg)| {
|
||||
pub(crate) fn unroll_requirements_for_arg(&self, arg: &Id, matcher: &ArgMatcher) -> Vec<Id> {
|
||||
let requires_if_or_not = |(val, req_arg): &(Option<&str>, Id)| -> Option<Id> {
|
||||
if let Some(v) = val {
|
||||
if matcher
|
||||
.get(arg)
|
||||
.map(|ma| ma.contains_val(v))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Some(req_arg)
|
||||
Some(req_arg.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
Some(req_arg)
|
||||
Some(req_arg.clone())
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2006,9 +2004,9 @@ impl<'b> App<'b> {
|
|||
if let Some(arg) = self.find(a) {
|
||||
if let Some(ref reqs) = arg.requires {
|
||||
for r in reqs.iter().filter_map(requires_if_or_not) {
|
||||
if let Some(req) = self.find(r) {
|
||||
if let Some(req) = self.find(&r) {
|
||||
if req.requires.is_some() {
|
||||
r_vec.push(req.id)
|
||||
r_vec.push(&req.id)
|
||||
}
|
||||
}
|
||||
args.push(r);
|
||||
|
|
|
@ -20,16 +20,14 @@ use crate::util::VecMap;
|
|||
|
||||
// Internal
|
||||
use crate::build::{arg::settings::ArgFlags, usage_parser::UsageParser};
|
||||
use crate::util::Key;
|
||||
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
|
||||
use crate::util::OsStrExt3;
|
||||
use crate::util::{Id, Key};
|
||||
use crate::INTERNAL_ERROR_MSG;
|
||||
|
||||
type Validator = Rc<dyn Fn(String) -> Result<(), String>>;
|
||||
type ValidatorOs = Rc<dyn Fn(&OsStr) -> Result<(), String>>;
|
||||
|
||||
type Id = u64;
|
||||
|
||||
/// The abstract representation of a command line argument. Used to set all the options and
|
||||
/// relationships that define a valid argument for the program.
|
||||
///
|
||||
|
@ -129,9 +127,9 @@ impl<'help> Arg<'help> {
|
|||
|
||||
impl<'help> Arg<'help> {
|
||||
/// @TODO @p2 @docs @v3-beta1: Write Docs
|
||||
pub fn new<T: Key>(t: T) -> Self {
|
||||
pub fn new<T: Key + ToString>(t: T) -> Self {
|
||||
Arg {
|
||||
id: t.key(),
|
||||
id: t.into(),
|
||||
disp_ord: 999,
|
||||
unified_ord: 999,
|
||||
..Default::default()
|
||||
|
@ -157,7 +155,7 @@ impl<'help> Arg<'help> {
|
|||
/// [`Arg`]: ./struct.Arg.html
|
||||
pub fn with_name(n: &'help str) -> Self {
|
||||
Arg {
|
||||
id: n.key(),
|
||||
id: n.into(),
|
||||
name: n,
|
||||
disp_ord: 999,
|
||||
unified_ord: 999,
|
||||
|
@ -626,11 +624,11 @@ impl<'help> Arg<'help> {
|
|||
/// [`Arg::required`]: ./struct.Arg.html#method.required
|
||||
/// [`Arg::required_unless(name)`]: ./struct.Arg.html#method.required_unless
|
||||
pub fn required_unless<T: Key>(mut self, arg_id: T) -> Self {
|
||||
let name = arg_id.key();
|
||||
let id = arg_id.into();
|
||||
if let Some(ref mut vec) = self.r_unless {
|
||||
vec.push(name);
|
||||
vec.push(id);
|
||||
} else {
|
||||
self.r_unless = Some(vec![name]);
|
||||
self.r_unless = Some(vec![id]);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -701,10 +699,10 @@ impl<'help> Arg<'help> {
|
|||
pub fn required_unless_all(mut self, names: &[&str]) -> Self {
|
||||
if let Some(ref mut vec) = self.r_unless {
|
||||
for s in names {
|
||||
vec.push(s.key());
|
||||
vec.push(s.into());
|
||||
}
|
||||
} else {
|
||||
self.r_unless = Some(names.iter().map(Key::key).collect());
|
||||
self.r_unless = Some(names.iter().map(Into::into).collect());
|
||||
}
|
||||
self.setting(ArgSettings::RequiredUnlessAll)
|
||||
}
|
||||
|
@ -776,10 +774,10 @@ impl<'help> Arg<'help> {
|
|||
pub fn required_unless_one(mut self, names: &[&str]) -> Self {
|
||||
if let Some(ref mut vec) = self.r_unless {
|
||||
for s in names {
|
||||
vec.push(s.key());
|
||||
vec.push(s.into());
|
||||
}
|
||||
} else {
|
||||
self.r_unless = Some(names.iter().map(Key::key).collect());
|
||||
self.r_unless = Some(names.iter().map(Into::into).collect());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -830,7 +828,7 @@ impl<'help> Arg<'help> {
|
|||
/// [`Arg::exclusive(true)`]: ./struct.Arg.html#method.exclusive
|
||||
|
||||
pub fn conflicts_with<T: Key>(mut self, arg_id: T) -> Self {
|
||||
let name = arg_id.key();
|
||||
let name = arg_id.into();
|
||||
if let Some(ref mut vec) = self.blacklist {
|
||||
vec.push(name);
|
||||
} else {
|
||||
|
@ -887,10 +885,10 @@ impl<'help> Arg<'help> {
|
|||
pub fn conflicts_with_all(mut self, names: &[&str]) -> Self {
|
||||
if let Some(ref mut vec) = self.blacklist {
|
||||
for s in names {
|
||||
vec.push(s.key());
|
||||
vec.push(s.into());
|
||||
}
|
||||
} else {
|
||||
self.blacklist = Some(names.iter().map(Key::key).collect());
|
||||
self.blacklist = Some(names.iter().map(Into::into).collect());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -1041,7 +1039,7 @@ impl<'help> Arg<'help> {
|
|||
/// [`Multiple*`]: ./enum.ArgSettings.html#variant.MultipleValues
|
||||
/// [`UseValueDelimiter`]: ./enum.ArgSettings.html#variant.UseValueDelimiter
|
||||
pub fn overrides_with<T: Key>(mut self, arg_id: T) -> Self {
|
||||
let name = arg_id.key();
|
||||
let name = arg_id.into();
|
||||
if let Some(ref mut vec) = self.overrides {
|
||||
vec.push(name);
|
||||
} else {
|
||||
|
@ -1080,10 +1078,10 @@ impl<'help> Arg<'help> {
|
|||
pub fn overrides_with_all<T: Key>(mut self, names: &[T]) -> Self {
|
||||
if let Some(ref mut vec) = self.overrides {
|
||||
for s in names {
|
||||
vec.push(s.key());
|
||||
vec.push(s.into());
|
||||
}
|
||||
} else {
|
||||
self.overrides = Some(names.iter().map(Key::key).collect());
|
||||
self.overrides = Some(names.iter().map(Into::into).collect());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -1144,7 +1142,7 @@ impl<'help> Arg<'help> {
|
|||
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
|
||||
/// [override]: ./struct.Arg.html#method.overrides_with
|
||||
pub fn requires<T: Key>(mut self, arg_id: T) -> Self {
|
||||
let arg = arg_id.key();
|
||||
let arg = arg_id.into();
|
||||
if let Some(ref mut vec) = self.requires {
|
||||
vec.push((None, arg));
|
||||
} else {
|
||||
|
@ -1213,7 +1211,7 @@ impl<'help> Arg<'help> {
|
|||
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
|
||||
/// [override]: ./struct.Arg.html#method.overrides_with
|
||||
pub fn requires_if<T: Key>(mut self, val: &'help str, arg_id: T) -> Self {
|
||||
let arg = arg_id.key();
|
||||
let arg = arg_id.into();
|
||||
if let Some(ref mut vec) = self.requires {
|
||||
vec.push((Some(val), arg));
|
||||
} else {
|
||||
|
@ -1276,12 +1274,12 @@ impl<'help> Arg<'help> {
|
|||
pub fn requires_ifs<T: Key>(mut self, ifs: &[(&'help str, T)]) -> Self {
|
||||
if let Some(ref mut vec) = self.requires {
|
||||
for (val, arg) in ifs {
|
||||
vec.push((Some(val), arg.key()));
|
||||
vec.push((Some(val), arg.into()));
|
||||
}
|
||||
} else {
|
||||
let mut vec = vec![];
|
||||
for (val, arg) in ifs {
|
||||
vec.push((Some(*val), arg.key()));
|
||||
vec.push((Some(*val), arg.into()));
|
||||
}
|
||||
self.requires = Some(vec);
|
||||
}
|
||||
|
@ -1352,7 +1350,7 @@ impl<'help> Arg<'help> {
|
|||
/// [Conflicting]: ./struct.Arg.html#method.conflicts_with
|
||||
/// [required]: ./struct.Arg.html#method.required
|
||||
pub fn required_if<T: Key>(mut self, arg_id: T, val: &'help str) -> Self {
|
||||
let arg = arg_id.key();
|
||||
let arg = arg_id.into();
|
||||
if let Some(ref mut vec) = self.r_ifs {
|
||||
vec.push((arg, val));
|
||||
} else {
|
||||
|
@ -1443,13 +1441,13 @@ impl<'help> Arg<'help> {
|
|||
/// [required]: ./struct.Arg.html#method.required
|
||||
pub fn required_ifs<T: Key>(mut self, ifs: &[(T, &'help str)]) -> Self {
|
||||
if let Some(ref mut vec) = self.r_ifs {
|
||||
for r_if in ifs {
|
||||
vec.push((r_if.0.key(), r_if.1));
|
||||
for (id, val) in ifs {
|
||||
vec.push((Id::from_ref(id), *val));
|
||||
}
|
||||
} else {
|
||||
let mut vec = vec![];
|
||||
for r_if in ifs {
|
||||
vec.push((r_if.0.key(), r_if.1));
|
||||
for (id, val) in ifs {
|
||||
vec.push((Id::from_ref(id), *val));
|
||||
}
|
||||
self.r_ifs = Some(vec);
|
||||
}
|
||||
|
@ -1521,10 +1519,10 @@ impl<'help> Arg<'help> {
|
|||
pub fn requires_all<T: Key>(mut self, names: &[T]) -> Self {
|
||||
if let Some(ref mut vec) = self.requires {
|
||||
for s in names {
|
||||
vec.push((None, s.key()));
|
||||
vec.push((None, s.into()));
|
||||
}
|
||||
} else {
|
||||
self.requires = Some(names.iter().map(|s| (None, s.key())).collect());
|
||||
self.requires = Some(names.iter().map(|s| (None, s.into())).collect());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -1785,7 +1783,7 @@ impl<'help> Arg<'help> {
|
|||
/// ```
|
||||
/// [`ArgGroup`]: ./struct.ArgGroup.html
|
||||
pub fn group<T: Key>(mut self, group_id: T) -> Self {
|
||||
let name = group_id.key();
|
||||
let name = group_id.into();
|
||||
if let Some(ref mut vec) = self.groups {
|
||||
vec.push(name);
|
||||
} else {
|
||||
|
@ -1828,10 +1826,10 @@ impl<'help> Arg<'help> {
|
|||
pub fn groups<T: Key>(mut self, group_ids: &[T]) -> Self {
|
||||
if let Some(ref mut vec) = self.groups {
|
||||
for s in group_ids {
|
||||
vec.push(s.key());
|
||||
vec.push(s.into());
|
||||
}
|
||||
} else {
|
||||
self.groups = Some(group_ids.iter().map(Key::key).collect());
|
||||
self.groups = Some(group_ids.iter().map(Into::into).collect());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -2477,7 +2475,7 @@ impl<'help> Arg<'help> {
|
|||
val: Option<&'help OsStr>,
|
||||
default: &'help OsStr,
|
||||
) -> Self {
|
||||
let arg = arg_id.key();
|
||||
let arg = arg_id.into();
|
||||
self.setb(ArgSettings::TakesValue);
|
||||
if let Some(ref mut vm) = self.default_vals_ifs {
|
||||
let l = vm.len();
|
||||
|
@ -4164,7 +4162,7 @@ impl<'a> Arg<'a> {
|
|||
// Self conflict
|
||||
if let Some(vec) = &self.blacklist {
|
||||
assert!(
|
||||
!vec.iter().any(|&x| x == self.id),
|
||||
!vec.iter().any(|x| *x == self.id),
|
||||
"Argument '{}' cannot conflict with itself",
|
||||
self.name,
|
||||
);
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// Std
|
||||
|
||||
use std::fmt::{Debug, Formatter, Result};
|
||||
|
||||
// Internal
|
||||
use crate::util::Key;
|
||||
|
||||
type Id = u64;
|
||||
use crate::util::{Id, Key};
|
||||
|
||||
/// `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
|
||||
|
@ -96,7 +95,7 @@ impl<'a> ArgGroup<'a> {
|
|||
}
|
||||
/// @TODO @p2 @docs @v3-beta1: Write Docs
|
||||
pub fn new<T: Key>(id: T) -> Self {
|
||||
ArgGroup::_with_id(id.key())
|
||||
ArgGroup::_with_id(id.into())
|
||||
}
|
||||
/// 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.
|
||||
|
@ -110,7 +109,7 @@ impl<'a> ArgGroup<'a> {
|
|||
/// ```
|
||||
pub fn with_name(n: &'a str) -> Self {
|
||||
ArgGroup {
|
||||
id: n.key(),
|
||||
id: n.into(),
|
||||
name: n,
|
||||
..ArgGroup::default()
|
||||
}
|
||||
|
@ -152,7 +151,7 @@ impl<'a> ArgGroup<'a> {
|
|||
/// ```
|
||||
/// [argument]: ./struct.Arg.html
|
||||
pub fn arg<T: Key>(mut self, arg_id: T) -> Self {
|
||||
self.args.push(arg_id.key());
|
||||
self.args.push(arg_id.into());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -298,7 +297,7 @@ impl<'a> ArgGroup<'a> {
|
|||
/// [required group]: ./struct.ArgGroup.html#method.required
|
||||
/// [argument requirement rules]: ./struct.Arg.html#method.requires
|
||||
pub fn requires<T: Key>(mut self, id: T) -> Self {
|
||||
let arg_id = id.key();
|
||||
let arg_id = id.into();
|
||||
if let Some(ref mut reqs) = self.requires {
|
||||
reqs.push(arg_id);
|
||||
} else {
|
||||
|
@ -374,7 +373,7 @@ impl<'a> ArgGroup<'a> {
|
|||
/// ```
|
||||
/// [argument exclusion rules]: ./struct.Arg.html#method.conflicts_with
|
||||
pub fn conflicts_with<T: Key>(mut self, id: T) -> Self {
|
||||
let arg_id = id.key();
|
||||
let arg_id = id.into();
|
||||
if let Some(ref mut confs) = self.conflicts {
|
||||
confs.push(arg_id);
|
||||
} else {
|
||||
|
@ -440,7 +439,7 @@ impl<'a> Debug for ArgGroup<'a> {
|
|||
impl<'a, 'z> From<&'z ArgGroup<'a>> for ArgGroup<'a> {
|
||||
fn from(g: &'z ArgGroup<'a>) -> Self {
|
||||
ArgGroup {
|
||||
id: g.id,
|
||||
id: g.id.clone(),
|
||||
name: g.name,
|
||||
required: g.required,
|
||||
args: g.args.clone(),
|
||||
|
@ -503,8 +502,7 @@ impl<'a> From<&'a yaml_rust::yaml::Hash> for ArgGroup<'a> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::ArgGroup;
|
||||
use super::Key;
|
||||
use super::{ArgGroup, Id};
|
||||
#[cfg(feature = "yaml")]
|
||||
use yaml_rust::YamlLoader;
|
||||
|
||||
|
@ -522,9 +520,9 @@ mod test {
|
|||
.requires_all(&["r2", "r3"])
|
||||
.requires("r4");
|
||||
|
||||
let args = vec!["a1".key(), "a4".key(), "a2".key(), "a3".key()];
|
||||
let reqs = vec!["r1".key(), "r2".key(), "r3".key(), "r4".key()];
|
||||
let confs = vec!["c1".key(), "c2".key(), "c3".key(), "c4".key()];
|
||||
let args = vec!["a1".into(), "a4".into(), "a2".into(), "a3".into()];
|
||||
let reqs = vec!["r1".into(), "r2".into(), "r3".into(), "r4".into()];
|
||||
let confs = vec!["c1".into(), "c2".into(), "c3".into(), "c4".into()];
|
||||
|
||||
assert_eq!(g.args, args);
|
||||
assert_eq!(g.requires, Some(reqs));
|
||||
|
@ -545,9 +543,24 @@ mod test {
|
|||
.requires_all(&["r2", "r3"])
|
||||
.requires("r4");
|
||||
|
||||
let args = vec!["a1".key(), "a4".key(), "a2".key(), "a3".key()];
|
||||
let reqs = vec!["r1".key(), "r2".key(), "r3".key(), "r4".key()];
|
||||
let confs = vec!["c1".key(), "c2".key(), "c3".key(), "c4".key()];
|
||||
let args = vec![
|
||||
Id::from("a1"),
|
||||
Id::from("a4"),
|
||||
Id::from("a2"),
|
||||
Id::from("a3"),
|
||||
];
|
||||
let reqs = vec![
|
||||
Id::from("r1"),
|
||||
Id::from("r2"),
|
||||
Id::from("r3"),
|
||||
Id::from("r4"),
|
||||
];
|
||||
let confs = vec![
|
||||
Id::from("c1"),
|
||||
Id::from("c2"),
|
||||
Id::from("c3"),
|
||||
Id::from("c4"),
|
||||
];
|
||||
|
||||
let debug_str = format!(
|
||||
"{{\n\
|
||||
|
@ -579,9 +592,9 @@ mod test {
|
|||
.requires_all(&["r2", "r3"])
|
||||
.requires("r4");
|
||||
|
||||
let args = vec!["a1".key(), "a4".key(), "a2".key(), "a3".key()];
|
||||
let reqs = vec!["r1".key(), "r2".key(), "r3".key(), "r4".key()];
|
||||
let confs = vec!["c1".key(), "c2".key(), "c3".key(), "c4".key()];
|
||||
let args = vec!["a1".into(), "a4".into(), "a2".into(), "a3".into()];
|
||||
let reqs = vec!["r1".into(), "r2".into(), "r3".into(), "r4".into()];
|
||||
let confs = vec!["c1".into(), "c2".into(), "c3".into(), "c4".into()];
|
||||
|
||||
let g2 = ArgGroup::from(&g);
|
||||
assert_eq!(g2.args, args);
|
||||
|
@ -610,9 +623,9 @@ requires:
|
|||
- 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".key(), "a4".key(), "a2".key(), "a3".key()];
|
||||
let reqs = vec!["r1".key(), "r2".key(), "r3".key(), "r4".key()];
|
||||
let confs = vec!["c1".key(), "c2".key(), "c3".key(), "c4".key()];
|
||||
let args = vec!["a1".into(), "a4".into(), "a2".into(), "a3".into()];
|
||||
let reqs = vec!["r1".into(), "r2".into(), "r3".into(), "r4".into()];
|
||||
let confs = vec!["c1".into(), "c2".into(), "c3".into(), "c4".into()];
|
||||
assert_eq!(g.args, args);
|
||||
assert_eq!(g.requires, Some(reqs));
|
||||
assert_eq!(g.conflicts, Some(confs));
|
||||
|
@ -622,7 +635,7 @@ requires:
|
|||
impl<'a> Clone for ArgGroup<'a> {
|
||||
fn clone(&self) -> Self {
|
||||
ArgGroup {
|
||||
id: self.id,
|
||||
id: self.id.clone(),
|
||||
name: self.name,
|
||||
required: self.required,
|
||||
args: self.args.clone(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Internal
|
||||
use crate::build::{Arg, ArgSettings};
|
||||
use crate::util::{Key, VecMap};
|
||||
use crate::util::VecMap;
|
||||
use crate::INTERNAL_ERROR_MSG;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
|
@ -90,7 +90,7 @@ impl<'a> UsageParser<'a> {
|
|||
let name = &self.usage[self.start..self.pos];
|
||||
if self.prev == UsageToken::Unknown {
|
||||
debugln!("UsageParser::name: setting name...{}", name);
|
||||
arg.id = name.key();
|
||||
arg.id = name.into();
|
||||
arg.name = name;
|
||||
if arg.long.is_none() && arg.short.is_none() {
|
||||
debugln!("UsageParser::name: explicit name set...");
|
||||
|
@ -147,7 +147,7 @@ impl<'a> UsageParser<'a> {
|
|||
let name = &self.usage[self.start..self.pos];
|
||||
if !self.explicit_name_set {
|
||||
debugln!("UsageParser::long: setting name...{}", name);
|
||||
arg.id = name.key();
|
||||
arg.id = name.into();
|
||||
arg.name = name;
|
||||
}
|
||||
debugln!("UsageParser::long: setting long...{}", name);
|
||||
|
@ -165,7 +165,7 @@ impl<'a> UsageParser<'a> {
|
|||
// --long takes precedence but doesn't set self.explicit_name_set
|
||||
let name = &start[..short.len_utf8()];
|
||||
debugln!("UsageParser::short: setting name...{}", name);
|
||||
arg.id = name.key();
|
||||
arg.id = name.into();
|
||||
arg.name = name;
|
||||
}
|
||||
self.prev = UsageToken::Short;
|
||||
|
|
|
@ -805,11 +805,11 @@ macro_rules! positionals {
|
|||
|
||||
macro_rules! groups_for_arg {
|
||||
($app:expr, $grp:expr) => {{
|
||||
debugln!("Parser::groups_for_arg: name={}", $grp);
|
||||
debugln!("Parser::groups_for_arg: name={:?}", $grp);
|
||||
$app.groups
|
||||
.iter()
|
||||
.filter(|grp| grp.args.iter().any(|&a| a == $grp))
|
||||
.map(|grp| grp.id)
|
||||
.filter(|grp| grp.args.iter().any(|a| *a == $grp))
|
||||
.map(|grp| grp.id.clone())
|
||||
}};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use crate::build::Arg;
|
||||
use crate::util::Id;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
|
||||
type Id = u64;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub(crate) struct Key {
|
||||
pub(crate) key: KeyType,
|
||||
|
@ -112,14 +111,14 @@ impl<'b> MKeyMap<'b> {
|
|||
//? probably shouldn't add a possibility for removal?
|
||||
//? or remove by replacement by some dummy object, so the order is preserved
|
||||
|
||||
pub(crate) fn remove_by_name(&mut self, _name: Id) -> Option<Arg<'b>> {
|
||||
pub(crate) fn remove_by_name(&mut self, name: &Id) -> Option<Arg<'b>> {
|
||||
if self.built {
|
||||
panic!("Cannot remove args after being built");
|
||||
}
|
||||
|
||||
self.args
|
||||
.iter()
|
||||
.position(|arg| arg.id == _name)
|
||||
.position(|arg| arg.id == *name)
|
||||
.map(|i| self.args.swap_remove(i))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// std
|
||||
use crate::util::Id;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
|
||||
// Internal
|
||||
|
@ -7,8 +8,6 @@ use crate::build::{Arg, ArgSettings};
|
|||
use crate::parse::{ArgMatcher, Parser};
|
||||
use crate::INTERNAL_ERROR_MSG;
|
||||
|
||||
type Id = u64;
|
||||
|
||||
pub(crate) struct Usage<'b, 'c, 'z>
|
||||
where
|
||||
'b: 'c,
|
||||
|
@ -187,7 +186,7 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
|
|||
{
|
||||
debugln!("usage::get_args_tag:iter:{}:", pos.name);
|
||||
for grp_s in groups_for_arg!(self.p.app, pos.id) {
|
||||
debugln!("usage::get_args_tag:iter:{}:iter:{};", pos.name, grp_s);
|
||||
debugln!("usage::get_args_tag:iter:{:?}:iter:{:?};", pos.name, grp_s);
|
||||
// if it's part of a required group we don't want to count it
|
||||
if self
|
||||
.p
|
||||
|
@ -283,7 +282,7 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
|
|||
}
|
||||
}
|
||||
for grp_s in groups_for_arg!(self.p.app, f.id) {
|
||||
debugln!("usage::needs_flags_tag:iter:iter: grp_s={};", grp_s);
|
||||
debugln!("usage::needs_flags_tag:iter:iter: grp_s={:?};", grp_s);
|
||||
if self
|
||||
.p
|
||||
.app
|
||||
|
@ -326,13 +325,13 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
|
|||
|
||||
let mut unrolled_reqs = vec![];
|
||||
|
||||
for &a in self.p.required.iter() {
|
||||
for a in self.p.required.iter() {
|
||||
if let Some(ref m) = matcher {
|
||||
for aa in self.p.app.unroll_requirements_for_arg(a, m) {
|
||||
unrolled_reqs.push(aa);
|
||||
}
|
||||
} else {
|
||||
unrolled_reqs.push(a);
|
||||
unrolled_reqs.push(a.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,8 +340,8 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
|
|||
.app
|
||||
.groups
|
||||
.iter()
|
||||
.filter(|gn| self.p.required.contains(gn.id))
|
||||
.flat_map(|g| self.p.app.unroll_args_in_group(g.id))
|
||||
.filter(|gn| self.p.required.contains(&gn.id))
|
||||
.flat_map(|g| self.p.app.unroll_args_in_group(&g.id))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let pmap = if let Some(m) = matcher {
|
||||
|
@ -350,8 +349,8 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
|
|||
.iter()
|
||||
.chain(incls.iter())
|
||||
.filter(|a| positionals!(self.p.app).any(|p| &&p.id == a))
|
||||
.filter(|&&pos| !m.contains(pos))
|
||||
.filter_map(|&pos| self.p.app.find(pos))
|
||||
.filter(|&pos| !m.contains(pos))
|
||||
.filter_map(|pos| self.p.app.find(pos))
|
||||
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
||||
.filter(|pos| !args_in_groups.contains(&pos.id))
|
||||
.map(|pos| (pos.index.unwrap(), pos))
|
||||
|
@ -361,38 +360,37 @@ impl<'b, 'c, 'z> Usage<'b, 'c, 'z> {
|
|||
.iter()
|
||||
.chain(incls.iter())
|
||||
.filter(|a| positionals!(self.p.app).any(|p| &&p.id == a))
|
||||
.filter_map(|&pos| self.p.app.find(pos))
|
||||
.filter_map(|pos| self.p.app.find(pos))
|
||||
.filter(|&pos| incl_last || !pos.is_set(ArgSettings::Last))
|
||||
.filter(|pos| !args_in_groups.contains(&pos.id))
|
||||
.map(|pos| (pos.index.unwrap(), pos))
|
||||
.collect::<BTreeMap<u64, &Arg>>() // sort by index
|
||||
};
|
||||
for &p in pmap.values() {
|
||||
debugln!("Usage::get_required_usage_from:iter:{}", p.id);
|
||||
let s = p.id;
|
||||
if args_in_groups.is_empty() || !args_in_groups.contains(&s) {
|
||||
for p in pmap.values() {
|
||||
debugln!("Usage::get_required_usage_from:iter:{:?}", p.id);
|
||||
if args_in_groups.is_empty() || !args_in_groups.contains(&p.id) {
|
||||
ret_val.push_back(p.to_string());
|
||||
}
|
||||
}
|
||||
for &a in unrolled_reqs
|
||||
for a in unrolled_reqs
|
||||
.iter()
|
||||
.chain(incls.iter())
|
||||
.filter(|name| !positionals!(self.p.app).any(|p| &&p.id == name))
|
||||
.filter(|name| !self.p.app.groups.iter().any(|g| &&g.id == name))
|
||||
.filter(|name| !args_in_groups.contains(name))
|
||||
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(**name)))
|
||||
.filter(|name| !(matcher.is_some() && matcher.as_ref().unwrap().contains(name)))
|
||||
{
|
||||
debugln!("Usage::get_required_usage_from:iter:{}:", a);
|
||||
debugln!("Usage::get_required_usage_from:iter:{:?}:", a);
|
||||
let arg = self
|
||||
.p
|
||||
.app
|
||||
.find(a)
|
||||
.find(&a)
|
||||
.map(ToString::to_string)
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
ret_val.push_back(arg);
|
||||
}
|
||||
let mut g_vec: Vec<String> = vec![];
|
||||
for &g in unrolled_reqs
|
||||
for g in unrolled_reqs
|
||||
.iter()
|
||||
.filter(|n| self.p.app.groups.iter().any(|g| g.id == **n))
|
||||
{
|
||||
|
|
|
@ -7,8 +7,7 @@ use std::ops::Deref;
|
|||
// Internal
|
||||
use crate::build::{Arg, ArgSettings};
|
||||
use crate::parse::{ArgMatches, MatchedArg, SubCommand};
|
||||
|
||||
type Id = u64;
|
||||
use crate::util::Id;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ArgMatcher(pub(crate) ArgMatches);
|
||||
|
@ -45,7 +44,7 @@ impl ArgMatcher {
|
|||
global_arg_vec: &[Id],
|
||||
vals_map: &mut HashMap<Id, MatchedArg>,
|
||||
) {
|
||||
for &global_arg in global_arg_vec {
|
||||
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.
|
||||
|
@ -53,7 +52,7 @@ impl ArgMatcher {
|
|||
// 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) {
|
||||
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 {
|
||||
|
@ -62,7 +61,7 @@ impl ArgMatcher {
|
|||
} else {
|
||||
ma.clone()
|
||||
};
|
||||
vals_map.insert(global_arg, to_update);
|
||||
vals_map.insert(global_arg.clone(), to_update);
|
||||
}
|
||||
}
|
||||
if let Some(ref mut sc) = self.0.subcommand {
|
||||
|
@ -71,21 +70,21 @@ impl ArgMatcher {
|
|||
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());
|
||||
for (name, matched_arg) in vals_map.iter_mut() {
|
||||
self.0.args.insert(name.clone(), matched_arg.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, arg: Id) -> Option<&mut MatchedArg> {
|
||||
self.0.args.get_mut(&arg)
|
||||
pub fn get_mut(&mut self, arg: &Id) -> Option<&mut MatchedArg> {
|
||||
self.0.args.get_mut(arg)
|
||||
}
|
||||
|
||||
pub fn get(&self, arg: Id) -> Option<&MatchedArg> {
|
||||
self.0.args.get(&arg)
|
||||
pub fn get(&self, arg: &Id) -> Option<&MatchedArg> {
|
||||
self.0.args.get(arg)
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, arg: Id) {
|
||||
self.0.args.swap_remove(&arg);
|
||||
pub fn remove(&mut self, arg: &Id) {
|
||||
self.0.args.swap_remove(arg);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -95,12 +94,12 @@ impl ArgMatcher {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, name: Id) {
|
||||
self.0.args.insert(name, MatchedArg::new());
|
||||
pub fn insert(&mut self, name: &Id) {
|
||||
self.0.args.insert(name.clone(), MatchedArg::new());
|
||||
}
|
||||
|
||||
pub fn contains(&self, arg: Id) -> bool {
|
||||
self.0.args.contains_key(&arg)
|
||||
pub fn contains(&self, arg: &Id) -> bool {
|
||||
self.0.args.contains_key(arg)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
|
@ -111,8 +110,8 @@ impl ArgMatcher {
|
|||
self.0.args.keys()
|
||||
}
|
||||
|
||||
pub fn entry(&mut self, arg: Id) -> indexmap::map::Entry<Id, MatchedArg> {
|
||||
self.0.args.entry(arg)
|
||||
pub fn entry(&mut self, arg: &Id) -> indexmap::map::Entry<Id, MatchedArg> {
|
||||
self.0.args.entry(arg.clone())
|
||||
}
|
||||
|
||||
pub fn subcommand(&mut self, sc: SubCommand) {
|
||||
|
@ -127,8 +126,8 @@ impl ArgMatcher {
|
|||
self.0.args.iter()
|
||||
}
|
||||
|
||||
pub fn inc_occurrence_of(&mut self, arg: Id) {
|
||||
debugln!("ArgMatcher::inc_occurrence_of: arg={}", arg);
|
||||
pub fn inc_occurrence_of(&mut self, arg: &Id) {
|
||||
debugln!("ArgMatcher::inc_occurrence_of: arg={:?}", arg);
|
||||
if let Some(a) = self.get_mut(arg) {
|
||||
a.occurs += 1;
|
||||
return;
|
||||
|
@ -137,7 +136,7 @@ impl ArgMatcher {
|
|||
self.insert(arg);
|
||||
}
|
||||
|
||||
pub fn add_val_to(&mut self, arg: Id, val: &OsStr) {
|
||||
pub fn add_val_to(&mut self, arg: &Id, val: &OsStr) {
|
||||
let ma = self.entry(arg).or_insert(MatchedArg {
|
||||
occurs: 0, // @TODO @question Shouldn't this be 1 if we're already adding a value to this arg?
|
||||
indices: Vec::with_capacity(1),
|
||||
|
@ -146,7 +145,7 @@ impl ArgMatcher {
|
|||
ma.vals.push(val.to_owned());
|
||||
}
|
||||
|
||||
pub fn add_index_to(&mut self, arg: Id, idx: usize) {
|
||||
pub fn add_index_to(&mut self, arg: &Id, idx: usize) {
|
||||
let ma = self.entry(arg).or_insert(MatchedArg {
|
||||
occurs: 0,
|
||||
indices: Vec::with_capacity(1),
|
||||
|
@ -157,7 +156,7 @@ impl ArgMatcher {
|
|||
|
||||
pub fn needs_more_vals(&self, o: &Arg) -> bool {
|
||||
debugln!("ArgMatcher::needs_more_vals: o={}", o.name);
|
||||
if let Some(ma) = self.get(o.id) {
|
||||
if let Some(ma) = self.get(&o.id) {
|
||||
if let Some(num) = o.num_vals {
|
||||
debugln!("ArgMatcher::needs_more_vals: num_vals...{}", num);
|
||||
return if o.is_set(ArgSettings::MultipleValues) {
|
||||
|
|
|
@ -11,11 +11,9 @@ use indexmap::IndexMap;
|
|||
|
||||
// Internal
|
||||
use crate::parse::{MatchedArg, SubCommand};
|
||||
use crate::util::Key;
|
||||
use crate::util::{Id, Key};
|
||||
use crate::{Error, INVALID_UTF8};
|
||||
|
||||
type Id = u64;
|
||||
|
||||
/// Used to get information about the arguments that were supplied to the program at runtime by
|
||||
/// the user. New instances of this struct are obtained by using the [`App::get_matches`] family of
|
||||
/// methods.
|
||||
|
@ -107,7 +105,7 @@ impl ArgMatches {
|
|||
/// [`ArgMatches::values_of`]: ./struct.ArgMatches.html#method.values_of
|
||||
/// [`panic!`]: https://doc.rust-lang.org/std/macro.panic!.html
|
||||
pub fn value_of<T: Key>(&self, id: T) -> Option<&str> {
|
||||
if let Some(arg) = self.args.get(&id.key()) {
|
||||
if let Some(arg) = self.args.get(&Id::from(id)) {
|
||||
if let Some(v) = arg.vals.get(0) {
|
||||
return Some(v.to_str().expect(INVALID_UTF8));
|
||||
}
|
||||
|
@ -139,7 +137,7 @@ impl ArgMatches {
|
|||
/// ```
|
||||
/// [`Arg::values_of_lossy`]: ./struct.ArgMatches.html#method.values_of_lossy
|
||||
pub fn value_of_lossy<T: Key>(&self, id: T) -> Option<Cow<'_, str>> {
|
||||
if let Some(arg) = self.args.get(&id.key()) {
|
||||
if let Some(arg) = self.args.get(&Id::from(id)) {
|
||||
if let Some(v) = arg.vals.get(0) {
|
||||
return Some(v.to_string_lossy());
|
||||
}
|
||||
|
@ -176,7 +174,7 @@ impl ArgMatches {
|
|||
/// [`ArgMatches::values_of_os`]: ./struct.ArgMatches.html#method.values_of_os
|
||||
pub fn value_of_os<T: Key>(&self, id: T) -> Option<&OsStr> {
|
||||
self.args
|
||||
.get(&id.key())
|
||||
.get(&Id::from(id))
|
||||
.and_then(|arg| arg.vals.get(0).map(OsString::as_os_str))
|
||||
}
|
||||
|
||||
|
@ -206,7 +204,7 @@ impl ArgMatches {
|
|||
/// [`Values`]: ./struct.Values.html
|
||||
/// [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
|
||||
pub fn values_of<T: Key>(&self, id: T) -> Option<Values<'_>> {
|
||||
self.args.get(&id.key()).map(|arg| {
|
||||
self.args.get(&Id::from(id)).map(|arg| {
|
||||
fn to_str_slice(o: &OsString) -> &str {
|
||||
o.to_str().expect(INVALID_UTF8)
|
||||
}
|
||||
|
@ -243,7 +241,7 @@ impl ArgMatches {
|
|||
/// assert_eq!(itr.next(), None);
|
||||
/// ```
|
||||
pub fn values_of_lossy<T: Key>(&self, id: T) -> Option<Vec<String>> {
|
||||
self.args.get(&id.key()).map(|arg| {
|
||||
self.args.get(&Id::from(id)).map(|arg| {
|
||||
arg.vals
|
||||
.iter()
|
||||
.map(|v| v.to_string_lossy().into_owned())
|
||||
|
@ -288,7 +286,7 @@ impl ArgMatches {
|
|||
}
|
||||
let to_str_slice: fn(&'a OsString) -> &'a OsStr = to_str_slice; // coerce to fn pointer
|
||||
|
||||
self.args.get(&id.key()).map(|arg| OsValues {
|
||||
self.args.get(&Id::from(id)).map(|arg| OsValues {
|
||||
iter: arg.vals.iter().map(to_str_slice),
|
||||
})
|
||||
}
|
||||
|
@ -489,7 +487,7 @@ impl ArgMatches {
|
|||
/// assert!(m.is_present("debug"));
|
||||
/// ```
|
||||
pub fn is_present<T: Key>(&self, id: T) -> bool {
|
||||
let id = id.key();
|
||||
let id = Id::from(id);
|
||||
|
||||
if let Some(ref sc) = self.subcommand {
|
||||
if sc.id == id {
|
||||
|
@ -539,7 +537,7 @@ impl ArgMatches {
|
|||
/// assert_eq!(m.occurrences_of("flag"), 1);
|
||||
/// ```
|
||||
pub fn occurrences_of<T: Key>(&self, id: T) -> u64 {
|
||||
self.args.get(&id.key()).map_or(0, |a| a.occurs)
|
||||
self.args.get(&Id::from(id)).map_or(0, |a| a.occurs)
|
||||
}
|
||||
|
||||
/// Gets the starting index of the argument in respect to all other arguments. Indices are
|
||||
|
@ -673,7 +671,7 @@ impl ArgMatches {
|
|||
/// [`ArgMatches`]: ./struct.ArgMatches.html
|
||||
/// [delimiter]: ./struct.Arg.html#method.value_delimiter
|
||||
pub fn index_of<T: Key>(&self, name: T) -> Option<usize> {
|
||||
if let Some(arg) = self.args.get(&name.key()) {
|
||||
if let Some(arg) = self.args.get(&Id::from(name)) {
|
||||
if let Some(i) = arg.indices.get(0) {
|
||||
return Some(*i);
|
||||
}
|
||||
|
@ -755,7 +753,7 @@ impl ArgMatches {
|
|||
/// [`ArgMatches::index_of`]: ./struct.ArgMatches.html#method.index_of
|
||||
/// [delimiter]: ./struct.Arg.html#method.value_delimiter
|
||||
pub fn indices_of<T: Key>(&self, id: T) -> Option<Indices<'_>> {
|
||||
self.args.get(&id.key()).map(|arg| Indices {
|
||||
self.args.get(&Id::from(id)).map(|arg| Indices {
|
||||
iter: arg.indices.iter().cloned(),
|
||||
})
|
||||
}
|
||||
|
@ -793,7 +791,7 @@ impl ArgMatches {
|
|||
/// [`ArgMatches`]: ./struct.ArgMatches.html
|
||||
pub fn subcommand_matches<T: Key>(&self, id: T) -> Option<&ArgMatches> {
|
||||
if let Some(ref s) = self.subcommand {
|
||||
if s.id == id.key() {
|
||||
if s.id == id.into() {
|
||||
return Some(&s.matches);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
// Internal
|
||||
use crate::util::Id;
|
||||
use crate::ArgMatches;
|
||||
|
||||
type Id = u64;
|
||||
|
||||
/// The abstract representation of a command line subcommand.
|
||||
///
|
||||
/// This struct describes all the valid options of the subcommand for the program. Subcommands are
|
||||
|
|
|
@ -20,13 +20,11 @@ use crate::parse::Validator;
|
|||
use crate::parse::{ArgMatcher, SubCommand};
|
||||
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
|
||||
use crate::util::OsStrExt3;
|
||||
use crate::util::{self, ChildGraph, Key, OsStrExt2, EMPTY_HASH};
|
||||
use crate::util::{ChildGraph, Id, OsStrExt2};
|
||||
use crate::INTERNAL_ERROR_MSG;
|
||||
use crate::INVALID_UTF8;
|
||||
|
||||
type Id = u64;
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub(crate) enum ParseResult {
|
||||
Flag,
|
||||
Opt(Id),
|
||||
|
@ -114,7 +112,7 @@ where
|
|||
.args
|
||||
.iter()
|
||||
.filter(|a| a.settings.is_set(ArgSettings::Required))
|
||||
.map(|a| a.id)
|
||||
.map(|a| a.id.clone())
|
||||
{
|
||||
reqs.insert(a);
|
||||
}
|
||||
|
@ -352,13 +350,13 @@ where
|
|||
// Add args with default requirements
|
||||
if a.is_set(ArgSettings::Required) {
|
||||
debugln!("Parser::_build: adding {} to default requires", a.name);
|
||||
let idx = self.required.insert(a.id);
|
||||
let idx = self.required.insert(a.id.clone());
|
||||
// If the arg is required, add all it's requirements to master required list
|
||||
if let Some(ref areqs) = a.requires {
|
||||
for name in areqs
|
||||
.iter()
|
||||
.filter(|&&(val, _)| val.is_none())
|
||||
.map(|&(_, name)| name)
|
||||
.filter(|(val, _)| val.is_none())
|
||||
.map(|(_, name)| name.clone())
|
||||
{
|
||||
self.required.insert_child(idx, name);
|
||||
}
|
||||
|
@ -386,7 +384,7 @@ where
|
|||
}) && positionals!(self.app).last().map_or(false, |p_name| {
|
||||
!self
|
||||
.app
|
||||
.find(p_name.id)
|
||||
.find(&p_name.id)
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
.is_set(ArgSettings::Last)
|
||||
}) {
|
||||
|
@ -395,10 +393,10 @@ where
|
|||
|
||||
for group in &self.app.groups {
|
||||
if group.required {
|
||||
let idx = self.required.insert(group.id);
|
||||
let idx = self.required.insert(group.id.clone());
|
||||
if let Some(ref reqs) = group.requires {
|
||||
for &a in reqs {
|
||||
self.required.insert_child(idx, a);
|
||||
for a in reqs {
|
||||
self.required.insert_child(idx, a.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +452,7 @@ where
|
|||
self.unset(AS::ValidNegNumFound);
|
||||
|
||||
// Is this a new argument, or values from a previous option?
|
||||
let starts_new_arg = self.is_new_arg(arg_os, needs_val_of);
|
||||
let starts_new_arg = self.is_new_arg(arg_os, needs_val_of.clone());
|
||||
|
||||
if !self.is_set(AS::TrailingValues)
|
||||
&& arg_os.starts_with(b"--")
|
||||
|
@ -536,7 +534,7 @@ where
|
|||
}
|
||||
} else if let ParseResult::Opt(name) = needs_val_of {
|
||||
// Check to see if parsing a value from a previous arg
|
||||
let arg = self.app.find(name).expect(INTERNAL_ERROR_MSG);
|
||||
let arg = self.app.find(&name).expect(INTERNAL_ERROR_MSG);
|
||||
// get the option so we can check the settings
|
||||
needs_val_of = self.add_val_to_arg(arg, arg_os, matcher)?;
|
||||
// get the next value from the iterator
|
||||
|
@ -599,7 +597,7 @@ where
|
|||
if let Some(p) =
|
||||
positionals!(self.app).find(|p| p.index == Some(pos_counter as u64))
|
||||
{
|
||||
ParseResult::Pos(p.id)
|
||||
ParseResult::Pos(p.id.clone())
|
||||
} else {
|
||||
ParseResult::ValuesDone
|
||||
}
|
||||
|
@ -609,7 +607,7 @@ where
|
|||
|
||||
let sc_match = { self.possible_subcommand(n).is_some() };
|
||||
|
||||
if self.is_new_arg(n, needs_val_of)
|
||||
if self.is_new_arg(n, needs_val_of.clone())
|
||||
|| sc_match
|
||||
|| !suggestions::did_you_mean(&n.to_string_lossy(), sc_names!(self.app))
|
||||
.is_empty()
|
||||
|
@ -675,12 +673,12 @@ where
|
|||
self.app.settings.set(AS::TrailingValues);
|
||||
}
|
||||
|
||||
self.seen.push(p.id);
|
||||
self.seen.push(p.id.clone());
|
||||
let _ = self.add_val_to_arg(p, arg_os, matcher)?;
|
||||
|
||||
matcher.inc_occurrence_of(p.id);
|
||||
matcher.inc_occurrence_of(&p.id);
|
||||
for grp in groups_for_arg!(self.app, p.id) {
|
||||
matcher.inc_occurrence_of(grp);
|
||||
matcher.inc_occurrence_of(&grp);
|
||||
}
|
||||
|
||||
self.app.settings.set(AS::ValidArgFound);
|
||||
|
@ -714,14 +712,12 @@ where
|
|||
self.app.color(),
|
||||
));
|
||||
}
|
||||
sc_m.add_val_to(EMPTY_HASH, &v);
|
||||
sc_m.add_val_to(&Id::empty_hash(), &v);
|
||||
}
|
||||
|
||||
let id = sc_name.key();
|
||||
|
||||
matcher.subcommand(SubCommand {
|
||||
name: sc_name,
|
||||
id,
|
||||
name: sc_name.clone(),
|
||||
id: sc_name.into(),
|
||||
matches: sc_m.into_inner(),
|
||||
});
|
||||
|
||||
|
@ -852,7 +848,7 @@ where
|
|||
help_help = true;
|
||||
break; // Maybe?
|
||||
}
|
||||
if let Some(id) = find_subcmd!(sc, cmd).map(|x| x.id) {
|
||||
if let Some(id) = find_subcmd!(sc, cmd).map(|x| x.id.clone()) {
|
||||
sc._propagate(Propagation::To(id));
|
||||
}
|
||||
|
||||
|
@ -927,11 +923,11 @@ where
|
|||
|
||||
let arg_allows_tac = match needs_val_of {
|
||||
ParseResult::Opt(name) => {
|
||||
let o = self.app.find(name).expect(INTERNAL_ERROR_MSG);
|
||||
let o = self.app.find(&name).expect(INTERNAL_ERROR_MSG);
|
||||
o.is_set(ArgSettings::AllowHyphenValues) || app_wide_settings
|
||||
}
|
||||
ParseResult::Pos(name) => {
|
||||
let p = self.app.find(name).expect(INTERNAL_ERROR_MSG);
|
||||
let p = self.app.find(&name).expect(INTERNAL_ERROR_MSG);
|
||||
p.is_set(ArgSettings::AllowHyphenValues) || app_wide_settings
|
||||
}
|
||||
ParseResult::ValuesDone => return true,
|
||||
|
@ -988,7 +984,7 @@ where
|
|||
|
||||
mid_string.push_str(" ");
|
||||
|
||||
if let Some(id) = find_subcmd!(self.app, sc_name).map(|x| x.id) {
|
||||
if let Some(id) = find_subcmd!(self.app, sc_name).map(|x| x.id.clone()) {
|
||||
self.app._propagate(Propagation::To(id));
|
||||
}
|
||||
|
||||
|
@ -1022,11 +1018,10 @@ where
|
|||
let mut p = Parser::new(sc);
|
||||
p.get_matches_with(&mut sc_matcher, it)?;
|
||||
}
|
||||
let name = sc.name.clone();
|
||||
let sc_id = name.key();
|
||||
let name = &sc.name;
|
||||
matcher.subcommand(SubCommand {
|
||||
id: sc_id, // @TODO @maybe: should be sc.id?
|
||||
name,
|
||||
id: Id::from_ref(&*name), // @TODO @maybe: should be sc.id?
|
||||
name: name.to_string(),
|
||||
matches: sc_matcher.into_inner(),
|
||||
});
|
||||
}
|
||||
|
@ -1065,7 +1060,7 @@ where
|
|||
);
|
||||
// Needs to use app.settings.is_set instead of just is_set() because is_set() checks
|
||||
// both global and local settings, we only want to check local
|
||||
if let Some(help) = self.app.find(util::HELP_HASH) {
|
||||
if let Some(help) = self.app.find(&Id::help_hash()) {
|
||||
if let Some(h) = help.short {
|
||||
if arg == h && !self.app.settings.is_set(AS::NoAutoHelp) {
|
||||
sdebugln!("Help");
|
||||
|
@ -1073,7 +1068,7 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
if let Some(version) = self.app.find(util::VERSION_HASH) {
|
||||
if let Some(version) = self.app.find(&Id::version_hash()) {
|
||||
if let Some(v) = version.short {
|
||||
if arg == v && !self.app.settings.is_set(AS::NoAutoVersion) {
|
||||
sdebugln!("Version");
|
||||
|
@ -1131,7 +1126,7 @@ where
|
|||
);
|
||||
self.app.settings.set(AS::ValidArgFound);
|
||||
|
||||
self.seen.push(opt.id);
|
||||
self.seen.push(opt.id.clone());
|
||||
|
||||
if opt.is_set(ArgSettings::TakesValue) {
|
||||
return Ok(self.parse_opt(val, opt, val.is_some(), matcher)?);
|
||||
|
@ -1194,7 +1189,7 @@ where
|
|||
c
|
||||
);
|
||||
self.app.settings.set(AS::ValidArgFound);
|
||||
self.seen.push(opt.id);
|
||||
self.seen.push(opt.id.clone());
|
||||
if !opt.is_set(ArgSettings::TakesValue) {
|
||||
self.check_for_help_and_version_char(c)?;
|
||||
ret = self.parse_flag(opt, matcher)?;
|
||||
|
@ -1284,10 +1279,10 @@ where
|
|||
sdebugln!("None");
|
||||
}
|
||||
|
||||
matcher.inc_occurrence_of(opt.id);
|
||||
matcher.inc_occurrence_of(&opt.id);
|
||||
// Increment or create the group "args"
|
||||
for grp in groups_for_arg!(self.app, opt.id) {
|
||||
matcher.inc_occurrence_of(grp);
|
||||
matcher.inc_occurrence_of(&grp);
|
||||
}
|
||||
|
||||
let needs_delim = opt.is_set(ArgSettings::RequireDelimiter);
|
||||
|
@ -1298,7 +1293,7 @@ where
|
|||
return Ok(ParseResult::ValuesDone);
|
||||
} else if no_val || (mult && !needs_delim) && !has_eq && matcher.needs_more_vals(opt) {
|
||||
debugln!("Parser::parse_opt: More arg vals required...");
|
||||
return Ok(ParseResult::Opt(opt.id));
|
||||
return Ok(ParseResult::Opt(opt.id.clone()));
|
||||
}
|
||||
debugln!("Parser::parse_opt: More arg vals not required...");
|
||||
Ok(ParseResult::ValuesDone)
|
||||
|
@ -1360,16 +1355,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
matcher.add_val_to(arg.id, v);
|
||||
matcher.add_index_to(arg.id, self.cur_idx.get());
|
||||
matcher.add_val_to(&arg.id, v);
|
||||
matcher.add_index_to(&arg.id, self.cur_idx.get());
|
||||
|
||||
// Increment or create the group "args"
|
||||
for grp in groups_for_arg!(self.app, arg.id) {
|
||||
matcher.add_val_to(grp, v);
|
||||
matcher.add_val_to(&grp, v);
|
||||
}
|
||||
|
||||
if matcher.needs_more_vals(arg) {
|
||||
return Ok(ParseResult::Opt(arg.id));
|
||||
return Ok(ParseResult::Opt(arg.id.clone()));
|
||||
}
|
||||
Ok(ParseResult::ValuesDone)
|
||||
}
|
||||
|
@ -1377,11 +1372,11 @@ where
|
|||
fn parse_flag(&self, flag: &Arg<'b>, matcher: &mut ArgMatcher) -> ClapResult<ParseResult> {
|
||||
debugln!("Parser::parse_flag;");
|
||||
|
||||
matcher.inc_occurrence_of(flag.id);
|
||||
matcher.add_index_to(flag.id, self.cur_idx.get());
|
||||
matcher.inc_occurrence_of(&flag.id);
|
||||
matcher.add_index_to(&flag.id, self.cur_idx.get());
|
||||
// Increment or create the group "args"
|
||||
for grp in groups_for_arg!(self.app, flag.id) {
|
||||
matcher.inc_occurrence_of(grp);
|
||||
matcher.inc_occurrence_of(&grp);
|
||||
}
|
||||
|
||||
Ok(ParseResult::Flag)
|
||||
|
@ -1392,10 +1387,10 @@ where
|
|||
let mut to_rem: Vec<Id> = Vec::new();
|
||||
let mut self_override: Vec<Id> = Vec::new();
|
||||
let mut arg_overrides = Vec::new();
|
||||
for &name in matcher.arg_names() {
|
||||
debugln!("Parser::remove_overrides:iter:{};", name);
|
||||
for name in matcher.arg_names() {
|
||||
debugln!("Parser::remove_overrides:iter:{:?};", name);
|
||||
if let Some(arg) = self.app.find(name) {
|
||||
let mut handle_self_override = |o| {
|
||||
let mut handle_self_override = |o: &Id| {
|
||||
if (arg.is_set(ArgSettings::MultipleValues)
|
||||
|| arg.is_set(ArgSettings::MultipleOccurrences))
|
||||
|| !arg.has_switch()
|
||||
|
@ -1403,44 +1398,44 @@ where
|
|||
return true;
|
||||
}
|
||||
debugln!(
|
||||
"Parser::remove_overrides:iter:{}:iter:{}: self override;",
|
||||
"Parser::remove_overrides:iter:{:?}:iter:{:?}: self override;",
|
||||
name,
|
||||
o
|
||||
);
|
||||
self_override.push(o);
|
||||
self_override.push(o.clone());
|
||||
false
|
||||
};
|
||||
if let Some(ref overrides) = arg.overrides {
|
||||
debugln!("Parser::remove_overrides:iter:{}:{:?};", name, overrides);
|
||||
for &o in overrides {
|
||||
if o == arg.id {
|
||||
debugln!("Parser::remove_overrides:iter:{:?}:{:?};", name, overrides);
|
||||
for o in overrides {
|
||||
if *o == arg.id {
|
||||
if handle_self_override(o) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
arg_overrides.push((arg.id, o));
|
||||
arg_overrides.push((o, arg.id));
|
||||
arg_overrides.push((arg.id.clone(), o));
|
||||
arg_overrides.push((o.clone(), &arg.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.is_set(AS::AllArgsOverrideSelf) {
|
||||
let _ = handle_self_override(arg.id);
|
||||
let _ = handle_self_override(&arg.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove future overrides in reverse seen order
|
||||
for &arg in self.seen.iter().rev() {
|
||||
for &(a, overr) in arg_overrides.iter().filter(|&&(a, _)| a == arg) {
|
||||
for arg in self.seen.iter().rev() {
|
||||
for (a, overr) in arg_overrides.iter().filter(|(a, _)| a == arg) {
|
||||
if !to_rem.contains(&a) {
|
||||
to_rem.push(overr);
|
||||
to_rem.push((*overr).clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do self overrides
|
||||
for &name in &self_override {
|
||||
debugln!("Parser::remove_overrides:iter:self:{}: resetting;", name);
|
||||
for name in &self_override {
|
||||
debugln!("Parser::remove_overrides:iter:self:{:?}: resetting;", name);
|
||||
if let Some(ma) = matcher.get_mut(name) {
|
||||
if ma.occurs < 2 {
|
||||
continue;
|
||||
|
@ -1455,22 +1450,24 @@ where
|
|||
}
|
||||
|
||||
// Finally remove conflicts
|
||||
for &name in &to_rem {
|
||||
debugln!("Parser::remove_overrides:iter:{}: removing;", name);
|
||||
for name in &to_rem {
|
||||
debugln!("Parser::remove_overrides:iter:{:?}: removing;", name);
|
||||
matcher.remove(name);
|
||||
self.overriden.push(name);
|
||||
self.overriden.push(name.clone());
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub(crate) fn add_defaults(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("Parser::add_defaults;");
|
||||
|
||||
// FIXME: Refactor into function (or at least most of it)
|
||||
macro_rules! add_val {
|
||||
(@default $_self:ident, $a:ident, $m:ident) => {
|
||||
if let Some(ref vals) = $a.default_vals {
|
||||
debugln!("Parser::add_defaults:iter:{}: has default vals", $a.name);
|
||||
if $m
|
||||
.get($a.id)
|
||||
.get(&$a.id)
|
||||
.map(|ma| ma.vals.len())
|
||||
.map(|len| len == 0)
|
||||
.unwrap_or(false)
|
||||
|
@ -1482,7 +1479,7 @@ where
|
|||
for val in vals {
|
||||
$_self.add_val_to_arg($a, val, $m)?;
|
||||
}
|
||||
} else if $m.get($a.id).is_some() {
|
||||
} else if $m.get(&$a.id).is_some() {
|
||||
debugln!(
|
||||
"Parser::add_defaults:iter:{}: has user defined vals",
|
||||
$a.name
|
||||
|
@ -1505,9 +1502,9 @@ where
|
|||
if let Some(ref vm) = $a.default_vals_ifs {
|
||||
sdebugln!(" has conditional defaults");
|
||||
let mut done = false;
|
||||
if $m.get($a.id).is_none() {
|
||||
for &(arg, val, default) in vm.values() {
|
||||
let add = if let Some(a) = $m.get(arg) {
|
||||
if $m.get(&$a.id).is_none() {
|
||||
for (arg, val, default) in vm.values() {
|
||||
let add = if let Some(a) = $m.get(&arg) {
|
||||
if let Some(v) = val {
|
||||
a.vals.iter().any(|value| v == value)
|
||||
} else {
|
||||
|
@ -1588,17 +1585,17 @@ where
|
|||
if let Some(ref name) = suffix.1 {
|
||||
if let Some(opt) = self.app.args.get(&KeyType::Long(OsString::from(name))) {
|
||||
for g in groups_for_arg!(self.app, opt.id) {
|
||||
matcher.inc_occurrence_of(g);
|
||||
matcher.inc_occurrence_of(&g);
|
||||
}
|
||||
matcher.insert(opt.id);
|
||||
matcher.insert(&opt.id);
|
||||
}
|
||||
}
|
||||
|
||||
let used: Vec<Id> = matcher
|
||||
.arg_names()
|
||||
.filter(|n| {
|
||||
if let Some(a) = self.app.find(**n) {
|
||||
!(self.required.contains(a.id) || a.is_set(ArgSettings::Hidden))
|
||||
if let Some(a) = self.app.find(n) {
|
||||
!(self.required.contains(&a.id) || a.is_set(ArgSettings::Hidden))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
|
|
@ -6,12 +6,10 @@ use crate::output::Usage;
|
|||
use crate::parse::errors::Result as ClapResult;
|
||||
use crate::parse::errors::{Error, ErrorKind};
|
||||
use crate::parse::{ArgMatcher, MatchedArg, ParseResult, Parser};
|
||||
use crate::util::ChildGraph;
|
||||
use crate::util::{ChildGraph, Id};
|
||||
use crate::INTERNAL_ERROR_MSG;
|
||||
use crate::INVALID_UTF8;
|
||||
|
||||
type Id = u64;
|
||||
|
||||
pub struct Validator<'b, 'c, 'z>
|
||||
where
|
||||
'b: 'c,
|
||||
|
@ -43,7 +41,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
debugln!("Validator::validate: needs_val_of={:?}", a);
|
||||
self.validate_required(matcher)?;
|
||||
|
||||
let o = self.p.app.find(a).expect(INTERNAL_ERROR_MSG);
|
||||
let o = self.p.app.find(&a).expect(INTERNAL_ERROR_MSG);
|
||||
reqs_validated = true;
|
||||
let should_err = if let Some(v) = matcher.0.args.get(&o.id) {
|
||||
v.vals.is_empty() && !(o.min_vals.is_some() && o.min_vals.unwrap() == 0)
|
||||
|
@ -111,9 +109,9 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
if !ok {
|
||||
let used: Vec<Id> = matcher
|
||||
.arg_names()
|
||||
.filter(|&&n| {
|
||||
.filter(|&n| {
|
||||
if let Some(a) = self.p.app.find(n) {
|
||||
!(self.p.required.contains(a.id) || a.is_set(ArgSettings::Hidden))
|
||||
!(self.p.required.contains(&a.id) || a.is_set(ArgSettings::Hidden))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -131,7 +129,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
}
|
||||
if !arg.is_set(ArgSettings::AllowEmptyValues)
|
||||
&& val.is_empty()
|
||||
&& matcher.contains(arg.id)
|
||||
&& matcher.contains(&arg.id)
|
||||
{
|
||||
debugln!("Validator::validate_arg_values: illegal empty val found");
|
||||
return Err(Error::empty_value(
|
||||
|
@ -166,11 +164,11 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn build_conflict_err(&self, name: Id, matcher: &ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("build_err!: name={}", name);
|
||||
fn build_conflict_err(&self, name: &Id, matcher: &ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("build_err!: name={:?}", name);
|
||||
let usg = Usage::new(self.p).create_usage_with_title(&[]);
|
||||
if let Some(other_arg) = self.p.app.find(name) {
|
||||
for &k in matcher.arg_names() {
|
||||
for k in matcher.arg_names() {
|
||||
if let Some(a) = self.p.app.find(k) {
|
||||
if let Some(ref v) = a.blacklist {
|
||||
if v.contains(&name) {
|
||||
|
@ -184,8 +182,8 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(g) = self.p.app.groups.iter().find(|x| x.id == name) {
|
||||
let args_in_group = self.p.app.unroll_args_in_group(g.id);
|
||||
} else if let Some(g) = self.p.app.groups.iter().find(|x| x.id == *name) {
|
||||
let args_in_group = self.p.app.unroll_args_in_group(&g.id);
|
||||
let first = matcher
|
||||
.arg_names()
|
||||
.find(|x| args_in_group.contains(x))
|
||||
|
@ -193,10 +191,10 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
let c_with = matcher
|
||||
.arg_names()
|
||||
.find(|x| x != &first && args_in_group.contains(x))
|
||||
.map(|&x| self.p.app.find(x).expect(INTERNAL_ERROR_MSG).to_string());
|
||||
.map(|x| self.p.app.find(x).expect(INTERNAL_ERROR_MSG).to_string());
|
||||
debugln!("build_err!:c_with={:?}:group", c_with);
|
||||
return Err(Error::argument_conflict(
|
||||
self.p.app.find(*first).expect(INTERNAL_ERROR_MSG),
|
||||
self.p.app.find(first).expect(INTERNAL_ERROR_MSG),
|
||||
c_with,
|
||||
&*usg,
|
||||
self.p.app.color(),
|
||||
|
@ -214,7 +212,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
}
|
||||
self.gather_conflicts(matcher);
|
||||
for name in self.c.iter() {
|
||||
debugln!("Validator::validate_conflicts:iter:{};", name);
|
||||
debugln!("Validator::validate_conflicts:iter:{:?};", name);
|
||||
let mut should_err = false;
|
||||
if let Some(g) = self
|
||||
.p
|
||||
|
@ -227,34 +225,34 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
let conf_with_self = self
|
||||
.p
|
||||
.app
|
||||
.unroll_args_in_group(g.id)
|
||||
.unroll_args_in_group(&g.id)
|
||||
.iter()
|
||||
.filter(|&&a| matcher.contains(a))
|
||||
.filter(|&a| matcher.contains(a))
|
||||
.count()
|
||||
> 1;
|
||||
|
||||
let conf_with_arg = if let Some(ref c) = g.conflicts {
|
||||
c.iter().any(|&x| matcher.contains(x))
|
||||
c.iter().any(|x| matcher.contains(x))
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let arg_conf_with_gr = matcher
|
||||
.arg_names()
|
||||
.filter_map(|&x| self.p.app.find(x))
|
||||
.filter_map(|x| self.p.app.find(x))
|
||||
.filter_map(|x| x.blacklist.as_ref())
|
||||
.any(|c| c.iter().any(|&c| c == g.id));
|
||||
.any(|c| c.iter().any(|c| *c == g.id));
|
||||
|
||||
should_err = conf_with_self || conf_with_arg || arg_conf_with_gr;
|
||||
} else if let Some(ma) = matcher.get(*name) {
|
||||
} else if let Some(ma) = matcher.get(name) {
|
||||
debugln!(
|
||||
"Validator::validate_conflicts:iter:{}: matcher contains it...",
|
||||
"Validator::validate_conflicts:iter:{:?}: matcher contains it...",
|
||||
name
|
||||
);
|
||||
should_err = ma.occurs > 0;
|
||||
}
|
||||
if should_err {
|
||||
return self.build_conflict_err(*name, matcher);
|
||||
return self.build_conflict_err(name, matcher);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -263,9 +261,9 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
fn validate_exclusive(&mut self, matcher: &mut ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_exclusive;");
|
||||
let args_count = matcher.arg_names().count();
|
||||
for &name in matcher.arg_names() {
|
||||
for name in matcher.arg_names() {
|
||||
debugln!(
|
||||
"Validator::validate_conflicts_with_everything:iter:{};",
|
||||
"Validator::validate_conflicts_with_everything:iter:{:?};",
|
||||
name
|
||||
);
|
||||
if let Some(arg) = self.p.app.find(name) {
|
||||
|
@ -292,29 +290,32 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
// and such
|
||||
fn gather_conflicts(&mut self, matcher: &mut ArgMatcher) {
|
||||
debugln!("Validator::gather_conflicts;");
|
||||
for &name in matcher.arg_names() {
|
||||
debugln!("Validator::gather_conflicts:iter:{};", name);
|
||||
for name in matcher.arg_names() {
|
||||
debugln!("Validator::gather_conflicts:iter:{:?};", name);
|
||||
if let Some(arg) = self.p.app.find(name) {
|
||||
// Since an arg was used, every arg it conflicts with is added to the conflicts
|
||||
if let Some(ref bl) = arg.blacklist {
|
||||
for &conf in bl {
|
||||
for conf in bl {
|
||||
if self.p.app.find(conf).is_some() {
|
||||
if conf != name {
|
||||
self.c.insert(conf);
|
||||
self.c.insert(conf.clone());
|
||||
}
|
||||
} else {
|
||||
// for g_arg in self.p.app.unroll_args_in_group(conf) {
|
||||
// if &g_arg != name {
|
||||
self.c.insert(conf); // TODO ERROR is here - groups allow one arg but this line disallows all group args
|
||||
// }
|
||||
// }
|
||||
self.c.insert(conf.clone()); // TODO ERROR is here - groups allow one arg but this line disallows all group args
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now we need to know which groups this arg was a memeber of, to add all other
|
||||
// args in that group to the conflicts, as well as any args those args conflict
|
||||
// with
|
||||
for grp in groups_for_arg!(self.p.app, name) {
|
||||
|
||||
// // FIXME: probably no need to cone the id here. Review the macro
|
||||
for grp in groups_for_arg!(self.p.app, name.clone()) {
|
||||
if let Some(g) = self
|
||||
.p
|
||||
.app
|
||||
|
@ -325,7 +326,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
{
|
||||
// for g_arg in self.p.app.unroll_args_in_group(&g.name) {
|
||||
// if &g_arg != name {
|
||||
self.c.insert(g.id);
|
||||
self.c.insert(g.id.clone());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@ -336,27 +337,27 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
.groups
|
||||
.iter()
|
||||
.filter(|g| !g.multiple)
|
||||
.find(|grp| grp.id == name)
|
||||
.find(|grp| grp.id == *name)
|
||||
{
|
||||
debugln!("Validator::gather_conflicts:iter:{}:group;", name);
|
||||
self.c.insert(g.id);
|
||||
debugln!("Validator::gather_conflicts:iter:{:?}:group;", name);
|
||||
self.c.insert(g.id.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gather_requirements(&mut self, matcher: &ArgMatcher) {
|
||||
debugln!("Validator::gather_requirements;");
|
||||
for &name in matcher.arg_names() {
|
||||
debugln!("Validator::gather_requirements:iter:{};", name);
|
||||
for name in matcher.arg_names() {
|
||||
debugln!("Validator::gather_requirements:iter:{:?};", name);
|
||||
if let Some(arg) = self.p.app.find(name) {
|
||||
for req in self.p.app.unroll_requirements_for_arg(arg.id, matcher) {
|
||||
for req in self.p.app.unroll_requirements_for_arg(&arg.id, matcher) {
|
||||
self.p.required.insert(req);
|
||||
}
|
||||
} else if let Some(g) = self.p.app.groups.iter().find(|grp| grp.id == name) {
|
||||
debugln!("Validator::gather_conflicts:iter:{}:group;", name);
|
||||
} else if let Some(g) = self.p.app.groups.iter().find(|grp| grp.id == *name) {
|
||||
debugln!("Validator::gather_conflicts:iter:{:?}:group;", name);
|
||||
if let Some(ref reqs) = g.requires {
|
||||
for &r in reqs {
|
||||
self.p.required.insert(r);
|
||||
for r in reqs {
|
||||
self.p.required.insert(r.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -365,9 +366,9 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
|
||||
fn validate_matched_args(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_matched_args;");
|
||||
for (&name, ma) in matcher.iter() {
|
||||
for (name, ma) in matcher.iter() {
|
||||
debugln!(
|
||||
"Validator::validate_matched_args:iter:{}: vals={:#?}",
|
||||
"Validator::validate_matched_args:iter:{:?}: vals={:#?}",
|
||||
name,
|
||||
ma.vals
|
||||
);
|
||||
|
@ -382,10 +383,10 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
.app
|
||||
.groups
|
||||
.iter()
|
||||
.find(|g| g.id == name)
|
||||
.find(|g| g.id == *name)
|
||||
.expect(INTERNAL_ERROR_MSG);
|
||||
if let Some(ref g_reqs) = grp.requires {
|
||||
if g_reqs.iter().any(|&n| !matcher.contains(n)) {
|
||||
if g_reqs.iter().any(|n| !matcher.contains(n)) {
|
||||
return self.missing_required_error(matcher, Some(name));
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +397,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
|
||||
fn validate_arg_num_occurs(&self, a: &Arg, ma: &MatchedArg) -> ClapResult<()> {
|
||||
debugln!(
|
||||
"Validator::validate_arg_num_occurs: {}={};",
|
||||
"Validator::validate_arg_num_occurs: {:?}={};",
|
||||
a.name,
|
||||
ma.occurs
|
||||
);
|
||||
|
@ -486,18 +487,18 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
ma: &MatchedArg,
|
||||
matcher: &ArgMatcher,
|
||||
) -> ClapResult<()> {
|
||||
debugln!("Validator::validate_arg_requires:{};", a.name);
|
||||
debugln!("Validator::validate_arg_requires:{:?};", a.name);
|
||||
if let Some(ref a_reqs) = a.requires {
|
||||
for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) {
|
||||
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);
|
||||
|v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(&name);
|
||||
if ma.vals.iter().any(missing_req) {
|
||||
return self.missing_required_error(matcher, Some(a.id));
|
||||
return self.missing_required_error(matcher, Some(&a.id));
|
||||
}
|
||||
}
|
||||
for &(_, name) in a_reqs.iter().filter(|&&(val, _)| val.is_none()) {
|
||||
if !matcher.contains(name) {
|
||||
return self.missing_required_error(matcher, Some(name));
|
||||
for (_, name) in a_reqs.iter().filter(|(val, _)| val.is_none()) {
|
||||
if !matcher.contains(&name) {
|
||||
return self.missing_required_error(matcher, Some(&name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -511,19 +512,19 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
);
|
||||
self.gather_requirements(matcher);
|
||||
|
||||
for &arg_or_group in self.p.required.iter().filter(|&&r| !matcher.contains(r)) {
|
||||
for arg_or_group in self.p.required.iter().filter(|r| !matcher.contains(r)) {
|
||||
debugln!("Validator::validate_required:iter:aog={:?};", arg_or_group);
|
||||
if let Some(arg) = self.p.app.find(arg_or_group) {
|
||||
if let Some(arg) = self.p.app.find(&arg_or_group) {
|
||||
if !self.is_missing_required_ok(arg, matcher) {
|
||||
return self.missing_required_error(matcher, None);
|
||||
}
|
||||
} else if let Some(group) = self.p.app.groups.iter().find(|g| g.id == arg_or_group) {
|
||||
} else if let Some(group) = self.p.app.groups.iter().find(|g| g.id == *arg_or_group) {
|
||||
if !self
|
||||
.p
|
||||
.app
|
||||
.unroll_args_in_group(group.id)
|
||||
.unroll_args_in_group(&group.id)
|
||||
.iter()
|
||||
.any(|&a| matcher.contains(a))
|
||||
.any(|a| matcher.contains(a))
|
||||
{
|
||||
return self.missing_required_error(matcher, None);
|
||||
}
|
||||
|
@ -541,9 +542,9 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
.map(|a| (a, a.r_ifs.as_ref().unwrap()))
|
||||
{
|
||||
for (other, val) in r_ifs.iter() {
|
||||
if let Some(ma) = matcher.get(*other) {
|
||||
if ma.contains_val(val) && !matcher.contains(a.id) {
|
||||
return self.missing_required_error(matcher, Some(a.id));
|
||||
if let Some(ma) = matcher.get(other) {
|
||||
if ma.contains_val(val) && !matcher.contains(&a.id) {
|
||||
return self.missing_required_error(matcher, Some(&a.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -561,15 +562,15 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
a.blacklist
|
||||
.as_ref()
|
||||
.map(|bl| {
|
||||
bl.iter().any(|&conf| {
|
||||
bl.iter().any(|conf| {
|
||||
matcher.contains(conf)
|
||||
|| self
|
||||
.p
|
||||
.app
|
||||
.groups
|
||||
.iter()
|
||||
.find(|g| g.id == conf)
|
||||
.map_or(false, |g| g.args.iter().any(|&arg| matcher.contains(arg)))
|
||||
.find(|g| g.id == *conf)
|
||||
.map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
|
||||
})
|
||||
})
|
||||
.unwrap_or(false)
|
||||
|
@ -584,11 +585,11 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
.args
|
||||
.iter()
|
||||
.filter(|a| a.r_unless.is_some())
|
||||
.filter(|a| !matcher.contains(a.id))
|
||||
.filter(|a| !matcher.contains(&a.id))
|
||||
{
|
||||
debugln!("Validator::validate_required_unless:iter:{};", a.name);
|
||||
if self.fails_arg_required_unless(a, matcher) {
|
||||
return self.missing_required_error(matcher, Some(a.id));
|
||||
return self.missing_required_error(matcher, Some(&a.id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,7 +603,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
($how:ident, $_self:expr, $a:ident, $m:ident) => {{
|
||||
$a.r_unless
|
||||
.as_ref()
|
||||
.map(|ru| !ru.iter().$how(|&n| $m.contains(n)))
|
||||
.map(|ru| !ru.iter().$how(|n| $m.contains(n)))
|
||||
.unwrap_or(false)
|
||||
}};
|
||||
}
|
||||
|
@ -616,7 +617,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
}
|
||||
|
||||
// `incl`: an arg to include in the error even if not used
|
||||
fn missing_required_error(&self, matcher: &ArgMatcher, incl: Option<Id>) -> ClapResult<()> {
|
||||
fn missing_required_error(&self, matcher: &ArgMatcher, incl: Option<&Id>) -> ClapResult<()> {
|
||||
debugln!("Validator::missing_required_error; incl={:?}", incl);
|
||||
let c = Colorizer::new(&ColorizerOption {
|
||||
use_stderr: true,
|
||||
|
@ -628,7 +629,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
);
|
||||
let usg = Usage::new(self.p);
|
||||
let req_args = if let Some(x) = incl {
|
||||
usg.get_required_usage_from(&[x], Some(matcher), true)
|
||||
usg.get_required_usage_from(&[x.clone()], Some(matcher), true)
|
||||
.iter()
|
||||
.fold(String::new(), |acc, s| {
|
||||
acc + &format!("\n {}", c.error(s))[..]
|
||||
|
@ -646,15 +647,15 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
|||
);
|
||||
let used: Vec<Id> = matcher
|
||||
.arg_names()
|
||||
.filter(|&&n| {
|
||||
.filter(|&n| {
|
||||
if let Some(a) = self.p.app.find(n) {
|
||||
!(self.p.required.contains(a.id) || a.is_set(ArgSettings::Hidden))
|
||||
!(self.p.required.contains(&a.id) || a.is_set(ArgSettings::Hidden))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.cloned()
|
||||
.chain(incl)
|
||||
.chain(incl.cloned())
|
||||
.collect();
|
||||
Err(Error::missing_required_argument(
|
||||
&*req_args,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::fmt::Display;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
// precompute some common values
|
||||
|
@ -6,13 +7,13 @@ pub static VERSION_HASH: u64 = 0x30FF_0B7C_4D07_9478;
|
|||
pub static EMPTY_HASH: u64 = 0x1C9D_3ADB_639F_298E;
|
||||
const MAGIC_INIT: u64 = 0x811C_9DC5;
|
||||
|
||||
pub trait Key: Hash {
|
||||
pub trait Key: Hash + Display {
|
||||
fn key(&self) -> u64;
|
||||
}
|
||||
|
||||
impl<T> Key for T
|
||||
where
|
||||
T: Hash,
|
||||
T: Hash + Display,
|
||||
{
|
||||
fn key(&self) -> u64 {
|
||||
let mut hasher = FnvHasher::new();
|
||||
|
|
|
@ -15,14 +15,14 @@ pub struct ChildGraph<T>(Vec<Child<T>>);
|
|||
|
||||
impl<T> ChildGraph<T>
|
||||
where
|
||||
T: Sized + PartialEq + Copy + Clone,
|
||||
T: Sized + PartialEq + Clone,
|
||||
{
|
||||
pub fn with_capacity(s: usize) -> Self {
|
||||
ChildGraph(Vec::with_capacity(s))
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, req: T) -> usize {
|
||||
if !self.contains(req) {
|
||||
if !self.contains(&req) {
|
||||
let idx = self.0.len();
|
||||
self.0.push(Child::new(req));
|
||||
idx
|
||||
|
@ -55,7 +55,7 @@ where
|
|||
self.0.iter().map(|r| &r.id)
|
||||
}
|
||||
|
||||
pub fn contains(&self, req: T) -> bool {
|
||||
self.0.iter().any(|r| r.id == req)
|
||||
pub fn contains(&self, req: &T) -> bool {
|
||||
self.0.iter().any(|r| r.id == *req)
|
||||
}
|
||||
}
|
||||
|
|
85
src/util/id.rs
Normal file
85
src/util/id.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
use crate::util::fnv::{Key, EMPTY_HASH, HELP_HASH, VERSION_HASH};
|
||||
use std::fmt::{Debug, Formatter, Result};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
|
||||
#[derive(Clone, Eq, Default)]
|
||||
#[cfg_attr(not(debug_assertions), derive(Copy), repr(transparent))]
|
||||
pub(crate) struct Id {
|
||||
#[cfg(debug_assertions)]
|
||||
name: String,
|
||||
id: u64,
|
||||
}
|
||||
|
||||
macro_rules! precomputed_hashes {
|
||||
($($fn_name:ident, $const_name:ident, $name:expr;)*) => {
|
||||
impl Id {
|
||||
$(
|
||||
pub(crate) fn $fn_name() -> Self {
|
||||
Id {
|
||||
#[cfg(debug_assertions)]
|
||||
name: $name.into(),
|
||||
id: $const_name,
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
precomputed_hashes! {
|
||||
empty_hash, EMPTY_HASH, "";
|
||||
help_hash, HELP_HASH, "help";
|
||||
version_hash, VERSION_HASH, "version";
|
||||
}
|
||||
|
||||
impl Id {
|
||||
pub(crate) fn from_ref<T: Key>(val: T) -> Self {
|
||||
Id {
|
||||
#[cfg(debug_assertions)]
|
||||
name: val.to_string(),
|
||||
id: val.key(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Id {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
#[cfg(debug_assertions)]
|
||||
write!(f, "{:?} ", self.name)?;
|
||||
write!(f, "[hash: {}]", self.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Id {
|
||||
type Target = u64;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.id
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Key> From<T> for Id {
|
||||
fn from(val: T) -> Self {
|
||||
Id {
|
||||
#[cfg(debug_assertions)]
|
||||
name: val.to_string(),
|
||||
id: val.key(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Id {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
self.id.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Id {
|
||||
fn eq(&self, other: &Id) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
mod fnv;
|
||||
mod graph;
|
||||
mod id;
|
||||
mod map;
|
||||
mod osstringext;
|
||||
mod strext;
|
||||
|
||||
pub use self::fnv::{Key, EMPTY_HASH, HELP_HASH, VERSION_HASH};
|
||||
pub use self::graph::ChildGraph;
|
||||
pub use self::map::{Values, VecMap};
|
||||
pub(crate) use self::osstringext::OsStrExt2;
|
||||
pub use self::{fnv::Key, map::Values};
|
||||
|
||||
pub(crate) use self::{graph::ChildGraph, id::Id, map::VecMap, osstringext::OsStrExt2};
|
||||
|
||||
#[cfg(any(target_os = "windows", target_arch = "wasm32"))]
|
||||
pub(crate) use self::osstringext::OsStrExt3;
|
||||
pub use self::strext::_StrExt;
|
||||
|
|
Loading…
Reference in a new issue