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