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