mod builder;
mod render;
pub use builder::{
emptyline, hardline, hardspace, line, line_prime, newline, push_comment, push_group,
push_group_ann, push_hcat, push_nested, push_offset, push_sep_by, push_surrounded, push_text,
push_trailing, push_trailing_comment, softline, softline_prime,
};
pub use render::{RenderConfig, fixup, render_with_config};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Spacing {
Softbreak,
Break,
Hardspace,
Softspace,
Space,
Hardline,
Emptyline,
Newlines(usize),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GroupAnn {
RegularG,
Priority,
Transparent,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TextAnn {
RegularT,
Comment,
TrailingComment,
Trailing,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DocE {
Text(usize, usize, TextAnn, String),
Spacing(Spacing),
Group(GroupAnn, Doc),
Nest(isize, isize),
}
pub type Doc = Vec<DocE>;
#[derive(Debug)]
pub struct IR(pub(crate) Doc);
pub trait Pretty {
fn pretty(&self, doc: &mut Doc);
}
impl Pretty for Doc {
fn pretty(&self, doc: &mut Doc) {
doc.extend(self.iter().cloned());
}
}
impl<T: Pretty> Pretty for Option<T> {
fn pretty(&self, doc: &mut Doc) {
if let Some(x) = self {
x.pretty(doc);
}
}
}
pub fn text_width(s: &str) -> usize {
s.chars().count()
}
pub fn unexpand_spacing_prime(mut limit: Option<i32>, doc: &[DocE]) -> Option<Doc> {
let mut result = Vec::new();
let mut stack: Vec<std::slice::Iter<'_, DocE>> = vec![doc.iter()];
while let Some(iter) = stack.last_mut() {
let Some(elem) = iter.next() else {
stack.pop();
continue;
};
match elem {
DocE::Text(_, _, _, t) => {
if let Some(n) = limit.as_mut() {
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
{
*n -= text_width(t) as i32;
}
}
result.push(elem.clone());
}
DocE::Spacing(Spacing::Hardspace | Spacing::Space | Spacing::Softspace) => {
if let Some(n) = limit.as_mut() {
*n -= 1;
}
result.push(DocE::Spacing(Spacing::Hardspace));
}
DocE::Spacing(Spacing::Break | Spacing::Softbreak) => {}
DocE::Spacing(_) => return None,
DocE::Nest(..) => result.push(elem.clone()),
DocE::Group(_, inner) => stack.push(inner.iter()),
}
if matches!(limit, Some(n) if n < 0) {
return None;
}
}
Some(result)
}