Skip to content

Commit

Permalink
Merge pull request #18 from mfontanini/pause-slide-increment
Browse files Browse the repository at this point in the history
Don't create new slide on pauses
  • Loading branch information
mfontanini authored Oct 21, 2023
2 parents 37473db + 6e4f041 commit 1c5faa3
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 105 deletions.
61 changes: 29 additions & 32 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
},
presentation::{
AsRenderOperations, MarginProperties, PreformattedLine, Presentation, PresentationMetadata,
PresentationThemeMetadata, RenderOnDemand, RenderOnDemandState, RenderOperation, Slide,
PresentationThemeMetadata, RenderOnDemand, RenderOnDemandState, RenderOperation, Slide, SlideChunk,
},
render::{
highlighting::{CodeHighlighter, CodeLine},
Expand All @@ -31,6 +31,7 @@ static DEFAULT_BOTTOM_SLIDE_MARGIN: u16 = 3;
/// This type transforms [MarkdownElement]s and turns them into a presentation, which is made up of
/// render operations.
pub(crate) struct PresentationBuilder<'a> {
slide_chunks: Vec<SlideChunk>,
slide_operations: Vec<RenderOperation>,
slides: Vec<Slide>,
highlighter: CodeHighlighter,
Expand All @@ -51,6 +52,7 @@ impl<'a> PresentationBuilder<'a> {
resources: &'a mut Resources,
) -> Self {
Self {
slide_chunks: Vec::new(),
slide_operations: Vec::new(),
slides: Vec::new(),
highlighter: default_highlighter,
Expand Down Expand Up @@ -82,8 +84,8 @@ impl<'a> PresentationBuilder<'a> {
self.push_line_break();
}
}
if !self.slide_operations.is_empty() {
self.terminate_slide(TerminateMode::ResetState);
if !self.slide_operations.is_empty() || !self.slide_chunks.is_empty() {
self.terminate_slide();
}
self.footer_context.borrow_mut().total_slides = self.slides.len();

Expand Down Expand Up @@ -217,7 +219,7 @@ impl<'a> PresentationBuilder<'a> {
};
self.push_text(Text::from(text), ElementType::PresentationAuthor);
}
self.terminate_slide(TerminateMode::ResetState);
self.terminate_slide();
}

fn process_comment(&mut self, comment: String) -> Result<(), BuildError> {
Expand All @@ -228,7 +230,7 @@ impl<'a> PresentationBuilder<'a> {
let comment = comment.parse::<CommentCommand>()?;
match comment {
CommentCommand::Pause => self.process_pause(),
CommentCommand::EndSlide => self.terminate_slide(TerminateMode::ResetState),
CommentCommand::EndSlide => self.terminate_slide(),
CommentCommand::InitColumnLayout(columns) => {
Self::validate_column_layout(&columns)?;
self.layout = LayoutState::InLayout { columns_count: columns.len() };
Expand Down Expand Up @@ -276,9 +278,9 @@ impl<'a> PresentationBuilder<'a> {
self.slide_operations.pop();
}

let next_operations = self.slide_operations.clone();
self.terminate_slide(TerminateMode::KeepState);
self.slide_operations = next_operations;
let chunk_operations = mem::take(&mut self.slide_operations);
self.slide_chunks.push(SlideChunk::new(chunk_operations));
// self.terminate_slide(TerminateMode::KeepState);
}

fn push_slide_title(&mut self, mut text: Text) {
Expand Down Expand Up @@ -482,34 +484,35 @@ impl<'a> PresentationBuilder<'a> {
self.slide_operations.push(operation);
}

fn terminate_slide(&mut self, mode: TerminateMode) {
self.push_footer();
fn terminate_slide(&mut self) {
let footer = self.generate_footer();

let elements = mem::take(&mut self.slide_operations);
self.slides.push(Slide { render_operations: elements });
let operations = mem::take(&mut self.slide_operations);
self.slide_chunks.push(SlideChunk::new(operations));

let chunks = mem::take(&mut self.slide_chunks);
self.slides.push(Slide::new(chunks, footer));
self.push_slide_prelude();
if matches!(mode, TerminateMode::ResetState) {
self.ignore_element_line_break = true;
self.needs_enter_column = false;
self.layout = Default::default();
}
self.ignore_element_line_break = true;
self.needs_enter_column = false;
self.layout = Default::default();
}

fn push_footer(&mut self) {
fn generate_footer(&mut self) -> Vec<RenderOperation> {
let generator = FooterGenerator {
style: self.theme.footer.clone(),
current_slide: self.slides.len(),
context: self.footer_context.clone(),
};
self.slide_operations.extend([
vec![
// Exit any layout we're in so this gets rendered on a default screen size.
RenderOperation::ExitLayout,
// Pop the slide margin so we're at the terminal rect.
RenderOperation::PopMargin,
// Jump to the very bottom of the terminal rect and draw the footer.
RenderOperation::JumpToBottom,
RenderOperation::RenderDynamic(Rc::new(generator)),
]);
]
}

fn push_table(&mut self, table: Table) {
Expand Down Expand Up @@ -564,11 +567,6 @@ impl<'a> PresentationBuilder<'a> {
}
}

enum TerminateMode {
KeepState,
ResetState,
}

#[derive(Debug, Default)]
enum LayoutState {
#[default]
Expand Down Expand Up @@ -933,9 +931,9 @@ mod test {
let presentation = build_presentation(elements);
for (index, slide) in presentation.iter_slides().into_iter().enumerate() {
let clear_screen_count =
slide.render_operations.iter().filter(|op| matches!(op, RenderOperation::ClearScreen)).count();
slide.iter_operations().filter(|op| matches!(op, RenderOperation::ClearScreen)).count();
let set_colors_count =
slide.render_operations.iter().filter(|op| matches!(op, RenderOperation::SetColors(_))).count();
slide.iter_operations().filter(|op| matches!(op, RenderOperation::SetColors(_))).count();
assert_eq!(clear_screen_count, 1, "{clear_screen_count} clear screens in slide {index}");
assert_eq!(set_colors_count, 1, "{set_colors_count} clear screens in slide {index}");
}
Expand All @@ -955,7 +953,7 @@ mod test {
// Don't process the intro slide as it's special
let slides = presentation.into_slides().into_iter().skip(1);
for slide in slides {
let mut ops = slide.render_operations.into_iter().filter(is_visible);
let mut ops = slide.into_operations().into_iter().filter(is_visible);
// We should start with a newline
assert!(matches!(ops.next(), Some(RenderOperation::RenderLineBreak)));
// And the second one should _not_ be a newline
Expand All @@ -977,8 +975,7 @@ mod test {
let presentation = build_presentation(elements);
let slides = presentation.into_slides();
let lengths: Vec<_> = slides[0]
.render_operations
.iter()
.iter_operations()
.filter_map(|op| match op {
RenderOperation::RenderPreformattedLine(PreformattedLine {
block_length, unformatted_length, ..
Expand All @@ -1000,7 +997,7 @@ mod test {
})];
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();
slides.into_iter().next().unwrap().into_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);
Expand Down Expand Up @@ -1079,6 +1076,6 @@ mod test {
fn pause_inside_layout() {
let elements = vec![build_column_layout(1), build_pause(), build_column(0)];
let presentation = build_presentation(elements);
assert_eq!(presentation.iter_slides().count(), 2);
assert_eq!(presentation.iter_slides().count(), 1);
}
}
Loading

0 comments on commit 1c5faa3

Please sign in to comment.