mirror of
https://github.com/mfontanini/presenterm.git
synced 2025-05-06 07:52:59 +00:00
Add tests for table rendering
This commit is contained in:
parent
3163d310be
commit
0500d51f8c
@ -329,7 +329,7 @@ impl<'a> PresentationBuilder<'a> {
|
|||||||
}
|
}
|
||||||
if !texts.is_empty() {
|
if !texts.is_empty() {
|
||||||
self.slide_operations.push(RenderOperation::RenderTextLine {
|
self.slide_operations.push(RenderOperation::RenderTextLine {
|
||||||
texts: WeightedLine::from(texts),
|
line: WeightedLine::from(texts),
|
||||||
alignment: alignment.clone(),
|
alignment: alignment.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -408,12 +408,15 @@ impl<'a> PresentationBuilder<'a> {
|
|||||||
let mut separator = Text { chunks: Vec::new() };
|
let mut separator = Text { chunks: Vec::new() };
|
||||||
for (index, width) in widths.iter().enumerate() {
|
for (index, width) in widths.iter().enumerate() {
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
let mut extra_lines = 1;
|
let mut margin = 1;
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
contents.push('┼');
|
contents.push('┼');
|
||||||
extra_lines += 1;
|
// Append an extra dash to have 1 column margin on both sides
|
||||||
|
if index < widths.len() - 1 {
|
||||||
|
margin += 1;
|
||||||
}
|
}
|
||||||
contents.extend(iter::repeat("─").take(*width + extra_lines));
|
}
|
||||||
|
contents.extend(iter::repeat("─").take(*width + margin));
|
||||||
separator.chunks.push(StyledText::from(contents));
|
separator.chunks.push(StyledText::from(contents));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,7 +483,7 @@ impl AsRenderOperations for FooterGenerator {
|
|||||||
operations.extend([
|
operations.extend([
|
||||||
RenderOperation::JumpToWindowBottom,
|
RenderOperation::JumpToWindowBottom,
|
||||||
RenderOperation::RenderTextLine {
|
RenderOperation::RenderTextLine {
|
||||||
texts: vec![Self::render_template(left, ¤t_slide, &context, colors.clone())].into(),
|
line: vec![Self::render_template(left, ¤t_slide, &context, colors.clone())].into(),
|
||||||
alignment: Alignment::Left { margin: 1 },
|
alignment: Alignment::Left { margin: 1 },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -489,7 +492,7 @@ impl AsRenderOperations for FooterGenerator {
|
|||||||
operations.extend([
|
operations.extend([
|
||||||
RenderOperation::JumpToWindowBottom,
|
RenderOperation::JumpToWindowBottom,
|
||||||
RenderOperation::RenderTextLine {
|
RenderOperation::RenderTextLine {
|
||||||
texts: vec![Self::render_template(right, ¤t_slide, &context, colors.clone())].into(),
|
line: vec![Self::render_template(right, ¤t_slide, &context, colors.clone())].into(),
|
||||||
alignment: Alignment::Right { margin: 1 },
|
alignment: Alignment::Right { margin: 1 },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -505,7 +508,7 @@ impl AsRenderOperations for FooterGenerator {
|
|||||||
let bar = vec![WeightedText::from(StyledText::new(bar, TextStyle::default().colors(colors.clone())))];
|
let bar = vec![WeightedText::from(StyledText::new(bar, TextStyle::default().colors(colors.clone())))];
|
||||||
vec![
|
vec![
|
||||||
RenderOperation::JumpToWindowBottom,
|
RenderOperation::JumpToWindowBottom,
|
||||||
RenderOperation::RenderTextLine { texts: bar.into(), alignment: Alignment::Left { margin: 0 } },
|
RenderOperation::RenderTextLine { line: bar.into(), alignment: Alignment::Left { margin: 0 } },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
FooterStyle::Empty => vec![],
|
FooterStyle::Empty => vec![],
|
||||||
@ -564,6 +567,20 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extract_text_lines(operations: &[RenderOperation]) -> Vec<String> {
|
||||||
|
let mut output = Vec::new();
|
||||||
|
for operation in operations {
|
||||||
|
match operation {
|
||||||
|
RenderOperation::RenderTextLine { line, .. } => {
|
||||||
|
let texts: Vec<_> = line.iter_texts().map(|text| text.text.text.clone()).collect();
|
||||||
|
output.push(texts.join(""));
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prelude_appears_once() {
|
fn prelude_appears_once() {
|
||||||
let elements = vec![
|
let elements = vec![
|
||||||
@ -629,4 +646,18 @@ mod test {
|
|||||||
assert_eq!(lengths[0], (width, width));
|
assert_eq!(lengths[0], (width, width));
|
||||||
assert_eq!(lengths[1], (width, width));
|
assert_eq!(lengths[1], (width, width));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn table() {
|
||||||
|
let elements = vec![MarkdownElement::Table(Table {
|
||||||
|
header: TableRow(vec![Text::from("key"), Text::from("value"), Text::from("other")]),
|
||||||
|
rows: vec![TableRow(vec![Text::from("potato"), Text::from("bar"), Text::from("yes")])],
|
||||||
|
})];
|
||||||
|
let slides = build_presentation(elements).into_slides();
|
||||||
|
let operations: Vec<_> =
|
||||||
|
slides.into_iter().next().unwrap().render_operations.into_iter().filter(|op| is_visible(op)).collect();
|
||||||
|
let lines = extract_text_lines(&operations);
|
||||||
|
let expected_lines = &["key │ value │ other", "───────┼───────┼──────", "potato │ bar │ yes "];
|
||||||
|
assert_eq!(lines, expected_lines);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
12
src/diff.rs
12
src/diff.rs
@ -50,7 +50,7 @@ impl ContentDiff for RenderOperation {
|
|||||||
|
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(SetColors(original), SetColors(updated)) if original != updated => false,
|
(SetColors(original), SetColors(updated)) if original != updated => false,
|
||||||
(RenderTextLine { texts: original, .. }, RenderTextLine { texts: updated, .. }) if original != updated => {
|
(RenderTextLine { line: original, .. }, RenderTextLine { line: updated, .. }) if original != updated => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
(RenderTextLine { alignment: original, .. }, RenderTextLine { alignment: updated, .. })
|
(RenderTextLine { alignment: original, .. }, RenderTextLine { alignment: updated, .. })
|
||||||
@ -114,7 +114,7 @@ mod test {
|
|||||||
#[case(RenderOperation::RenderSeparator)]
|
#[case(RenderOperation::RenderSeparator)]
|
||||||
#[case(RenderOperation::RenderLineBreak)]
|
#[case(RenderOperation::RenderLineBreak)]
|
||||||
#[case(RenderOperation::SetColors(Colors{background: None, foreground: None}))]
|
#[case(RenderOperation::SetColors(Colors{background: None, foreground: None}))]
|
||||||
#[case(RenderOperation::RenderTextLine{texts: String::from("asd").into(), alignment: Default::default()})]
|
#[case(RenderOperation::RenderTextLine{line: String::from("asd").into(), alignment: Default::default()})]
|
||||||
#[case(RenderOperation::RenderPreformattedLine(
|
#[case(RenderOperation::RenderPreformattedLine(
|
||||||
PreformattedLine{
|
PreformattedLine{
|
||||||
text: "asd".into(),
|
text: "asd".into(),
|
||||||
@ -131,19 +131,19 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn different_text() {
|
fn different_text() {
|
||||||
let lhs = RenderOperation::RenderTextLine { texts: String::from("foo").into(), alignment: Default::default() };
|
let lhs = RenderOperation::RenderTextLine { line: String::from("foo").into(), alignment: Default::default() };
|
||||||
let rhs = RenderOperation::RenderTextLine { texts: String::from("bar").into(), alignment: Default::default() };
|
let rhs = RenderOperation::RenderTextLine { line: String::from("bar").into(), alignment: Default::default() };
|
||||||
assert!(lhs.is_content_different(&rhs));
|
assert!(lhs.is_content_different(&rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn different_text_alignment() {
|
fn different_text_alignment() {
|
||||||
let lhs = RenderOperation::RenderTextLine {
|
let lhs = RenderOperation::RenderTextLine {
|
||||||
texts: String::from("foo").into(),
|
line: String::from("foo").into(),
|
||||||
alignment: Alignment::Left { margin: 42 },
|
alignment: Alignment::Left { margin: 42 },
|
||||||
};
|
};
|
||||||
let rhs = RenderOperation::RenderTextLine {
|
let rhs = RenderOperation::RenderTextLine {
|
||||||
texts: String::from("foo").into(),
|
line: String::from("foo").into(),
|
||||||
alignment: Alignment::Left { margin: 1337 },
|
alignment: Alignment::Left { margin: 1337 },
|
||||||
};
|
};
|
||||||
assert!(!lhs.is_content_different(&rhs));
|
assert!(!lhs.is_content_different(&rhs));
|
||||||
|
@ -18,6 +18,11 @@ impl WeightedLine {
|
|||||||
pub fn width(&self) -> usize {
|
pub fn width(&self) -> usize {
|
||||||
self.0.iter().map(|text| text.width()).sum()
|
self.0.iter().map(|text| text.width()).sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get an iterator to the underlying text chunks.
|
||||||
|
pub fn iter_texts(&self) -> impl Iterator<Item = &WeightedText> {
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<WeightedText>> for WeightedLine {
|
impl From<Vec<WeightedText>> for WeightedLine {
|
||||||
@ -42,7 +47,7 @@ struct CharAccumulator {
|
|||||||
/// A piece of weighted text.
|
/// A piece of weighted text.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct WeightedText {
|
pub struct WeightedText {
|
||||||
text: StyledText,
|
pub text: StyledText,
|
||||||
accumulators: Vec<CharAccumulator>,
|
accumulators: Vec<CharAccumulator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ pub enum RenderOperation {
|
|||||||
JumpToSlideBottom,
|
JumpToSlideBottom,
|
||||||
|
|
||||||
/// Render a line of text.
|
/// Render a line of text.
|
||||||
RenderTextLine { texts: WeightedLine, alignment: Alignment },
|
RenderTextLine { line: WeightedLine, alignment: Alignment },
|
||||||
|
|
||||||
/// Render a horizontal separator line.
|
/// Render a horizontal separator line.
|
||||||
RenderSeparator,
|
RenderSeparator,
|
||||||
|
@ -64,10 +64,10 @@ where
|
|||||||
RenderOperation::ClearScreen,
|
RenderOperation::ClearScreen,
|
||||||
RenderOperation::SetColors(Colors { foreground: Some(Color::Red), background: Some(Color::Black) }),
|
RenderOperation::SetColors(Colors { foreground: Some(Color::Red), background: Some(Color::Black) }),
|
||||||
RenderOperation::JumpToVerticalCenter,
|
RenderOperation::JumpToVerticalCenter,
|
||||||
RenderOperation::RenderTextLine { texts: WeightedLine::from(heading), alignment: alignment.clone() },
|
RenderOperation::RenderTextLine { line: WeightedLine::from(heading), alignment: alignment.clone() },
|
||||||
RenderOperation::RenderLineBreak,
|
RenderOperation::RenderLineBreak,
|
||||||
RenderOperation::RenderLineBreak,
|
RenderOperation::RenderLineBreak,
|
||||||
RenderOperation::RenderTextLine { texts: WeightedLine::from(error), alignment: alignment.clone() },
|
RenderOperation::RenderTextLine { line: WeightedLine::from(error), alignment: alignment.clone() },
|
||||||
];
|
];
|
||||||
let mut operator = RenderOperator::new(&mut self.handle, dimensions.clone(), dimensions, Default::default());
|
let mut operator = RenderOperator::new(&mut self.handle, dimensions.clone(), dimensions, Default::default());
|
||||||
for operation in operations {
|
for operation in operations {
|
||||||
|
@ -44,7 +44,7 @@ where
|
|||||||
RenderOperation::JumpToVerticalCenter => self.jump_to_vertical_center(),
|
RenderOperation::JumpToVerticalCenter => self.jump_to_vertical_center(),
|
||||||
RenderOperation::JumpToSlideBottom => self.jump_to_slide_bottom(),
|
RenderOperation::JumpToSlideBottom => self.jump_to_slide_bottom(),
|
||||||
RenderOperation::JumpToWindowBottom => self.jump_to_window_bottom(),
|
RenderOperation::JumpToWindowBottom => self.jump_to_window_bottom(),
|
||||||
RenderOperation::RenderTextLine { texts, alignment } => self.render_text(texts, alignment),
|
RenderOperation::RenderTextLine { line: texts, alignment } => self.render_text(texts, alignment),
|
||||||
RenderOperation::RenderSeparator => self.render_separator(),
|
RenderOperation::RenderSeparator => self.render_separator(),
|
||||||
RenderOperation::RenderLineBreak => self.render_line_break(),
|
RenderOperation::RenderLineBreak => self.render_line_break(),
|
||||||
RenderOperation::RenderImage(image) => self.render_image(image),
|
RenderOperation::RenderImage(image) => self.render_image(image),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user