clap/args/
arg_matcher.rs

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