1 | use crate::builder::IntoResettable; |
2 | use crate::builder::Str; |
3 | use crate::builder::StyledStr; |
4 | use crate::util::eq_ignore_case; |
5 | |
6 | /// A possible value of an argument. |
7 | /// |
8 | /// This is used for specifying [possible values] of [Args]. |
9 | /// |
10 | /// See also [`PossibleValuesParser`][crate::builder::PossibleValuesParser] |
11 | /// |
12 | /// **NOTE:** Most likely you can use strings, rather than `PossibleValue` as it is only required |
13 | /// to [hide] single values from help messages and shell completions or to attach [help] to |
14 | /// possible values. |
15 | /// |
16 | /// # Examples |
17 | /// |
18 | /// ```rust |
19 | /// # use clap_builder as clap; |
20 | /// # use clap::{Arg, builder::PossibleValue, ArgAction}; |
21 | /// let cfg = Arg::new("config" ) |
22 | /// .action(ArgAction::Set) |
23 | /// .value_name("FILE" ) |
24 | /// .value_parser([ |
25 | /// PossibleValue::new("fast" ), |
26 | /// PossibleValue::new("slow" ).help("slower than fast" ), |
27 | /// PossibleValue::new("secret speed" ).hide(true) |
28 | /// ]); |
29 | /// ``` |
30 | /// |
31 | /// [Args]: crate::Arg |
32 | /// [possible values]: crate::builder::ValueParser::possible_values |
33 | /// [hide]: PossibleValue::hide() |
34 | /// [help]: PossibleValue::help() |
35 | #[derive(Debug, Default, Clone, PartialEq, Eq)] |
36 | pub struct PossibleValue { |
37 | name: Str, |
38 | help: Option<StyledStr>, |
39 | aliases: Vec<Str>, // (name, visible) |
40 | hide: bool, |
41 | } |
42 | |
43 | impl PossibleValue { |
44 | /// Create a [`PossibleValue`] with its name. |
45 | /// |
46 | /// The name will be used to decide whether this value was provided by the user to an argument. |
47 | /// |
48 | /// **NOTE:** In case it is not [hidden] it will also be shown in help messages for arguments |
49 | /// that use it as a [possible value] and have not hidden them through [`Arg::hide_possible_values(true)`]. |
50 | /// |
51 | /// # Examples |
52 | /// |
53 | /// ```rust |
54 | /// # use clap_builder as clap; |
55 | /// # use clap::builder::PossibleValue; |
56 | /// PossibleValue::new("fast" ) |
57 | /// # ; |
58 | /// ``` |
59 | /// [hidden]: PossibleValue::hide |
60 | /// [possible value]: crate::builder::PossibleValuesParser |
61 | /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values() |
62 | pub fn new(name: impl Into<Str>) -> Self { |
63 | PossibleValue { |
64 | name: name.into(), |
65 | ..Default::default() |
66 | } |
67 | } |
68 | |
69 | /// Sets the help description of the value. |
70 | /// |
71 | /// This is typically displayed in completions (where supported) and should be a short, one-line |
72 | /// description. |
73 | /// |
74 | /// # Examples |
75 | /// |
76 | /// ```rust |
77 | /// # use clap_builder as clap; |
78 | /// # use clap::builder::PossibleValue; |
79 | /// PossibleValue::new("slow" ) |
80 | /// .help("not fast" ) |
81 | /// # ; |
82 | /// ``` |
83 | #[inline ] |
84 | #[must_use ] |
85 | pub fn help(mut self, help: impl IntoResettable<StyledStr>) -> Self { |
86 | self.help = help.into_resettable().into_option(); |
87 | self |
88 | } |
89 | |
90 | /// Hides this value from help and shell completions. |
91 | /// |
92 | /// This is an alternative to hiding through [`Arg::hide_possible_values(true)`], if you only |
93 | /// want to hide some values. |
94 | /// |
95 | /// # Examples |
96 | /// |
97 | /// ```rust |
98 | /// # use clap_builder as clap; |
99 | /// # use clap::builder::PossibleValue; |
100 | /// PossibleValue::new("secret" ) |
101 | /// .hide(true) |
102 | /// # ; |
103 | /// ``` |
104 | /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values() |
105 | #[inline ] |
106 | #[must_use ] |
107 | pub fn hide(mut self, yes: bool) -> Self { |
108 | self.hide = yes; |
109 | self |
110 | } |
111 | |
112 | /// Sets a *hidden* alias for this argument value. |
113 | /// |
114 | /// # Examples |
115 | /// |
116 | /// ```rust |
117 | /// # use clap_builder as clap; |
118 | /// # use clap::builder::PossibleValue; |
119 | /// PossibleValue::new("slow" ) |
120 | /// .alias("not-fast" ) |
121 | /// # ; |
122 | /// ``` |
123 | #[must_use ] |
124 | pub fn alias(mut self, name: impl IntoResettable<Str>) -> Self { |
125 | if let Some(name) = name.into_resettable().into_option() { |
126 | self.aliases.push(name); |
127 | } else { |
128 | self.aliases.clear(); |
129 | } |
130 | self |
131 | } |
132 | |
133 | /// Sets multiple *hidden* aliases for this argument value. |
134 | /// |
135 | /// # Examples |
136 | /// |
137 | /// ```rust |
138 | /// # use clap_builder as clap; |
139 | /// # use clap::builder::PossibleValue; |
140 | /// PossibleValue::new("slow" ) |
141 | /// .aliases(["not-fast" , "snake-like" ]) |
142 | /// # ; |
143 | /// ``` |
144 | #[must_use ] |
145 | pub fn aliases(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self { |
146 | self.aliases.extend(names.into_iter().map(|a| a.into())); |
147 | self |
148 | } |
149 | } |
150 | |
151 | /// Reflection |
152 | impl PossibleValue { |
153 | /// Get the name of the argument value |
154 | #[inline ] |
155 | pub fn get_name(&self) -> &str { |
156 | self.name.as_str() |
157 | } |
158 | |
159 | /// Get the help specified for this argument, if any |
160 | #[inline ] |
161 | pub fn get_help(&self) -> Option<&StyledStr> { |
162 | self.help.as_ref() |
163 | } |
164 | |
165 | /// Report if [`PossibleValue::hide`] is set |
166 | #[inline ] |
167 | pub fn is_hide_set(&self) -> bool { |
168 | self.hide |
169 | } |
170 | |
171 | /// Report if PossibleValue is not hidden and has a help message |
172 | pub(crate) fn should_show_help(&self) -> bool { |
173 | !self.hide && self.help.is_some() |
174 | } |
175 | |
176 | /// Get the name if argument value is not hidden, `None` otherwise, |
177 | /// but wrapped in quotes if it contains whitespace |
178 | #[cfg (feature = "help" )] |
179 | pub(crate) fn get_visible_quoted_name(&self) -> Option<std::borrow::Cow<'_, str>> { |
180 | if !self.hide { |
181 | Some(if self.name.contains(char::is_whitespace) { |
182 | format!("{:?}" , self.name).into() |
183 | } else { |
184 | self.name.as_str().into() |
185 | }) |
186 | } else { |
187 | None |
188 | } |
189 | } |
190 | |
191 | /// Returns all valid values of the argument value. |
192 | /// |
193 | /// Namely the name and all aliases. |
194 | pub fn get_name_and_aliases(&self) -> impl Iterator<Item = &str> + '_ { |
195 | std::iter::once(self.get_name()).chain(self.aliases.iter().map(|s| s.as_str())) |
196 | } |
197 | |
198 | /// Tests if the value is valid for this argument value |
199 | /// |
200 | /// The value is valid if it is either the name or one of the aliases. |
201 | /// |
202 | /// # Examples |
203 | /// |
204 | /// ```rust |
205 | /// # use clap_builder as clap; |
206 | /// # use clap::builder::PossibleValue; |
207 | /// let arg_value = PossibleValue::new("fast" ).alias("not-slow" ); |
208 | /// |
209 | /// assert!(arg_value.matches("fast" , false)); |
210 | /// assert!(arg_value.matches("not-slow" , false)); |
211 | /// |
212 | /// assert!(arg_value.matches("FAST" , true)); |
213 | /// assert!(!arg_value.matches("FAST" , false)); |
214 | /// ``` |
215 | pub fn matches(&self, value: &str, ignore_case: bool) -> bool { |
216 | if ignore_case { |
217 | self.get_name_and_aliases() |
218 | .any(|name| eq_ignore_case(name, value)) |
219 | } else { |
220 | self.get_name_and_aliases().any(|name| name == value) |
221 | } |
222 | } |
223 | } |
224 | |
225 | impl<S: Into<Str>> From<S> for PossibleValue { |
226 | fn from(s: S) -> Self { |
227 | Self::new(s) |
228 | } |
229 | } |
230 | |