use typst_syntax::{SyntaxNode, ast::*};
use super::{Context, PrettyPrinter, prelude::*};
use crate::ext::StrExt;
impl<'a> PrettyPrinter<'a> {
pub(super) fn convert_text(&'a self, text: Text<'a>) -> ArenaDoc<'a> {
self.convert_literal(text.get())
}
pub(super) fn convert_text_wrapped(&'a self, text: Text<'a>) -> ArenaDoc<'a> {
wrap_text(&self.arena, text.get())
}
pub(super) fn convert_space(&'a self, ctx: Context, space: Space<'a>) -> ArenaDoc<'a> {
self.convert_space_untyped(ctx, space.to_untyped())
}
pub(super) fn convert_space_untyped(
&'a self,
ctx: Context,
node: &'a SyntaxNode,
) -> ArenaDoc<'a> {
if node.leaf_text().has_linebreak() {
self.arena.hardline()
} else if ctx.mode.is_markup() && !self.config.collapse_markup_spaces {
self.arena.text(node.leaf_text().as_str())
} else {
self.arena.space()
}
}
pub(super) fn convert_parbreak(&'a self, parbreak: Parbreak) -> ArenaDoc<'a> {
let newline_count = parbreak.to_untyped().leaf_text().count_linebreaks();
self.arena.hardline().repeat(newline_count)
}
}
fn wrap_text<'a>(arena: &'a Arena<'a>, text: &'a str) -> ArenaDoc<'a> {
let mut tokens = text.split_ascii_whitespace();
let mut doc = if let Some(first) = tokens.next() {
arena.text(first)
} else {
return arena.nil();
};
doc = tokens.fold(doc, |doc, token| {
let sep = if is_enum_marker(token) {
arena.space()
} else {
arena.softline()
};
doc + sep + arena.text(token)
});
if text.ends_with(' ') {
doc += arena.softline();
}
doc
}
pub(super) fn is_enum_marker(token: &str) -> bool {
if let Some(stripped) = token.strip_suffix('.') {
return stripped.parse::<usize>().is_ok();
}
false
}
#[cfg(test)]
mod tests {
use insta::assert_snapshot;
use super::*;
#[test]
fn enum_marker_glues() {
let text = "a. 1. 01. 18446744073709551615. 18446744073709551616. 18446744073709551617.";
let arena = Arena::new();
let doc = wrap_text(&arena, text);
assert_snapshot!(doc.print(0).to_string(), @r"
a. 1. 01. 18446744073709551615.
18446744073709551616.
18446744073709551617.
")
}
}