-
-
Notifications
You must be signed in to change notification settings - Fork 1k
/
arg_matcher.rs
134 lines (111 loc) · 4.45 KB
/
arg_matcher.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Std
use std::collections::hash_map::{Entry, Iter};
use std::ffi::OsStr;
use std::ops::Deref;
use std::mem;
// Internal
use args::{ArgMatches, MatchedArg, SubCommand};
use args::AnyArg;
use args::settings::ArgSettings;
#[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 propagate(&mut self, arg: &'a str) {
debugln!("ArgMatcher::propagate: arg={}", arg);
let vals: Vec<_> = if let Some(ma) = self.get(arg) {
ma.vals.clone()
} else {
debugln!("ArgMatcher::propagate: arg wasn't used");
return;
};
if let Some(ref mut sc) = self.0.subcommand {
{
let sma = (*sc).matches.args.entry(arg).or_insert_with(|| {
let mut gma = MatchedArg::new();
gma.occurs += 1;
gma.vals = vals.clone();
gma
});
if sma.vals.is_empty() {
sma.vals = vals.clone();
}
}
let mut am = ArgMatcher(mem::replace(&mut sc.matches, ArgMatches::new()));
am.propagate(arg);
mem::swap(&mut am.0, &mut sc.matches);
} else {
debugln!("ArgMatcher::propagate: Subcommand wasn't used");
}
}
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,
vals: Vec::with_capacity(1),
});
// let len = ma.vals.len() + 1;
ma.vals.push(val.to_owned());
}
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
}
}
impl<'a> Into<ArgMatches<'a>> for ArgMatcher<'a> {
fn into(self) -> ArgMatches<'a> { self.0 }
}