|
1 | 1 | use std::convert::TryInto;
|
2 | 2 | use std::ops::RangeBounds;
|
3 | 3 |
|
| 4 | +use crate::builder::Str; |
| 5 | +use crate::builder::StyledStr; |
4 | 6 | use crate::util::AnyValue;
|
5 | 7 | use crate::util::AnyValueId;
|
6 | 8 |
|
@@ -2086,6 +2088,105 @@ where
|
2086 | 2088 | }
|
2087 | 2089 | }
|
2088 | 2090 |
|
| 2091 | +/// When encountered, report [ErrorKind::UnknownArgument][crate::error::ErrorKind::UnknownArgument] |
| 2092 | +/// |
| 2093 | +/// Useful to help users migrate, either from old versions or similar tools. |
| 2094 | +/// |
| 2095 | +/// # Examples |
| 2096 | +/// |
| 2097 | +/// ```rust |
| 2098 | +/// # use clap_builder as clap; |
| 2099 | +/// # use clap::Command; |
| 2100 | +/// # use clap::Arg; |
| 2101 | +/// let cmd = Command::new("mycmd") |
| 2102 | +/// .args([ |
| 2103 | +/// Arg::new("current-dir") |
| 2104 | +/// .short('C'), |
| 2105 | +/// Arg::new("current-dir-unknown") |
| 2106 | +/// .long("cwd") |
| 2107 | +/// .aliases(["current-dir", "directory", "working-directory", "root"]) |
| 2108 | +/// .value_parser(clap::builder::UnknownArgumentValueParser::suggest_arg("-C")) |
| 2109 | +/// .hide(true), |
| 2110 | +/// ]); |
| 2111 | +/// |
| 2112 | +/// // Use a supported version of the argument |
| 2113 | +/// let matches = cmd.clone().try_get_matches_from(["mycmd", "-C", ".."]).unwrap(); |
| 2114 | +/// assert!(matches.contains_id("current-dir")); |
| 2115 | +/// assert_eq!( |
| 2116 | +/// matches.get_many::<String>("current-dir").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(), |
| 2117 | +/// vec![".."] |
| 2118 | +/// ); |
| 2119 | +/// |
| 2120 | +/// // Use one of the invalid versions |
| 2121 | +/// let err = cmd.try_get_matches_from(["mycmd", "--cwd", ".."]).unwrap_err(); |
| 2122 | +/// assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument); |
| 2123 | +/// ``` |
| 2124 | +#[derive(Clone, Debug)] |
| 2125 | +pub struct UnknownArgumentValueParser { |
| 2126 | + arg: Option<Str>, |
| 2127 | + suggestions: Vec<StyledStr>, |
| 2128 | +} |
| 2129 | + |
| 2130 | +impl UnknownArgumentValueParser { |
| 2131 | + /// Suggest an alternative argument |
| 2132 | + pub fn suggest_arg(arg: impl Into<Str>) -> Self { |
| 2133 | + Self { |
| 2134 | + arg: Some(arg.into()), |
| 2135 | + suggestions: Default::default(), |
| 2136 | + } |
| 2137 | + } |
| 2138 | + |
| 2139 | + /// Provide a general suggestion |
| 2140 | + pub fn suggest(text: impl Into<StyledStr>) -> Self { |
| 2141 | + Self { |
| 2142 | + arg: Default::default(), |
| 2143 | + suggestions: vec![text.into()], |
| 2144 | + } |
| 2145 | + } |
| 2146 | + |
| 2147 | + /// Extend the suggestions |
| 2148 | + pub fn and_suggest(mut self, text: impl Into<StyledStr>) -> Self { |
| 2149 | + self.suggestions.push(text.into()); |
| 2150 | + self |
| 2151 | + } |
| 2152 | +} |
| 2153 | + |
| 2154 | +impl TypedValueParser for UnknownArgumentValueParser { |
| 2155 | + type Value = String; |
| 2156 | + |
| 2157 | + fn parse_ref( |
| 2158 | + &self, |
| 2159 | + cmd: &crate::Command, |
| 2160 | + arg: Option<&crate::Arg>, |
| 2161 | + _value: &std::ffi::OsStr, |
| 2162 | + ) -> Result<Self::Value, crate::Error> { |
| 2163 | + let arg = match arg { |
| 2164 | + Some(arg) => arg.to_string(), |
| 2165 | + None => "..".to_owned(), |
| 2166 | + }; |
| 2167 | + let err = crate::Error::unknown_argument( |
| 2168 | + cmd, |
| 2169 | + arg, |
| 2170 | + self.arg.as_ref().map(|s| (s.as_str().to_owned(), None)), |
| 2171 | + false, |
| 2172 | + crate::output::Usage::new(cmd).create_usage_with_title(&[]), |
| 2173 | + ); |
| 2174 | + #[cfg(feature = "error-context")] |
| 2175 | + let err = { |
| 2176 | + debug_assert_eq!( |
| 2177 | + err.get(crate::error::ContextKind::Suggested), |
| 2178 | + None, |
| 2179 | + "Assuming `Error::unknown_argument` doesn't apply any `Suggested` so we can without caution" |
| 2180 | + ); |
| 2181 | + err.insert_context_unchecked( |
| 2182 | + crate::error::ContextKind::Suggested, |
| 2183 | + crate::error::ContextValue::StyledStrs(self.suggestions.clone()), |
| 2184 | + ) |
| 2185 | + }; |
| 2186 | + Err(err) |
| 2187 | + } |
| 2188 | +} |
| 2189 | + |
2089 | 2190 | /// Register a type with [value_parser!][crate::value_parser!]
|
2090 | 2191 | ///
|
2091 | 2192 | /// # Example
|
|
0 commit comments