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