diff --git a/kkdisp/src/component.rs b/kkdisp/src/component.rs index efc6606..caa67ab 100644 --- a/kkdisp/src/component.rs +++ b/kkdisp/src/component.rs @@ -1,10 +1,12 @@ +use termion::raw::RawTerminal; + use crate::{ theme::{Color, ColorSet}, token::Token, }; -use std::iter::Extend; +use std::io::{Stdout, Write}; -#[derive(Eq, Debug, Clone)] +#[derive(Eq, Clone, Debug)] pub enum Component { NextLine, X(usize), @@ -14,24 +16,57 @@ pub enum Component { } impl Component { - fn make_for_line( + fn debug(&self) -> String { + match self { + Component::NextLine => "NextLine".to_string(), + Component::X(x) => format!("X({})", x), + Component::String(s) => format!("\"{}\"", s), + Component::Fg(c) => format!("FG({:#?})", c) + .replace('\n', "") + .replace(' ', ""), + Component::Bg(c) => format!("BG({:#?})", c) + .replace('\n', "") + .replace(' ', ""), + } + } +} + +pub trait Cursed { + fn scene( + &mut self, comp: Vec, - line: usize, - offset: usize, - ) -> String { - comp.into_iter() + ) -> Result<(), anyhow::Error>; +} + +impl Cursed for RawTerminal { + fn scene( + &mut self, + comp: Vec, + ) -> Result<(), anyhow::Error> { + let mut line = 1; + let screen_str = comp + .into_iter() .map(|c| match c { - Component::X(x) => termion::cursor::Goto( - (x + offset) as u16, - line as u16, - ) - .into(), + Component::NextLine => { + line += 1; + String::from("\r\n") + } + Component::X(x) => { + termion::cursor::Goto((x + 1) as u16, line).into() + } Component::String(s) => s, Component::Fg(c) => c.fg(), Component::Bg(c) => c.bg(), - Component::NextLine => "\r\n".into(), }) - .collect() + .collect::(); + write!( + self, + "{clear}{start}{scene}", + clear = termion::clear::All, + start = termion::cursor::Goto(1, 1), + scene = screen_str, + )?; + Ok(()) } } @@ -163,6 +198,7 @@ impl Instruction { self, line_width: usize, height_left: usize, + color_reset: ColorSet, ) -> Vec { if height_left == 0 { return vec![]; @@ -198,18 +234,21 @@ impl Instruction { result.push(Component::X(offset)); } result + .push(Component::Fg(color_reset.fg)); + result + .push(Component::Bg(color_reset.bg)); + result }) .flatten() .chain(vec![Component::NextLine]) .collect::>() }) .flatten() - .chain( - next.into_components( - line_width, - height_left - lines, - ), - ) + .chain(next.into_components( + line_width, + height_left - lines, + color_reset, + )) .collect(), Instruction::End => (0..height_left) .map(|_| Component::NextLine) @@ -243,7 +282,7 @@ impl Plan { .into_iter() .map(|wd| wd.want_width.abs_size(100)) .sum::() - >= 100 + > 100 { panic!("widgets do not fit screen") } @@ -302,10 +341,6 @@ impl Plan { } } - pub fn line(self, widgets: Vec) -> Self { - self.fixed(1, widgets) - } - pub fn fixed(self, height: usize, widgets: Vec) -> Self { Self::fit_check(&widgets); Self::FixedHeight(Box::new(self), height, widgets) @@ -316,14 +351,17 @@ impl Plan { Self::Fill(Box::new(self), widgets) } - // fn make_line(&self, term_width: u16, ) - - // pub fn make( - // &self, - // (term_width, term_height): (u16, u16), - // ) -> String { - - // } + pub fn make( + self, + base_colors: ColorSet, + (term_width, term_height): (usize, usize), + ) -> Vec { + self.to_instruction_set(term_height - 1).into_components( + term_width, + term_height - 1, + base_colors, + ) + } } #[cfg(test)] @@ -353,6 +391,10 @@ mod tests { fn test_instructions_to_components() { const WIDTH: usize = 120; const HEIGHT: usize = 40; + const BASE_COLOR: ColorSet = ColorSet { + fg: Color::WHITE, + bg: Color::BLACK, + }; let (w1, w2, w3) = test_widgets(); vec![ ( @@ -367,7 +409,11 @@ mod tests { .clone() .with_width(WIDTH / 3) .into_iter() - .chain(vec![Component::X(WIDTH / 3)]) + .chain(vec![ + Component::X(WIDTH / 3), + Component::Fg(BASE_COLOR.fg), + Component::Bg(BASE_COLOR.bg), + ]) .chain( w2.clone() .get_line(0) @@ -375,7 +421,11 @@ mod tests { .clone() .with_width(WIDTH / 3), ) - .chain(vec![Component::X((WIDTH / 3) * 2)]) + .chain(vec![ + Component::X((WIDTH / 3) * 2), + Component::Fg(BASE_COLOR.fg), + Component::Bg(BASE_COLOR.bg), + ]) .chain( w3.clone() .get_line(0) @@ -383,13 +433,23 @@ mod tests { .clone() .with_width(WIDTH / 3), ) - .chain(vec![Component::NextLine]) + .chain(vec![ + Component::Fg(BASE_COLOR.fg), + Component::Bg(BASE_COLOR.bg), + Component::NextLine, + ]) .chain( (1..30) .map(|_| { vec![ Component::X(WIDTH / 3), + Component::Fg(BASE_COLOR.fg), + Component::Bg(BASE_COLOR.bg), Component::X((WIDTH / 3) * 2), + Component::Fg(BASE_COLOR.fg), + Component::Bg(BASE_COLOR.bg), + Component::Fg(BASE_COLOR.fg), + Component::Bg(BASE_COLOR.bg), Component::NextLine, ] }) @@ -415,6 +475,8 @@ mod tests { .map(|_| { vec![ Component::X(WIDTH / 3), + Component::Fg(BASE_COLOR.fg), + Component::Bg(BASE_COLOR.bg), Component::NextLine, ] }) @@ -429,17 +491,37 @@ mod tests { ] .into_iter() .for_each(|(name, instruction, expected)| { - let actual = instruction.into_components(WIDTH, HEIGHT); + let actual = instruction + .into_components(WIDTH, HEIGHT, BASE_COLOR); + let diff = actual + .clone() + .into_iter() + .zip(expected.clone()) + .enumerate() + // .filter(|(i, (left, right))| left != right) + .map(|(i, (act, exp))| { + format!( + "{}{}: {} || {}", + if act != exp { "## " } else { "" }, + i, + exp.debug(), + act.debug(), + ) + .replace('\n', " ") + }) + .collect::>(); assert!( expected == actual, "<{}>: - expected({}):\n{:#?} - actual({}):\n{:#?}", + expected({}) + actual({}) + diff:\n{:#?}", name, expected.len(), - expected, actual.len(), - actual, + diff, + // expected, + // actual ); }); } diff --git a/kkdisp/src/lib.rs b/kkdisp/src/lib.rs index 35c1252..746b9ec 100644 --- a/kkdisp/src/lib.rs +++ b/kkdisp/src/lib.rs @@ -1,5 +1,12 @@ -use std::io::{Stdout, Write}; +use crate::component::Cursed; +use component::{Plan, Widget}; +use std::{ + io::{Stdout, Write}, + time::Duration, +}; use termion::raw::{IntoRawMode, RawTerminal}; +use theme::{Color, ColorSet}; +use token::Token; extern crate termion; mod component; @@ -18,18 +25,3 @@ impl Display { }) } } - -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/kkdisp/src/theme.rs b/kkdisp/src/theme.rs index 1009407..4407374 100644 --- a/kkdisp/src/theme.rs +++ b/kkdisp/src/theme.rs @@ -34,6 +34,7 @@ pub struct Color(u8, u8, u8); impl Color { pub const BLACK: Color = Color(0, 0, 0); + pub const WHITE: Color = Color(255, 255, 255); pub const RED: Color = Color(255, 0, 0); pub const GREEN: Color = Color(0, 255, 0); pub const BLUE: Color = Color(0, 0, 255); diff --git a/kkx/src/main.rs b/kkx/src/main.rs index e7a11a9..e202cf2 100644 --- a/kkx/src/main.rs +++ b/kkx/src/main.rs @@ -1,3 +1,7 @@ +use kkdisp::Display; + fn main() { - println!("Hello, world!"); + // let disp = Display::new(); + // let widget_idk = Widget::new() + Display::test(); }