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}