src/gleedoc@parse.erl

-module(gleedoc@parse).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleedoc/parse.gleam").
-export([extract_code_blocks/1, gleam_blocks/1]).
-export_type([code_block/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.

-type code_block() :: {code_block,
        binary(),
        binary(),
        gleedoc@extract:doc_block(),
        integer(),
        list(binary())}.

-file("src/gleedoc/parse.gleam", 76).
?DOC(" Extract import statements from code and return them separately.\n").
-spec extract_imports(binary()) -> {list(binary()), binary()}.
extract_imports(Code) ->
    {Imports, Rest} = begin
        _pipe = Code,
        _pipe@1 = gleam@string:split(_pipe, <<"\n"/utf8>>),
        _pipe@2 = gleam@list:map(
            _pipe@1,
            fun(Line) -> {gleam@string:trim(Line), Line} end
        ),
        gleam@list:partition(
            _pipe@2,
            fun(Pair) ->
                gleam_stdlib:string_starts_with(
                    erlang:element(1, Pair),
                    <<"import "/utf8>>
                )
            end
        )
    end,
    {begin
            _pipe@3 = Imports,
            gleam@list:map(
                _pipe@3,
                fun(Pair@1) -> erlang:element(1, Pair@1) end
            )
        end,
        begin
            _pipe@4 = Rest,
            _pipe@5 = gleam@list:map(
                _pipe@4,
                fun(Pair@2) -> erlang:element(2, Pair@2) end
            ),
            gleam@string:join(_pipe@5, <<"\n"/utf8>>)
        end}.

-file("src/gleedoc/parse.gleam", 58).
-spec build_block(
    binary(),
    list(binary()),
    integer(),
    gleedoc@extract:doc_block()
) -> code_block().
build_block(Lang, Code_lines, Start, Doc) ->
    Code = begin
        _pipe = lists:reverse(Code_lines),
        gleam@string:join(_pipe, <<"\n"/utf8>>)
    end,
    {Imports, Code@1} = extract_imports(Code),
    {code_block, Lang, Code@1, Doc, Start, Imports}.

-file("src/gleedoc/parse.gleam", 27).
-spec extract_code_blocks_from_doc(gleedoc@extract:doc_block()) -> list(code_block()).
extract_code_blocks_from_doc(Doc) ->
    {Accumulated@1, Current@1} = gleam@list:index_fold(
        erlang:element(2, Doc),
        {[], none},
        fun(State, Line, Line_no) ->
            {Accumulated, Current} = State,
            Trimmed = gleam@string:trim(Line),
            case {Current, Trimmed} of
                {none, <<"```"/utf8, Rest/binary>>} ->
                    Lang = gleam@string:trim(Rest),
                    {Accumulated, {some, {Lang, [], Line_no + 1}}};

                {none, _} ->
                    State;

                {{some, {Lang@1, Code_lines, Start}}, <<"```"/utf8>>} ->
                    {[build_block(Lang@1, Code_lines, Start, Doc) | Accumulated],
                        none};

                {{some, {Lang@2, Code_lines@1, Start@1}}, _} ->
                    {Accumulated,
                        {some, {Lang@2, [Line | Code_lines@1], Start@1}}}
            end
        end
    ),
    Final_accumulated = case Current@1 of
        {some, {Lang@3, Code_lines@2, Start@2}} ->
            [build_block(Lang@3, Code_lines@2, Start@2, Doc) | Accumulated@1];

        none ->
            Accumulated@1
    end,
    lists:reverse(Final_accumulated).

-file("src/gleedoc/parse.gleam", 23).
?DOC(" Extract all fenced code blocks from a list of doc blocks.\n").
-spec extract_code_blocks(list(gleedoc@extract:doc_block())) -> list(code_block()).
extract_code_blocks(Doc_blocks) ->
    _pipe = Doc_blocks,
    gleam@list:flat_map(_pipe, fun extract_code_blocks_from_doc/1).

-file("src/gleedoc/parse.gleam", 90).
?DOC(" Filter code blocks to only those tagged as `gleam`.\n").
-spec gleam_blocks(list(code_block())) -> list(code_block()).
gleam_blocks(Blocks) ->
    gleam@list:filter(
        Blocks,
        fun(B) ->
            string:lowercase(erlang:element(2, B)) =:= <<"gleam"/utf8>>
        end
    ).