std.doc
Pretty-printing documents: Wadler’s algorithm as Haskell’s prettyprinter
has it (layoutPretty, ribbon 1.0), so that the formatter, and any other
code that lays text out, can be written in heff. A Doc is built with
text, line, group, nest and align, and render lays it out at a
width: a group goes on one line if it fits, and breaks otherwise.
The language is call-by-value, so the layout’s laziness — fits looks at
the first line only — is a Unit -> SDoc at each step.
Doc
data Doc = Fail | None | Text String | Line | FlatAlt Doc Doc | Cat Doc Doc | Nest Int Doc | Union Doc Doc | Column (Int -> Doc) | Nesting (Int -> Doc)emptyDoc
emptyDoc : Doctext
text : String -> DocText without newlines (pretty takes text with them).
hardline
hardline : DocA line break, kept when its group is flattened.
line
line : DocA line break, a space when its group is flattened.
linebreak
linebreak : DocA line break, nothing when its group is flattened.
softline
softline : DocA space if what follows fits on the line, a line break otherwise.
<>
(<>) : Doc -> Doc -> Doc<+>
(<+>) : Doc -> Doc -> Docnest
nest : Int -> Doc -> DocThe document, its line breaks after nest’s further columns in.
flatAlt
flatAlt : Doc -> Doc -> DocThe first when flattened, the second when not.
flatten
flatten : Doc -> DocThe document on one line: each line a space, each linebreak nothing,
each hardline a failure the layout backs out of.
Flat
data Flat = Flattened Doc | AlreadyFlat | NeverFlatgroup
group : Doc -> DocOn one line if it fits, as written otherwise.
align
align : Doc -> DocThe document, its line breaks at the column where it starts.
hang
hang : Int -> Doc -> Docindent
indent : Int -> Doc -> DocconcatWith
concatWith : (Doc -> Doc -> Doc) -> List Doc -> Docpretty
pretty : String -> DocText, its newlines hard line breaks.
vsep
vsep : List Doc -> Dochsep
hsep : List Doc -> Docvcat
vcat : List Doc -> Docsep
sep : List Doc -> Docenclose
enclose : Doc -> Doc -> Doc -> DoctextWidth
textWidth : String -> IntHow many columns a text takes: one a rune, whatever units it takes
(an East Asian wide one too, as Go’s text/tabwriter counts).
>>> List.map textWidth ["abc", "é😀", ""][3, 2, 0]SDoc
data SDoc = SEmpty | SFail | SText String Int (Unit -> SDoc) | SLine Int (Unit -> SDoc)fits
fits : Int -> Int -> Int -> SDoc -> Booldisplay
display : SDoc -> StringrenderWidth
renderWidth : Int -> Doc -> Stringrender
render : Doc -> String