From a18532a23ad9c68266a5f45ce6d7569458df436b Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 20 Nov 2022 20:33:29 +0100 Subject: [PATCH] Start pretty printing comments --- src/pretty/basic.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/pretty/basic.rs diff --git a/src/pretty/basic.rs b/src/pretty/basic.rs new file mode 100644 index 0000000..c3e6dcc --- /dev/null +++ b/src/pretty/basic.rs @@ -0,0 +1,86 @@ +use std::mem; + +use pretty::{DocAllocator, DocBuilder, Pretty, RcAllocator, RcDoc}; + +use crate::ast::{Ident, Line, Space}; + +pub enum Group<'a> { + EmptyLine, + CommentBlock(Vec<&'a str>), +} + +/// Group comments and deduplicate empty lines +fn group_comments(lines: &[Line]) -> Vec { + let mut result = vec![]; + + let mut current_block = vec![]; + let mut last_line_was_empty = false; + for line in lines { + match line { + Line::Empty if last_line_was_empty => {} + Line::Empty => { + last_line_was_empty = true; + if !current_block.is_empty() { + result.push(Group::CommentBlock(mem::take(&mut current_block))); + } + result.push(Group::EmptyLine); + } + Line::Comment(comment) => { + last_line_was_empty = false; + current_block.push(comment); + } + } + } + + if !current_block.is_empty() { + result.push(Group::CommentBlock(current_block)); + } + + result +} + +fn remove_leading_empty_line(groups: &mut Vec) { + if let Some(Group::EmptyLine) = groups.first() { + groups.remove(0); + } +} + +fn remove_trailing_empty_line(groups: &mut Vec) { + if let Some(Group::EmptyLine) = groups.last() { + groups.pop(); + } +} + +fn comment_group_to_doc(comment: Vec<&str>) -> RcDoc { + RcAllocator + .concat(comment.into_iter().map(|c| { + RcDoc::text("# ") + .append(RcDoc::text(c)) + .append(RcDoc::hardline()) + })) + .indent(0) + .into_doc() +} + +impl Space { + /// Format as document for inline use, prefering nil if possible. + pub fn to_doc_inline_nospace(&self) -> RcDoc { + RcDoc::nil() + } + + /// Format as document, prefering a single space if possible. + pub fn to_doc_inline_space(&self) -> RcDoc { + RcDoc::space() + } + + /// Format as document, prefering a newline if possible. + pub fn to_doc_newline(&self) -> RcDoc { + RcDoc::line() + } +} + +impl Ident { + pub fn to_doc(&self) -> RcDoc { + RcDoc::text(&self.name) + } +}