1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Copyright Materialize, Inc. and contributors. All rights reserved.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

//! Utility functions used by the doc functions.

use pretty::{Doc, RcDoc};

use crate::TAB;

pub(crate) fn intersperse_line_nest<'a, I>(v: I) -> RcDoc<'a>
where
    I: IntoIterator<Item = RcDoc<'a, ()>>,
{
    RcDoc::intersperse(v, Doc::line()).nest(TAB).group()
}

pub(crate) fn nest<'a>(title: RcDoc<'a>, v: RcDoc<'a>) -> RcDoc<'a> {
    intersperse_line_nest([title, v])
}

pub(crate) fn nest_title<S>(title: S, v: RcDoc) -> RcDoc
where
    S: Into<String>,
{
    nest(RcDoc::text(title.into()), v)
}

pub(crate) fn title_comma_separate<'a, F, T, S>(title: S, f: F, v: &'a [T]) -> RcDoc<'a, ()>
where
    F: Fn(&'a T) -> RcDoc,
    S: Into<String>,
{
    let title = RcDoc::text(title.into());
    if v.is_empty() {
        title
    } else {
        nest_comma_separate(title, f, v)
    }
}

pub(crate) fn nest_comma_separate<'a, F, T: 'a, I>(
    title: RcDoc<'a, ()>,
    f: F,
    v: I,
) -> RcDoc<'a, ()>
where
    F: Fn(&'a T) -> RcDoc,
    I: IntoIterator<Item = &'a T>,
{
    nest(title, comma_separate(f, v))
}

pub(crate) fn comma_separate<'a, F, T: 'a, I>(f: F, v: I) -> RcDoc<'a, ()>
where
    F: Fn(&'a T) -> RcDoc,
    I: IntoIterator<Item = &'a T>,
{
    let docs = v.into_iter().map(f);
    comma_separated(docs)
}

pub(crate) fn comma_separated<'a, I>(v: I) -> RcDoc<'a, ()>
where
    I: IntoIterator<Item = RcDoc<'a, ()>>,
{
    RcDoc::intersperse(v, RcDoc::concat([RcDoc::text(","), RcDoc::line()])).group()
}

pub(crate) fn bracket<A: Into<String>, B: Into<String>>(left: A, d: RcDoc, right: B) -> RcDoc {
    bracket_doc(
        RcDoc::text(left.into()),
        d,
        RcDoc::text(right.into()),
        RcDoc::line_(),
    )
}

pub(crate) fn bracket_doc<'a>(
    left: RcDoc<'a>,
    d: RcDoc<'a>,
    right: RcDoc<'a>,
    line: RcDoc<'a>,
) -> RcDoc<'a> {
    RcDoc::concat([
        left,
        RcDoc::concat([line.clone(), d]).nest(TAB),
        line,
        right,
    ])
    .group()
}