-module(molt@internal@cst@insert).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/molt/internal/cst/insert.gleam").
-export([place/4, table_ordered/3, ensure_table/2, ensure_array_of_tables/2]).
-export_type([placement/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 placement() :: kv_region_end |
{before_kv_key, binary()} |
{family_scope_end, list(binary())} |
{before_family_index, list(binary()), integer()}.
-file("src/molt/internal/cst/insert.gleam", 147).
?DOC(false).
-spec do_insert_before_index(
list(greenwood:element(molt@types:toml_kind())),
list(binary()),
integer(),
greenwood:node_(molt@types:toml_kind()),
integer(),
list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
do_insert_before_index(Children, Segments, Index, Entry, Current, Acc) ->
case Children of
[] ->
lists:reverse([{node_element, Entry} | Acc]);
[{node_element, N} = El | Rest] when erlang:element(2, N) =:= array_of_tables ->
case molt@internal@cst@elements:extract_key_segments(
erlang:element(3, N)
)
=:= Segments of
true when Current =:= Index ->
lists:append(
lists:reverse(Acc),
[{node_element, Entry}, El | Rest]
);
true ->
do_insert_before_index(
Rest,
Segments,
Index,
Entry,
Current + 1,
[El | Acc]
);
false ->
do_insert_before_index(
Rest,
Segments,
Index,
Entry,
Current,
[El | Acc]
)
end;
[El@1 | Rest@1] ->
do_insert_before_index(
Rest@1,
Segments,
Index,
Entry,
Current,
[El@1 | Acc]
)
end.
-file("src/molt/internal/cst/insert.gleam", 291).
?DOC(false).
-spec do_insert_after_path_scope(
list(greenwood:element(molt@types:toml_kind())),
greenwood:node_(molt@types:toml_kind()),
list(binary()),
boolean(),
list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
do_insert_after_path_scope(Children, New_header, Prefix, Saw_in_scope, Acc) ->
case Children of
[] ->
lists:reverse([{node_element, New_header} | Acc]);
[{node_element, N} = El | Rest] when (erlang:element(2, N) =:= table) orelse (erlang:element(
2,
N
) =:= array_of_tables) ->
Header_path = molt@internal@cst@elements:extract_key_segments(
erlang:element(3, N)
),
case gleam@list:take(Header_path, erlang:length(Prefix)) =:= Prefix of
true ->
do_insert_after_path_scope(
Rest,
New_header,
Prefix,
true,
[El | Acc]
);
false ->
case Saw_in_scope of
true ->
_pipe = lists:reverse(
[{node_element, New_header} | Acc]
),
lists:append(_pipe, [El | Rest]);
false ->
do_insert_after_path_scope(
Rest,
New_header,
Prefix,
false,
[El | Acc]
)
end
end;
[El@1 | Rest@1] ->
do_insert_after_path_scope(
Rest@1,
New_header,
Prefix,
Saw_in_scope,
[El@1 | Acc]
)
end.
-file("src/molt/internal/cst/insert.gleam", 277).
?DOC(false).
-spec insert_after_path_scope(
list(greenwood:element(molt@types:toml_kind())),
greenwood:node_(molt@types:toml_kind()),
list(binary())
) -> list(greenwood:element(molt@types:toml_kind())).
insert_after_path_scope(Children, New_header, Prefix) ->
do_insert_after_path_scope(Children, New_header, Prefix, false, []).
-file("src/molt/internal/cst/insert.gleam", 128).
?DOC(false).
-spec do_insert_before_key(
list(greenwood:element(molt@types:toml_kind())),
binary(),
greenwood:node_(molt@types:toml_kind()),
list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
do_insert_before_key(Children, Before, Kv, Acc) ->
case Children of
[] ->
lists:reverse([{node_element, Kv} | Acc]);
[{node_element, N} = El | Rest] when erlang:element(2, N) =:= key_value ->
case molt@internal@cst@elements:key_name(erlang:element(3, N)) =:= {some,
Before} of
true ->
lists:append(
lists:reverse(Acc),
[{node_element, Kv}, El | Rest]
);
false ->
do_insert_before_key(Rest, Before, Kv, [El | Acc])
end;
[El@1 | Rest@1] ->
do_insert_before_key(Rest@1, Before, Kv, [El@1 | Acc])
end.
-file("src/molt/internal/cst/insert.gleam", 192).
?DOC(false).
-spec insert_after_last_kv(
list(greenwood:element(molt@types:toml_kind())),
greenwood:node_(molt@types:toml_kind()),
list(greenwood:element(molt@types:toml_kind()))
) -> list(greenwood:element(molt@types:toml_kind())).
insert_after_last_kv(Children, Kv, Acc) ->
case Children of
[] ->
lists:reverse([{node_element, Kv} | Acc]);
[{node_element, N} = El | Rest] when (erlang:element(2, N) =:= table) orelse (erlang:element(
2,
N
) =:= array_of_tables) ->
lists:append(lists:reverse([{node_element, Kv} | Acc]), [El | Rest]);
[El@1 | Rest@1] ->
insert_after_last_kv(Rest@1, Kv, [El@1 | Acc])
end.
-file("src/molt/internal/cst/insert.gleam", 83).
?DOC(false).
-spec do_insert_kv_in_placement(
greenwood:node_(molt@types:toml_kind()),
greenwood:node_(molt@types:toml_kind()),
placement()
) -> greenwood:node_(molt@types:toml_kind()).
do_insert_kv_in_placement(Container, New, At) ->
case At of
kv_region_end ->
Children = insert_after_last_kv(
erlang:element(3, Container),
New,
[]
),
{node,
erlang:element(2, Container),
Children,
erlang:element(4, Container)};
{before_kv_key, Key} ->
Children@1 = do_insert_before_key(
erlang:element(3, Container),
Key,
New,
[]
),
{node,
erlang:element(2, Container),
Children@1,
erlang:element(4, Container)};
{family_scope_end, Family} ->
New_children = insert_after_path_scope(
erlang:element(3, Container),
New,
Family
),
{node,
erlang:element(2, Container),
New_children,
erlang:element(4, Container)};
{before_family_index, Family@1, Index} ->
Children@2 = do_insert_before_index(
erlang:element(3, Container),
Family@1,
Index,
New,
0,
[]
),
{node,
erlang:element(2, Container),
Children@2,
erlang:element(4, Container)}
end.
-file("src/molt/internal/cst/insert.gleam", 32).
?DOC(false).
-spec place(
greenwood:node_(molt@types:toml_kind()),
list(molt@types:path_segment()),
greenwood:node_(molt@types:toml_kind()),
placement()
) -> {ok, greenwood:node_(molt@types:toml_kind())} |
{error, molt@error:molt_error()}.
place(Node, Container, New, At) ->
case Container of
[] ->
{ok, do_insert_kv_in_placement(Node, New, At)};
_ ->
gleam@result:'try'(
molt@internal@cst@query:get_cursor(Node, Container),
fun(Cursor) ->
case erlang:element(2, erlang:element(2, Cursor)) of
root ->
_pipe = greenwood@zipper:map_focus(
Cursor,
fun(_capture) ->
do_insert_kv_in_placement(_capture, New, At)
end
),
_pipe@1 = greenwood@zipper:unzip(_pipe),
{ok, _pipe@1};
table ->
_pipe = greenwood@zipper:map_focus(
Cursor,
fun(_capture) ->
do_insert_kv_in_placement(_capture, New, At)
end
),
_pipe@1 = greenwood@zipper:unzip(_pipe),
{ok, _pipe@1};
array_of_tables ->
_pipe = greenwood@zipper:map_focus(
Cursor,
fun(_capture) ->
do_insert_kv_in_placement(_capture, New, At)
end
),
_pipe@1 = greenwood@zipper:unzip(_pipe),
{ok, _pipe@1};
_ ->
{error,
{type_mismatch,
none,
<<"table-node"/utf8>>,
molt@internal@utils:toml_kind(
erlang:element(
2,
erlang:element(2, Cursor)
)
)}}
end
end
)
end.
-file("src/molt/internal/cst/insert.gleam", 363).
?DOC(false).
-spec is_child_path(list(binary()), list(binary())) -> boolean().
is_child_path(Parent, Child) ->
case {Parent, Child} of
{[], [_ | _]} ->
true;
{[P | Prest], [C | Crest]} when P =:= C ->
is_child_path(Prest, Crest);
{_, _} ->
false
end.
-file("src/molt/internal/cst/insert.gleam", 340).
?DOC(false).
-spec table_path(greenwood:node_(molt@types:toml_kind())) -> {ok,
list(binary())} |
{error, nil}.
table_path(Node) ->
case erlang:element(2, Node) of
table ->
{ok,
molt@internal@cst@elements:extract_key_segments(
erlang:element(3, Node)
)};
array_of_tables ->
{ok,
molt@internal@cst@elements:extract_key_segments(
erlang:element(3, Node)
)};
_ ->
{error, nil}
end.
-file("src/molt/internal/cst/insert.gleam", 355).
?DOC(false).
-spec in_parent_family(greenwood:node_(molt@types:toml_kind()), list(binary())) -> boolean().
in_parent_family(Node, Parent) ->
case table_path(Node) of
{ok, P} ->
(P =:= Parent) orelse is_child_path(Parent, P);
_ ->
false
end.
-file("src/molt/internal/cst/insert.gleam", 348).
?DOC(false).
-spec is_descendant_table(
greenwood:node_(molt@types:toml_kind()),
list(binary())
) -> boolean().
is_descendant_table(Node, Parent) ->
case table_path(Node) of
{ok, P} ->
is_child_path(Parent, P);
_ ->
false
end.
-file("src/molt/internal/cst/insert.gleam", 211).
?DOC(false).
-spec table_ordered(
greenwood:node_(molt@types:toml_kind()),
greenwood:node_(molt@types:toml_kind()),
list(binary())
) -> greenwood:node_(molt@types:toml_kind()).
table_ordered(Node, New_table, Segments) ->
Parent_path = gleam@list:take(Segments, erlang:length(Segments) - 1),
Append = fun(Into) ->
Table = case erlang:element(3, Into) of
[] ->
molt@internal@cst@builder:drop_leading_newlines(New_table);
_ ->
molt@internal@cst@builder:ensure_leading_newline(New_table)
end,
greenwood:append_child(Into, {node_element, Table})
end,
case greenwood@zipper:down_where(
greenwood@zipper:zip(Node),
fun(_capture) -> is_descendant_table(_capture, Segments) end
) of
{some, Cursor} ->
Table@1 = case greenwood@zipper:left(Cursor) of
none ->
molt@internal@cst@builder:drop_leading_newlines(New_table);
{some, _} ->
molt@internal@cst@builder:ensure_leading_newline(New_table)
end,
_pipe = greenwood@zipper:insert_left(
Cursor,
{node_element, Table@1}
),
_pipe@1 = gleam@option:map(_pipe, fun greenwood@zipper:unzip/1),
gleam@option:unwrap(_pipe@1, Node);
none ->
case Parent_path of
[_ | _] ->
case greenwood@zipper:down_last_where(
greenwood@zipper:zip(Node),
fun(_capture@1) ->
in_parent_family(_capture@1, Parent_path)
end
) of
{some, Cursor@1} ->
_pipe@2 = greenwood@zipper:insert_right(
Cursor@1,
{node_element,
molt@internal@cst@builder:ensure_leading_newline(
New_table
)}
),
_pipe@3 = gleam@option:map(
_pipe@2,
fun greenwood@zipper:unzip/1
),
gleam@option:unwrap(_pipe@3, Node);
none ->
Append(Node)
end;
[] ->
Append(Node)
end
end.
-file("src/molt/internal/cst/insert.gleam", 63).
?DOC(false).
-spec ensure_table(greenwood:node_(molt@types:toml_kind()), list(binary())) -> greenwood:node_(molt@types:toml_kind()).
ensure_table(Node, Path) ->
New_table = molt@internal@cst@builder:build_empty_table(Path),
table_ordered(Node, New_table, Path).
-file("src/molt/internal/cst/insert.gleam", 73).
?DOC(false).
-spec ensure_array_of_tables(
greenwood:node_(molt@types:toml_kind()),
list(binary())
) -> greenwood:node_(molt@types:toml_kind()).
ensure_array_of_tables(Node, Path) ->
New_table = molt@internal@cst@builder:build_empty_array_of_tables(Path),
table_ordered(Node, New_table, Path).