1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
use crossterm::style::{ Attribute, Color, Print, ResetColor, SetAttribute, SetBackgroundColor, SetForegroundColor, }; use crossterm::QueueableCommand; use crate::error::Result; use crate::style::{Style, StyleBundle}; use crate::token::Token; pub struct Stylizer { colors: Vec<StyleBundle>, } impl Stylizer { pub fn new(colors: Vec<StyleBundle>) -> Self { Self { colors } } fn stylize<T>(&self, color_index: usize, s: String, queue: &mut T) -> Result<usize> where T: std::io::Write, { if let Some(color) = self.colors.get(color_index % self.colors.len()) { let (mut colored, mut attributed) = (false, false); for style in &color.0 { match style { Style::Fg(c) => { queue.queue(SetForegroundColor(*c))?; colored = true; } Style::Bg(c) => { queue.queue(SetBackgroundColor(*c))?; colored = true; } Style::Attr(a) => { queue.queue(SetAttribute(*a))?; attributed = true; } }; } let len = s.len(); queue.queue(Print(s))?; if attributed { queue.queue(SetAttribute(Attribute::Reset))?; } if colored { queue.queue(ResetColor)?; } Ok(len) } else { unreachable!() } } pub fn forward<T>(&self, t: Token, queue: &mut T) -> Result<usize> where T: std::io::Write, { match t { Token::Matched(v, s) => self.stylize(v, s, queue), Token::Unmatched(s) => { let len = s.len(); queue.queue(Print(s))?; Ok(len) } Token::Undecided(_) => unreachable!(), } } }