Skip to content

Commit

Permalink
refactor(help): Future proof styling
Browse files Browse the repository at this point in the history
We can add a new style and default it to what it was split out of
without a breaking change.
  • Loading branch information
epage committed Apr 18, 2023
1 parent c2f6200 commit ca74207
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 50 deletions.
6 changes: 3 additions & 3 deletions clap_builder/src/builder/arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4274,7 +4274,7 @@ impl Arg {

pub(crate) fn stylized(&self, styles: &Styles, required: Option<bool>) -> StyledStr {
use std::fmt::Write as _;
let literal = &styles.literal;
let literal = styles.get_literal();

let mut styled = StyledStr::new();
// Write the name such --long or -l
Expand All @@ -4294,8 +4294,8 @@ impl Arg {

pub(crate) fn stylize_arg_suffix(&self, styles: &Styles, required: Option<bool>) -> StyledStr {
use std::fmt::Write as _;
let literal = &styles.literal;
let placeholder = &styles.placeholder;
let literal = styles.get_literal();
let placeholder = styles.get_placeholder();
let mut styled = StyledStr::new();

let mut need_closing_bracket = false;
Expand Down
115 changes: 100 additions & 15 deletions clap_builder/src/builder/styled_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,23 +200,15 @@ impl std::fmt::Display for StyledStr {

/// Terminal styling definitions
#[derive(Clone, Debug)]
#[non_exhaustive]
#[allow(missing_copy_implementations)] // Large enough type that I want an explicit `clone()` for now
pub struct Styles {
/// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading]
pub header: anstyle::Style,
/// Error heading
pub error: anstyle::Style,
/// Usage heading
pub usage: anstyle::Style,
/// Literal command-line syntax, e.g. `--help`
pub literal: anstyle::Style,
/// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name]
pub placeholder: anstyle::Style,
/// Highlight suggested usage
pub valid: anstyle::Style,
/// Highlight invalid usage
pub invalid: anstyle::Style,
header: anstyle::Style,
error: anstyle::Style,
usage: anstyle::Style,
literal: anstyle::Style,
placeholder: anstyle::Style,
valid: anstyle::Style,
invalid: anstyle::Style,
}

impl Styles {
Expand Down Expand Up @@ -256,6 +248,99 @@ impl Styles {
Self::plain()
}
}

/// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading]
#[inline]
pub const fn header(mut self, style: anstyle::Style) -> Self {
self.header = style;
self
}

/// Error heading
#[inline]
pub const fn error(mut self, style: anstyle::Style) -> Self {
self.error = style;
self
}

/// Usage heading
#[inline]
pub const fn usage(mut self, style: anstyle::Style) -> Self {
self.usage = style;
self
}

/// Literal command-line syntax, e.g. `--help`
#[inline]
pub const fn literal(mut self, style: anstyle::Style) -> Self {
self.literal = style;
self
}

/// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name]
#[inline]
pub const fn placeholder(mut self, style: anstyle::Style) -> Self {
self.placeholder = style;
self
}

/// Highlight suggested usage
#[inline]
pub const fn valid(mut self, style: anstyle::Style) -> Self {
self.valid = style;
self
}

/// Highlight invalid usage
#[inline]
pub const fn invalid(mut self, style: anstyle::Style) -> Self {
self.invalid = style;
self
}
}

/// Reflection
impl Styles {
#[inline(always)]
pub const fn get_header(&self) -> anstyle::Style {
self.header
}

/// Error heading
#[inline(always)]
pub const fn get_error(&self) -> anstyle::Style {
self.error
}

/// Usage heading
#[inline(always)]
pub const fn get_usage(&self) -> anstyle::Style {
self.usage
}

/// Literal command-line syntax, e.g. `--help`
#[inline(always)]
pub const fn get_literal(&self) -> anstyle::Style {
self.literal
}

/// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name]
#[inline(always)]
pub const fn get_placeholder(&self) -> anstyle::Style {
self.placeholder
}

/// Highlight suggested usage
#[inline(always)]
pub const fn get_valid(&self) -> anstyle::Style {
self.valid
}

/// Highlight invalid usage
#[inline(always)]
pub const fn get_invalid(&self) -> anstyle::Style {
self.invalid
}
}

impl super::AppTag for Styles {}
Expand Down
24 changes: 12 additions & 12 deletions clap_builder/src/error/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl ErrorFormatter for RichFormatter {
fn format_error(error: &crate::error::Error<Self>) -> StyledStr {
use std::fmt::Write as _;
let styles = &error.inner.styles;
let valid = &styles.valid;
let valid = &styles.get_valid();

let mut styled = StyledStr::new();
start_error(&mut styled, styles);
Expand Down Expand Up @@ -128,7 +128,7 @@ impl ErrorFormatter for RichFormatter {

fn start_error(styled: &mut StyledStr, styles: &Styles) {
use std::fmt::Write as _;
let error = &styles.error;
let error = &styles.get_error();
let _ = write!(styled, "{}error:{} ", error.render(), error.render_reset());
}

Expand All @@ -140,9 +140,9 @@ fn write_dynamic_context(
styles: &Styles,
) -> bool {
use std::fmt::Write as _;
let valid = styles.valid;
let invalid = styles.invalid;
let literal = styles.literal;
let valid = styles.get_valid();
let invalid = styles.get_invalid();
let literal = styles.get_literal();

match error.kind() {
ErrorKind::ArgumentConflict => {
Expand Down Expand Up @@ -503,7 +503,7 @@ pub(crate) fn get_help_flag(cmd: &Command) -> Option<&'static str> {
fn try_help(styled: &mut StyledStr, styles: &Styles, help: Option<&str>) {
if let Some(help) = help {
use std::fmt::Write as _;
let literal = &styles.literal;
let literal = &styles.get_literal();
let _ = write!(
styled,
"\n\nFor more information, try '{}{help}{}'.\n",
Expand All @@ -522,15 +522,15 @@ fn did_you_mean(styled: &mut StyledStr, styles: &Styles, context: &str, valid: &
let _ = write!(
styled,
"{TAB}{}tip:{}",
styles.valid.render(),
styles.valid.render_reset()
styles.get_valid().render(),
styles.get_valid().render_reset()
);
if let ContextValue::String(valid) = valid {
let _ = write!(
styled,
" a similar {context} exists: '{}{valid}{}'",
styles.valid.render(),
styles.valid.render_reset()
styles.get_valid().render(),
styles.get_valid().render_reset()
);
} else if let ContextValue::Strings(valid) = valid {
if valid.len() == 1 {
Expand All @@ -545,8 +545,8 @@ fn did_you_mean(styled: &mut StyledStr, styles: &Styles, context: &str, valid: &
let _ = write!(
styled,
"'{}{valid}{}'",
styles.valid.render(),
styles.valid.render_reset()
styles.get_valid().render(),
styles.get_valid().render_reset()
);
}
}
Expand Down
12 changes: 6 additions & 6 deletions clap_builder/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,8 @@ impl<F: ErrorFormatter> Error<F> {
) -> Self {
use std::fmt::Write as _;
let styles = cmd.get_styles();
let invalid = &styles.invalid;
let valid = &styles.valid;
let invalid = &styles.get_invalid();
let valid = &styles.get_valid();
let mut err = Self::new(ErrorKind::InvalidSubcommand).with_cmd(cmd);

#[cfg(feature = "error-context")]
Expand Down Expand Up @@ -677,8 +677,8 @@ impl<F: ErrorFormatter> Error<F> {
) -> Self {
use std::fmt::Write as _;
let styles = cmd.get_styles();
let invalid = &styles.invalid;
let valid = &styles.valid;
let invalid = &styles.get_invalid();
let valid = &styles.get_valid();
let mut err = Self::new(ErrorKind::UnknownArgument).with_cmd(cmd);

#[cfg(feature = "error-context")]
Expand Down Expand Up @@ -740,8 +740,8 @@ impl<F: ErrorFormatter> Error<F> {
) -> Self {
use std::fmt::Write as _;
let styles = cmd.get_styles();
let invalid = &styles.invalid;
let valid = &styles.valid;
let invalid = &styles.get_invalid();
let valid = &styles.get_valid();
let mut err = Self::new(ErrorKind::UnknownArgument).with_cmd(cmd);

#[cfg(feature = "error-context")]
Expand Down
14 changes: 7 additions & 7 deletions clap_builder/src/output/help_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> {
let _ = write!(
self.writer,
"{}Usage:{}",
self.styles.usage.render(),
self.styles.usage.render_reset()
self.styles.get_usage().render(),
self.styles.get_usage().render_reset()
);
}
"usage" => {
Expand Down Expand Up @@ -341,7 +341,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> {
pub(crate) fn write_all_args(&mut self) {
debug!("HelpTemplate::write_all_args");
use std::fmt::Write as _;
let header = &self.styles.header;
let header = &self.styles.get_header();

let pos = self
.cmd
Expand Down Expand Up @@ -514,7 +514,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> {
fn short(&mut self, arg: &Arg) {
debug!("HelpTemplate::short");
use std::fmt::Write as _;
let literal = &self.styles.literal;
let literal = &self.styles.get_literal();

if let Some(s) = arg.get_short() {
let _ = write!(
Expand All @@ -532,7 +532,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> {
fn long(&mut self, arg: &Arg) {
debug!("HelpTemplate::long");
use std::fmt::Write as _;
let literal = &self.styles.literal;
let literal = &self.styles.get_literal();

if let Some(long) = arg.get_long() {
if arg.get_short().is_some() {
Expand Down Expand Up @@ -603,7 +603,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> {
) {
debug!("HelpTemplate::help");
use std::fmt::Write as _;
let literal = &self.styles.literal;
let literal = &self.styles.get_literal();

// Is help on next line, if so then indent
if next_line_help {
Expand Down Expand Up @@ -867,7 +867,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> {
fn write_subcommands(&mut self, cmd: &Command) {
debug!("HelpTemplate::write_subcommands");
use std::fmt::Write as _;
let literal = &self.styles.literal;
let literal = &self.styles.get_literal();

// The shortest an arg can legally be is 2 (i.e. '-x')
let mut longest = 2;
Expand Down
14 changes: 7 additions & 7 deletions clap_builder/src/output/usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ impl<'cmd> Usage<'cmd> {
let _ = write!(
styled,
"{}Usage:{} ",
self.styles.usage.render(),
self.styles.usage.render_reset()
self.styles.get_usage().render(),
self.styles.get_usage().render_reset()
);
styled.push_styled(&usage);
Some(styled)
Expand Down Expand Up @@ -81,8 +81,8 @@ impl<'cmd> Usage<'cmd> {
fn create_help_usage(&self, incl_reqs: bool) -> StyledStr {
debug!("Usage::create_help_usage; incl_reqs={:?}", incl_reqs);
use std::fmt::Write as _;
let literal = &self.styles.literal;
let placeholder = &self.styles.placeholder;
let literal = &self.styles.get_literal();
let placeholder = &self.styles.get_placeholder();
let mut styled = StyledStr::new();

let name = self
Expand Down Expand Up @@ -166,8 +166,8 @@ impl<'cmd> Usage<'cmd> {
fn create_smart_usage(&self, used: &[Id]) -> StyledStr {
debug!("Usage::create_smart_usage");
use std::fmt::Write;
let literal = &self.styles.literal;
let placeholder = &self.styles.placeholder;
let literal = &self.styles.get_literal();
let placeholder = &self.styles.get_placeholder();
let mut styled = StyledStr::new();

let bin_name = self
Expand Down Expand Up @@ -246,7 +246,7 @@ impl<'cmd> Usage<'cmd> {
pub(crate) fn get_args(&self, incls: &[Id], force_optional: bool) -> Vec<StyledStr> {
debug!("Usage::get_args: incls={:?}", incls,);
use std::fmt::Write as _;
let literal = &self.styles.literal;
let literal = &self.styles.get_literal();

let required_owned;
let required = if let Some(required) = self.required {
Expand Down

0 comments on commit ca74207

Please sign in to comment.