mfmt/document.rs
1// https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf
2//
3// Unlike the Wadler's algorithm or some other formatters like prettier, we do
4// not need to search the best format given source codes. For example, we do
5// not have any "group" combinator.
6//
7// However, we are rather given the "best" format by all information available
8// in the source codes like Go.
9//
10// We need soft-line and if-break nodes to make nodes totally agnostic about if
11// parent nodes are broken or not. But that also makes IR more complex.
12// (e.g. handling trailing commas in function calls)
13
14/// A document.
15#[derive(Clone, Debug, PartialEq)]
16pub enum Document<'a> {
17 /// A document broken into multiple lines.
18 Break {
19 broken: bool,
20 document: &'a Document<'a>,
21 },
22 /// An indented document.
23 Indent(&'a Document<'a>),
24 /// A line.
25 ///
26 /// A formatter considers it as a space if a document is not broken by
27 /// [`Break`](Document::Break).
28 Line,
29 /// A line suffix.
30 LineSuffix(&'a str),
31 /// A document indented to a current column.
32 ///
33 /// If it is `soft`, an indent becomes equal to or more than a current
34 /// indent.
35 Offside {
36 document: &'a Document<'a>,
37 soft: bool,
38 },
39 /// A sequence of documents.
40 Sequence(&'a [Document<'a>]),
41 /// A string.
42 String(&'a str),
43}
44
45impl<'a> From<&'a str> for Document<'a> {
46 fn from(string: &'a str) -> Self {
47 Self::String(string)
48 }
49}
50
51impl<'a> From<&'a [Self]> for Document<'a> {
52 fn from(documents: &'a [Self]) -> Self {
53 Self::Sequence(documents)
54 }
55}