use termwiz::cell::{Blink, Intensity, Underline};
use termwiz::color::ColorSpec;
use termwiz::escape::{
csi::{Sgr, CSI},
parser::Parser,
Action, ControlCode,
};
use tui::style::{Color, Modifier, Style};
use tui::text::{Span, Spans, Text};
pub fn bytes_to_text<'a, B: AsRef<[u8]>>(bytes: B) -> Text<'a> {
let mut parser = Parser::new();
let parsed = parser.parse_as_vec(bytes.as_ref());
let mut spans = Vec::<Spans>::new();
let mut span_style = Style::default();
let mut span_text = String::new();
let mut current_line = Vec::<Span>::new();
for item in parsed {
match item {
Action::Print(c) => {
span_text.push(c);
}
Action::Control(ControlCode::LineFeed) => {
current_line.push(Span::styled(span_text, span_style.into()));
span_text = String::new();
spans.push(Spans::from(current_line));
current_line = Vec::new();
}
Action::CSI(CSI::Sgr(sgr)) => {
if let Sgr::Font(_) = sgr {
continue;
}
current_line.push(Span::styled(span_text, span_style.into()));
span_text = String::new();
match sgr {
Sgr::Reset => span_style = Style::default(),
Sgr::Intensity(i) => match i {
Intensity::Bold => {
span_style = span_style.remove_modifier(Modifier::DIM);
span_style = span_style.add_modifier(Modifier::BOLD);
}
Intensity::Half => {
span_style = span_style.add_modifier(Modifier::DIM);
span_style = span_style.remove_modifier(Modifier::BOLD);
}
Intensity::Normal => {
span_style = span_style.remove_modifier(Modifier::DIM);
span_style = span_style.remove_modifier(Modifier::BOLD);
}
},
Sgr::Underline(u) => match u {
Underline::Double | Underline::Single => {
span_style = span_style.add_modifier(Modifier::UNDERLINED);
}
_ => span_style = span_style.remove_modifier(Modifier::UNDERLINED),
},
Sgr::Blink(b) => match b {
Blink::Slow => {
span_style = span_style.add_modifier(Modifier::SLOW_BLINK);
span_style = span_style.remove_modifier(Modifier::RAPID_BLINK);
}
Blink::Rapid => {
span_style = span_style.remove_modifier(Modifier::SLOW_BLINK);
span_style = span_style.add_modifier(Modifier::RAPID_BLINK);
}
Blink::None => {
span_style = span_style.remove_modifier(Modifier::SLOW_BLINK);
span_style = span_style.remove_modifier(Modifier::RAPID_BLINK);
}
},
Sgr::Italic(true) => span_style = span_style.add_modifier(Modifier::ITALIC),
Sgr::Italic(false) => span_style = span_style.remove_modifier(Modifier::ITALIC),
Sgr::Inverse(true) => span_style = span_style.add_modifier(Modifier::REVERSED),
Sgr::Inverse(false) => {
span_style = span_style.remove_modifier(Modifier::REVERSED)
}
Sgr::Invisible(true) => span_style = span_style.add_modifier(Modifier::HIDDEN),
Sgr::Invisible(false) => {
span_style = span_style.remove_modifier(Modifier::HIDDEN)
}
Sgr::StrikeThrough(true) => {
span_style = span_style.add_modifier(Modifier::CROSSED_OUT)
}
Sgr::StrikeThrough(false) => {
span_style = span_style.remove_modifier(Modifier::CROSSED_OUT)
}
Sgr::Foreground(c) => match c {
ColorSpec::Default => span_style = span_style.fg(Color::Reset),
ColorSpec::PaletteIndex(i) => span_style = span_style.fg(Color::Indexed(i)),
ColorSpec::TrueColor(rgb) => {
span_style = span_style.fg(Color::Rgb(rgb.red, rgb.green, rgb.blue))
}
},
Sgr::Background(c) => match c {
ColorSpec::Default => span_style = span_style.bg(Color::Reset),
ColorSpec::PaletteIndex(i) => span_style = span_style.bg(Color::Indexed(i)),
ColorSpec::TrueColor(rgb) => {
span_style = span_style.bg(Color::Rgb(rgb.red, rgb.green, rgb.blue))
}
},
_ => {}
}
}
_ => {}
}
}
if !span_text.is_empty() {
current_line.push(Span::styled(span_text, span_style.into()));
spans.push(Spans::from(current_line));
}
spans.into()
}