Skip to content

Commit

Permalink
feat: Expose ANSI styling to the user
Browse files Browse the repository at this point in the history
This gives users the control over where clap outputs while still getting
colors.  For users who want to support old windows versions, check out
`fwdansi` crate.
  • Loading branch information
epage committed Sep 22, 2022
1 parent a2272a2 commit 037b075
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Expand Up @@ -272,10 +272,11 @@ Behavior Changes
- Can now pass runtime generated data to `Command`, `Arg`, `ArgGroup`, `PossibleValue`, etc without managing lifetimes with the `string` feature flag (#2150, #4223)
- New default `error-context`, `help` and `usage` feature flags that can be turned off for smaller binaries (#4236)
- *(error)* `Error::apply` for changing the formatter for dropping binary size (#4111)
- *(error)* `Command::render`
- *(error)* `Command::render` which can render to plain text or ANSI escape codes
- *(help)* Show `PossibleValue::help` in long help (`--help`) (#3312)
- *(help)* New `{tab}` variable for `Command::help_template` (#4161)
- *(help)* `Command::render_help` and `Command::render_long_help`
- *(help)* `Command::render_help` and `Command::render_long_help` which can render to plain text or ANSI escape codes
- *(help)* `Command::render_usage` now returns a `StyledStr` which can render to plain text or ANSI escape codes

### Fixes

Expand Down
26 changes: 26 additions & 0 deletions src/builder/styled_str.rs
Expand Up @@ -22,6 +22,12 @@ impl StyledStr {
}
}

/// Display using [ANSI Escape Code](https://en.wikipedia.org/wiki/ANSI_escape_code) styling
#[cfg(feature = "color")]
pub fn ansi(&self) -> impl std::fmt::Display + '_ {
AnsiDisplay { styled: self }
}

pub(crate) fn header(&mut self, msg: impl Into<String>) {
self.stylize_(Some(Style::Header), msg.into());
}
Expand Down Expand Up @@ -289,6 +295,26 @@ impl std::fmt::Display for StyledStr {
}
}

#[cfg(feature = "color")]
struct AnsiDisplay<'s> {
styled: &'s StyledStr,
}

#[cfg(feature = "color")]
impl std::fmt::Display for AnsiDisplay<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let mut buffer = termcolor::Buffer::ansi();
self.styled
.write_colored(&mut buffer)
.map_err(|_| std::fmt::Error)?;
let buffer = buffer.into_inner();
let buffer = String::from_utf8(buffer).map_err(|_| std::fmt::Error)?;
std::fmt::Display::fmt(&buffer, f)?;

Ok(())
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum Style {
Header,
Expand Down

0 comments on commit 037b075

Please sign in to comment.