diff --git a/Cargo.toml b/Cargo.toml index 9b35595..88a3b11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fwdansi" -version = "1.0.1" +version = "1.1.0" authors = ["kennytm "] description = "Forwards a byte string with ANSI escape code to a termcolor terminal" repository = "https://github.com/kennytm/fwdansi" diff --git a/examples/colors.rs b/examples/colors.rs new file mode 100644 index 0000000..28ae65b --- /dev/null +++ b/examples/colors.rs @@ -0,0 +1,22 @@ +extern crate fwdansi; +extern crate termcolor; + +use fwdansi::write_ansi; +use std::io; +use termcolor::*; + +fn main() -> io::Result<()> { + let mut stdout = StandardStream::stdout(ColorChoice::Always); + + for fg in (30..=37).chain(90..=97) { + for bg in (40..=47).chain(100..=107) { + write_ansi( + &mut stdout, + format!("<\u{1b}[{fg};{bg}m{fg:2},{bg:3}\u{1b}[0m>", fg = fg, bg = bg).as_bytes(), + )?; + } + write_ansi(&mut stdout, b"\n")?; + } + + Ok(()) +} diff --git a/examples/run-rustc.rs b/examples/run-rustc.rs index 3bc303a..7951601 100644 --- a/examples/run-rustc.rs +++ b/examples/run-rustc.rs @@ -1,10 +1,10 @@ -extern crate termcolor; extern crate fwdansi; +extern crate termcolor; -use termcolor::*; +use fwdansi::write_ansi; use std::io; use std::process::Command; -use fwdansi::write_ansi; +use termcolor::*; fn main() -> io::Result<()> { let output = Command::new("rustc").args(&["--color", "always"]).output()?; diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..7530651 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +max_width = 120 diff --git a/src/lib.rs b/src/lib.rs index d5dcdbc..45638c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,14 +29,13 @@ //! } //! ``` -extern crate termcolor; extern crate memchr; +extern crate termcolor; use memchr::memchr; use termcolor::{Color, ColorSpec, WriteColor}; use std::io; -use std::mem; /// Writes a string with ANSI escape code into the colored output stream. /// @@ -55,7 +54,11 @@ pub fn write_ansi(mut writer: W, mut ansi: &[u8]) -> io::Result<( writer.write_all(&right[..1])?; ansi = &right[1..]; } else { - writer.set_color(&parser.spec)?; + if parser.reset { + writer.reset()?; + } else { + writer.set_color(&parser.spec)?; + } ansi = parser.ansi; } } @@ -69,6 +72,7 @@ enum State { Ansi256, Rgb, } +#[derive(Debug)] struct ColorSpecParser<'a> { spec: ColorSpec, ansi: &'a [u8], @@ -92,7 +96,7 @@ impl<'a> ColorSpecParser<'a> { } fn parse(&mut self) { - #[derive(PartialEq, Eq)] + #[derive(PartialEq, Eq, Debug)] enum Expected { Escape, OpenBracket, @@ -121,14 +125,13 @@ impl<'a> ColorSpecParser<'a> { (b':', Expected::Number(number)) | (b';', Expected::Number(number)) | (b'm', Expected::Number(number)) => { - if self.apply_number(number) { - if *b == b'm' { - expected = Expected::Escape; - break; - } else { - expected = Expected::Number(0); - continue; - } + self.apply_number(number); + if *b == b'm' { + expected = Expected::Escape; + break; + } else { + expected = Expected::Number(0); + continue; } } _ => {} @@ -151,12 +154,11 @@ impl<'a> ColorSpecParser<'a> { } } - fn apply_number(&mut self, number: u8) -> bool { + fn apply_number(&mut self, number: u8) { + self.reset = false; match (number, self.state) { (0, State::Normal) => { - if mem::replace(&mut self.reset, true) { - return false; - } + self.reset = true; } (1, State::Normal) => { self.spec.set_bold(true); @@ -198,25 +200,22 @@ impl<'a> ColorSpecParser<'a> { self.set_color(Color::Ansi256(n)); self.state = State::Normal; } - (b, State::Rgb) => { - match (self.red, self.green) { - (None, _) => { - self.red = Some(b); - } - (Some(_), None) => { - self.green = Some(b); - } - (Some(r), Some(g)) => { - self.set_color(Color::Rgb(r, g, b)); - self.state = State::Normal; - } + (b, State::Rgb) => match (self.red, self.green) { + (None, _) => { + self.red = Some(b); } - } + (Some(_), None) => { + self.green = Some(b); + } + (Some(r), Some(g)) => { + self.set_color(Color::Rgb(r, g, b)); + self.state = State::Normal; + } + }, _ => { self.state = State::Normal; } } - true } } diff --git a/tests/tests.rs b/tests/tests.rs index 4446793..c82f6f2 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,5 +1,5 @@ -extern crate proptest; extern crate fwdansi; +extern crate proptest; extern crate termcolor; use fwdansi::write_ansi; @@ -76,19 +76,18 @@ impl Element { prop_oneof![ Just(Element::Reset), any_color_spec().prop_map(Element::ColorSpec), - any::>() - .prop_filter_map( - "ignored empty SGR", - |v| if v.windows(3).find(|w| w == b"\x1b[m").is_some() { - None - } else { - Some(Element::Text(v)) - } - ), + any::>().prop_filter_map("ignored empty SGR", |v| { + if v.windows(3).find(|w| w == b"\x1b[m").is_some() { + None + } else { + Some(Element::Text(v)) + } + }), ] } fn write(&self, mut w: W) -> io::Result<()> { + w.write_all(b"~")?; match self { Element::ColorSpec(cs) => w.set_color(cs), Element::Reset => w.reset(),