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
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)]
40pub struct PossibleValue {
41    name: Str,
42    help: Option<StyledStr>,
43    aliases: Vec<Str>, // (name, visible)
44    hide: bool,
45}
46
47impl 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
160impl 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
233impl<S: Into<Str>> From<S> for PossibleValue {
234    fn from(s: S) -> Self {
235        Self::new(s)
236    }
237}