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