use std::{ iter::Map, ops::{Deref, Range}, vec::IntoIter, }; use super::{frame::Frame, theme::ColorSet}; #[derive(Clone, Debug)] pub enum Component { String(String), Goto(u16, u16), Theme(ColorSet), Padding(u16), // Pre-formatted Internal(String), Repeated(char, u16), Clear, } impl Component { pub fn prepare_for(self, frame: &Frame) -> String { match self { Component::String(s) => s, Component::Goto(x, y) => frame.goto(x, y), Component::Theme(c) => c.to_string(), Component::Clear => termion::clear::All.to_string(), Component::Padding(len) => " ".repeat(len as usize), Component::Internal(i) => i, Component::Repeated(ch, len) => { ch.to_string().repeat(len as usize) } } } } #[derive(Clone, Debug)] pub struct Components(pub Vec); impl Deref for Components { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } } impl From> for Components { fn from(value: Vec) -> Self { Self(value) } } impl From for Components { fn from(value: Component) -> Self { Self(vec![value]) } } impl Components { pub fn str_len(&self) -> u16 { (&self.0) .into_iter() .map(|comp| { if let Component::String(s) = comp { s.len() as u16 } else { 0 } }) .sum() } pub fn concat_for(self, frame: &Frame) -> String { self.0 .into_iter() .map(|component| component.prepare_for(frame)) .collect::() } pub fn push(&mut self, comp: Component) { self.0.push(comp) } }