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