use unicode_width::UnicodeWidthStr;
use super::{ParagraphState, ParagraphWriter, PrefixLine};
pub(in crate::wrap) struct PendingPrefix {
pub(in crate::wrap) prefix: String,
pub(in crate::wrap) rest: String,
pub(in crate::wrap) original_lines: Vec<String>,
pub(in crate::wrap) synthetic_join_spaces: Vec<usize>,
pub(in crate::wrap) rest_width: usize,
pub(in crate::wrap) repeat_prefix: bool,
pub(in crate::wrap) outer_prefix: Option<String>,
pub(in crate::wrap) hard_break: bool,
pub(in crate::wrap) open_fence_len: Option<usize>,
pub(in crate::wrap) continuation_mode: ContinuationMode,
pub(in crate::wrap) used_prefix: bool,
pub(in crate::wrap) tail_reflow: TailReflow,
}
#[derive(Debug, PartialEq)]
pub(in crate::wrap) enum ContinuationMode {
Normalize,
TightCodeSpan,
VerbatimFlush,
}
#[derive(Debug, PartialEq)]
pub(in crate::wrap) enum TailReflow {
Allowed,
Disallowed,
}
pub(in crate::wrap) fn pending_prefix_for_next_segment(pending: &mut PendingPrefix) -> String {
if pending.used_prefix {
continuation_prefix_for(
pending.prefix.as_str(),
pending.repeat_prefix,
pending.outer_prefix.as_deref(),
)
} else {
pending.used_prefix = true;
pending.prefix.clone()
}
}
pub(in crate::wrap) fn continuation_prefix_for(
prefix: &str,
repeat_prefix: bool,
outer_prefix: Option<&str>,
) -> String {
if repeat_prefix {
return prefix.to_string();
}
let prefix_width = UnicodeWidthStr::width(prefix);
if let Some(outer_prefix) = outer_prefix {
let outer_width = UnicodeWidthStr::width(outer_prefix);
return format!(
"{outer_prefix}{}",
" ".repeat(prefix_width.saturating_sub(outer_width))
);
}
let indent_str = crate::textproc::leading_indent(prefix);
let indent_width = UnicodeWidthStr::width(indent_str);
format!("{}{}", indent_str, " ".repeat(prefix_width - indent_width))
}
impl ParagraphWriter<'_> {
pub(super) fn defer_prefix_line(
&mut self,
state: &mut ParagraphState,
prefix_line: &PrefixLine<'_>,
open_fence_len: Option<usize>,
continuation_mode: ContinuationMode,
) {
let prefix = prefix_line.prefix.as_ref().to_string();
let prefix_width = UnicodeWidthStr::width(prefix.as_str());
state.pending_prefix = Some(PendingPrefix {
prefix,
rest: prefix_line.rest.to_string(),
original_lines: vec![format!(
"{prefix}{rest}",
prefix = prefix_line.prefix.as_ref(),
rest = prefix_line.rest,
)],
synthetic_join_spaces: Vec::new(),
rest_width: self.width.saturating_sub(prefix_width).max(1),
repeat_prefix: prefix_line.repeat_prefix,
outer_prefix: prefix_line.outer_prefix.as_deref().map(ToOwned::to_owned),
hard_break: false,
open_fence_len,
continuation_mode,
used_prefix: false,
tail_reflow: TailReflow::Allowed,
});
}
}