1 // Std
2 use std::ffi::{OsStr, OsString};
3 use std::fmt::{Display, Formatter, Result};
4 use std::mem;
5 use std::rc::Rc;
6 use std::result::Result as StdResult;
7 
8 // Internal
9 use args::{AnyArg, Arg, ArgSettings, Base, DispOrder, Switched, Valued};
10 use map::{self, VecMap};
11 use INTERNAL_ERROR_MSG;
12 
13 #[allow(missing_debug_implementations)]
14 #[doc(hidden)]
15 #[derive(Default, Clone)]
16 pub struct OptBuilder<'n, 'e>
17 where
18     'n: 'e,
19 {
20     pub b: Base<'n, 'e>,
21     pub s: Switched<'e>,
22     pub v: Valued<'n, 'e>,
23 }
24 
25 impl<'n, 'e> OptBuilder<'n, 'e> {
new(name: &'n str) -> Self26     pub fn new(name: &'n str) -> Self {
27         OptBuilder {
28             b: Base::new(name),
29             ..Default::default()
30         }
31     }
32 }
33 
34 impl<'n, 'e, 'z> From<&'z Arg<'n, 'e>> for OptBuilder<'n, 'e> {
from(a: &'z Arg<'n, 'e>) -> Self35     fn from(a: &'z Arg<'n, 'e>) -> Self {
36         OptBuilder {
37             b: Base::from(a),
38             s: Switched::from(a),
39             v: Valued::from(a),
40         }
41     }
42 }
43 
44 impl<'n, 'e> From<Arg<'n, 'e>> for OptBuilder<'n, 'e> {
from(mut a: Arg<'n, 'e>) -> Self45     fn from(mut a: Arg<'n, 'e>) -> Self {
46         a.v.fill_in();
47         OptBuilder {
48             b: mem::replace(&mut a.b, Base::default()),
49             s: mem::replace(&mut a.s, Switched::default()),
50             v: mem::replace(&mut a.v, Valued::default()),
51         }
52     }
53 }
54 
55 impl<'n, 'e> Display for OptBuilder<'n, 'e> {
fmt(&self, f: &mut Formatter) -> Result56     fn fmt(&self, f: &mut Formatter) -> Result {
57         debugln!("OptBuilder::fmt:{}", self.b.name);
58         let sep = if self.b.is_set(ArgSettings::RequireEquals) {
59             "="
60         } else {
61             " "
62         };
63         // Write the name such --long or -l
64         if let Some(l) = self.s.long {
65             write!(f, "--{}{}", l, sep)?;
66         } else {
67             write!(f, "-{}{}", self.s.short.unwrap(), sep)?;
68         }
69         let delim = if self.is_set(ArgSettings::RequireDelimiter) {
70             self.v.val_delim.expect(INTERNAL_ERROR_MSG)
71         } else {
72             ' '
73         };
74 
75         // Write the values such as <name1> <name2>
76         if let Some(ref vec) = self.v.val_names {
77             let mut it = vec.iter().peekable();
78             while let Some((_, val)) = it.next() {
79                 write!(f, "<{}>", val)?;
80                 if it.peek().is_some() {
81                     write!(f, "{}", delim)?;
82                 }
83             }
84             let num = vec.len();
85             if self.is_set(ArgSettings::Multiple) && num == 1 {
86                 write!(f, "...")?;
87             }
88         } else if let Some(num) = self.v.num_vals {
89             let mut it = (0..num).peekable();
90             while let Some(_) = it.next() {
91                 write!(f, "<{}>", self.b.name)?;
92                 if it.peek().is_some() {
93                     write!(f, "{}", delim)?;
94                 }
95             }
96             if self.is_set(ArgSettings::Multiple) && num == 1 {
97                 write!(f, "...")?;
98             }
99         } else {
100             write!(
101                 f,
102                 "<{}>{}",
103                 self.b.name,
104                 if self.is_set(ArgSettings::Multiple) {
105                     "..."
106                 } else {
107                     ""
108                 }
109             )?;
110         }
111 
112         Ok(())
113     }
114 }
115 
116 impl<'n, 'e> AnyArg<'n, 'e> for OptBuilder<'n, 'e> {
name(&self) -> &'n str117     fn name(&self) -> &'n str {
118         self.b.name
119     }
overrides(&self) -> Option<&[&'e str]>120     fn overrides(&self) -> Option<&[&'e str]> {
121         self.b.overrides.as_ref().map(|o| &o[..])
122     }
requires(&self) -> Option<&[(Option<&'e str>, &'n str)]>123     fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
124         self.b.requires.as_ref().map(|o| &o[..])
125     }
blacklist(&self) -> Option<&[&'e str]>126     fn blacklist(&self) -> Option<&[&'e str]> {
127         self.b.blacklist.as_ref().map(|o| &o[..])
128     }
required_unless(&self) -> Option<&[&'e str]>129     fn required_unless(&self) -> Option<&[&'e str]> {
130         self.b.r_unless.as_ref().map(|o| &o[..])
131     }
val_names(&self) -> Option<&VecMap<&'e str>>132     fn val_names(&self) -> Option<&VecMap<&'e str>> {
133         self.v.val_names.as_ref()
134     }
is_set(&self, s: ArgSettings) -> bool135     fn is_set(&self, s: ArgSettings) -> bool {
136         self.b.settings.is_set(s)
137     }
has_switch(&self) -> bool138     fn has_switch(&self) -> bool {
139         true
140     }
set(&mut self, s: ArgSettings)141     fn set(&mut self, s: ArgSettings) {
142         self.b.settings.set(s)
143     }
max_vals(&self) -> Option<u64>144     fn max_vals(&self) -> Option<u64> {
145         self.v.max_vals
146     }
val_terminator(&self) -> Option<&'e str>147     fn val_terminator(&self) -> Option<&'e str> {
148         self.v.terminator
149     }
num_vals(&self) -> Option<u64>150     fn num_vals(&self) -> Option<u64> {
151         self.v.num_vals
152     }
possible_vals(&self) -> Option<&[&'e str]>153     fn possible_vals(&self) -> Option<&[&'e str]> {
154         self.v.possible_vals.as_ref().map(|o| &o[..])
155     }
validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>>156     fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> {
157         self.v.validator.as_ref()
158     }
validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>>159     fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> {
160         self.v.validator_os.as_ref()
161     }
min_vals(&self) -> Option<u64>162     fn min_vals(&self) -> Option<u64> {
163         self.v.min_vals
164     }
short(&self) -> Option<char>165     fn short(&self) -> Option<char> {
166         self.s.short
167     }
long(&self) -> Option<&'e str>168     fn long(&self) -> Option<&'e str> {
169         self.s.long
170     }
val_delim(&self) -> Option<char>171     fn val_delim(&self) -> Option<char> {
172         self.v.val_delim
173     }
takes_value(&self) -> bool174     fn takes_value(&self) -> bool {
175         true
176     }
help(&self) -> Option<&'e str>177     fn help(&self) -> Option<&'e str> {
178         self.b.help
179     }
long_help(&self) -> Option<&'e str>180     fn long_help(&self) -> Option<&'e str> {
181         self.b.long_help
182     }
default_val(&self) -> Option<&'e OsStr>183     fn default_val(&self) -> Option<&'e OsStr> {
184         self.v.default_val
185     }
default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>>186     fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
187         self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
188     }
env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)>189     fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
190         self.v
191             .env
192             .as_ref()
193             .map(|&(key, ref value)| (key, value.as_ref()))
194     }
longest_filter(&self) -> bool195     fn longest_filter(&self) -> bool {
196         true
197     }
aliases(&self) -> Option<Vec<&'e str>>198     fn aliases(&self) -> Option<Vec<&'e str>> {
199         if let Some(ref aliases) = self.s.aliases {
200             let vis_aliases: Vec<_> = aliases
201                 .iter()
202                 .filter_map(|&(n, v)| if v { Some(n) } else { None })
203                 .collect();
204             if vis_aliases.is_empty() {
205                 None
206             } else {
207                 Some(vis_aliases)
208             }
209         } else {
210             None
211         }
212     }
213 }
214 
215 impl<'n, 'e> DispOrder for OptBuilder<'n, 'e> {
disp_ord(&self) -> usize216     fn disp_ord(&self) -> usize {
217         self.s.disp_ord
218     }
219 }
220 
221 impl<'n, 'e> PartialEq for OptBuilder<'n, 'e> {
eq(&self, other: &OptBuilder<'n, 'e>) -> bool222     fn eq(&self, other: &OptBuilder<'n, 'e>) -> bool {
223         self.b == other.b
224     }
225 }
226 
227 #[cfg(test)]
228 mod test {
229     use super::OptBuilder;
230     use args::settings::ArgSettings;
231     use map::VecMap;
232 
233     #[test]
optbuilder_display1()234     fn optbuilder_display1() {
235         let mut o = OptBuilder::new("opt");
236         o.s.long = Some("option");
237         o.b.settings.set(ArgSettings::Multiple);
238 
239         assert_eq!(&*format!("{}", o), "--option <opt>...");
240     }
241 
242     #[test]
optbuilder_display2()243     fn optbuilder_display2() {
244         let mut v_names = VecMap::new();
245         v_names.insert(0, "file");
246         v_names.insert(1, "name");
247 
248         let mut o2 = OptBuilder::new("opt");
249         o2.s.short = Some('o');
250         o2.v.val_names = Some(v_names);
251 
252         assert_eq!(&*format!("{}", o2), "-o <file> <name>");
253     }
254 
255     #[test]
optbuilder_display3()256     fn optbuilder_display3() {
257         let mut v_names = VecMap::new();
258         v_names.insert(0, "file");
259         v_names.insert(1, "name");
260 
261         let mut o2 = OptBuilder::new("opt");
262         o2.s.short = Some('o');
263         o2.v.val_names = Some(v_names);
264         o2.b.settings.set(ArgSettings::Multiple);
265 
266         assert_eq!(&*format!("{}", o2), "-o <file> <name>");
267     }
268 
269     #[test]
optbuilder_display_single_alias()270     fn optbuilder_display_single_alias() {
271         let mut o = OptBuilder::new("opt");
272         o.s.long = Some("option");
273         o.s.aliases = Some(vec![("als", true)]);
274 
275         assert_eq!(&*format!("{}", o), "--option <opt>");
276     }
277 
278     #[test]
optbuilder_display_multiple_aliases()279     fn optbuilder_display_multiple_aliases() {
280         let mut o = OptBuilder::new("opt");
281         o.s.long = Some("option");
282         o.s.aliases = Some(vec![
283             ("als_not_visible", false),
284             ("als2", true),
285             ("als3", true),
286             ("als4", true),
287         ]);
288         assert_eq!(&*format!("{}", o), "--option <opt>");
289     }
290 }
291