1 // Std 2 use std::ffi::OsString; 3 use std::mem; 4 use std::ops::Deref; 5 6 // Internal 7 use crate::builder::{Arg, ArgPredicate, Command}; 8 use crate::parser::Identifier; 9 use crate::parser::PendingArg; 10 use crate::parser::{ArgMatches, MatchedArg, SubCommand, ValueSource}; 11 use crate::util::AnyValue; 12 use crate::util::FlatMap; 13 use crate::util::Id; 14 use crate::INTERNAL_ERROR_MSG; 15 16 #[derive(Debug, Default)] 17 pub(crate) struct ArgMatcher { 18 matches: ArgMatches, 19 pending: Option<PendingArg>, 20 } 21 22 impl ArgMatcher { new(_cmd: &Command) -> Self23 pub(crate) fn new(_cmd: &Command) -> Self { 24 ArgMatcher { 25 matches: ArgMatches { 26 #[cfg(debug_assertions)] 27 valid_args: { 28 let args = _cmd.get_arguments().map(|a| a.get_id().clone()); 29 let groups = _cmd.get_groups().map(|g| g.get_id().clone()); 30 args.chain(groups).collect() 31 }, 32 #[cfg(debug_assertions)] 33 valid_subcommands: _cmd 34 .get_subcommands() 35 .map(|sc| sc.get_name_str().clone()) 36 .collect(), 37 ..Default::default() 38 }, 39 pending: None, 40 } 41 } 42 into_inner(self) -> ArgMatches43 pub(crate) fn into_inner(self) -> ArgMatches { 44 self.matches 45 } 46 propagate_globals(&mut self, global_arg_vec: &[Id])47 pub(crate) fn propagate_globals(&mut self, global_arg_vec: &[Id]) { 48 debug!("ArgMatcher::get_global_values: global_arg_vec={global_arg_vec:?}"); 49 let mut vals_map = FlatMap::new(); 50 self.fill_in_global_values(global_arg_vec, &mut vals_map); 51 } 52 fill_in_global_values( &mut self, global_arg_vec: &[Id], vals_map: &mut FlatMap<Id, MatchedArg>, )53 fn fill_in_global_values( 54 &mut self, 55 global_arg_vec: &[Id], 56 vals_map: &mut FlatMap<Id, MatchedArg>, 57 ) { 58 for global_arg in global_arg_vec { 59 if let Some(ma) = self.get(global_arg) { 60 // We have to check if the parent's global arg wasn't used but still exists 61 // such as from a default value. 62 // 63 // For example, `myprog subcommand --global-arg=value` where `--global-arg` defines 64 // a default value of `other` myprog would have an existing MatchedArg for 65 // `--global-arg` where the value is `other` 66 let to_update = if let Some(parent_ma) = vals_map.get(global_arg) { 67 if parent_ma.source() > ma.source() { 68 parent_ma 69 } else { 70 ma 71 } 72 } else { 73 ma 74 } 75 .clone(); 76 vals_map.insert(global_arg.clone(), to_update); 77 } 78 } 79 if let Some(ref mut sc) = self.matches.subcommand { 80 let mut am = ArgMatcher { 81 matches: mem::take(&mut sc.matches), 82 pending: None, 83 }; 84 am.fill_in_global_values(global_arg_vec, vals_map); 85 mem::swap(&mut am.matches, &mut sc.matches); 86 } 87 88 for (name, matched_arg) in vals_map.iter_mut() { 89 self.matches.args.insert(name.clone(), matched_arg.clone()); 90 } 91 } 92 get(&self, arg: &Id) -> Option<&MatchedArg>93 pub(crate) fn get(&self, arg: &Id) -> Option<&MatchedArg> { 94 self.matches.args.get(arg) 95 } 96 get_mut(&mut self, arg: &Id) -> Option<&mut MatchedArg>97 pub(crate) fn get_mut(&mut self, arg: &Id) -> Option<&mut MatchedArg> { 98 self.matches.args.get_mut(arg) 99 } 100 remove(&mut self, arg: &Id) -> bool101 pub(crate) fn remove(&mut self, arg: &Id) -> bool { 102 self.matches.args.remove(arg).is_some() 103 } 104 contains(&self, arg: &Id) -> bool105 pub(crate) fn contains(&self, arg: &Id) -> bool { 106 self.matches.args.contains_key(arg) 107 } 108 arg_ids(&self) -> std::slice::Iter<'_, Id>109 pub(crate) fn arg_ids(&self) -> std::slice::Iter<'_, Id> { 110 self.matches.args.keys() 111 } 112 args(&self) -> crate::util::flat_map::Iter<'_, Id, MatchedArg>113 pub(crate) fn args(&self) -> crate::util::flat_map::Iter<'_, Id, MatchedArg> { 114 self.matches.args.iter() 115 } 116 entry(&mut self, arg: Id) -> crate::util::Entry<Id, MatchedArg>117 pub(crate) fn entry(&mut self, arg: Id) -> crate::util::Entry<Id, MatchedArg> { 118 self.matches.args.entry(arg) 119 } 120 subcommand(&mut self, sc: SubCommand)121 pub(crate) fn subcommand(&mut self, sc: SubCommand) { 122 self.matches.subcommand = Some(Box::new(sc)); 123 } 124 subcommand_name(&self) -> Option<&str>125 pub(crate) fn subcommand_name(&self) -> Option<&str> { 126 self.matches.subcommand_name() 127 } 128 check_explicit(&self, arg: &Id, predicate: &ArgPredicate) -> bool129 pub(crate) fn check_explicit(&self, arg: &Id, predicate: &ArgPredicate) -> bool { 130 self.get(arg) 131 .map(|a| a.check_explicit(predicate)) 132 .unwrap_or_default() 133 } 134 start_custom_arg(&mut self, arg: &Arg, source: ValueSource)135 pub(crate) fn start_custom_arg(&mut self, arg: &Arg, source: ValueSource) { 136 let id = arg.get_id().clone(); 137 debug!("ArgMatcher::start_custom_arg: id={id:?}, source={source:?}"); 138 let ma = self.entry(id).or_insert(MatchedArg::new_arg(arg)); 139 debug_assert_eq!(ma.type_id(), Some(arg.get_value_parser().type_id())); 140 ma.set_source(source); 141 ma.new_val_group(); 142 } 143 start_custom_group(&mut self, id: Id, source: ValueSource)144 pub(crate) fn start_custom_group(&mut self, id: Id, source: ValueSource) { 145 debug!("ArgMatcher::start_custom_arg: id={id:?}, source={source:?}"); 146 let ma = self.entry(id).or_insert(MatchedArg::new_group()); 147 debug_assert_eq!(ma.type_id(), None); 148 ma.set_source(source); 149 ma.new_val_group(); 150 } 151 start_occurrence_of_external(&mut self, cmd: &crate::Command)152 pub(crate) fn start_occurrence_of_external(&mut self, cmd: &crate::Command) { 153 let id = Id::from_static_ref(Id::EXTERNAL); 154 debug!("ArgMatcher::start_occurrence_of_external: id={id:?}"); 155 let ma = self.entry(id).or_insert(MatchedArg::new_external(cmd)); 156 debug_assert_eq!( 157 ma.type_id(), 158 Some( 159 cmd.get_external_subcommand_value_parser() 160 .expect(INTERNAL_ERROR_MSG) 161 .type_id() 162 ) 163 ); 164 ma.set_source(ValueSource::CommandLine); 165 ma.new_val_group(); 166 } 167 add_val_to(&mut self, arg: &Id, val: AnyValue, raw_val: OsString)168 pub(crate) fn add_val_to(&mut self, arg: &Id, val: AnyValue, raw_val: OsString) { 169 let ma = self.get_mut(arg).expect(INTERNAL_ERROR_MSG); 170 ma.append_val(val, raw_val); 171 } 172 add_index_to(&mut self, arg: &Id, idx: usize)173 pub(crate) fn add_index_to(&mut self, arg: &Id, idx: usize) { 174 let ma = self.get_mut(arg).expect(INTERNAL_ERROR_MSG); 175 ma.push_index(idx); 176 } 177 needs_more_vals(&self, o: &Arg) -> bool178 pub(crate) fn needs_more_vals(&self, o: &Arg) -> bool { 179 let num_pending = self 180 .pending 181 .as_ref() 182 .and_then(|p| (p.id == *o.get_id()).then_some(p.raw_vals.len())) 183 .unwrap_or(0); 184 debug!( 185 "ArgMatcher::needs_more_vals: o={}, pending={}", 186 o.get_id(), 187 num_pending 188 ); 189 let expected = o.get_num_args().expect(INTERNAL_ERROR_MSG); 190 debug!("ArgMatcher::needs_more_vals: expected={expected}, actual={num_pending}"); 191 expected.accepts_more(num_pending) 192 } 193 pending_arg_id(&self) -> Option<&Id>194 pub(crate) fn pending_arg_id(&self) -> Option<&Id> { 195 self.pending.as_ref().map(|p| &p.id) 196 } 197 pending_values_mut( &mut self, id: &Id, ident: Option<Identifier>, trailing_values: bool, ) -> &mut Vec<OsString>198 pub(crate) fn pending_values_mut( 199 &mut self, 200 id: &Id, 201 ident: Option<Identifier>, 202 trailing_values: bool, 203 ) -> &mut Vec<OsString> { 204 let pending = self.pending.get_or_insert_with(|| PendingArg { 205 id: id.clone(), 206 ident, 207 raw_vals: Default::default(), 208 trailing_idx: None, 209 }); 210 debug_assert_eq!(pending.id, *id, "{INTERNAL_ERROR_MSG}"); 211 if ident.is_some() { 212 debug_assert_eq!(pending.ident, ident, "{INTERNAL_ERROR_MSG}"); 213 } 214 if trailing_values { 215 pending.trailing_idx.get_or_insert(pending.raw_vals.len()); 216 } 217 &mut pending.raw_vals 218 } 219 start_trailing(&mut self)220 pub(crate) fn start_trailing(&mut self) { 221 if let Some(pending) = &mut self.pending { 222 // Allow asserting its started on subsequent calls 223 pending.trailing_idx.get_or_insert(pending.raw_vals.len()); 224 } 225 } 226 take_pending(&mut self) -> Option<PendingArg>227 pub(crate) fn take_pending(&mut self) -> Option<PendingArg> { 228 self.pending.take() 229 } 230 } 231 232 impl Deref for ArgMatcher { 233 type Target = ArgMatches; 234 deref(&self) -> &Self::Target235 fn deref(&self) -> &Self::Target { 236 &self.matches 237 } 238 } 239