1 // Unlike `impl Into<Option<T>>` or `Option<impl Into<T>>`, this isn't ambiguous for the `None` 2 // case. 3 4 use crate::builder::ArgAction; 5 use crate::builder::OsStr; 6 use crate::builder::Str; 7 use crate::builder::StyledStr; 8 use crate::builder::ValueHint; 9 use crate::builder::ValueParser; 10 use crate::builder::ValueRange; 11 12 /// Clearable builder value 13 /// 14 /// This allows a builder function to both accept any value that can [`Into::into`] `T` (like 15 /// `&str` into `OsStr`) as well as `None` to reset it to the default. This is needed to 16 /// workaround a limitation where you can't have a function argument that is `impl Into<Option<T>>` 17 /// where `T` is `impl Into<S>` accept `None` as its type is ambiguous. 18 /// 19 /// # Example 20 /// 21 /// ```rust 22 /// # use clap_builder as clap; 23 /// # use clap::Command; 24 /// # use clap::Arg; 25 /// fn common() -> Command { 26 /// Command::new("cli") 27 /// .arg(Arg::new("input").short('i').long("input")) 28 /// } 29 /// let mut command = common(); 30 /// command.mut_arg("input", |arg| arg.short(None)); 31 /// ``` 32 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 33 pub enum Resettable<T> { 34 /// Overwrite builder value 35 Value(T), 36 /// Reset builder value 37 Reset, 38 } 39 40 impl<T> Resettable<T> { into_option(self) -> Option<T>41 pub(crate) fn into_option(self) -> Option<T> { 42 match self { 43 Self::Value(t) => Some(t), 44 Self::Reset => None, 45 } 46 } 47 } 48 49 impl<T> From<T> for Resettable<T> { from(other: T) -> Self50 fn from(other: T) -> Self { 51 Self::Value(other) 52 } 53 } 54 55 impl<T> From<Option<T>> for Resettable<T> { from(other: Option<T>) -> Self56 fn from(other: Option<T>) -> Self { 57 match other { 58 Some(inner) => Self::Value(inner), 59 None => Self::Reset, 60 } 61 } 62 } 63 64 /// Convert to the intended resettable type 65 pub trait IntoResettable<T> { 66 /// Convert to the intended resettable type into_resettable(self) -> Resettable<T>67 fn into_resettable(self) -> Resettable<T>; 68 } 69 70 impl IntoResettable<char> for Option<char> { into_resettable(self) -> Resettable<char>71 fn into_resettable(self) -> Resettable<char> { 72 match self { 73 Some(s) => Resettable::Value(s), 74 None => Resettable::Reset, 75 } 76 } 77 } 78 79 impl IntoResettable<usize> for Option<usize> { into_resettable(self) -> Resettable<usize>80 fn into_resettable(self) -> Resettable<usize> { 81 match self { 82 Some(s) => Resettable::Value(s), 83 None => Resettable::Reset, 84 } 85 } 86 } 87 88 impl IntoResettable<ArgAction> for Option<ArgAction> { into_resettable(self) -> Resettable<ArgAction>89 fn into_resettable(self) -> Resettable<ArgAction> { 90 match self { 91 Some(s) => Resettable::Value(s), 92 None => Resettable::Reset, 93 } 94 } 95 } 96 97 impl IntoResettable<ValueHint> for Option<ValueHint> { into_resettable(self) -> Resettable<ValueHint>98 fn into_resettable(self) -> Resettable<ValueHint> { 99 match self { 100 Some(s) => Resettable::Value(s), 101 None => Resettable::Reset, 102 } 103 } 104 } 105 106 impl IntoResettable<ValueParser> for Option<ValueParser> { into_resettable(self) -> Resettable<ValueParser>107 fn into_resettable(self) -> Resettable<ValueParser> { 108 match self { 109 Some(s) => Resettable::Value(s), 110 None => Resettable::Reset, 111 } 112 } 113 } 114 115 impl IntoResettable<StyledStr> for Option<&'static str> { into_resettable(self) -> Resettable<StyledStr>116 fn into_resettable(self) -> Resettable<StyledStr> { 117 match self { 118 Some(s) => Resettable::Value(s.into()), 119 None => Resettable::Reset, 120 } 121 } 122 } 123 124 impl IntoResettable<OsStr> for Option<&'static str> { into_resettable(self) -> Resettable<OsStr>125 fn into_resettable(self) -> Resettable<OsStr> { 126 match self { 127 Some(s) => Resettable::Value(s.into()), 128 None => Resettable::Reset, 129 } 130 } 131 } 132 133 impl IntoResettable<Str> for Option<&'static str> { into_resettable(self) -> Resettable<Str>134 fn into_resettable(self) -> Resettable<Str> { 135 match self { 136 Some(s) => Resettable::Value(s.into()), 137 None => Resettable::Reset, 138 } 139 } 140 } 141 142 impl<T> IntoResettable<T> for Resettable<T> { into_resettable(self) -> Resettable<T>143 fn into_resettable(self) -> Resettable<T> { 144 self 145 } 146 } 147 148 impl IntoResettable<char> for char { into_resettable(self) -> Resettable<char>149 fn into_resettable(self) -> Resettable<char> { 150 Resettable::Value(self) 151 } 152 } 153 154 impl IntoResettable<usize> for usize { into_resettable(self) -> Resettable<usize>155 fn into_resettable(self) -> Resettable<usize> { 156 Resettable::Value(self) 157 } 158 } 159 160 impl IntoResettable<ArgAction> for ArgAction { into_resettable(self) -> Resettable<ArgAction>161 fn into_resettable(self) -> Resettable<ArgAction> { 162 Resettable::Value(self) 163 } 164 } 165 166 impl IntoResettable<ValueHint> for ValueHint { into_resettable(self) -> Resettable<ValueHint>167 fn into_resettable(self) -> Resettable<ValueHint> { 168 Resettable::Value(self) 169 } 170 } 171 172 impl<I: Into<ValueRange>> IntoResettable<ValueRange> for I { into_resettable(self) -> Resettable<ValueRange>173 fn into_resettable(self) -> Resettable<ValueRange> { 174 Resettable::Value(self.into()) 175 } 176 } 177 178 impl<I: Into<ValueParser>> IntoResettable<ValueParser> for I { into_resettable(self) -> Resettable<ValueParser>179 fn into_resettable(self) -> Resettable<ValueParser> { 180 Resettable::Value(self.into()) 181 } 182 } 183 184 impl<I: Into<String>> IntoResettable<String> for I { into_resettable(self) -> Resettable<String>185 fn into_resettable(self) -> Resettable<String> { 186 Resettable::Value(self.into()) 187 } 188 } 189 190 impl<I: Into<StyledStr>> IntoResettable<StyledStr> for I { into_resettable(self) -> Resettable<StyledStr>191 fn into_resettable(self) -> Resettable<StyledStr> { 192 Resettable::Value(self.into()) 193 } 194 } 195 196 impl<I: Into<OsStr>> IntoResettable<OsStr> for I { into_resettable(self) -> Resettable<OsStr>197 fn into_resettable(self) -> Resettable<OsStr> { 198 Resettable::Value(self.into()) 199 } 200 } 201 202 impl<I: Into<Str>> IntoResettable<Str> for I { into_resettable(self) -> Resettable<Str>203 fn into_resettable(self) -> Resettable<Str> { 204 Resettable::Value(self.into()) 205 } 206 } 207 208 impl<I: Into<crate::Id>> IntoResettable<crate::Id> for I { into_resettable(self) -> Resettable<crate::Id>209 fn into_resettable(self) -> Resettable<crate::Id> { 210 Resettable::Value(self.into()) 211 } 212 } 213