/// Defines how to format an error for displaying to the user pubtrait ErrorFormatter: Sized { /// Stylize the error for the terminal fn format_error(error: &crate::error::Error<Self>) -> StyledStr;
}
/// Report [`ErrorKind`] /// /// No context is included. /// /// **NOTE:** Consider removing the `error-context` default feature if using this to remove all /// overhead for [`RichFormatter`]. #[non_exhaustive] pubstruct KindFormatter;
impl ErrorFormatter for KindFormatter { fn format_error(error: &crate::error::Error<Self>) -> StyledStr { use std::fmt::Write as _; let styles = &error.inner.styles;
fn start_error(styled: &mut StyledStr, styles: &Styles) { use std::fmt::Write as _; let error = &styles.get_error(); let _ = write!(styled, "{}error:{} ", error.render(), error.render_reset());
}
#[must_use] #[cfg(feature = "error-context")] fn write_dynamic_context(
error: &crate::error::Error,
styled: &mut StyledStr,
styles: &Styles,
) -> bool { use std::fmt::Write as _; let valid = styles.get_valid(); let invalid = styles.get_invalid(); let literal = styles.get_literal();
match error.kind() {
ErrorKind::ArgumentConflict => { letmut prior_arg = error.get(ContextKind::PriorArg); iflet Some(ContextValue::String(invalid_arg)) = error.get(ContextKind::InvalidArg) { if Some(&ContextValue::String(invalid_arg.clone())) == prior_arg {
prior_arg = None; let _ = write!(
styled, "the argument '{}{invalid_arg}{}' cannot be used multiple times",
invalid.render(),
invalid.render_reset()
);
} else { let _ = write!(
styled, "the argument '{}{invalid_arg}{}' cannot be used with",
invalid.render(),
invalid.render_reset()
);
}
} elseiflet Some(ContextValue::String(invalid_arg)) =
error.get(ContextKind::InvalidSubcommand)
{ let _ = write!(
styled, "the subcommand '{}{invalid_arg}{}' cannot be used with",
invalid.render(),
invalid.render_reset()
);
} else {
styled.push_str(error.kind().as_str().unwrap());
}
iflet Some(prior_arg) = prior_arg { match prior_arg {
ContextValue::Strings(values) => {
styled.push_str(":"); for v in values { let _ = write!(
styled, "\n{TAB}{}{v}{}",
invalid.render(),
invalid.render_reset()
);
}
}
ContextValue::String(value) => { let _ = write!(
styled, " '{}{value}{}'",
invalid.render(),
invalid.render_reset()
);
}
_ => {
styled.push_str(" one or more of the other specified arguments");
}
}
}
true
}
ErrorKind::NoEquals => { let invalid_arg = error.get(ContextKind::InvalidArg); iflet Some(ContextValue::String(invalid_arg)) = invalid_arg { let _ = write!(
styled, "equal sign is needed when assigning values to '{}{invalid_arg}{}'",
invalid.render(),
invalid.render_reset()
); true
} else { false
}
}
ErrorKind::InvalidValue => { let invalid_arg = error.get(ContextKind::InvalidArg); let invalid_value = error.get(ContextKind::InvalidValue); iflet (
Some(ContextValue::String(invalid_arg)),
Some(ContextValue::String(invalid_value)),
) = (invalid_arg, invalid_value)
{ if invalid_value.is_empty() { let _ = write!(
styled, "a value is required for '{}{invalid_arg}{}' but none was supplied",
invalid.render(),
invalid.render_reset()
);
} else { let _ = write!(
styled, "invalid value '{}{invalid_value}{}' for '{}{invalid_arg}{}'",
invalid.render(),
invalid.render_reset(),
literal.render(),
literal.render_reset()
);
}
let values = error.get(ContextKind::ValidValue);
write_values_list("possible values", styled, valid, values);
true
} else { false
}
}
ErrorKind::InvalidSubcommand => { let invalid_sub = error.get(ContextKind::InvalidSubcommand); iflet Some(ContextValue::String(invalid_sub)) = invalid_sub { let _ = write!(
styled, "unrecognized subcommand '{}{invalid_sub}{}'",
invalid.render(),
invalid.render_reset()
); true
} else { false
}
}
ErrorKind::MissingRequiredArgument => { let invalid_arg = error.get(ContextKind::InvalidArg); iflet Some(ContextValue::Strings(invalid_arg)) = invalid_arg {
styled.push_str("the following required arguments were not provided:"); for v in invalid_arg { let _ = write!(
styled, "\n{TAB}{}{v}{}",
valid.render(),
valid.render_reset()
);
} true
} else { false
}
}
ErrorKind::MissingSubcommand => { let invalid_sub = error.get(ContextKind::InvalidSubcommand); iflet Some(ContextValue::String(invalid_sub)) = invalid_sub { let _ = write!(
styled, "'{}{invalid_sub}{}' requires a subcommand but one was not provided",
invalid.render(),
invalid.render_reset()
); let values = error.get(ContextKind::ValidSubcommand);
write_values_list("subcommands", styled, valid, values);
true
} else { false
}
}
ErrorKind::InvalidUtf8 => false,
ErrorKind::TooManyValues => { let invalid_arg = error.get(ContextKind::InvalidArg); let invalid_value = error.get(ContextKind::InvalidValue); iflet (
Some(ContextValue::String(invalid_arg)),
Some(ContextValue::String(invalid_value)),
) = (invalid_arg, invalid_value)
{ let _ = write!(
styled, "unexpected value '{}{invalid_value}{}' for '{}{invalid_arg}{}' found; no more were expected",
invalid.render(),
invalid.render_reset(),
literal.render(),
literal.render_reset(),
); true
} else { false
}
}
ErrorKind::TooFewValues => { let invalid_arg = error.get(ContextKind::InvalidArg); let actual_num_values = error.get(ContextKind::ActualNumValues); let min_values = error.get(ContextKind::MinValues); iflet (
Some(ContextValue::String(invalid_arg)),
Some(ContextValue::Number(actual_num_values)),
Some(ContextValue::Number(min_values)),
) = (invalid_arg, actual_num_values, min_values)
{ let were_provided = singular_or_plural(*actual_num_values as usize); let _ = write!(
styled, "{}{min_values}{} values required by '{}{invalid_arg}{}'; only {}{actual_num_values}{}{were_provided}",
valid.render(),
valid.render_reset(),
literal.render(),
literal.render_reset(),
invalid.render(),
invalid.render_reset(),
); true
} else { false
}
}
ErrorKind::ValueValidation => { let invalid_arg = error.get(ContextKind::InvalidArg); let invalid_value = error.get(ContextKind::InvalidValue); iflet (
Some(ContextValue::String(invalid_arg)),
Some(ContextValue::String(invalid_value)),
) = (invalid_arg, invalid_value)
{ let _ = write!(
styled, "invalid value '{}{invalid_value}{}' for '{}{invalid_arg}{}'",
invalid.render(),
invalid.render_reset(),
literal.render(),
literal.render_reset(),
); iflet Some(source) = error.inner.source.as_deref() { let _ = write!(styled, ": {source}");
} true
} else { false
}
}
ErrorKind::WrongNumberOfValues => { let invalid_arg = error.get(ContextKind::InvalidArg); let actual_num_values = error.get(ContextKind::ActualNumValues); let num_values = error.get(ContextKind::ExpectedNumValues); iflet (
Some(ContextValue::String(invalid_arg)),
Some(ContextValue::Number(actual_num_values)),
Some(ContextValue::Number(num_values)),
) = (invalid_arg, actual_num_values, num_values)
{ let were_provided = singular_or_plural(*actual_num_values as usize); let _ = write!(
styled, "{}{num_values}{} values required for '{}{invalid_arg}{}' but {}{actual_num_values}{}{were_provided}",
valid.render(),
valid.render_reset(),
literal.render(),
literal.render_reset(),
invalid.render(),
invalid.render_reset(),
); true
} else { false
}
}
ErrorKind::UnknownArgument => { let invalid_arg = error.get(ContextKind::InvalidArg); iflet Some(ContextValue::String(invalid_arg)) = invalid_arg { let _ = write!(
styled, "unexpected argument '{}{invalid_arg}{}' found",
invalid.render(),
invalid.render_reset(),
); true
} else { false
}
}
ErrorKind::DisplayHelp
| ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand
| ErrorKind::DisplayVersion
| ErrorKind::Io
| ErrorKind::Format => false,
}
}
#[cfg(feature = "error-context")] fn write_values_list(
list_name: &'static str,
styled: &mut StyledStr,
valid: &anstyle::Style,
possible_values: Option<&ContextValue>,
) { use std::fmt::Write as _; iflet Some(ContextValue::Strings(possible_values)) = possible_values { if !possible_values.is_empty() { let _ = write!(styled, "\n{TAB}[{list_name}: ");
let style = valid.render(); let reset = valid.render_reset(); for (idx, val) in possible_values.iter().enumerate() { if idx > 0 {
styled.push_str(", ");
} let _ = write!(styled, "{style}{}{reset}", Escape(val));
}
/// Returns the singular or plural form on the verb to be based on the argument's value. fn singular_or_plural(n: usize) -> &'static str { if n > 1 { " were provided"
} else { " was provided"
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.