Skip to main content

src/internal@module.erl

-module(internal@module).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/internal/module.gleam").
-export([change_to_string/1, error_to_string/1, adjust/3]).
-export_type([module_change/0, module_error/0]).

-type module_change() :: {added, binary()} | {updated, binary()}.

-type module_error() :: {module_is_not_a_file_error, binary()} |
    {cannot_read_module, binary(), simplifile:file_error()} |
    {cannot_write_module, binary(), simplifile:file_error()} |
    {cannot_format_error, binary(), {integer(), binary()}}.

-file("src/internal/module.gleam", 37).
-spec change_to_string(module_change()) -> binary().
change_to_string(Change) ->
    case Change of
        {added, Filename} ->
            <<"added to "/utf8, Filename/binary>>;

        {updated, Filename@1} ->
            <<"updated in "/utf8, Filename@1/binary>>
    end.

-file("src/internal/module.gleam", 44).
-spec error_to_string(module_error()) -> binary().
error_to_string(Error) ->
    case Error of
        {module_is_not_a_file_error, Filename} ->
            <<<<"Module '"/utf8, Filename/binary>>/binary,
                "' exists but is not a file"/utf8>>;

        {cannot_read_module, Filename@1, Error@1} ->
            <<<<<<"Cannot read '"/utf8, Filename@1/binary>>/binary, "', "/utf8>>/binary,
                (simplifile:describe_error(Error@1))/binary>>;

        {cannot_write_module, Filename@2, Error@2} ->
            <<<<<<"Cannot write '"/utf8, Filename@2/binary>>/binary,
                    "', "/utf8>>/binary,
                (simplifile:describe_error(Error@2))/binary>>;

        {cannot_format_error, Filename@3, {_, Error@3}} ->
            <<<<<<"Cannot format '"/utf8, Filename@3/binary>>/binary,
                    "', "/utf8>>/binary,
                Error@3/binary>>
    end.

-file("src/internal/module.gleam", 84).
-spec format_module(binary()) -> {ok, nil} | {error, module_error()}.
format_module(Filename) ->
    _pipe = shellout:command(
        <<"gleam"/utf8>>,
        [<<"format"/utf8>>, Filename],
        <<"."/utf8>>,
        []
    ),
    _pipe@1 = gleam@result:replace(_pipe, nil),
    gleam@result:map_error(
        _pipe@1,
        fun(_capture) -> {cannot_format_error, Filename, _capture} end
    ).

-file("src/internal/module.gleam", 157).
-spec normalize(binary()) -> binary().
normalize(Fn_name) ->
    Normalized_name = begin
        _pipe = Fn_name,
        _pipe@1 = string:lowercase(_pipe),
        _pipe@2 = gleam@string:split(_pipe@1, <<""/utf8>>),
        _pipe@3 = gleam@list:map(_pipe@2, fun(Char) -> case Char of
                    <<"a"/utf8>> ->
                        Char;

                    <<"b"/utf8>> ->
                        Char;

                    <<"c"/utf8>> ->
                        Char;

                    <<"d"/utf8>> ->
                        Char;

                    <<"e"/utf8>> ->
                        Char;

                    <<"f"/utf8>> ->
                        Char;

                    <<"g"/utf8>> ->
                        Char;

                    <<"h"/utf8>> ->
                        Char;

                    <<"i"/utf8>> ->
                        Char;

                    <<"j"/utf8>> ->
                        Char;

                    <<"k"/utf8>> ->
                        Char;

                    <<"l"/utf8>> ->
                        Char;

                    <<"m"/utf8>> ->
                        Char;

                    <<"n"/utf8>> ->
                        Char;

                    <<"o"/utf8>> ->
                        Char;

                    <<"p"/utf8>> ->
                        Char;

                    <<"q"/utf8>> ->
                        Char;

                    <<"r"/utf8>> ->
                        Char;

                    <<"s"/utf8>> ->
                        Char;

                    <<"t"/utf8>> ->
                        Char;

                    <<"u"/utf8>> ->
                        Char;

                    <<"v"/utf8>> ->
                        Char;

                    <<"w"/utf8>> ->
                        Char;

                    <<"x"/utf8>> ->
                        Char;

                    <<"y"/utf8>> ->
                        Char;

                    <<"z"/utf8>> ->
                        Char;

                    _ ->
                        <<"_"/utf8>>
                end end),
        gleam@string:join(_pipe@3, <<""/utf8>>)
    end,
    case Normalized_name of
        <<"as"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"assert"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"auto"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"case"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"delegate"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"derive"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"echo"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"else"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"fn"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"if"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"implement"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"import"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"let"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"macro"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"opaque"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"panic"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"pub"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"test"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"todo"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"type"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        <<"use"/utf8>> ->
            <<Normalized_name/binary, "_"/utf8>>;

        _ ->
            Normalized_name
    end.

-file("src/internal/module.gleam", 136).
-spec split_module(binary(), list(binary())) -> {list(binary()),
    list(binary()),
    list(binary()),
    list(binary())}.
split_module(Fn_name, Content) ->
    {Rest, Epilogue} = gleam@list:split_while(
        Content,
        fun(Line) ->
            not gleam_stdlib:string_starts_with(
                Line,
                <<"fn add_defaults("/utf8>>
            )
        end
    ),
    {Before_function, Rest@1} = gleam@list:split_while(
        Rest,
        fun(Line@1) ->
            not gleam_stdlib:string_starts_with(
                Line@1,
                <<<<"pub fn "/utf8, Fn_name/binary>>/binary, "("/utf8>>
            )
        end
    ),
    {Function, After_function} = gleam@list:split_while(
        Rest@1,
        fun(Line@2) ->
            not gleam_stdlib:string_starts_with(Line@2, <<"pub fn"/utf8>>)
            orelse gleam_stdlib:string_starts_with(
                Line@2,
                <<<<"pub fn "/utf8, Fn_name/binary>>/binary, "("/utf8>>
            )
        end
    ),
    {Before_function, Function, After_function, Epilogue}.

-file("src/internal/module.gleam", 126).
-spec read_lines(binary()) -> {ok, list(binary())} |
    {error, simplifile:file_error()}.
read_lines(Filename) ->
    _pipe = Filename,
    _pipe@1 = simplifile:read(_pipe),
    gleam@result:map(_pipe@1, fun(Content) -> _pipe@2 = Content,
            _pipe@3 = gleam@string:split(_pipe@2, <<"\n"/utf8>>),
            gleam@list:map(_pipe@3, fun gleam@string:trim_end/1) end).

-file("src/internal/module.gleam", 90).
-spec update_module(binary(), binary(), binary()) -> {ok, module_change()} |
    {error, module_error()}.
update_module(Fn_body, Fn_name, Filename) ->
    _pipe = Filename,
    _pipe@1 = read_lines(_pipe),
    _pipe@2 = gleam@result:map_error(
        _pipe@1,
        fun(_capture) -> {cannot_read_module, Filename, _capture} end
    ),
    _pipe@3 = gleam@result:map(
        _pipe@2,
        fun(_capture@1) -> split_module(Fn_name, _capture@1) end
    ),
    gleam@result:'try'(
        _pipe@3,
        fun(Split) ->
            {Before_function, Function, After_function, Epilogue} = Split,
            _pipe@4 = [Before_function,
                [<<<<"pub fn "/utf8, Fn_name/binary>>/binary,
                        "(attributes: List(Attribute(msg))) -> Element(msg) {"/utf8>>,
                    Fn_body,
                    <<"}"/utf8>>],
                After_function,
                Epilogue],
            _pipe@5 = lists:append(_pipe@4),
            _pipe@6 = gleam@string:join(_pipe@5, <<"\n"/utf8>>),
            _pipe@7 = simplifile:write(Filename, _pipe@6),
            _pipe@8 = gleam@result:map_error(
                _pipe@7,
                fun(_capture@2) ->
                    {cannot_write_module, Filename, _capture@2}
                end
            ),
            gleam@result:map(_pipe@8, fun(_) -> case Function of
                        [] ->
                            {added, Filename};

                        _ ->
                            {updated, Filename}
                    end end)
        end
    ).

-file("src/internal/module.gleam", 71).
-spec ensure_module(binary()) -> {ok, nil} | {error, module_error()}.
ensure_module(Filename) ->
    case simplifile_erl:file_info(Filename) of
        {ok, Info} ->
            case simplifile:file_info_type(Info) of
                file ->
                    {ok, nil};

                _ ->
                    {error, {module_is_not_a_file_error, Filename}}
            end;

        {error, _} ->
            _pipe = simplifile:write(
                Filename,
                <<"// This file is auto-generated by iconify_lustre.

import gleam/list
import lustre/attribute.{type Attribute, attribute}
import lustre/element.{type Element}
import lustre/element/svg

fn add_defaults(attributes: List(Attribute(msg)),
  defaults: List(Attribute(msg)),
) -> List(Attribute(msg)) {
  list.fold(defaults, attributes, fn(accumulator, default) {
    case list.any(accumulator, fn(item) { item.name == default.name }) {
      False -> [default, ..accumulator]
      True -> accumulator
    }
  })
}"/utf8>>
            ),
            gleam@result:map_error(
                _pipe,
                fun(_capture) -> {cannot_write_module, Filename, _capture} end
            )
    end.

-file("src/internal/module.gleam", 60).
-spec adjust(binary(), binary(), binary()) -> {ok, module_change()} |
    {error, module_error()}.
adjust(Filename, Fn_name, Fn_body) ->
    _pipe = ensure_module(Filename),
    _pipe@1 = gleam@result:'try'(_pipe, fun(_) -> format_module(Filename) end),
    _pipe@2 = gleam@result:'try'(
        _pipe@1,
        fun(_) -> update_module(Fn_body, normalize(Fn_name), Filename) end
    ),
    gleam@result:'try'(
        _pipe@2,
        fun(Result) -> _pipe@3 = format_module(Filename),
            gleam@result:replace(_pipe@3, Result) end
    ).