command/error.rs: add suggestions to BadValue variant
Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>pull/384/head
parent
8f3dee9b22
commit
89c7972e12
|
@ -656,9 +656,15 @@ mod tests {
|
|||
assert_eq!(
|
||||
parse_command(b"set foo").unwrap_err().to_string(),
|
||||
BadValue {
|
||||
inner: "Bad argument for `set`. Accepted arguments are [seen, unseen, plain, \
|
||||
threaded, compact, conversations]."
|
||||
.into(),
|
||||
inner: "foo".into(),
|
||||
suggestions: Some(&[
|
||||
"seen",
|
||||
"unseen",
|
||||
"plain",
|
||||
"threaded",
|
||||
"compact",
|
||||
"conversations"
|
||||
])
|
||||
}
|
||||
.to_string(),
|
||||
);
|
||||
|
|
|
@ -29,6 +29,7 @@ pub enum CommandError {
|
|||
},
|
||||
BadValue {
|
||||
inner: Cow<'static, str>,
|
||||
suggestions: Option<&'static [&'static str]>,
|
||||
},
|
||||
WrongNumberOfArguments {
|
||||
too_many: bool,
|
||||
|
@ -63,7 +64,25 @@ impl std::fmt::Display for CommandError {
|
|||
Self::Parsing { inner, kind: _ } => {
|
||||
write!(fmt, "Could not parse command: {}", inner)
|
||||
}
|
||||
Self::BadValue { inner } => {
|
||||
Self::BadValue {
|
||||
inner,
|
||||
suggestions: Some(suggs),
|
||||
} => {
|
||||
write!(fmt, "Bad value/argument: {}. Possible values are: ", inner)?;
|
||||
let len = suggs.len();
|
||||
for (i, val) in suggs.iter().enumerate() {
|
||||
if i == len.saturating_sub(1) {
|
||||
write!(fmt, "{}", val)?;
|
||||
} else {
|
||||
write!(fmt, "{}, ", val)?;
|
||||
}
|
||||
}
|
||||
write!(fmt, "")
|
||||
}
|
||||
Self::BadValue {
|
||||
inner,
|
||||
suggestions: None,
|
||||
} => {
|
||||
write!(fmt, "Bad value/argument: {}", inner)
|
||||
}
|
||||
Self::WrongNumberOfArguments {
|
||||
|
@ -121,3 +140,28 @@ impl std::fmt::Display for CommandError {
|
|||
}
|
||||
|
||||
impl std::error::Error for CommandError {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::CommandError;
|
||||
|
||||
#[test]
|
||||
fn test_command_error_display() {
|
||||
assert_eq!(
|
||||
&CommandError::BadValue {
|
||||
inner: "foo".into(),
|
||||
suggestions: Some(&[
|
||||
"seen",
|
||||
"unseen",
|
||||
"plain",
|
||||
"threaded",
|
||||
"compact",
|
||||
"conversations"
|
||||
])
|
||||
}
|
||||
.to_string(),
|
||||
"Bad value/argument: foo. Possible values are: seen, unseen, plain, threaded, \
|
||||
compact, conversations"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,22 +24,37 @@
|
|||
use super::*;
|
||||
use crate::command::{argcheck::*, error::*};
|
||||
|
||||
const FLAG_SUGGESTIONS: &[&str] = &[
|
||||
"passed",
|
||||
"replied",
|
||||
"seen or read",
|
||||
"junk or trash or trashed",
|
||||
"draft",
|
||||
"flagged",
|
||||
];
|
||||
|
||||
macro_rules! command_err {
|
||||
(nom $b:expr, $input: expr, $msg:literal) => {{
|
||||
(nom $b:expr, $input: expr, $msg:expr, $suggs:expr) => {{
|
||||
let evaluated: IResult<&'_ [u8], _> = { $b };
|
||||
match evaluated {
|
||||
Err(_) => {
|
||||
let err = CommandError::BadValue { inner: $msg.into() };
|
||||
let err = CommandError::BadValue {
|
||||
inner: $msg.into(),
|
||||
suggestions: $suggs,
|
||||
};
|
||||
return Ok(($input, Err(err)));
|
||||
}
|
||||
Ok(v) => v,
|
||||
}
|
||||
}};
|
||||
($b:expr, $input: expr, $msg:literal) => {{
|
||||
($b:expr, $input: expr, $msg:expr, $suggs:expr) => {{
|
||||
let evaluated = { $b };
|
||||
match evaluated {
|
||||
Err(_) => {
|
||||
let err = CommandError::BadValue { inner: $msg.into() };
|
||||
let err = CommandError::BadValue {
|
||||
inner: $msg.into(),
|
||||
suggestions: $suggs,
|
||||
};
|
||||
return Ok(($input, Err(err)));
|
||||
}
|
||||
Ok(v) => v,
|
||||
|
@ -206,7 +221,7 @@ pub fn parse_command(input: &[u8]) -> Result<Action, CommandError> {
|
|||
/// assert_eq!(
|
||||
/// &parsed.unwrap_err().to_string(),
|
||||
/// "Bad value/argument: xunk is not a valid flag name. Possible values are: passed, replied, \
|
||||
/// seen or read, junk or trash or trashed, draft and flagged."
|
||||
/// seen or read, junk or trash or trashed, draft, flagged"
|
||||
/// );
|
||||
/// ```
|
||||
pub fn flag<'a>(input: &'a [u8]) -> IResult<&'a [u8], Result<Action, CommandError>> {
|
||||
|
@ -243,12 +258,8 @@ pub fn flag<'a>(input: &'a [u8]) -> IResult<&'a [u8], Result<Action, CommandErro
|
|||
return Ok((
|
||||
b"",
|
||||
Err(CommandError::BadValue {
|
||||
inner: format!(
|
||||
"{flag} is not a valid flag name. Possible values are: passed, \
|
||||
replied, seen or read, junk or trash or trashed, draft and \
|
||||
flagged."
|
||||
)
|
||||
.into(),
|
||||
inner: format!("{flag} is not a valid flag name").into(),
|
||||
suggestions: Some(FLAG_SUGGESTIONS),
|
||||
}),
|
||||
));
|
||||
};
|
||||
|
@ -267,12 +278,8 @@ pub fn flag<'a>(input: &'a [u8]) -> IResult<&'a [u8], Result<Action, CommandErro
|
|||
return Ok((
|
||||
b"",
|
||||
Err(CommandError::BadValue {
|
||||
inner: format!(
|
||||
"{flag} is not a valid flag name. Possible values are: passed, \
|
||||
replied, seen or read, junk or trash or trashed, draft and \
|
||||
flagged."
|
||||
)
|
||||
.into(),
|
||||
inner: format!("{flag} is not a valid flag name").into(),
|
||||
suggestions: Some(FLAG_SUGGESTIONS),
|
||||
}),
|
||||
));
|
||||
};
|
||||
|
@ -301,9 +308,13 @@ pub fn set(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|||
let (input, _) = is_a(" ")(input)?;
|
||||
arg_chk!(inc check, input);
|
||||
let (input, ret) = command_err!(nom
|
||||
alt((map(tag("seen"), |_| Listing(SetSeen)), map(tag("unseen"), |_| Listing(SetUnseen))))(input),
|
||||
alt((
|
||||
map(tag("seen"), |_| Listing(SetSeen)),
|
||||
map(tag("unseen"), |_| Listing(SetUnseen)
|
||||
)))(input),
|
||||
input,
|
||||
"Bad argument for `set`. Accepted arguments are [seen, unseen, plain, threaded, compact, conversations].");
|
||||
String::from_utf8_lossy(input.trim()).to_string(),
|
||||
Some(&["seen", "unseen", "plain", "threaded", "compact", "conversations"]));
|
||||
arg_chk!(finish check, input);
|
||||
let (input, _) = eof(input)?;
|
||||
Ok((input, Ok(ret)))
|
||||
|
@ -408,7 +419,8 @@ pub fn goto(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|||
let (input, nth) = command_err!(nom
|
||||
usize_c(input),
|
||||
input,
|
||||
"Argument must be an integer.");
|
||||
"Argument must be an integer.",
|
||||
None);
|
||||
arg_chk!(finish check, input);
|
||||
let (input, _) = eof(input)?;
|
||||
Ok((input, Ok(Action::ViewMailbox(nth))))
|
||||
|
@ -581,7 +593,8 @@ pub fn mailto(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|||
let (input, val) = command_err!(
|
||||
parser(val.as_bytes()),
|
||||
val.as_bytes(),
|
||||
"Could not parse mailto value. If the value is valid, please report this bug."
|
||||
"Could not parse mailto value. If the value is valid, please report this bug.",
|
||||
None
|
||||
);
|
||||
Ok((input, Ok(Compose(Mailto(val)))))
|
||||
}
|
||||
|
@ -958,7 +971,8 @@ pub fn toggle(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|||
return Ok((
|
||||
input,
|
||||
Err(CommandError::BadValue {
|
||||
inner: "Valid toggle values are thread_snooze, mouse, sign, encrypt.".into(),
|
||||
inner: String::from_utf8_lossy(input).to_string().into(),
|
||||
suggestions: Some(&["thread_snooze", "mouse", "sign", "encrypt"]),
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue