fixes and testing for the instructions -> set of components converter
This commit is contained in:
parent
4a3c5ac492
commit
ec6998ff30
|
@ -2,15 +2,39 @@ use crate::{
|
|||
theme::{Color, ColorSet},
|
||||
token::Token,
|
||||
};
|
||||
use std::iter::Extend;
|
||||
|
||||
#[derive(Eq, Debug, Clone)]
|
||||
pub enum Component {
|
||||
NextLine,
|
||||
X(usize),
|
||||
String(String),
|
||||
Fg(Color),
|
||||
Bg(Color),
|
||||
}
|
||||
|
||||
impl Component {
|
||||
fn make_for_line(
|
||||
comp: Vec<Component>,
|
||||
line: usize,
|
||||
offset: usize,
|
||||
) -> String {
|
||||
comp.into_iter()
|
||||
.map(|c| match c {
|
||||
Component::X(x) => termion::cursor::Goto(
|
||||
(x + offset) as u16,
|
||||
line as u16,
|
||||
)
|
||||
.into(),
|
||||
Component::String(s) => s,
|
||||
Component::Fg(c) => c.fg(),
|
||||
Component::Bg(c) => c.bg(),
|
||||
Component::NextLine => "\r\n".into(),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Component {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match self {
|
||||
|
@ -30,6 +54,10 @@ impl PartialEq for Component {
|
|||
Self::Bg(other_c) => c == other_c,
|
||||
_ => false,
|
||||
},
|
||||
Self::NextLine => match other {
|
||||
Self::NextLine => true,
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +114,7 @@ impl Widget {
|
|||
}
|
||||
|
||||
fn get_line(&self, line: usize) -> Option<&Token> {
|
||||
self.per_line.get(line - 1)
|
||||
self.per_line.get(line)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,11 +159,62 @@ impl PartialEq for Instruction {
|
|||
}
|
||||
|
||||
impl Instruction {
|
||||
pub fn make(
|
||||
pub fn into_components(
|
||||
self,
|
||||
(term_width, term_height): (u16, u16),
|
||||
) -> String {
|
||||
todo!()
|
||||
line_width: usize,
|
||||
height_left: usize,
|
||||
) -> Vec<Component> {
|
||||
if height_left == 0 {
|
||||
return vec![];
|
||||
}
|
||||
match self {
|
||||
Instruction::FixedHeight(next, lines, wdg) => (0..lines)
|
||||
.map(|line| {
|
||||
let mut offset = 0;
|
||||
(&wdg)
|
||||
.into_iter()
|
||||
.map(|w| {
|
||||
let (width, token) = (
|
||||
w.want_width.abs_size(line_width),
|
||||
w.get_line(line).map(|t| t.clone()),
|
||||
);
|
||||
let mut result = match token {
|
||||
Some(tok) => tok
|
||||
.with_width(width)
|
||||
.into_iter()
|
||||
.map(|comp| {
|
||||
if let Component::X(x) = comp
|
||||
{
|
||||
Component::X(offset + x)
|
||||
} else {
|
||||
comp
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
None => Vec::new(),
|
||||
};
|
||||
offset += width;
|
||||
if offset < line_width {
|
||||
result.push(Component::X(offset));
|
||||
}
|
||||
result
|
||||
})
|
||||
.flatten()
|
||||
.chain(vec![Component::NextLine])
|
||||
.collect::<Vec<Component>>()
|
||||
})
|
||||
.flatten()
|
||||
.chain(
|
||||
next.into_components(
|
||||
line_width,
|
||||
height_left - lines,
|
||||
),
|
||||
)
|
||||
.collect(),
|
||||
Instruction::End => (0..height_left)
|
||||
.map(|_| Component::NextLine)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start() -> Self {
|
||||
|
@ -251,13 +330,11 @@ impl Plan {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_plan_to_instructions() {
|
||||
const HEIGHT: usize = 40;
|
||||
let (widget_1, widget_2, widget_3) = (
|
||||
fn test_widgets() -> (Widget, Widget, Widget) {
|
||||
(
|
||||
Widget::new(
|
||||
SectionWidth::Third,
|
||||
vec![Token::text("hello")],
|
||||
vec![Token::text("hello").centered()],
|
||||
),
|
||||
Widget::new(
|
||||
SectionWidth::Third,
|
||||
|
@ -269,7 +346,108 @@ mod tests {
|
|||
SectionWidth::Third,
|
||||
vec![Token::text("hello").limited(16).padded(20)],
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_instructions_to_components() {
|
||||
const WIDTH: usize = 120;
|
||||
const HEIGHT: usize = 40;
|
||||
let (w1, w2, w3) = test_widgets();
|
||||
vec![
|
||||
(
|
||||
"all the widgets, 30 lines",
|
||||
Instruction::start().fixed(
|
||||
30,
|
||||
vec![w1.clone(), w2.clone(), w3.clone()],
|
||||
),
|
||||
w1.clone()
|
||||
.get_line(0)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.with_width(WIDTH / 3)
|
||||
.into_iter()
|
||||
.chain(vec![Component::X(WIDTH / 3)])
|
||||
.chain(
|
||||
w2.clone()
|
||||
.get_line(0)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.with_width(WIDTH / 3),
|
||||
)
|
||||
.chain(vec![Component::X((WIDTH / 3) * 2)])
|
||||
.chain(
|
||||
w3.clone()
|
||||
.get_line(0)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.with_width(WIDTH / 3),
|
||||
)
|
||||
.chain(vec![Component::NextLine])
|
||||
.chain(
|
||||
(1..30)
|
||||
.map(|_| {
|
||||
vec![
|
||||
Component::X(WIDTH / 3),
|
||||
Component::X((WIDTH / 3) * 2),
|
||||
Component::NextLine,
|
||||
]
|
||||
})
|
||||
.flatten(),
|
||||
)
|
||||
.chain(
|
||||
(0..(HEIGHT - 30))
|
||||
.map(|_| Component::NextLine),
|
||||
)
|
||||
.collect::<Vec<Component>>(),
|
||||
),
|
||||
(
|
||||
"Single widget, single 10 lines section",
|
||||
Instruction::start().fixed(10, vec![w1.clone()]),
|
||||
w1.clone()
|
||||
.get_line(0)
|
||||
.unwrap()
|
||||
.clone()
|
||||
.with_width(WIDTH / 3)
|
||||
.into_iter()
|
||||
.chain(
|
||||
(0..10)
|
||||
.map(|_| {
|
||||
vec![
|
||||
Component::X(WIDTH / 3),
|
||||
Component::NextLine,
|
||||
]
|
||||
})
|
||||
.flatten(),
|
||||
)
|
||||
.chain(
|
||||
(0..(HEIGHT - 10))
|
||||
.map(|_| Component::NextLine),
|
||||
)
|
||||
.collect(),
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.for_each(|(name, instruction, expected)| {
|
||||
let actual = instruction.into_components(WIDTH, HEIGHT);
|
||||
assert!(
|
||||
expected == actual,
|
||||
"<{}>:
|
||||
expected({}):\n{:#?}
|
||||
actual({}):\n{:#?}",
|
||||
name,
|
||||
expected.len(),
|
||||
expected,
|
||||
actual.len(),
|
||||
actual,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plan_to_instructions() {
|
||||
const HEIGHT: usize = 40;
|
||||
let (widget_1, widget_2, widget_3) = test_widgets();
|
||||
|
||||
vec![
|
||||
("end -> end", Plan::start(), Instruction::End),
|
||||
|
|
|
@ -76,7 +76,7 @@ impl Token {
|
|||
Self::Bg(Box::new(self), c)
|
||||
}
|
||||
|
||||
fn with_width(self, width: usize) -> Vec<Component> {
|
||||
pub fn with_width(self, width: usize) -> Vec<Component> {
|
||||
match self {
|
||||
Token::String(t, s) => vec![Component::String(s)]
|
||||
.into_iter()
|
||||
|
|
Loading…
Reference in New Issue