]> git.proxmox.com Git - rustc.git/blame - vendor/clap-2.34.0/src/args/arg_matcher.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / vendor / clap-2.34.0 / src / args / arg_matcher.rs
CommitLineData
8bb4bdeb 1// Std
a2a8927a
XL
2use std::{
3 collections::{
4 hash_map::{Entry, Iter},
5 HashMap,
6 },
7 ffi::OsStr,
8 mem,
9 ops::Deref,
10};
8bb4bdeb 11
8bb4bdeb 12// Internal
a2a8927a 13use crate::args::{settings::ArgSettings, AnyArg, ArgMatches, MatchedArg, SubCommand};
8bb4bdeb
XL
14
15#[doc(hidden)]
16#[allow(missing_debug_implementations)]
17pub struct ArgMatcher<'a>(pub ArgMatches<'a>);
18
19impl<'a> Default for ArgMatcher<'a> {
3dfed10e
XL
20 fn default() -> Self {
21 ArgMatcher(ArgMatches::default())
22 }
8bb4bdeb
XL
23}
24
25impl<'a> ArgMatcher<'a> {
3dfed10e
XL
26 pub fn new() -> Self {
27 ArgMatcher::default()
28 }
8bb4bdeb 29
3dfed10e
XL
30 pub fn process_arg_overrides<'b>(
31 &mut self,
32 a: Option<&AnyArg<'a, 'b>>,
33 overrides: &mut Vec<(&'b str, &'a str)>,
34 required: &mut Vec<&'a str>,
35 check_all: bool,
36 ) {
37 debugln!(
38 "ArgMatcher::process_arg_overrides:{:?};",
39 a.map_or(None, |a| Some(a.name()))
40 );
0531ce1d
XL
41 if let Some(aa) = a {
42 let mut self_done = false;
43 if let Some(a_overrides) = aa.overrides() {
44 for overr in a_overrides {
45 debugln!("ArgMatcher::process_arg_overrides:iter:{};", overr);
46 if overr == &aa.name() {
47 self_done = true;
48 self.handle_self_overrides(a);
49 } else if self.is_present(overr) {
3dfed10e
XL
50 debugln!(
51 "ArgMatcher::process_arg_overrides:iter:{}: removing from matches;",
52 overr
53 );
0531ce1d 54 self.remove(overr);
3dfed10e 55 for i in (0..required.len()).rev() {
0531ce1d 56 if &required[i] == overr {
3dfed10e
XL
57 debugln!(
58 "ArgMatcher::process_arg_overrides:iter:{}: removing required;",
59 overr
60 );
0531ce1d
XL
61 required.swap_remove(i);
62 break;
63 }
64 }
65 overrides.push((overr, aa.name()));
66 } else {
67 overrides.push((overr, aa.name()));
68 }
69 }
70 }
71 if check_all && !self_done {
72 self.handle_self_overrides(a);
73 }
74 }
75 }
76
77 pub fn handle_self_overrides<'b>(&mut self, a: Option<&AnyArg<'a, 'b>>) {
3dfed10e
XL
78 debugln!(
79 "ArgMatcher::handle_self_overrides:{:?};",
80 a.map_or(None, |a| Some(a.name()))
81 );
0531ce1d
XL
82 if let Some(aa) = a {
83 if !aa.has_switch() || aa.is_set(ArgSettings::Multiple) {
84 // positional args can't override self or else we would never advance to the next
85
86 // Also flags with --multiple set are ignored otherwise we could never have more
87 // than one
88 return;
89 }
90 if let Some(ma) = self.get_mut(aa.name()) {
91 if ma.vals.len() > 1 {
92 // swap_remove(0) would be O(1) but does not preserve order, which
93 // we need
94 ma.vals.remove(0);
95 ma.occurs = 1;
96 } else if !aa.takes_value() && ma.occurs > 1 {
97 ma.occurs = 1;
98 }
99 }
100 }
101 }
102
103 pub fn is_present(&self, name: &str) -> bool {
104 self.0.is_present(name)
105 }
106
ff7c6d11 107 pub fn propagate_globals(&mut self, global_arg_vec: &[&'a str]) {
3dfed10e
XL
108 debugln!(
109 "ArgMatcher::get_global_values: global_arg_vec={:?}",
110 global_arg_vec
111 );
abe05a73
XL
112 let mut vals_map = HashMap::new();
113 self.fill_in_global_values(global_arg_vec, &mut vals_map);
114 }
115
116 fn fill_in_global_values(
ff7c6d11
XL
117 &mut self,
118 global_arg_vec: &[&'a str],
119 vals_map: &mut HashMap<&'a str, MatchedArg>,
abe05a73
XL
120 ) {
121 for global_arg in global_arg_vec {
122 if let Some(ma) = self.get(global_arg) {
123 // We have to check if the parent's global arg wasn't used but still exists
124 // such as from a default value.
125 //
126 // For example, `myprog subcommand --global-arg=value` where --global-arg defines
127 // a default value of `other` myprog would have an existing MatchedArg for
128 // --global-arg where the value is `other`, however the occurs will be 0.
129 let to_update = if let Some(parent_ma) = vals_map.get(global_arg) {
130 if parent_ma.occurs > 0 && ma.occurs == 0 {
131 parent_ma.clone()
132 } else {
133 ma.clone()
134 }
135 } else {
136 ma.clone()
137 };
138 vals_map.insert(global_arg, to_update);
041b39d2 139 }
abe05a73
XL
140 }
141 if let Some(ref mut sc) = self.0.subcommand {
041b39d2 142 let mut am = ArgMatcher(mem::replace(&mut sc.matches, ArgMatches::new()));
abe05a73 143 am.fill_in_global_values(global_arg_vec, vals_map);
041b39d2 144 mem::swap(&mut am.0, &mut sc.matches);
abe05a73
XL
145 }
146
a2a8927a 147 for (name, matched_arg) in vals_map.iter_mut() {
abe05a73 148 self.0.args.insert(name, matched_arg.clone());
041b39d2
XL
149 }
150 }
151
3dfed10e
XL
152 pub fn get_mut(&mut self, arg: &str) -> Option<&mut MatchedArg> {
153 self.0.args.get_mut(arg)
154 }
8bb4bdeb 155
3dfed10e
XL
156 pub fn get(&self, arg: &str) -> Option<&MatchedArg> {
157 self.0.args.get(arg)
158 }
8bb4bdeb 159
3dfed10e
XL
160 pub fn remove(&mut self, arg: &str) {
161 self.0.args.remove(arg);
162 }
8bb4bdeb
XL
163
164 pub fn remove_all(&mut self, args: &[&str]) {
165 for &arg in args {
166 self.0.args.remove(arg);
167 }
168 }
169
3dfed10e
XL
170 pub fn insert(&mut self, name: &'a str) {
171 self.0.args.insert(name, MatchedArg::new());
172 }
8bb4bdeb 173
3dfed10e
XL
174 pub fn contains(&self, arg: &str) -> bool {
175 self.0.args.contains_key(arg)
176 }
8bb4bdeb 177
3dfed10e
XL
178 pub fn is_empty(&self) -> bool {
179 self.0.args.is_empty()
180 }
8bb4bdeb 181
3dfed10e
XL
182 pub fn usage(&mut self, usage: String) {
183 self.0.usage = Some(usage);
184 }
8bb4bdeb 185
3dfed10e
XL
186 pub fn arg_names(&'a self) -> Vec<&'a str> {
187 self.0.args.keys().map(Deref::deref).collect()
188 }
8bb4bdeb 189
3dfed10e
XL
190 pub fn entry(&mut self, arg: &'a str) -> Entry<&'a str, MatchedArg> {
191 self.0.args.entry(arg)
192 }
8bb4bdeb 193
3dfed10e
XL
194 pub fn subcommand(&mut self, sc: SubCommand<'a>) {
195 self.0.subcommand = Some(Box::new(sc));
196 }
8bb4bdeb 197
3dfed10e
XL
198 pub fn subcommand_name(&self) -> Option<&str> {
199 self.0.subcommand_name()
200 }
8bb4bdeb 201
3dfed10e
XL
202 pub fn iter(&self) -> Iter<&str, MatchedArg> {
203 self.0.args.iter()
204 }
8bb4bdeb
XL
205
206 pub fn inc_occurrence_of(&mut self, arg: &'a str) {
041b39d2 207 debugln!("ArgMatcher::inc_occurrence_of: arg={}", arg);
8bb4bdeb
XL
208 if let Some(a) = self.get_mut(arg) {
209 a.occurs += 1;
210 return;
211 }
041b39d2 212 debugln!("ArgMatcher::inc_occurrence_of: first instance");
8bb4bdeb
XL
213 self.insert(arg);
214 }
215
216 pub fn inc_occurrences_of(&mut self, args: &[&'a str]) {
041b39d2 217 debugln!("ArgMatcher::inc_occurrences_of: args={:?}", args);
8bb4bdeb
XL
218 for arg in args {
219 self.inc_occurrence_of(arg);
220 }
221 }
222
223 pub fn add_val_to(&mut self, arg: &'a str, val: &OsStr) {
224 let ma = self.entry(arg).or_insert(MatchedArg {
225 occurs: 0,
0531ce1d 226 indices: Vec::with_capacity(1),
041b39d2 227 vals: Vec::with_capacity(1),
8bb4bdeb 228 });
041b39d2 229 ma.vals.push(val.to_owned());
8bb4bdeb
XL
230 }
231
0531ce1d
XL
232 pub fn add_index_to(&mut self, arg: &'a str, idx: usize) {
233 let ma = self.entry(arg).or_insert(MatchedArg {
234 occurs: 0,
235 indices: Vec::with_capacity(1),
236 vals: Vec::new(),
237 });
238 ma.indices.push(idx);
239 }
240
8bb4bdeb 241 pub fn needs_more_vals<'b, A>(&self, o: &A) -> bool
ff7c6d11
XL
242 where
243 A: AnyArg<'a, 'b>,
8bb4bdeb 244 {
041b39d2 245 debugln!("ArgMatcher::needs_more_vals: o={}", o.name());
8bb4bdeb
XL
246 if let Some(ma) = self.get(o.name()) {
247 if let Some(num) = o.num_vals() {
041b39d2 248 debugln!("ArgMatcher::needs_more_vals: num_vals...{}", num);
8bb4bdeb
XL
249 return if o.is_set(ArgSettings::Multiple) {
250 ((ma.vals.len() as u64) % num) != 0
251 } else {
252 num != (ma.vals.len() as u64)
253 };
254 } else if let Some(num) = o.max_vals() {
041b39d2 255 debugln!("ArgMatcher::needs_more_vals: max_vals...{}", num);
a2a8927a 256 return (ma.vals.len() as u64) <= num;
8bb4bdeb 257 } else if o.min_vals().is_some() {
041b39d2 258 debugln!("ArgMatcher::needs_more_vals: min_vals...true");
8bb4bdeb
XL
259 return true;
260 }
261 return o.is_set(ArgSettings::Multiple);
262 }
263 true
264 }
265}
266
a2a8927a
XL
267// Not changing to From just to not deal with possible breaking changes on v2 since v3 is coming
268// in the future anyways
269#[cfg_attr(feature = "cargo-clippy", allow(clippy::from_over_into))]
8bb4bdeb 270impl<'a> Into<ArgMatches<'a>> for ArgMatcher<'a> {
3dfed10e
XL
271 fn into(self) -> ArgMatches<'a> {
272 self.0
273 }
8bb4bdeb 274}