Added color resetting after widget

This commit is contained in:
emilis 2023-01-19 23:15:50 +00:00
parent ec6998ff30
commit 1960123e3f
4 changed files with 137 additions and 58 deletions

View File

@ -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<Component>,
line: usize,
offset: usize,
) -> String {
comp.into_iter()
) -> Result<(), anyhow::Error>;
}
impl Cursed for RawTerminal<Stdout> {
fn scene(
&mut self,
comp: Vec<Component>,
) -> 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::<String>();
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<Component> {
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::<Vec<Component>>()
})
.flatten()
.chain(
next.into_components(
.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::<usize>()
>= 100
> 100
{
panic!("widgets do not fit screen")
}
@ -302,10 +341,6 @@ impl Plan {
}
}
pub fn line(self, widgets: Vec<Widget>) -> Self {
self.fixed(1, widgets)
}
pub fn fixed(self, height: usize, widgets: Vec<Widget>) -> 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<Component> {
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::<Vec<String>>();
assert!(
expected == actual,
"<{}>:
expected({}):\n{:#?}
actual({}):\n{:#?}",
expected({})
actual({})
diff:\n{:#?}",
name,
expected.len(),
expected,
actual.len(),
actual,
diff,
// expected,
// actual
);
});
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -1,3 +1,7 @@
use kkdisp::Display;
fn main() {
println!("Hello, world!");
// let disp = Display::new();
// let widget_idk = Widget::new()
Display::test();
}