Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(error): Allow custmizing formatting #4111

Merged
merged 4 commits into from Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -60,6 +60,7 @@ MSRV is now 1.60.0

- `Arg::num_args` now accepts ranges, allowing setting both the minimum and maximum number of values per occurrence
- Added `TypedValueParser::map` to make it easier to reuse existing value parsers
- *(error)* `Error::apply` for changing the formatter for dropping binary size
- *(help)* Show `PossibleValue::help` in long help (`--help`) (#3312)

### Fixes
Expand Down
11 changes: 5 additions & 6 deletions src/builder/command.rs
Expand Up @@ -4390,12 +4390,11 @@ impl Command {
self.disp_ord.unwrap_or(999)
}

pub(crate) fn write_help_err(&self, mut use_long: bool, stream: Stream) -> Colorizer {
pub(crate) fn write_help_err(&self, mut use_long: bool) -> StyledStr {
debug!(
"Command::write_help_err: {}, use_long={:?}, stream={:?}",
"Command::write_help_err: {}, use_long={:?}",
self.get_display_name().unwrap_or_else(|| self.get_name()),
use_long && self.use_long_help(),
stream
);

use_long = use_long && self.use_long_help();
Expand All @@ -4404,14 +4403,14 @@ impl Command {
let mut styled = StyledStr::new();
Help::new(&mut styled, self, &usage, use_long).write_help();

Colorizer::new(stream, self.color_help()).with_content(styled)
styled
}

pub(crate) fn write_version_err(&self, use_long: bool) -> Colorizer {
pub(crate) fn write_version_err(&self, use_long: bool) -> StyledStr {
let msg = self._render_version(use_long);
let mut styled = StyledStr::new();
styled.none(msg);
Colorizer::new(Stream::Stdout, self.color_help()).with_content(styled)
styled
}

pub(crate) fn use_long_help(&self) -> bool {
Expand Down
2 changes: 1 addition & 1 deletion src/builder/mod.rs
Expand Up @@ -33,6 +33,7 @@ pub use possible_value::PossibleValue;
pub use range::ValueRange;
pub use resettable::IntoResettable;
pub use resettable::Resettable;
pub use styled_str::StyledStr;
pub use value_hint::ValueHint;
pub use value_parser::_AutoValueParser;
pub use value_parser::via_prelude;
Expand All @@ -55,7 +56,6 @@ pub use value_parser::_AnonymousValueParser;

#[allow(unused_imports)]
pub(crate) use self::str::Inner as StrInner;
pub(crate) use self::styled_str::StyledStr;
pub(crate) use action::CountType;
pub(crate) use arg::render_arg_val;
pub(crate) use arg_settings::{ArgFlags, ArgSettings};
6 changes: 4 additions & 2 deletions src/builder/styled_str.rs
@@ -1,10 +1,12 @@
/// Terminal-styling container
#[derive(Clone, Default, Debug, PartialEq, Eq)]
pub(crate) struct StyledStr {
pub struct StyledStr {
pieces: Vec<(Option<Style>, String)>,
}

impl StyledStr {
pub(crate) const fn new() -> Self {
/// Create an empty buffer
pub const fn new() -> Self {
Self { pieces: Vec::new() }
}

Expand Down
43 changes: 42 additions & 1 deletion src/error/context.rs
@@ -1,5 +1,5 @@
/// Semantics for a piece of error information
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ContextKind {
/// The cause of the error
Expand Down Expand Up @@ -34,6 +34,35 @@ pub enum ContextKind {
Custom,
}

impl ContextKind {
/// End-user description of the error case, where relevant
pub fn as_str(self) -> Option<&'static str> {
match self {
Self::InvalidSubcommand => Some("Invalid Subcommand"),
Self::InvalidArg => Some("Invalid Argument"),
Self::PriorArg => Some("Prior Argument"),
Self::ValidValue => Some("Value Value"),
Self::InvalidValue => Some("Invalid Value"),
Self::ActualNumValues => Some("Actual Number of Values"),
Self::ExpectedNumValues => Some("Expected Number of Values"),
Self::MinValues => Some("Minimum Number of Values"),
Self::SuggestedCommand => Some("Suggested Command"),
Self::SuggestedSubcommand => Some("Suggested Subcommand"),
Self::SuggestedArg => Some("Suggested Argument"),
Self::SuggestedValue => Some("Suggested Value"),
Self::TrailingArg => Some("Trailing Argument"),
Self::Usage => None,
Self::Custom => None,
}
}
}

impl std::fmt::Display for ContextKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.as_str().unwrap_or_default().fmt(f)
}
}

/// A piece of error information
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
Expand All @@ -49,3 +78,15 @@ pub enum ContextValue {
/// A single value
Number(isize),
}

impl std::fmt::Display for ContextValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::None => "".fmt(f),
Self::Bool(v) => v.fmt(f),
Self::String(v) => v.fmt(f),
Self::Strings(v) => v.join(", ").fmt(f),
Self::Number(v) => v.fmt(f),
}
}
}