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