Add support for other underline types and the ability to color them (#679)
This commit is contained in:
parent
73a8ecc95f
commit
ad0d100304
@ -8,6 +8,10 @@ const ATTRIBUTES: [(style::Attribute, style::Attribute); 6] = [
|
|||||||
(style::Attribute::Bold, style::Attribute::NormalIntensity),
|
(style::Attribute::Bold, style::Attribute::NormalIntensity),
|
||||||
(style::Attribute::Italic, style::Attribute::NoItalic),
|
(style::Attribute::Italic, style::Attribute::NoItalic),
|
||||||
(style::Attribute::Underlined, style::Attribute::NoUnderline),
|
(style::Attribute::Underlined, style::Attribute::NoUnderline),
|
||||||
|
(style::Attribute::DoubleUnderlined, style::Attribute::NoUnderline),
|
||||||
|
(style::Attribute::Undercurled, style::Attribute::NoUnderline),
|
||||||
|
(style::Attribute::Underdotted, style::Attribute::NoUnderline),
|
||||||
|
(style::Attribute::Underdashed, style::Attribute::NoUnderline),
|
||||||
(style::Attribute::Reverse, style::Attribute::NoReverse),
|
(style::Attribute::Reverse, style::Attribute::NoReverse),
|
||||||
(
|
(
|
||||||
style::Attribute::CrossedOut,
|
style::Attribute::CrossedOut,
|
||||||
|
24
src/style.rs
24
src/style.rs
@ -217,6 +217,25 @@ impl Command for SetBackgroundColor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A command that sets the the underline color.
|
||||||
|
///
|
||||||
|
/// See [`Color`](enum.Color.html) for more info.
|
||||||
|
///
|
||||||
|
/// [`SetColors`](struct.SetColors.html) can also be used to set both the foreground and background
|
||||||
|
/// color with one command.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
///
|
||||||
|
/// Commands must be executed/queued for execution otherwise they do nothing.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct SetUnderlineColor(pub Color);
|
||||||
|
|
||||||
|
impl Command for SetUnderlineColor {
|
||||||
|
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
|
||||||
|
write!(f, csi!("{}m"), Colored::UnderlineColor(self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A command that optionally sets the foreground and/or background color.
|
/// A command that optionally sets the foreground and/or background color.
|
||||||
///
|
///
|
||||||
/// For example:
|
/// For example:
|
||||||
@ -340,6 +359,11 @@ impl<D: Display> Command for PrintStyledContent<D> {
|
|||||||
reset_foreground = true;
|
reset_foreground = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ul) = style.underline_color {
|
||||||
|
execute_fmt(f, SetUnderlineColor(ul)).map_err(|_| fmt::Error)?;
|
||||||
|
reset_foreground = true;
|
||||||
|
}
|
||||||
|
|
||||||
if !style.attributes.is_empty() {
|
if !style.attributes.is_empty() {
|
||||||
execute_fmt(f, SetAttributes(style.attributes)).map_err(|_| fmt::Error)?;
|
execute_fmt(f, SetAttributes(style.attributes)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
|
@ -11,6 +11,8 @@ pub struct ContentStyle {
|
|||||||
pub foreground_color: Option<Color>,
|
pub foreground_color: Option<Color>,
|
||||||
/// The background color.
|
/// The background color.
|
||||||
pub background_color: Option<Color>,
|
pub background_color: Option<Color>,
|
||||||
|
/// The underline color.
|
||||||
|
pub underline_color: Option<Color>,
|
||||||
/// List of attributes.
|
/// List of attributes.
|
||||||
pub attributes: Attributes,
|
pub attributes: Attributes,
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ macro_rules! stylize_method {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($method_name_fg:ident, $method_name_bg:ident Color::$color:ident) => {
|
($method_name_fg:ident, $method_name_bg:ident, $method_name_ul:ident Color::$color:ident) => {
|
||||||
calculated_docs! {
|
calculated_docs! {
|
||||||
#[doc = concat!(
|
#[doc = concat!(
|
||||||
"Sets the foreground color to [`",
|
"Sets the foreground color to [`",
|
||||||
@ -40,6 +40,17 @@ macro_rules! stylize_method {
|
|||||||
fn $method_name_bg(self) -> Self::Styled {
|
fn $method_name_bg(self) -> Self::Styled {
|
||||||
self.on(Color::$color)
|
self.on(Color::$color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc = concat!(
|
||||||
|
"Sets the underline color to [`",
|
||||||
|
stringify!($color),
|
||||||
|
"`](Color::",
|
||||||
|
stringify!($color),
|
||||||
|
")."
|
||||||
|
)]
|
||||||
|
fn $method_name_ul(self) -> Self::Styled {
|
||||||
|
self.underline(Color::$color)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -77,6 +88,13 @@ pub trait Stylize: Sized {
|
|||||||
styled
|
styled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the underline color.
|
||||||
|
fn underline(self, color: Color) -> Self::Styled {
|
||||||
|
let mut styled = self.stylize();
|
||||||
|
styled.as_mut().underline_color = Some(color);
|
||||||
|
styled
|
||||||
|
}
|
||||||
|
|
||||||
/// Styles the content with the attribute.
|
/// Styles the content with the attribute.
|
||||||
fn attribute(self, attr: Attribute) -> Self::Styled {
|
fn attribute(self, attr: Attribute) -> Self::Styled {
|
||||||
let mut styled = self.stylize();
|
let mut styled = self.stylize();
|
||||||
@ -96,22 +114,22 @@ pub trait Stylize: Sized {
|
|||||||
stylize_method!(hidden Attribute::Hidden);
|
stylize_method!(hidden Attribute::Hidden);
|
||||||
stylize_method!(crossed_out Attribute::CrossedOut);
|
stylize_method!(crossed_out Attribute::CrossedOut);
|
||||||
|
|
||||||
stylize_method!(black, on_black Color::Black);
|
stylize_method!(black, on_black, underline_black Color::Black);
|
||||||
stylize_method!(dark_grey, on_dark_grey Color::DarkGrey);
|
stylize_method!(dark_grey, on_dark_grey, underline_dark_grey Color::DarkGrey);
|
||||||
stylize_method!(red, on_red Color::Red);
|
stylize_method!(red, on_red, underline_red Color::Red);
|
||||||
stylize_method!(dark_red, on_dark_red Color::DarkRed);
|
stylize_method!(dark_red, on_dark_red, underline_dark_red Color::DarkRed);
|
||||||
stylize_method!(green, on_green Color::Green);
|
stylize_method!(green, on_green, underline_green Color::Green);
|
||||||
stylize_method!(dark_green, on_dark_green Color::DarkGreen);
|
stylize_method!(dark_green, on_dark_green, underline_dark_green Color::DarkGreen);
|
||||||
stylize_method!(yellow, on_yellow Color::Yellow);
|
stylize_method!(yellow, on_yellow, underline_yellow Color::Yellow);
|
||||||
stylize_method!(dark_yellow, on_dark_yellow Color::DarkYellow);
|
stylize_method!(dark_yellow, on_dark_yellow, underline_dark_yellow Color::DarkYellow);
|
||||||
stylize_method!(blue, on_blue Color::Blue);
|
stylize_method!(blue, on_blue, underline_blue Color::Blue);
|
||||||
stylize_method!(dark_blue, on_dark_blue Color::DarkBlue);
|
stylize_method!(dark_blue, on_dark_blue, underline_dark_blue Color::DarkBlue);
|
||||||
stylize_method!(magenta, on_magenta Color::Magenta);
|
stylize_method!(magenta, on_magenta, underline_magenta Color::Magenta);
|
||||||
stylize_method!(dark_magenta, on_dark_magenta Color::DarkMagenta);
|
stylize_method!(dark_magenta, on_dark_magenta, underline_dark_magenta Color::DarkMagenta);
|
||||||
stylize_method!(cyan, on_cyan Color::Cyan);
|
stylize_method!(cyan, on_cyan, underline_cyan Color::Cyan);
|
||||||
stylize_method!(dark_cyan, on_dark_cyan Color::DarkCyan);
|
stylize_method!(dark_cyan, on_dark_cyan, underline_dark_cyan Color::DarkCyan);
|
||||||
stylize_method!(white, on_white Color::White);
|
stylize_method!(white, on_white, underline_white Color::White);
|
||||||
stylize_method!(grey, on_grey Color::Grey);
|
stylize_method!(grey, on_grey, underline_grey Color::Grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_stylize_for_display {
|
macro_rules! impl_stylize_for_display {
|
||||||
|
@ -100,6 +100,17 @@ Attribute! {
|
|||||||
Italic = 3,
|
Italic = 3,
|
||||||
/// Underlines the text.
|
/// Underlines the text.
|
||||||
Underlined = 4,
|
Underlined = 4,
|
||||||
|
|
||||||
|
// Other types of underlining
|
||||||
|
/// Double underlines the text.
|
||||||
|
DoubleUnderlined = 2,
|
||||||
|
/// Undercurls the text.
|
||||||
|
Undercurled = 3,
|
||||||
|
/// Underdots the text.
|
||||||
|
Underdotted = 4,
|
||||||
|
/// Underdashes the text.
|
||||||
|
Underdashed = 5,
|
||||||
|
|
||||||
/// Makes the text blinking (< 150 per minute).
|
/// Makes the text blinking (< 150 per minute).
|
||||||
SlowBlink = 5,
|
SlowBlink = 5,
|
||||||
/// Makes the text blinking (>= 150 per minute).
|
/// Makes the text blinking (>= 150 per minute).
|
||||||
@ -163,7 +174,10 @@ impl Attribute {
|
|||||||
/// Returns the SGR attribute value.
|
/// Returns the SGR attribute value.
|
||||||
///
|
///
|
||||||
/// See <https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters>
|
/// See <https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters>
|
||||||
pub fn sgr(self) -> i16 {
|
pub fn sgr(self) -> String {
|
||||||
SGR[self as usize]
|
if (self as usize) > 4 && (self as usize) < 9 {
|
||||||
|
return "4:".to_string() + SGR[self as usize].to_string().as_str()
|
||||||
|
}
|
||||||
|
SGR[self as usize].to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ pub enum Colored {
|
|||||||
ForegroundColor(Color),
|
ForegroundColor(Color),
|
||||||
/// A background color.
|
/// A background color.
|
||||||
BackgroundColor(Color),
|
BackgroundColor(Color),
|
||||||
|
/// An underline color.
|
||||||
|
UnderlineColor(Color),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Colored {
|
impl Colored {
|
||||||
@ -39,16 +41,18 @@ impl Colored {
|
|||||||
///
|
///
|
||||||
/// See also: [`Color::parse_ansi`].
|
/// See also: [`Color::parse_ansi`].
|
||||||
pub fn parse_ansi(ansi: &str) -> Option<Self> {
|
pub fn parse_ansi(ansi: &str) -> Option<Self> {
|
||||||
use Colored::{BackgroundColor, ForegroundColor};
|
use Colored::{BackgroundColor, ForegroundColor, UnderlineColor};
|
||||||
|
|
||||||
let values = &mut ansi.split(';');
|
let values = &mut ansi.split(';');
|
||||||
|
|
||||||
let output = match parse_next_u8(values)? {
|
let output = match parse_next_u8(values)? {
|
||||||
38 => return Color::parse_ansi_iter(values).map(ForegroundColor),
|
38 => return Color::parse_ansi_iter(values).map(ForegroundColor),
|
||||||
48 => return Color::parse_ansi_iter(values).map(BackgroundColor),
|
48 => return Color::parse_ansi_iter(values).map(BackgroundColor),
|
||||||
|
58 => return Color::parse_ansi_iter(values).map(UnderlineColor),
|
||||||
|
|
||||||
39 => ForegroundColor(Color::Reset),
|
39 => ForegroundColor(Color::Reset),
|
||||||
49 => BackgroundColor(Color::Reset),
|
49 => BackgroundColor(Color::Reset),
|
||||||
|
59 => UnderlineColor(Color::Reset),
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
@ -82,6 +86,14 @@ impl fmt::Display for Colored {
|
|||||||
color = new_color;
|
color = new_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Colored::UnderlineColor(new_color) => {
|
||||||
|
if new_color == Color::Reset {
|
||||||
|
return f.write_str("59");
|
||||||
|
} else {
|
||||||
|
f.write_str("58;")?;
|
||||||
|
color = new_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match color {
|
match color {
|
||||||
|
@ -63,6 +63,10 @@ impl From<Colored> for Colors {
|
|||||||
foreground: None,
|
foreground: None,
|
||||||
background: Some(color),
|
background: Some(color),
|
||||||
},
|
},
|
||||||
|
Colored::UnderlineColor(color) => Colors {
|
||||||
|
foreground: None,
|
||||||
|
background: Some(color),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user