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/// **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)]
36pub struct PossibleValue {
37    name: Str,
38    help: Option<StyledStr>,
39    aliases: Vec<Str>, // (name, visible)
40    hide: bool,
41}
42
43impl 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
152impl 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
225impl<S: Into<Str>> From<S> for PossibleValue {
226    fn from(s: S) -> Self {
227        Self::new(s)
228    }
229}