use std::iter::once;
use fmtt::{format, Hanging};
use super::*;
pub struct FmttParagraph {
line_width: Option<usize>,
buffer: String,
hard_break_points: Vec<usize>,
}
impl Write for FmttParagraph {
fn write_str(&mut self, s: &str) -> std::fmt::Result {
trace!(s, "FmttParagraph::write_str");
match s {
r"\
" => {
self.buffer.push_str(s);
self.hard_break_points.push(self.buffer.len());
}
"[ ] " => self.buffer.push_str("[ ]\0"),
"[x] " => self.buffer.push_str("[x]\0"),
_ => self.buffer.push_str(s),
};
Ok(())
}
}
impl ExternalFormatter for FmttParagraph {
fn new(_buffer_type: BufferType, max_width: Option<usize>, capacity: usize) -> Self {
Self {
line_width: max_width,
buffer: String::with_capacity(capacity),
hard_break_points: Vec::new(),
}
}
fn is_empty(&self) -> bool {
self.buffer.is_empty()
}
fn context(&self) -> FormattingContext {
FormattingContext::Paragraph
}
fn into_buffer(self) -> String {
let Self {
line_width,
buffer,
hard_break_points,
} = self;
let chunk_border_indices = hard_break_points.iter().copied();
match line_width {
Some(line_width) => {
let paragraph_starts = Default::default();
once(0)
.chain(chunk_border_indices.clone())
.zip(chunk_border_indices.chain(once(buffer.len())))
.map(|(start, end)| {
format(
&buffer[start..end],
line_width,
Hanging::Hang,
¶graph_starts,
)
.join("")
})
.collect::<String>()
}
None => buffer,
}
.replace("\0", " ")
}
}