clap/args/arg_builder/
flag.rs

1// Std
2use std::{
3    convert::From,
4    ffi::{OsStr, OsString},
5    fmt::{Display, Formatter, Result},
6    mem,
7    rc::Rc,
8    result::Result as StdResult,
9};
10
11// Internal
12use crate::{
13    args::{AnyArg, Arg, ArgSettings, Base, DispOrder, Switched},
14    map::{self, VecMap},
15};
16
17#[derive(Default, Clone, Debug)]
18#[doc(hidden)]
19pub struct FlagBuilder<'n, 'e>
20where
21    'n: 'e,
22{
23    pub b: Base<'n, 'e>,
24    pub s: Switched<'e>,
25}
26
27impl<'n, 'e> FlagBuilder<'n, 'e> {
28    pub fn new(name: &'n str) -> Self {
29        FlagBuilder {
30            b: Base::new(name),
31            ..Default::default()
32        }
33    }
34}
35
36impl<'a, 'b, 'z> From<&'z Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
37    fn from(a: &'z Arg<'a, 'b>) -> Self {
38        FlagBuilder {
39            b: Base::from(a),
40            s: Switched::from(a),
41        }
42    }
43}
44
45impl<'a, 'b> From<Arg<'a, 'b>> for FlagBuilder<'a, 'b> {
46    fn from(mut a: Arg<'a, 'b>) -> Self {
47        FlagBuilder {
48            b: mem::take(&mut a.b),
49            s: mem::take(&mut a.s),
50        }
51    }
52}
53
54impl<'n, 'e> Display for FlagBuilder<'n, 'e> {
55    fn fmt(&self, f: &mut Formatter) -> Result {
56        if let Some(l) = self.s.long {
57            write!(f, "--{}", l)?;
58        } else {
59            write!(f, "-{}", self.s.short.unwrap())?;
60        }
61
62        Ok(())
63    }
64}
65
66impl<'n, 'e> AnyArg<'n, 'e> for FlagBuilder<'n, 'e> {
67    fn name(&self) -> &'n str {
68        self.b.name
69    }
70    fn overrides(&self) -> Option<&[&'e str]> {
71        self.b.overrides.as_ref().map(|o| &o[..])
72    }
73    fn requires(&self) -> Option<&[(Option<&'e str>, &'n str)]> {
74        self.b.requires.as_ref().map(|o| &o[..])
75    }
76    fn blacklist(&self) -> Option<&[&'e str]> {
77        self.b.blacklist.as_ref().map(|o| &o[..])
78    }
79    fn required_unless(&self) -> Option<&[&'e str]> {
80        self.b.r_unless.as_ref().map(|o| &o[..])
81    }
82    fn is_set(&self, s: ArgSettings) -> bool {
83        self.b.settings.is_set(s)
84    }
85    fn has_switch(&self) -> bool {
86        true
87    }
88    fn takes_value(&self) -> bool {
89        false
90    }
91    fn set(&mut self, s: ArgSettings) {
92        self.b.settings.set(s)
93    }
94    fn max_vals(&self) -> Option<u64> {
95        None
96    }
97    fn val_names(&self) -> Option<&VecMap<&'e str>> {
98        None
99    }
100    fn num_vals(&self) -> Option<u64> {
101        None
102    }
103    fn possible_vals(&self) -> Option<&[&'e str]> {
104        None
105    }
106    #[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
107    fn validator(&self) -> Option<&Rc<Fn(String) -> StdResult<(), String>>> {
108        None
109    }
110    #[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
111    fn validator_os(&self) -> Option<&Rc<Fn(&OsStr) -> StdResult<(), OsString>>> {
112        None
113    }
114    fn min_vals(&self) -> Option<u64> {
115        None
116    }
117    fn short(&self) -> Option<char> {
118        self.s.short
119    }
120    fn long(&self) -> Option<&'e str> {
121        self.s.long
122    }
123    fn val_delim(&self) -> Option<char> {
124        None
125    }
126    fn help(&self) -> Option<&'e str> {
127        self.b.help
128    }
129    fn long_help(&self) -> Option<&'e str> {
130        self.b.long_help
131    }
132    fn val_terminator(&self) -> Option<&'e str> {
133        None
134    }
135    fn default_val(&self) -> Option<&'e OsStr> {
136        None
137    }
138    fn default_vals_ifs(&self) -> Option<map::Values<(&'n str, Option<&'e OsStr>, &'e OsStr)>> {
139        None
140    }
141    fn env<'s>(&'s self) -> Option<(&'n OsStr, Option<&'s OsString>)> {
142        None
143    }
144    fn longest_filter(&self) -> bool {
145        self.s.long.is_some()
146    }
147    fn aliases(&self) -> Option<Vec<&'e str>> {
148        if let Some(ref aliases) = self.s.aliases {
149            let vis_aliases: Vec<_> = aliases
150                .iter()
151                .filter_map(|&(n, v)| if v { Some(n) } else { None })
152                .collect();
153            if vis_aliases.is_empty() {
154                None
155            } else {
156                Some(vis_aliases)
157            }
158        } else {
159            None
160        }
161    }
162}
163
164impl<'n, 'e> DispOrder for FlagBuilder<'n, 'e> {
165    fn disp_ord(&self) -> usize {
166        self.s.disp_ord
167    }
168}
169
170impl<'n, 'e> PartialEq for FlagBuilder<'n, 'e> {
171    fn eq(&self, other: &FlagBuilder<'n, 'e>) -> bool {
172        self.b == other.b
173    }
174}
175
176#[cfg(test)]
177mod test {
178    use super::FlagBuilder;
179    use crate::args::settings::ArgSettings;
180
181    #[test]
182    fn flagbuilder_display() {
183        let mut f = FlagBuilder::new("flg");
184        f.b.settings.set(ArgSettings::Multiple);
185        f.s.long = Some("flag");
186
187        assert_eq!(&*format!("{}", f), "--flag");
188
189        let mut f2 = FlagBuilder::new("flg");
190        f2.s.short = Some('f');
191
192        assert_eq!(&*format!("{}", f2), "-f");
193    }
194
195    #[test]
196    fn flagbuilder_display_single_alias() {
197        let mut f = FlagBuilder::new("flg");
198        f.s.long = Some("flag");
199        f.s.aliases = Some(vec![("als", true)]);
200
201        assert_eq!(&*format!("{}", f), "--flag");
202    }
203
204    #[test]
205    fn flagbuilder_display_multiple_aliases() {
206        let mut f = FlagBuilder::new("flg");
207        f.s.short = Some('f');
208        f.s.aliases = Some(vec![
209            ("alias_not_visible", false),
210            ("f2", true),
211            ("f3", true),
212            ("f4", true),
213        ]);
214        assert_eq!(&*format!("{}", f), "-f");
215    }
216}