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