Skip to content

Commit

Permalink
Merge pull request #4110 from epage/styled
Browse files Browse the repository at this point in the history
refactor(help): Prepare for user-visible styled string
  • Loading branch information
epage authored Aug 24, 2022
2 parents 79bdeb2 + 74f29fc commit 956789c
Show file tree
Hide file tree
Showing 10 changed files with 420 additions and 412 deletions.
44 changes: 28 additions & 16 deletions src/builder/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ use crate::builder::ArgAction;
use crate::builder::IntoResettable;
use crate::builder::PossibleValue;
use crate::builder::Str;
use crate::builder::StyledStr;
use crate::builder::{Arg, ArgGroup, ArgPredicate};
use crate::error::ErrorKind;
use crate::error::Result as ClapResult;
use crate::mkeymap::MKeyMap;
use crate::output::fmt::Stream;
use crate::output::{fmt::Colorizer, Help, HelpWriter, Usage};
use crate::output::{fmt::Colorizer, Help, Usage};
use crate::parser::{ArgMatcher, ArgMatches, Parser};
use crate::util::ChildGraph;
use crate::util::FlatMap;
Expand Down Expand Up @@ -718,9 +719,11 @@ impl Command {
self._build_self();
let color = self.get_color();

let mut c = Colorizer::new(Stream::Stdout, color);
let mut styled = StyledStr::new();
let usage = Usage::new(self);
Help::new(HelpWriter::Buffer(&mut c), self, &usage, false).write_help()?;
Help::new(&mut styled, self, &usage, false).write_help();

let c = Colorizer::new(Stream::Stdout, color).with_content(styled);
c.print()
}

Expand All @@ -743,9 +746,11 @@ impl Command {
self._build_self();
let color = self.get_color();

let mut c = Colorizer::new(Stream::Stdout, color);
let mut styled = StyledStr::new();
let usage = Usage::new(self);
Help::new(HelpWriter::Buffer(&mut c), self, &usage, true).write_help()?;
Help::new(&mut styled, self, &usage, true).write_help();

let c = Colorizer::new(Stream::Stdout, color).with_content(styled);
c.print()
}

Expand All @@ -768,8 +773,10 @@ impl Command {
pub fn write_help<W: io::Write>(&mut self, w: &mut W) -> io::Result<()> {
self._build_self();

let mut styled = StyledStr::new();
let usage = Usage::new(self);
Help::new(HelpWriter::Normal(w), self, &usage, false).write_help()?;
Help::new(&mut styled, self, &usage, false).write_help();
write!(w, "{}", styled)?;
w.flush()
}

Expand All @@ -792,8 +799,10 @@ impl Command {
pub fn write_long_help<W: io::Write>(&mut self, w: &mut W) -> io::Result<()> {
self._build_self();

let mut styled = StyledStr::new();
let usage = Usage::new(self);
Help::new(HelpWriter::Normal(w), self, &usage, true).write_help()?;
Help::new(&mut styled, self, &usage, true).write_help();
write!(w, "{}", styled)?;
w.flush()
}

Expand Down Expand Up @@ -3282,7 +3291,6 @@ impl Command {
}

/// Should we color the output?
#[inline(never)]
pub fn get_color(&self) -> ColorChoice {
debug!("Command::color: Color setting...");

Expand Down Expand Up @@ -4382,11 +4390,7 @@ impl Command {
self.disp_ord.unwrap_or(999)
}

pub(crate) fn write_help_err(
&self,
mut use_long: bool,
stream: Stream,
) -> ClapResult<Colorizer> {
pub(crate) fn write_help_err(&self, mut use_long: bool, stream: Stream) -> Colorizer {
debug!(
"Command::write_help_err: {}, use_long={:?}, stream={:?}",
self.get_display_name().unwrap_or_else(|| self.get_name()),
Expand All @@ -4397,9 +4401,17 @@ impl Command {
use_long = use_long && self.use_long_help();
let usage = Usage::new(self);

let mut c = Colorizer::new(stream, self.color_help());
Help::new(HelpWriter::Buffer(&mut c), self, &usage, use_long).write_help()?;
Ok(c)
let mut styled = StyledStr::new();
Help::new(&mut styled, self, &usage, use_long).write_help();

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

pub(crate) fn write_version_err(&self, use_long: bool) -> Colorizer {
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)
}

pub(crate) fn use_long_help(&self) -> bool {
Expand Down
2 changes: 2 additions & 0 deletions src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod possible_value;
mod range;
mod resettable;
mod str;
mod styled_str;
mod value_hint;
mod value_parser;

Expand Down Expand Up @@ -54,6 +55,7 @@ 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};
116 changes: 116 additions & 0 deletions src/builder/styled_str.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#[derive(Clone, Default, Debug, PartialEq, Eq)]
pub(crate) struct StyledStr {
pieces: Vec<(Option<Style>, String)>,
}

impl StyledStr {
pub(crate) const fn new() -> Self {
Self { pieces: Vec::new() }
}

pub(crate) fn good(&mut self, msg: impl Into<String>) {
self.stylize(Some(Style::Good), msg.into());
}

pub(crate) fn warning(&mut self, msg: impl Into<String>) {
self.stylize(Some(Style::Warning), msg.into());
}

pub(crate) fn error(&mut self, msg: impl Into<String>) {
self.stylize(Some(Style::Error), msg.into());
}

#[allow(dead_code)]
pub(crate) fn hint(&mut self, msg: impl Into<String>) {
self.stylize(Some(Style::Hint), msg.into());
}

pub(crate) fn none(&mut self, msg: impl Into<String>) {
self.stylize(None, msg.into());
}

fn stylize(&mut self, style: Option<Style>, msg: String) {
self.pieces.push((style, msg));
}

#[cfg(feature = "color")]
pub(crate) fn write_colored(&self, buffer: &mut termcolor::Buffer) -> std::io::Result<()> {
use std::io::Write;
use termcolor::WriteColor;

for (style, content) in &self.pieces {
let mut color = termcolor::ColorSpec::new();
match style {
Some(Style::Good) => {
color.set_fg(Some(termcolor::Color::Green));
}
Some(Style::Warning) => {
color.set_fg(Some(termcolor::Color::Yellow));
}
Some(Style::Error) => {
color.set_fg(Some(termcolor::Color::Red));
color.set_bold(true);
}
Some(Style::Hint) => {
color.set_dimmed(true);
}
None => {}
}

buffer.set_color(&color)?;
buffer.write_all(content.as_bytes())?;
buffer.reset()?;
}

Ok(())
}
}

impl From<std::string::String> for StyledStr {
fn from(name: std::string::String) -> Self {
let mut styled = StyledStr::new();
styled.none(name);
styled
}
}

impl From<&'_ std::string::String> for StyledStr {
fn from(name: &'_ std::string::String) -> Self {
let mut styled = StyledStr::new();
styled.none(name);
styled
}
}

impl From<&'static str> for StyledStr {
fn from(name: &'static str) -> Self {
let mut styled = StyledStr::new();
styled.none(name);
styled
}
}

impl From<&'_ &'static str> for StyledStr {
fn from(name: &'_ &'static str) -> Self {
StyledStr::from(*name)
}
}

/// Color-unaware printing. Never uses coloring.
impl std::fmt::Display for StyledStr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
for (_, content) in &self.pieces {
std::fmt::Display::fmt(content, f)?;
}

Ok(())
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum Style {
Good,
Warning,
Error,
Hint,
}
Loading

0 comments on commit 956789c

Please sign in to comment.