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

Add resetted styling #40

Merged
merged 6 commits into from
May 24, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ Red.normal().paint("yet another red string");
Style::default().paint("a completely regular string");
```

Sometimes it is desirable to hard-reset a style/color just before
applying a new one. To reset and apply, the `reset_before_style` method can
be used on either `Color` or `Style` structs.

```rust
use nu_ansi_term::Style;

println!("\x1b[33mHow about some {} \x1b[33mand {}?\x1b[0m",
Style::new().reset_before_style().bold().paint("bold"),
Style::new().reset_before_style().underline().paint("underline"));
```

## Extended colors

You can access the extended range of 256 colors by using the `Color::Fixed` variant, which takes an argument of the color number to use.
Expand Down
14 changes: 14 additions & 0 deletions examples/basic_colors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,18 @@ fn main() {
println!("{} {}", Purple.paint("Purple"), Purple.bold().paint("bold"));
println!("{} {}", Cyan.paint("Cyan"), Cyan.bold().paint("bold"));
println!("{} {}", White.paint("White"), White.bold().paint("bold"));
println!("\nreset_before_style at work:");
println!(
"\x1b[33mReset {} \x1b[33mand {}\x1b[0m",
Style::new().reset_before_style().bold().paint("bold"),
Style::new()
.reset_before_style()
.underline()
.paint("underline")
);
println!(
"\x1b[33mDo not reset {} \x1b[33mand {}\x1b[0m",
Style::new().bold().paint("bold"),
Style::new().underline().paint("underline")
);
}
13 changes: 13 additions & 0 deletions src/ansi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ impl Style {
return Ok(());
}

// Prefix everything with reset characters if needed
if self.with_reset {
write!(f, "\x1B[0m")?
}

// Write the codes’ prefix, then write numbers, separated by
// semicolons, for each text style we want to apply.
write!(f, "\x1B[")?;
Expand Down Expand Up @@ -407,6 +412,8 @@ mod test {
test!(magenta_on_white: Magenta.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(magenta_on_white_2: Magenta.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue_2: Cyan.on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
test!(yellow_on_blue_reset: Cyan.on(Blue).reset_before_style().fg(Yellow); "hi" => "\x1B[0m\x1B[44;33mhi\x1B[0m");
test!(yellow_on_blue_reset_2: Cyan.on(Blue).fg(Yellow).reset_before_style(); "hi" => "\x1B[0m\x1B[44;33mhi\x1B[0m");
test!(cyan_bold_on_white: Cyan.bold().on(White); "hi" => "\x1B[1;47;36mhi\x1B[0m");
test!(cyan_ul_on_white: Cyan.underline().on(White); "hi" => "\x1B[4;47;36mhi\x1B[0m");
test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
Expand All @@ -419,6 +426,8 @@ mod test {
test!(blue_on_rgb: Blue.on(Rgb(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
test!(rgb_on_rgb: Rgb(70,130,180).on(Rgb(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
test!(bold: Style::new().bold(); "hi" => "\x1B[1mhi\x1B[0m");
test!(bold_with_reset: Style::new().reset_before_style().bold(); "hi" => "\x1B[0m\x1B[1mhi\x1B[0m");
test!(bold_with_reset_2: Style::new().bold().reset_before_style(); "hi" => "\x1B[0m\x1B[1mhi\x1B[0m");
test!(underline: Style::new().underline(); "hi" => "\x1B[4mhi\x1B[0m");
test!(bunderline: Style::new().bold().underline(); "hi" => "\x1B[1;4mhi\x1B[0m");
test!(dimmed: Style::new().dimmed(); "hi" => "\x1B[2mhi\x1B[0m");
Expand Down Expand Up @@ -462,6 +471,8 @@ mod gnu_legacy_test {
test!(purple_on_white: Purple.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(purple_on_white_2: Purple.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue: Style::new().on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
test!(yellow_on_blue_reset: Cyan.on(Blue).reset_before_style().fg(Yellow); "hi" => "\x1B[0m\x1B[44;33mhi\x1B[0m");
test!(yellow_on_blue_reset_2: Cyan.on(Blue).fg(Yellow).reset_before_style(); "hi" => "\x1B[0m\x1B[44;33mhi\x1B[0m");
test!(magenta_on_white: Magenta.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(magenta_on_white_2: Magenta.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue_2: Cyan.on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
Expand All @@ -477,6 +488,8 @@ mod gnu_legacy_test {
test!(blue_on_rgb: Blue.on(Rgb(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
test!(rgb_on_rgb: Rgb(70,130,180).on(Rgb(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
test!(bold: Style::new().bold(); "hi" => "\x1B[01mhi\x1B[0m");
test!(bold_with_reset: Style::new().reset_before_style().bold(); "hi" => "\x1B[0m\x1B[01mhi\x1B[0m");
test!(bold_with_reset_2: Style::new().bold().reset_before_style(); "hi" => "\x1B[0m\x1B[01mhi\x1B[0m");
test!(underline: Style::new().underline(); "hi" => "\x1B[04mhi\x1B[0m");
test!(bunderline: Style::new().bold().underline(); "hi" => "\x1B[01;04mhi\x1B[0m");
test!(dimmed: Style::new().dimmed(); "hi" => "\x1B[02mhi\x1B[0m");
Expand Down
42 changes: 41 additions & 1 deletion src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ pub struct Style {

/// Whether this style is struckthrough.
pub is_strikethrough: bool,

/// Wether this style starts with reset code
pub with_reset: bool,
}

impl Style {
Expand All @@ -61,6 +64,23 @@ impl Style {
Style::default()
}

/// Returns a `Style` with the reset_before_style property set.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Style;
///
/// let style = Style::new().reset_before_style();
/// println!("{}", style.paint("hey"));
/// ```
pub const fn reset_before_style(&self) -> Style {
Style {
with_reset: true,
..*self
}
}

/// Returns a `Style` with the bold property set.
///
/// # Examples
Expand Down Expand Up @@ -269,6 +289,7 @@ impl Default for Style {
is_reverse: false,
is_hidden: false,
is_strikethrough: false,
with_reset: false,
}
}
}
Expand Down Expand Up @@ -542,6 +563,25 @@ impl Color {
}
}

/// Returns a `Style` thats resets all styling before applying
/// the foreground color set to this color.
///
/// # Examples
///
/// ```
/// use nu_ansi_term::Color;
///
/// let style = Color::Fixed(244).reset_before_style();
/// println!("{}", style.paint("yo"));
/// ```
pub fn reset_before_style(self) -> Style {
Style {
foreground: Some(self),
with_reset: true,
..Style::default()
}
}

/// Returns a `Style` with the foreground color set to this color and the
/// background color property set to the given color.
///
Expand Down Expand Up @@ -619,6 +659,6 @@ mod serde_json_tests {
fn style_serialization() {
let style = Style::default();

assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string());
assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false,\"with_reset\":false}".to_string());
}
}