Skip to content

Commit

Permalink
Generate reset() for \e[0m.
Browse files Browse the repository at this point in the history
Fix #1.
  • Loading branch information
kennytm committed Nov 17, 2019
1 parent 08466a4 commit d228a29
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 44 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fwdansi"
version = "1.0.1"
version = "1.1.0"
authors = ["kennytm <kennytm@gmail.com>"]
description = "Forwards a byte string with ANSI escape code to a termcolor terminal"
repository = "https://github.com/kennytm/fwdansi"
Expand Down
22 changes: 22 additions & 0 deletions examples/colors.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
6 changes: 3 additions & 3 deletions examples/run-rustc.rs
Original file line number Diff line number Diff line change
@@ -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()?;
Expand Down
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
max_width = 120
59 changes: 29 additions & 30 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand All @@ -55,7 +54,11 @@ pub fn write_ansi<W: WriteColor>(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;
}
}
Expand All @@ -69,6 +72,7 @@ enum State {
Ansi256,
Rgb,
}
#[derive(Debug)]
struct ColorSpecParser<'a> {
spec: ColorSpec,
ansi: &'a [u8],
Expand All @@ -92,7 +96,7 @@ impl<'a> ColorSpecParser<'a> {
}

fn parse(&mut self) {
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Debug)]
enum Expected {
Escape,
OpenBracket,
Expand Down Expand Up @@ -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;
}
}
_ => {}
Expand All @@ -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);
Expand Down Expand Up @@ -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
}
}

Expand Down
19 changes: 9 additions & 10 deletions tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
extern crate proptest;
extern crate fwdansi;
extern crate proptest;
extern crate termcolor;

use fwdansi::write_ansi;
Expand Down Expand Up @@ -76,19 +76,18 @@ impl Element {
prop_oneof![
Just(Element::Reset),
any_color_spec().prop_map(Element::ColorSpec),
any::<Vec<u8>>()
.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::<Vec<u8>>().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<W: WriteColor>(&self, mut w: W) -> io::Result<()> {
w.write_all(b"~")?;
match self {
Element::ColorSpec(cs) => w.set_color(cs),
Element::Reset => w.reset(),
Expand Down

0 comments on commit d228a29

Please sign in to comment.