• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::{borrow::Cow, iter};
2 
3 use crate::util::eq_ignore_case;
4 
5 /// A possible value of an argument.
6 ///
7 /// This is used for specifying [possible values] of [Args].
8 ///
9 /// **NOTE:** This struct is likely not needed for most usecases as it is only required to
10 /// [hide] single values from help messages and shell completions or to attach [help] to possible values.
11 ///
12 /// # Examples
13 ///
14 /// ```rust
15 /// # use clap::{Arg, PossibleValue};
16 /// let cfg = Arg::new("config")
17 ///     .takes_value(true)
18 ///     .value_name("FILE")
19 ///     .value_parser([
20 ///         PossibleValue::new("fast"),
21 ///         PossibleValue::new("slow").help("slower than fast"),
22 ///         PossibleValue::new("secret speed").hide(true)
23 ///     ]);
24 /// ```
25 /// [Args]: crate::Arg
26 /// [possible values]: crate::builder::ValueParser::possible_values
27 /// [hide]: PossibleValue::hide()
28 /// [help]: PossibleValue::help()
29 #[derive(Debug, Default, Clone, PartialEq, Eq)]
30 pub struct PossibleValue<'help> {
31     name: &'help str,
32     help: Option<&'help str>,
33     aliases: Vec<&'help str>, // (name, visible)
34     hide: bool,
35 }
36 
37 impl<'help> PossibleValue<'help> {
38     /// Create a [`PossibleValue`] with its name.
39     ///
40     /// The name will be used to decide whether this value was provided by the user to an argument.
41     ///
42     /// **NOTE:** In case it is not [hidden] it will also be shown in help messages for arguments
43     /// that use it as a [possible value] and have not hidden them through [`Arg::hide_possible_values(true)`].
44     ///
45     /// # Examples
46     ///
47     /// ```rust
48     /// # use clap::PossibleValue;
49     /// PossibleValue::new("fast")
50     /// # ;
51     /// ```
52     /// [hidden]: PossibleValue::hide
53     /// [possible value]: crate::Arg::possible_values
54     /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values()
new(name: &'help str) -> Self55     pub fn new(name: &'help str) -> Self {
56         PossibleValue {
57             name,
58             ..Default::default()
59         }
60     }
61 
62     /// Sets the help description of the value.
63     ///
64     /// This is typically displayed in completions (where supported) and should be a short, one-line
65     /// description.
66     ///
67     /// # Examples
68     ///
69     /// ```rust
70     /// # use clap::PossibleValue;
71     /// PossibleValue::new("slow")
72     ///     .help("not fast")
73     /// # ;
74     /// ```
75     #[inline]
76     #[must_use]
help(mut self, help: &'help str) -> Self77     pub fn help(mut self, help: &'help str) -> Self {
78         self.help = Some(help);
79         self
80     }
81 
82     /// Hides this value from help and shell completions.
83     ///
84     /// This is an alternative to hiding through [`Arg::hide_possible_values(true)`], if you only
85     /// want to hide some values.
86     ///
87     /// # Examples
88     ///
89     /// ```rust
90     /// # use clap::PossibleValue;
91     /// PossibleValue::new("secret")
92     ///     .hide(true)
93     /// # ;
94     /// ```
95     /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values()
96     #[inline]
97     #[must_use]
hide(mut self, yes: bool) -> Self98     pub fn hide(mut self, yes: bool) -> Self {
99         self.hide = yes;
100         self
101     }
102 
103     /// Sets a *hidden* alias for this argument value.
104     ///
105     /// # Examples
106     ///
107     /// ```rust
108     /// # use clap::PossibleValue;
109     /// PossibleValue::new("slow")
110     ///     .alias("not-fast")
111     /// # ;
112     /// ```
113     #[must_use]
alias(mut self, name: &'help str) -> Self114     pub fn alias(mut self, name: &'help str) -> Self {
115         self.aliases.push(name);
116         self
117     }
118 
119     /// Sets multiple *hidden* aliases for this argument value.
120     ///
121     /// # Examples
122     ///
123     /// ```rust
124     /// # use clap::PossibleValue;
125     /// PossibleValue::new("slow")
126     ///     .aliases(["not-fast", "snake-like"])
127     /// # ;
128     /// ```
129     #[must_use]
aliases<I>(mut self, names: I) -> Self where I: IntoIterator<Item = &'help str>,130     pub fn aliases<I>(mut self, names: I) -> Self
131     where
132         I: IntoIterator<Item = &'help str>,
133     {
134         self.aliases.extend(names.into_iter());
135         self
136     }
137 }
138 
139 /// Reflection
140 impl<'help> PossibleValue<'help> {
141     /// Get the name of the argument value
142     #[inline]
get_name(&self) -> &'help str143     pub fn get_name(&self) -> &'help str {
144         self.name
145     }
146 
147     /// Get the help specified for this argument, if any
148     #[inline]
get_help(&self) -> Option<&'help str>149     pub fn get_help(&self) -> Option<&'help str> {
150         self.help
151     }
152 
153     /// Get the help specified for this argument, if any and the argument
154     /// value is not hidden
155     #[inline]
156     #[cfg(feature = "unstable-v4")]
get_visible_help(&self) -> Option<&'help str>157     pub(crate) fn get_visible_help(&self) -> Option<&'help str> {
158         if !self.hide {
159             self.help
160         } else {
161             None
162         }
163     }
164 
165     /// Deprecated, replaced with [`PossibleValue::is_hide_set`]
166     #[inline]
167     #[cfg_attr(
168         feature = "deprecated",
169         deprecated(since = "3.1.0", note = "Replaced with `PossibleValue::is_hide_set`")
170     )]
is_hidden(&self) -> bool171     pub fn is_hidden(&self) -> bool {
172         self.is_hide_set()
173     }
174 
175     /// Report if [`PossibleValue::hide`] is set
176     #[inline]
is_hide_set(&self) -> bool177     pub fn is_hide_set(&self) -> bool {
178         self.hide
179     }
180 
181     /// Report if PossibleValue is not hidden and has a help message
should_show_help(&self) -> bool182     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     #[cfg_attr(
188         feature = "deprecated",
189         deprecated(
190             since = "3.1.4",
191             note = "Use `PossibleValue::is_hide_set` and `PossibleValue::get_name`"
192         )
193     )]
get_visible_name(&self) -> Option<&'help str>194     pub fn get_visible_name(&self) -> Option<&'help str> {
195         if self.hide {
196             None
197         } else {
198             Some(self.name)
199         }
200     }
201 
202     /// Get the name if argument value is not hidden, `None` otherwise,
203     /// but wrapped in quotes if it contains whitespace
get_visible_quoted_name(&self) -> Option<Cow<'help, str>>204     pub(crate) fn get_visible_quoted_name(&self) -> Option<Cow<'help, str>> {
205         if !self.hide {
206             Some(if self.name.contains(char::is_whitespace) {
207                 format!("{:?}", self.name).into()
208             } else {
209                 self.name.into()
210             })
211         } else {
212             None
213         }
214     }
215 
216     /// Returns all valid values of the argument value.
217     ///
218     /// Namely the name and all aliases.
get_name_and_aliases(&self) -> impl Iterator<Item = &'help str> + '_219     pub fn get_name_and_aliases(&self) -> impl Iterator<Item = &'help str> + '_ {
220         iter::once(&self.name).chain(&self.aliases).copied()
221     }
222 
223     /// Tests if the value is valid for this argument value
224     ///
225     /// The value is valid if it is either the name or one of the aliases.
226     ///
227     /// # Examples
228     ///
229     /// ```rust
230     /// # use clap::PossibleValue;
231     /// let arg_value = PossibleValue::new("fast").alias("not-slow");
232     ///
233     /// assert!(arg_value.matches("fast", false));
234     /// assert!(arg_value.matches("not-slow", false));
235     ///
236     /// assert!(arg_value.matches("FAST", true));
237     /// assert!(!arg_value.matches("FAST", false));
238     /// ```
matches(&self, value: &str, ignore_case: bool) -> bool239     pub fn matches(&self, value: &str, ignore_case: bool) -> bool {
240         if ignore_case {
241             self.get_name_and_aliases()
242                 .any(|name| eq_ignore_case(name, value))
243         } else {
244             self.get_name_and_aliases().any(|name| name == value)
245         }
246     }
247 }
248 
249 impl<'help> From<&'help str> for PossibleValue<'help> {
from(s: &'help str) -> Self250     fn from(s: &'help str) -> Self {
251         Self::new(s)
252     }
253 }
254 
255 impl<'help> From<&'help &'help str> for PossibleValue<'help> {
from(s: &'help &'help str) -> Self256     fn from(s: &'help &'help str) -> Self {
257         Self::new(s)
258     }
259 }
260