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