mirror of
https://github.com/mfontanini/presenterm.git
synced 2025-05-06 07:52:59 +00:00
Add support for footer styles
This commit is contained in:
parent
02097f04f9
commit
8f9c8db9b6
@ -201,8 +201,7 @@ impl<'a> MarkdownProcessor<'a> {
|
|||||||
let formatted = formatted.trim_end();
|
let formatted = formatted.trim_end();
|
||||||
self.slide_operations.push(RenderOperation::RenderPreformattedLine {
|
self.slide_operations.push(RenderOperation::RenderPreformattedLine {
|
||||||
text: formatted.into(),
|
text: formatted.into(),
|
||||||
// TODO: remove once measuring character widths is in place
|
unformatted_length: original.len(),
|
||||||
original_length: original.len(),
|
|
||||||
block_length,
|
block_length,
|
||||||
});
|
});
|
||||||
self.push_line_break();
|
self.push_line_break();
|
||||||
|
@ -82,5 +82,5 @@ pub enum RenderOperation {
|
|||||||
RenderSeparator,
|
RenderSeparator,
|
||||||
RenderLineBreak,
|
RenderLineBreak,
|
||||||
RenderImage(Image),
|
RenderImage(Image),
|
||||||
RenderPreformattedLine { text: String, original_length: usize, block_length: usize },
|
RenderPreformattedLine { text: String, unformatted_length: usize, block_length: usize },
|
||||||
}
|
}
|
||||||
|
@ -42,10 +42,12 @@ where
|
|||||||
let slide_drawer = SlideDrawer { handle: &mut self.handle, theme, dimensions: slide_dimensions };
|
let slide_drawer = SlideDrawer { handle: &mut self.handle, theme, dimensions: slide_dimensions };
|
||||||
slide_drawer.render_slide(slide)?;
|
slide_drawer.render_slide(slide)?;
|
||||||
|
|
||||||
if let Some(template) = &theme.styles.footer.template {
|
let rendered_footer = theme.styles.footer.render(
|
||||||
let current_slide = (presentation.current_slide_index() + 1).to_string();
|
presentation.current_slide_index(),
|
||||||
let total_slides = presentation.total_slides().to_string();
|
presentation.total_slides(),
|
||||||
let footer = template.replace("{current_slide}", ¤t_slide).replace("{total_slides}", &total_slides);
|
dimensions.columns as usize,
|
||||||
|
);
|
||||||
|
if let Some(footer) = rendered_footer {
|
||||||
self.handle.queue(cursor::MoveTo(0, dimensions.rows - 1))?;
|
self.handle.queue(cursor::MoveTo(0, dimensions.rows - 1))?;
|
||||||
self.handle.queue(style::Print(footer))?;
|
self.handle.queue(style::Print(footer))?;
|
||||||
}
|
}
|
||||||
@ -97,8 +99,8 @@ where
|
|||||||
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),
|
||||||
RenderOperation::RenderPreformattedLine { text, original_length, block_length } => {
|
RenderOperation::RenderPreformattedLine { text, unformatted_length, block_length } => {
|
||||||
self.render_preformatted_line(text, *original_length, *block_length)
|
self.render_preformatted_line(text, *unformatted_length, *block_length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,7 +144,7 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_preformatted_line(&mut self, text: &str, original_length: usize, block_length: usize) -> DrawResult {
|
fn render_preformatted_line(&mut self, text: &str, unformatted_length: usize, block_length: usize) -> DrawResult {
|
||||||
let style = self.theme.alignment(&ElementType::Code);
|
let style = self.theme.alignment(&ElementType::Code);
|
||||||
let start_column = match *style {
|
let start_column = match *style {
|
||||||
Alignment::Left { margin } => margin,
|
Alignment::Left { margin } => margin,
|
||||||
@ -155,7 +157,7 @@ where
|
|||||||
self.handle.queue(cursor::MoveToColumn(start_column))?;
|
self.handle.queue(cursor::MoveToColumn(start_column))?;
|
||||||
|
|
||||||
let max_line_length = (self.dimensions.columns - start_column * 2) as usize;
|
let max_line_length = (self.dimensions.columns - start_column * 2) as usize;
|
||||||
let until_right_edge = max_line_length.saturating_sub(original_length);
|
let until_right_edge = max_line_length.saturating_sub(unformatted_length);
|
||||||
// Pad this code block with spaces so we get a nice little rectangle.
|
// Pad this code block with spaces so we get a nice little rectangle.
|
||||||
self.handle.queue(style::Print(&text))?;
|
self.handle.queue(style::Print(&text))?;
|
||||||
self.handle.queue(style::Print(" ".repeat(until_right_edge)))?;
|
self.handle.queue(style::Print(" ".repeat(until_right_edge)))?;
|
||||||
|
40
src/theme.rs
40
src/theme.rs
@ -142,10 +142,38 @@ pub struct AuthorStyle {
|
|||||||
pub positioning: AuthorPositioning,
|
pub positioning: AuthorPositioning,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct FooterStyle {
|
#[serde(tag = "style", rename_all = "snake_case")]
|
||||||
#[serde(default = "default_footer_template")]
|
pub enum FooterStyle {
|
||||||
pub template: Option<String>,
|
Template { format: String },
|
||||||
|
ProgressBar,
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FooterStyle {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Template { format: " {current_slide} / {total_slides}".to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FooterStyle {
|
||||||
|
pub fn render(&self, current_slide: usize, total_slides: usize, total_columns: usize) -> Option<String> {
|
||||||
|
match self {
|
||||||
|
FooterStyle::Template { format } => {
|
||||||
|
let current_slide = (current_slide + 1).to_string();
|
||||||
|
let total_slides = total_slides.to_string();
|
||||||
|
let footer = format.replace("{current_slide}", ¤t_slide).replace("{total_slides}", &total_slides);
|
||||||
|
Some(footer)
|
||||||
|
}
|
||||||
|
FooterStyle::ProgressBar => {
|
||||||
|
let progress_ratio = (current_slide + 1) as f64 / total_slides as f64;
|
||||||
|
let columns_ratio = (total_columns as f64 * progress_ratio).ceil();
|
||||||
|
let bar = "█".repeat(columns_ratio as usize);
|
||||||
|
Some(bar)
|
||||||
|
}
|
||||||
|
FooterStyle::Empty => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize)]
|
#[derive(Debug, Default, Deserialize)]
|
||||||
@ -191,10 +219,6 @@ pub enum AuthorPositioning {
|
|||||||
PageBottom,
|
PageBottom,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_footer_template() -> Option<String> {
|
|
||||||
Some("{current_slide} / {total_slides}".to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -36,3 +36,5 @@ styles:
|
|||||||
prefix: "░░░░░░"
|
prefix: "░░░░░░"
|
||||||
h6:
|
h6:
|
||||||
prefix: "░░░░░░░"
|
prefix: "░░░░░░░"
|
||||||
|
footer:
|
||||||
|
style: progress_bar
|
||||||
|
Loading…
x
Reference in New Issue
Block a user