clap/args/arg_builder/
positional.rs1use std::borrow::Cow;
3use std::fmt::{Display, Formatter, Result};
4use std::rc::Rc;
5use std::result::Result as StdResult;
6use std::ffi::{OsStr, OsString};
7use std::mem;
8
9use Arg;
11use args::{AnyArg, ArgSettings, Base, DispOrder, Valued};
12use INTERNAL_ERROR_MSG;
13use map::{self, VecMap};
14
15#[allow(missing_debug_implementations)]
16#[doc(hidden)]
17#[derive(Clone, Default)]
18pub struct PosBuilder<'n, 'e>
19where
20 'n: 'e,
21{
22 pub b: Base<'n, 'e>,
23 pub v: Valued<'n, 'e>,
24 pub index: u64,
25}
26
27impl<'n, 'e> PosBuilder<'n, 'e> {
28 pub fn new(name: &'n str, idx: u64) -> Self {
29 PosBuilder {
30 b: Base::new(name),
31 index: idx,
32 ..Default::default()
33 }
34 }
35
36 pub fn from_arg_ref(a: &Arg<'n, 'e>, idx: u64) -> Self {
37 let mut pb = PosBuilder {
38 b: Base::from(a),
39 v: Valued::from(a),
40 index: idx,
41 };
42 if a.v.max_vals.is_some() || a.v.min_vals.is_some()
43 || (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1)
44 {
45 pb.b.settings.set(ArgSettings::Multiple);
46 }
47 pb
48 }
49
50 pub fn from_arg(mut a: Arg<'n, 'e>, idx: u64) -> Self {
51 if a.v.max_vals.is_some() || a.v.min_vals.is_some()
52 || (a.v.num_vals.is_some() && a.v.num_vals.unwrap() > 1)
53 {
54 a.b.settings.set(ArgSettings::Multiple);
55 }
56 PosBuilder {
57 b: mem::replace(&mut a.b, Base::default()),
58 v: mem::replace(&mut a.v, Valued::default()),
59 index: idx,
60 }
61 }
62
63 pub fn multiple_str(&self) -> &str {
64 let mult_vals = self.v
65 .val_names
66 .as_ref()
67 .map_or(true, |names| names.len() < 2);
68 if self.is_set(ArgSettings::Multiple) && mult_vals {
69 "..."
70 } else {
71 ""
72 }
73 }
74
75 pub fn name_no_brackets(&self) -> Cow<str> {
76 debugln!("PosBuilder::name_no_brackets;");
77 let mut delim = String::new();
78 delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
79 self.v.val_delim.expect(INTERNAL_ERROR_MSG)
80 } else {
81 ' '
82 });
83 if let Some(ref names) = self.v.val_names {
84 debugln!("PosBuilder:name_no_brackets: val_names={:#?}", names);
85 if names.len() > 1 {
86 Cow::Owned(
87 names
88 .values()
89 .map(|n| format!("<{}>", n))
90 .collect::<Vec<_>>()
91 .join(&*delim),
92 )
93 } else {
94 Cow::Borrowed(names.values().next().expect(INTERNAL_ERROR_MSG))
95 }
96 } else {
97 debugln!("PosBuilder:name_no_brackets: just name");
98 Cow::Borrowed(self.b.name)
99 }
100 }
101}
102
103impl<'n, 'e> Display for PosBuilder<'n, 'e> {
104 fn fmt(&self, f: &mut Formatter) -> Result {
105 let mut delim = String::new();
106 delim.push(if self.is_set(ArgSettings::RequireDelimiter) {
107 self.v.val_delim.expect(INTERNAL_ERROR_MSG)
108 } else {
109 ' '
110 });
111 if let Some(ref names) = self.v.val_names {
112 write!(
113 f,
114 "{}",
115 names
116 .values()
117 .map(|n| format!("<{}>", n))
118 .collect::<Vec<_>>()
119 .join(&*delim)
120 )?;
121 } else {
122 write!(f, "<{}>", self.b.name)?;
123 }
124 if self.b.settings.is_set(ArgSettings::Multiple)
125 && (self.v.val_names.is_none() || self.v.val_names.as_ref().unwrap().len() == 1)
126 {
127 write!(f, "...")?;
128 }
129
130 Ok(())
131 }
132}
133
134impl<'n, 'e> AnyArg<'n, 'e> for PosBuilder<'n, 'e> {
135 fn name(&self) -> &'n str { self.b.name }
136 fn overrides(&self) -> Option<&[&'e str]> { self.b.overrides.as_ref().map(|o| &o[..]) }
137 fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
138 self.b.requires.as_ref().map(|o| &o[..])
139 }
140 fn blacklist(&self) -> Option<&[&'e str]> { self.b.blacklist.as_ref().map(|o| &o[..]) }
141 fn required_unless(&self) -> Option<&[&'e str]> { self.b.r_unless.as_ref().map(|o| &o[..]) }
142 fn val_names(&self) -> Option<&VecMap<&'e str>> { self.v.val_names.as_ref() }
143 fn is_set(&self, s: ArgSettings) -> bool { self.b.settings.is_set(s) }
144 fn set(&mut self, s: ArgSettings) { self.b.settings.set(s) }
145 fn has_switch(&self) -> bool { false }
146 fn max_vals(&self) -> Option<u64> { self.v.max_vals }
147 fn val_terminator(&self) -> Option<&'e str> { self.v.terminator }
148 fn num_vals(&self) -> Option<u64> { self.v.num_vals }
149 fn possible_vals(&self) -> Option<&[&'e str]> { self.v.possible_vals.as_ref().map(|o| &o[..]) }
150 fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> {
151 self.v.validator.as_ref()
152 }
153 fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> {
154 self.v.validator_os.as_ref()
155 }
156 fn min_vals(&self) -> Option<u64> { self.v.min_vals }
157 fn short(&self) -> Option<char> { None }
158 fn long(&self) -> Option<&'e str> { None }
159 fn val_delim(&self) -> Option<char> { self.v.val_delim }
160 fn takes_value(&self) -> bool { true }
161 fn help(&self) -> Option<&'e str> { self.b.help }
162 fn long_help(&self) -> Option<&'e str> { self.b.long_help }
163 fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
164 self.v.default_vals_ifs.as_ref().map(|vm| vm.values())
165 }
166 fn default_val(&self) -> Option<&'e OsStr> { self.v.default_val }
167 fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
168 self.v
169 .env
170 .as_ref()
171 .map(|&(key, ref value)| (key, value.as_ref()))
172 }
173 fn longest_filter(&self) -> bool { true }
174 fn aliases(&self) -> Option<Vec<&'e str>> { None }
175}
176
177impl<'n, 'e> DispOrder for PosBuilder<'n, 'e> {
178 fn disp_ord(&self) -> usize { self.index as usize }
179}
180
181impl<'n, 'e> PartialEq for PosBuilder<'n, 'e> {
182 fn eq(&self, other: &PosBuilder<'n, 'e>) -> bool { self.b == other.b }
183}
184
185#[cfg(test)]
186mod test {
187 use args::settings::ArgSettings;
188 use super::PosBuilder;
189 use map::VecMap;
190
191 #[test]
192 fn display_mult() {
193 let mut p = PosBuilder::new("pos", 1);
194 p.b.settings.set(ArgSettings::Multiple);
195
196 assert_eq!(&*format!("{}", p), "<pos>...");
197 }
198
199 #[test]
200 fn display_required() {
201 let mut p2 = PosBuilder::new("pos", 1);
202 p2.b.settings.set(ArgSettings::Required);
203
204 assert_eq!(&*format!("{}", p2), "<pos>");
205 }
206
207 #[test]
208 fn display_val_names() {
209 let mut p2 = PosBuilder::new("pos", 1);
210 let mut vm = VecMap::new();
211 vm.insert(0, "file1");
212 vm.insert(1, "file2");
213 p2.v.val_names = Some(vm);
214
215 assert_eq!(&*format!("{}", p2), "<file1> <file2>");
216 }
217
218 #[test]
219 fn display_val_names_req() {
220 let mut p2 = PosBuilder::new("pos", 1);
221 p2.b.settings.set(ArgSettings::Required);
222 let mut vm = VecMap::new();
223 vm.insert(0, "file1");
224 vm.insert(1, "file2");
225 p2.v.val_names = Some(vm);
226
227 assert_eq!(&*format!("{}", p2), "<file1> <file2>");
228 }
229}