///|
/// `[ a, b ]` on one line, or one item per line with leading commas (the
/// elm-format form): `[ a\n, b\n]`. With no items: `[]`. `leads[i]` (for
/// `i >= 1`) comes before the `,` of item `i` (see `Ctx::before_item`).
/// `inner` comes before the closing token (see `Ctx::inner`, and
/// `Ctx::inner_alone` for no items).
fn sequence(
split : Split,
open : String,
close : String,
items : Array[@pretty.Doc],
leads? : Array[@pretty.Doc] = [],
inner? : @pretty.Doc = @pretty.empty(),
) -> @pretty.Doc {
guard !items.is_empty() else {
return @pretty.text(open) + inner + @pretty.text(close)
}
let mut body = @pretty.text(open + " ") + @pretty.nest(2, items[0])
for i in 1.. @pretty.Doc {
let mut body = @pretty.text("| ") + @pretty.nest(2, fields[0])
for i in 1.. @pretty.Doc {
label + separator + @pretty.group(@pretty.tab(4, split_line(split) + value))
}
///|
/// `(d)`; when `d` breaks, the `)` goes on its own line in the column of
/// the `(`, and the lines of `d` are indented from the column after the `(`
/// (the elm-format form). `inner` comes before the `)`.
fn parens(
split : Split,
d : @pretty.Doc,
inner? : @pretty.Doc = @pretty.empty(),
) -> @pretty.Doc {
@pretty.group(
@pretty.align(
@pretty.text("(") +
@pretty.nest(1, d + inner) +
split_softline(split) +
@pretty.text(")"),
),
)
}
///|
/// `head a b` on one line, or each item on its own line at the next tab
/// stop (a multiple of 4), as elm-format indents.
fn spaced(
split : Split,
head : @pretty.Doc,
items : Array[@pretty.Doc],
) -> @pretty.Doc {
let mut rest = @pretty.empty()
for x in items {
rest = rest + split_line(split) + x
}
@pretty.group(head + @pretty.tab(4, rest))
}
///|
/// `head a b c` as elm-format lays out an application
/// (`ElmStructure.application`). `first` is `Split` for `FASplitFirst`:
/// each argument on its own line. `rest` is `Split` for
/// `FAJoinFirst SplitAll`: the first argument on the line, the others on
/// their own lines. With `Join` for both (`FAJoinFirst JoinAll`), the first
/// argument leaves the line only when the head or it is multi-line, and the
/// others leave it when one of them is multi-line. With `Fit`, this is
/// `spaced`. `args` is not empty.
fn application(
first : Split,
rest : Split,
head : @pretty.Doc,
args : Array[@pretty.Doc],
) -> @pretty.Doc {
match first {
Fit | Split => spaced(first, head, args)
Join => {
let mut tail = @pretty.empty()
for i in 1.. @pretty.Doc {
guard !items.is_empty() else {
return @pretty.text(open) + inner + @pretty.text(close)
}
let mut body = @pretty.text(open + " ") + items[0]
for i in 1.. @pretty.Doc {
@pretty.text("(") + d + @pretty.text(")")
}
///|
/// `n` line breaks.
fn line_breaks(n : Int) -> @pretty.Doc {
let mut d = @pretty.empty()
for _ in 0..