Skip to main content

src/molt@internal@cst@elements.erl

-module(molt@internal@cst@elements).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/molt/internal/cst/elements.gleam").
-export([document_newline/1, extract_key_segments/1, key_path/1, child_key_paths/1, skip_trivia/1, skip_all_trivia/1, key_name/1, value_tokens/1, find_first_value/1, get_kv_children/1, is_toml/1, split_at_equals/1, split_leading_ws/1, split_before_trivia/1, take_trailing_ws/1, extract_inline_entries/1, extract_array_items/1, array_layout/1, build_array_item/2, rebuild_array/2, kv_to_section_form/1, section_kvs_to_inline_table/1, inline_tables_to_array/1, inline_tables_to_multiline_array/2, inline_trailing_trivia/1, rewrite_kv_key_in_place/2]).
-export_type([array_layout/0]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(false).

-type array_layout() :: single_line | {multi_line, binary()}.

-file("src/molt/internal/cst/elements.gleam", 42).
?DOC(false).
-spec first_literal_newline_in_tokens(
    list(greenwood:token(molt@types:toml_kind()))
) -> gleam@option:option(binary()).
first_literal_newline_in_tokens(Tokens) ->
    case Tokens of
        [] ->
            none;

        [{token, newline, Text} | _] when Text =/= <<""/utf8>> ->
            {some, Text};

        [_ | Rest] ->
            first_literal_newline_in_tokens(Rest)
    end.

-file("src/molt/internal/cst/elements.gleam", 52).
?DOC(false).
-spec first_literal_newline_in_children(
    list(greenwood:element(molt@types:toml_kind()))
) -> gleam@option:option(binary()).
first_literal_newline_in_children(Els) ->
    case Els of
        [] ->
            none;

        [{token_element, {token, newline, Text}} | _] when Text =/= <<""/utf8>> ->
            {some, Text};

        [{token_element, _} | Rest] ->
            first_literal_newline_in_children(Rest);

        [{node_element, N} | Rest@1] ->
            _pipe = first_literal_newline(N),
            gleam@option:lazy_or(
                _pipe,
                fun() -> first_literal_newline_in_children(Rest@1) end
            )
    end.

-file("src/molt/internal/cst/elements.gleam", 30).
?DOC(false).
-spec first_literal_newline(greenwood:node_(molt@types:toml_kind())) -> gleam@option:option(binary()).
first_literal_newline(Node) ->
    case erlang:element(4, Node) of
        {trivia, Leading, Trailing} ->
            _pipe = first_literal_newline_in_tokens(Leading),
            _pipe@1 = gleam@option:lazy_or(
                _pipe,
                fun() ->
                    first_literal_newline_in_children(erlang:element(3, Node))
                end
            ),
            gleam@option:lazy_or(
                _pipe@1,
                fun() -> first_literal_newline_in_tokens(Trailing) end
            );

        bare ->
            first_literal_newline_in_children(erlang:element(3, Node))
    end.

-file("src/molt/internal/cst/elements.gleam", 23).
?DOC(false).
-spec document_newline(greenwood:node_(molt@types:toml_kind())) -> binary().
document_newline(Node) ->
    case first_literal_newline(Node) of
        {some, <<"\r\n"/utf8>>} ->
            <<"\r\n"/utf8>>;

        _ ->
            <<"\n"/utf8>>
    end.

-file("src/molt/internal/cst/elements.gleam", 116).
?DOC(false).
-spec extract_key_segments(list(greenwood:element(molt@types:toml_kind()))) -> list(binary()).
extract_key_segments(Children) ->
    gleam@list:filter_map(Children, fun(El) -> case El of
                {token_element, {token, bare_key, Text}} ->
                    {ok, Text};

                {token_element, {token, integer, Text@1}} ->
                    {ok, Text@1};

                {token_element, {token, basic_string, Text@2}} ->
                    {ok, molt@internal@utils:unescape_basic_string(Text@2)};

                {token_element, {token, literal_string, Text@3}} ->
                    {ok, Text@3};

                _ ->
                    {error, nil}
            end end).

-file("src/molt/internal/cst/elements.gleam", 65).
?DOC(false).
-spec key_path(list(greenwood:element(molt@types:toml_kind()))) -> gleam@option:option(list(binary())).
key_path(Children) ->
    case Children of
        [] ->
            none;

        [{token_element, {token, equals, _}} | _] ->
            none;

        [{node_element, N} | _] when erlang:element(2, N) =:= key ->
            {some, extract_key_segments(erlang:element(3, N))};

        [{token_element, {token, bare_key, Text}} | _] ->
            {some, [Text]};

        [{token_element, {token, integer, Text@1}} | _] ->
            {some, [Text@1]};

        [{token_element, {token, basic_string, Text@2}} | _] ->
            {some, [molt@internal@utils:unescape_basic_string(Text@2)]};

        [{token_element, {token, literal_string, Text@3}} | _] ->
            {some, [Text@3]};

        [_ | Rest] ->
            key_path(Rest)
    end.

-file("src/molt/internal/cst/elements.gleam", 81).
?DOC(false).
-spec child_key_paths(greenwood:node_(molt@types:toml_kind())) -> list(list(binary())).
child_key_paths(Node) ->
    gleam@list:filter_map(erlang:element(3, Node), fun(El) -> case El of
                {node_element, Kv} when erlang:element(2, Kv) =:= key_value ->
                    gleam@option:to_result(key_path(erlang:element(3, Kv)), nil);

                _ ->
                    {error, nil}
            end end).

-file("src/molt/internal/cst/elements.gleam", 92).
?DOC(false).
-spec skip_trivia(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
skip_trivia(Children) ->
    case Children of
        [{token_element, {token, whitespace, _}} | Rest] ->
            skip_trivia(Rest);

        [{token_element, {token, newline, _}} | Rest] ->
            skip_trivia(Rest);

        _ ->
            Children
    end.

-file("src/molt/internal/cst/elements.gleam", 103).
?DOC(false).
-spec skip_all_trivia(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
skip_all_trivia(Children) ->
    case Children of
        [{token_element, {token, whitespace, _}} | Rest] ->
            skip_all_trivia(Rest);

        [{token_element, {token, newline, _}} | Rest] ->
            skip_all_trivia(Rest);

        [{token_element, {token, comment, _}} | Rest] ->
            skip_all_trivia(Rest);

        _ ->
            Children
    end.

-file("src/molt/internal/cst/elements.gleam", 130).
?DOC(false).
-spec key_name(list(greenwood:element(molt@types:toml_kind()))) -> gleam@option:option(binary()).
key_name(Children) ->
    case Children of
        [] ->
            none;

        [{token_element, {token, equals, _}} | _] ->
            none;

        [{token_element, {token, bare_key, Text}} | _] ->
            {some, Text};

        [{token_element, {token, integer, Text@1}} | _] ->
            {some, Text@1};

        [{token_element, {token, basic_string, Text@2}} | _] ->
            {some, molt@internal@utils:unescape_basic_string(Text@2)};

        [{token_element, {token, literal_string, Text@3}} | _] ->
            {some, Text@3};

        [_ | Rest] ->
            key_name(Rest)
    end.

-file("src/molt/internal/cst/elements.gleam", 144).
?DOC(false).
-spec value_tokens(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
value_tokens(Children) ->
    case Children of
        [] ->
            [];

        [{token_element, {token, equals, _}} | Rest] ->
            Rest;

        [_ | Rest@1] ->
            value_tokens(Rest@1)
    end.

-file("src/molt/internal/cst/elements.gleam", 155).
?DOC(false).
-spec find_first_value(list(greenwood:element(molt@types:toml_kind()))) -> gleam@option:option(greenwood:element(molt@types:toml_kind())).
find_first_value(Elements) ->
    case Elements of
        [] ->
            none;

        [{token_element, {token, whitespace, _}} | Rest] ->
            find_first_value(Rest);

        [{token_element, {token, newline, _}} | Rest] ->
            find_first_value(Rest);

        [{token_element, {token, comment, _}} | Rest] ->
            find_first_value(Rest);

        [El | _] ->
            {some, El}
    end.

-file("src/molt/internal/cst/elements.gleam", 835).
?DOC(false).
-spec child_nodes_of_kind(
    list(greenwood:element(molt@types:toml_kind())),
    molt@types:toml_kind()
) -> list(greenwood:node_(molt@types:toml_kind())).
child_nodes_of_kind(Children, Kind) ->
    gleam@list:filter_map(Children, fun(El) -> case El of
                {node_element, N} when erlang:element(2, N) =:= Kind ->
                    {ok, N};

                _ ->
                    {error, nil}
            end end).

-file("src/molt/internal/cst/elements.gleam", 168).
?DOC(false).
-spec get_kv_children(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:node_(molt@types:toml_kind())).
get_kv_children(Children) ->
    child_nodes_of_kind(Children, key_value).

-file("src/molt/internal/cst/elements.gleam", 858).
?DOC(false).
-spec is_only_trivia(list(greenwood:element(molt@types:toml_kind()))) -> boolean().
is_only_trivia(Children) ->
    gleam@list:all(Children, fun(El) -> case El of
                {token_element, {token, bom, _}} ->
                    true;

                {token_element, {token, comment, _}} ->
                    true;

                {token_element, {token, whitespace, _}} ->
                    true;

                {token_element, {token, newline, _}} ->
                    true;

                {node_element, N} when erlang:element(2, N) =:= post_script ->
                    true;

                _ ->
                    false
            end end).

-file("src/molt/internal/cst/elements.gleam", 847).
?DOC(false).
-spec node_has_equals(greenwood:node_(molt@types:toml_kind())) -> boolean().
node_has_equals(Node) ->
    gleam@list:any(erlang:element(3, Node), fun(El) -> case El of
                {token_element, {token, equals, _}} ->
                    true;

                _ ->
                    false
            end end).

-file("src/molt/internal/cst/elements.gleam", 876).
?DOC(false).
-spec has_toml_nodes(list(greenwood:element(molt@types:toml_kind()))) -> boolean().
has_toml_nodes(Children) ->
    gleam@list:any(Children, fun(El) -> case El of
                {node_element, N} when erlang:element(2, N) =:= table ->
                    true;

                {node_element, N@1} when erlang:element(2, N@1) =:= array_of_tables ->
                    true;

                {node_element, N@2} when erlang:element(2, N@2) =:= key_value ->
                    node_has_equals(N@2);

                _ ->
                    false
            end end).

-file("src/molt/internal/cst/elements.gleam", 178).
?DOC(false).
-spec is_toml(list(greenwood:element(molt@types:toml_kind()))) -> boolean().
is_toml(Children) ->
    has_toml_nodes(Children) orelse is_only_trivia(Children).

-file("src/molt/internal/cst/elements.gleam", 184).
?DOC(false).
-spec split_at_equals(list(greenwood:element(molt@types:toml_kind()))) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
split_at_equals(Children) ->
    gleam@list:split_while(Children, fun(El) -> case El of
                {token_element, {token, equals, _}} ->
                    false;

                _ ->
                    true
            end end).

-file("src/molt/internal/cst/elements.gleam", 196).
?DOC(false).
-spec split_leading_ws(list(greenwood:element(molt@types:toml_kind()))) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
split_leading_ws(Children) ->
    gleam@list:split_while(Children, fun(El) -> case El of
                {token_element, {token, whitespace, _}} ->
                    true;

                _ ->
                    false
            end end).

-file("src/molt/internal/cst/elements.gleam", 209).
?DOC(false).
-spec split_before_trivia(list(greenwood:element(molt@types:toml_kind()))) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
split_before_trivia(Children) ->
    gleam@list:split_while(Children, fun(El) -> case El of
                {token_element, {token, comment, _}} ->
                    false;

                {token_element, {token, newline, _}} ->
                    false;

                _ ->
                    true
            end end).

-file("src/molt/internal/cst/elements.gleam", 223).
?DOC(false).
-spec take_trailing_ws(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
take_trailing_ws(Els) ->
    _pipe = Els,
    _pipe@1 = lists:reverse(_pipe),
    _pipe@2 = gleam@list:take_while(_pipe@1, fun(El) -> case El of
                {token_element, {token, whitespace, _}} ->
                    true;

                _ ->
                    false
            end end),
    lists:reverse(_pipe@2).

-file("src/molt/internal/cst/elements.gleam", 250).
?DOC(false).
-spec extract_inline_entries(greenwood:node_(molt@types:toml_kind())) -> list(greenwood:node_(molt@types:toml_kind())).
extract_inline_entries(Inline_table) ->
    get_kv_children(erlang:element(3, Inline_table)).

-file("src/molt/internal/cst/elements.gleam", 258).
?DOC(false).
-spec extract_array_items(greenwood:node_(molt@types:toml_kind())) -> list(greenwood:node_(molt@types:toml_kind())).
extract_array_items(Array) ->
    child_nodes_of_kind(erlang:element(3, Array), array_element).

-file("src/molt/internal/cst/elements.gleam", 306).
?DOC(false).
-spec leading_indent(greenwood:node_(molt@types:toml_kind())) -> {ok, binary()} |
    {error, nil}.
leading_indent(Element) ->
    case erlang:element(4, Element) of
        {trivia, Leading, _} ->
            gleam@list:find_map(Leading, fun(T) -> case erlang:element(2, T) of
                        whitespace ->
                            {ok, erlang:element(3, T)};

                        _ ->
                            {error, nil}
                    end end);

        bare ->
            {error, nil}
    end.

-file("src/molt/internal/cst/elements.gleam", 299).
?DOC(false).
-spec detect_array_indent(list(greenwood:node_(molt@types:toml_kind()))) -> binary().
detect_array_indent(Items) ->
    case gleam@list:filter_map(Items, fun leading_indent/1) of
        [Indent | _] ->
            Indent;

        [] ->
            <<"  "/utf8>>
    end.

-file("src/molt/internal/cst/elements.gleam", 283).
?DOC(false).
-spec element_is_multiline(greenwood:node_(molt@types:toml_kind())) -> boolean().
element_is_multiline(Element) ->
    In_children = gleam@list:any(
        erlang:element(3, Element),
        fun(El) -> case El of
                {token_element, {token, newline, _}} ->
                    true;

                _ ->
                    false
            end end
    ),
    In_children orelse case erlang:element(4, Element) of
        {trivia, Leading, Trailing} ->
            gleam@list:any(
                lists:append(Leading, Trailing),
                fun(T) -> erlang:element(2, T) =:= newline end
            );

        bare ->
            false
    end.

-file("src/molt/internal/cst/elements.gleam", 275).
?DOC(false).
-spec array_layout(greenwood:node_(molt@types:toml_kind())) -> array_layout().
array_layout(Array) ->
    Items = extract_array_items(Array),
    case gleam@list:any(Items, fun element_is_multiline/1) of
        false ->
            single_line;

        true ->
            {multi_line, detect_array_indent(Items)}
    end.

-file("src/molt/internal/cst/elements.gleam", 323).
?DOC(false).
-spec build_array_item(
    greenwood:element(molt@types:toml_kind()),
    array_layout()
) -> greenwood:node_(molt@types:toml_kind()).
build_array_item(Value, Layout) ->
    case Layout of
        single_line ->
            {node, array_element, [Value], bare};

        {multi_line, Indent} ->
            {node,
                array_element,
                [Value,
                    {token_element, {token, comma, <<""/utf8>>}},
                    {token_element, {token, newline, <<""/utf8>>}}],
                {trivia, [{token, whitespace, Indent}], []}}
    end.

-file("src/molt/internal/cst/elements.gleam", 797).
?DOC(false).
-spec extract_trailing_after_last(
    list(greenwood:element(molt@types:toml_kind())),
    molt@types:toml_kind()
) -> list(greenwood:element(molt@types:toml_kind())).
extract_trailing_after_last(Body, Kind) ->
    Match = gleam@list:any(Body, fun(El) -> case El of
                {node_element, N} when erlang:element(2, N) =:= Kind ->
                    true;

                _ ->
                    false
            end end),
    gleam@bool:guard(not Match, Body, fun() -> _pipe = Body,
            _pipe@1 = lists:reverse(_pipe),
            _pipe@2 = gleam@list:take_while(_pipe@1, fun(El@1) -> case El@1 of
                        {node_element, N@1} when erlang:element(2, N@1) =:= Kind ->
                            false;

                        _ ->
                            true
                    end end),
            lists:reverse(_pipe@2) end).

-file("src/molt/internal/cst/elements.gleam", 783).
?DOC(false).
-spec take_up_to_token(
    list(greenwood:element(molt@types:toml_kind())),
    molt@types:toml_kind()
) -> {list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))}.
take_up_to_token(Children, Kind) ->
    case Children of
        [] ->
            {[], []};

        [{token_element, {token, K, _}} = Tok | Rest] when K =:= Kind ->
            {[Tok], Rest};

        [El | Rest@1] ->
            {Prefix, After} = take_up_to_token(Rest@1, Kind),
            {[El | Prefix], After}
    end.

-file("src/molt/internal/cst/elements.gleam", 771).
?DOC(false).
-spec has_comma_token(list(greenwood:element(molt@types:toml_kind()))) -> boolean().
has_comma_token(Children) ->
    gleam@list:any(Children, fun(El) -> case El of
                {token_element, {token, comma, _}} ->
                    true;

                _ ->
                    false
            end end).

-file("src/molt/internal/cst/elements.gleam", 747).
?DOC(false).
-spec ensure_trailing_comma(
    greenwood:node_(molt@types:toml_kind()),
    array_layout()
) -> greenwood:node_(molt@types:toml_kind()).
ensure_trailing_comma(Elem, Layout) ->
    gleam@bool:guard(
        has_comma_token(erlang:element(3, Elem)),
        Elem,
        fun() ->
            Separator = case Layout of
                single_line ->
                    [{token_element, {token, comma, <<""/utf8>>}},
                        {token_element, {token, whitespace, <<" "/utf8>>}}];

                {multi_line, _} ->
                    [{token_element, {token, comma, <<""/utf8>>}},
                        {token_element, {token, newline, <<""/utf8>>}}]
            end,
            case erlang:element(3, Elem) of
                [Value | Trailing] ->
                    {node,
                        erlang:element(2, Elem),
                        lists:append([[Value], Separator, Trailing]),
                        erlang:element(4, Elem)};

                [] ->
                    Elem
            end
        end
    ).

-file("src/molt/internal/cst/elements.gleam", 729).
?DOC(false).
-spec ensure_separating_commas(
    list(greenwood:node_(molt@types:toml_kind())),
    array_layout()
) -> list(greenwood:node_(molt@types:toml_kind())).
ensure_separating_commas(Items, Layout) ->
    case Items of
        [] ->
            [];

        [Single] ->
            [Single];

        [Head | Rest] ->
            [ensure_trailing_comma(Head, Layout) |
                ensure_separating_commas(Rest, Layout)]
    end.

-file("src/molt/internal/cst/elements.gleam", 350).
?DOC(false).
-spec rebuild_array(
    greenwood:node_(molt@types:toml_kind()),
    list(greenwood:node_(molt@types:toml_kind()))
) -> greenwood:node_(molt@types:toml_kind()).
rebuild_array(Source, Items) ->
    Normalized = ensure_separating_commas(Items, array_layout(Source)),
    {Prefix, Body} = take_up_to_token(erlang:element(3, Source), left_bracket),
    Trailing = extract_trailing_after_last(Body, array_element),
    Item_elements = gleam@list:map(
        Normalized,
        fun(Item) -> {node_element, Item} end
    ),
    {node,
        erlang:element(2, Source),
        lists:append([Prefix, Item_elements, Trailing]),
        erlang:element(4, Source)}.

-file("src/molt/internal/cst/elements.gleam", 390).
?DOC(false).
-spec drop_ws_tokens(list(greenwood:token(molt@types:toml_kind()))) -> list(greenwood:token(molt@types:toml_kind())).
drop_ws_tokens(Tokens) ->
    case Tokens of
        [{token, whitespace, _} | Rest] ->
            drop_ws_tokens(Rest);

        _ ->
            Tokens
    end.

-file("src/molt/internal/cst/elements.gleam", 382).
?DOC(false).
-spec strip_leading_trivia_whitespace(greenwood:node_(molt@types:toml_kind())) -> greenwood:node_(molt@types:toml_kind()).
strip_leading_trivia_whitespace(Node) ->
    case erlang:element(4, Node) of
        bare ->
            Node;

        {trivia, Leading, Trailing} ->
            {node,
                erlang:element(2, Node),
                erlang:element(3, Node),
                {trivia, drop_ws_tokens(Leading), Trailing}}
    end.

-file("src/molt/internal/cst/elements.gleam", 421).
?DOC(false).
-spec ensure_trailing_newline(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
ensure_trailing_newline(Children) ->
    case lists:reverse(Children) of
        [{token_element, {token, newline, _}} | _] ->
            Children;

        _ ->
            lists:append(
                Children,
                [{token_element, {token, newline, <<""/utf8>>}}]
            )
    end.

-file("src/molt/internal/cst/elements.gleam", 411).
?DOC(false).
-spec drop_leading_whitespace(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
drop_leading_whitespace(Children) ->
    case Children of
        [{token_element, {token, whitespace, _}} | Rest] ->
            drop_leading_whitespace(Rest);

        _ ->
            Children
    end.

-file("src/molt/internal/cst/elements.gleam", 401).
?DOC(false).
-spec trim_edge_whitespace(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
trim_edge_whitespace(Children) ->
    _pipe = Children,
    _pipe@1 = drop_leading_whitespace(_pipe),
    _pipe@2 = lists:reverse(_pipe@1),
    _pipe@3 = drop_leading_whitespace(_pipe@2),
    lists:reverse(_pipe@3).

-file("src/molt/internal/cst/elements.gleam", 364).
?DOC(false).
-spec kv_to_section_form(greenwood:node_(molt@types:toml_kind())) -> greenwood:node_(molt@types:toml_kind()).
kv_to_section_form(Kv) ->
    Children = begin
        _pipe = erlang:element(3, Kv),
        _pipe@1 = gleam@list:filter(_pipe, fun(El) -> case El of
                    {token_element, {token, comma, _}} ->
                        false;

                    _ ->
                        true
                end end),
        _pipe@2 = trim_edge_whitespace(_pipe@1),
        ensure_trailing_newline(_pipe@2)
    end,
    strip_leading_trivia_whitespace(
        {node, erlang:element(2, Kv), Children, erlang:element(4, Kv)}
    ).

-file("src/molt/internal/cst/elements.gleam", 685).
?DOC(false).
-spec is_trailing_trivia_tok(greenwood:element(molt@types:toml_kind())) -> boolean().
is_trailing_trivia_tok(El) ->
    case El of
        {token_element, {token, newline, _}} ->
            true;

        {token_element, {token, whitespace, _}} ->
            true;

        {token_element, {token, comment, _}} ->
            true;

        _ ->
            false
    end.

-file("src/molt/internal/cst/elements.gleam", 673).
?DOC(false).
-spec insert_comma_before_trailing(
    list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
insert_comma_before_trailing(Children) ->
    {Tail_rev, Head_rev} = gleam@list:split_while(
        lists:reverse(Children),
        fun is_trailing_trivia_tok/1
    ),
    lists:append(
        [lists:reverse(Head_rev),
            [{token_element, {token, comma, <<""/utf8>>}}],
            lists:reverse(Tail_rev)]
    ).

-file("src/molt/internal/cst/elements.gleam", 587).
?DOC(false).
-spec multiline_inline_body(list(greenwood:node_(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
multiline_inline_body(Kvs) ->
    gleam@list:index_map(
        Kvs,
        fun(Kv, I) ->
            Children = begin
                _pipe = erlang:element(3, Kv),
                _pipe@1 = ensure_trailing_newline(_pipe),
                insert_comma_before_trailing(_pipe@1)
            end,
            Leading = case I of
                0 ->
                    [{token, newline, <<""/utf8>>}];

                _ ->
                    []
            end,
            {node_element,
                {node,
                    erlang:element(2, Kv),
                    Children,
                    {trivia, Leading, greenwood:trailing_trivia(Kv)}}}
        end
    ).

-file("src/molt/internal/cst/elements.gleam", 612).
?DOC(false).
-spec strip_kv_to_inline(greenwood:node_(molt@types:toml_kind())) -> greenwood:node_(molt@types:toml_kind()).
strip_kv_to_inline(Kv) ->
    Children = gleam@list:filter(erlang:element(3, Kv), fun(El) -> case El of
                {token_element, {token, newline, _}} ->
                    false;

                _ ->
                    true
            end end),
    {node, erlang:element(2, Kv), Children, bare}.

-file("src/molt/internal/cst/elements.gleam", 573).
?DOC(false).
-spec with_trailing_separator(
    greenwood:node_(molt@types:toml_kind()),
    boolean()
) -> greenwood:node_(molt@types:toml_kind()).
with_trailing_separator(Node, Needs_comma) ->
    gleam@bool:guard(
        not Needs_comma,
        Node,
        fun() ->
            {node,
                erlang:element(2, Node),
                lists:append(
                    erlang:element(3, Node),
                    [{token_element, {token, comma, <<""/utf8>>}},
                        {token_element, {token, whitespace, <<" "/utf8>>}}]
                ),
                erlang:element(4, Node)}
        end
    ).

-file("src/molt/internal/cst/elements.gleam", 559).
?DOC(false).
-spec single_line_inline_body(list(greenwood:node_(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
single_line_inline_body(Kvs) ->
    Space = {token_element, {token, whitespace, <<" "/utf8>>}},
    Last = erlang:length(Kvs) - 1,
    Entries = gleam@list:index_map(
        Kvs,
        fun(Kv, I) ->
            {node_element,
                with_trailing_separator(strip_kv_to_inline(Kv), I < Last)}
        end
    ),
    lists:append([[Space], Entries, [Space]]).

-file("src/molt/internal/cst/elements.gleam", 694).
?DOC(false).
-spec kv_has_comment(greenwood:node_(molt@types:toml_kind())) -> boolean().
kv_has_comment(Kv) ->
    gleam@list:any(erlang:element(3, Kv), fun(El) -> case El of
                {token_element, {token, comment, _}} ->
                    true;

                _ ->
                    false
            end end) orelse case erlang:element(4, Kv) of
        {trivia, L, T} ->
            gleam@list:any(
                lists:append(L, T),
                fun(Tok) -> erlang:element(2, Tok) =:= comment end
            );

        bare ->
            false
    end.

-file("src/molt/internal/cst/elements.gleam", 435).
?DOC(false).
-spec section_kvs_to_inline_table(list(greenwood:node_(molt@types:toml_kind()))) -> greenwood:node_(molt@types:toml_kind()).
section_kvs_to_inline_table(Kvs) ->
    Body = case Kvs of
        [] ->
            [];

        _ ->
            case gleam@list:any(Kvs, fun kv_has_comment/1) of
                false ->
                    single_line_inline_body(Kvs);

                true ->
                    multiline_inline_body(Kvs)
            end
    end,
    {node,
        inline_table,
        lists:append(
            [[{token_element, {token, left_brace, <<""/utf8>>}}],
                Body,
                [{token_element, {token, right_brace, <<""/utf8>>}}]]
        ),
        bare}.

-file("src/molt/internal/cst/elements.gleam", 461).
?DOC(false).
-spec inline_tables_to_array(list(greenwood:node_(molt@types:toml_kind()))) -> greenwood:node_(molt@types:toml_kind()).
inline_tables_to_array(Tables) ->
    Last = erlang:length(Tables) - 1,
    Items = gleam@list:index_map(
        Tables,
        fun(T, I) ->
            {node_element,
                with_trailing_separator(
                    build_array_item({node_element, T}, single_line),
                    I < Last
                )}
        end
    ),
    {node,
        array,
        lists:append(
            [[{token_element, {token, left_bracket, <<""/utf8>>}}],
                Items,
                [{token_element, {token, right_bracket, <<""/utf8>>}}]]
        ),
        bare}.

-file("src/molt/internal/cst/elements.gleam", 526).
?DOC(false).
-spec multiline_array_element(
    greenwood:node_(molt@types:toml_kind()),
    list(binary()),
    gleam@option:option(binary()),
    boolean()
) -> greenwood:node_(molt@types:toml_kind()).
multiline_array_element(Table, Leading, Trailing, Needs_comma) ->
    Newline = {token, newline, <<""/utf8>>},
    Indent = {token, whitespace, <<"  "/utf8>>},
    Leading_trivia = lists:append(
        [[Newline, Indent],
            gleam@list:flat_map(
                Leading,
                fun(C) -> [{token, comment, C}, Newline, Indent] end
            )]
    ),
    Comma = case Needs_comma of
        true ->
            [{token_element, {token, comma, <<","/utf8>>}}];

        false ->
            []
    end,
    Trailing_tokens = case Trailing of
        {some, C@1} ->
            [{token_element, {token, whitespace, <<" "/utf8>>}},
                {token_element, {token, comment, C@1}}];

        none ->
            []
    end,
    {node,
        array_element,
        lists:append([[{node_element, Table}], Comma, Trailing_tokens]),
        {trivia, Leading_trivia, []}}.

-file("src/molt/internal/cst/elements.gleam", 494).
?DOC(false).
-spec inline_tables_to_multiline_array(
    list(greenwood:node_(molt@types:toml_kind())),
    list({list(binary()), gleam@option:option(binary())})
) -> greenwood:node_(molt@types:toml_kind()).
inline_tables_to_multiline_array(Tables, Comments) ->
    Last = erlang:length(Tables) - 1,
    Items = gleam@list:index_map(
        gleam@list:zip(Tables, Comments),
        fun(Pair, I) ->
            {Table, {Leading, Trailing}} = Pair,
            {node_element,
                multiline_array_element(Table, Leading, Trailing, I < Last)}
        end
    ),
    {node,
        array,
        lists:append(
            [[{token_element, {token, left_bracket, <<"["/utf8>>}}],
                Items,
                [{token_element, {token, newline, <<""/utf8>>}},
                    {token_element, {token, right_bracket, <<"]"/utf8>>}}]]
        ),
        bare}.

-file("src/molt/internal/cst/elements.gleam", 655).
?DOC(false).
-spec insert_before_first_newline(
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind())),
    list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
insert_before_first_newline(Els, Extra, Acc) ->
    case Els of
        [] ->
            lists:append(lists:reverse(Acc), Extra);

        [First | Rest] ->
            case First of
                {token_element, {token, newline, _}} ->
                    lists:append(
                        lists:reverse(Acc),
                        lists:append(Extra, [First | Rest])
                    );

                _ ->
                    insert_before_first_newline(Rest, Extra, [First | Acc])
            end
    end.

-file("src/molt/internal/cst/elements.gleam", 632).
?DOC(false).
-spec inline_trailing_trivia(greenwood:node_(molt@types:toml_kind())) -> greenwood:node_(molt@types:toml_kind()).
inline_trailing_trivia(Node) ->
    Children = gleam@list:map(erlang:element(3, Node), fun(El) -> case El of
                {node_element, N} ->
                    {node_element, inline_trailing_trivia(N)};

                {token_element, _} ->
                    El
            end end),
    case erlang:element(4, Node) of
        {trivia, Leading, Trailing} when Trailing =/= [] ->
            {node,
                erlang:element(2, Node),
                insert_before_first_newline(
                    Children,
                    gleam@list:map(
                        Trailing,
                        fun(Field@0) -> {token_element, Field@0} end
                    ),
                    []
                ),
                {trivia, Leading, []}};

        _ ->
            {node, erlang:element(2, Node), Children, erlang:element(4, Node)}
    end.

-file("src/molt/internal/cst/elements.gleam", 823).
?DOC(false).
-spec value_tokens_with_equals(list(greenwood:element(molt@types:toml_kind()))) -> list(greenwood:element(molt@types:toml_kind())).
value_tokens_with_equals(Children) ->
    case Children of
        [] ->
            [];

        [{token_element, {token, equals, _}} | _] ->
            Children;

        [_ | Rest] ->
            value_tokens_with_equals(Rest)
    end.

-file("src/molt/internal/cst/elements.gleam", 711).
?DOC(false).
-spec rewrite_kv_key_in_place(
    greenwood:node_(molt@types:toml_kind()),
    list(binary())
) -> greenwood:node_(molt@types:toml_kind()).
rewrite_kv_key_in_place(Kv, New_key) ->
    After_key = value_tokens_with_equals(erlang:element(3, Kv)),
    Key_elements = case New_key of
        [Single] ->
            [{token_element, molt@internal@utils:make_key_token(Single)}];

        _ ->
            [{node_element,
                    greenwood:node(
                        key,
                        molt@internal@cst@builder:build_key_tokens(New_key)
                    )}]
    end,
    Children = lists:append(
        [Key_elements,
            [{token_element, {token, whitespace, <<" "/utf8>>}}],
            After_key]
    ),
    {node, erlang:element(2, Kv), Children, erlang:element(4, Kv)}.