src/gleamdoc.erl
-module(gleamdoc).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleamdoc.gleam").
-export([main/0]).
-export_type([format/0, scope/0, action/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(" Command-line entrypoint for Gleamdoc.\n").
-type format() :: text | json.
-type scope() :: {scope, gleam@option:option(binary()), boolean()}.
-type action() :: {lookup, binary(), format(), scope()} |
{search, binary(), format(), scope(), integer(), binary(), binary()} |
{packages, format(), boolean()} |
{index, format(), scope()}.
-file("src/gleamdoc.gleam", 368).
-spec print(format(), binary(), gleam@json:json(), gleamdoc@output:style()) -> nil.
print(Format, Text, Json_value, Style) ->
case Format of
text ->
case gleamdoc_ffi:stdout_supports_color() of
true ->
_pipe = Text,
_pipe@1 = gleamdoc@output:text(_pipe, Style),
gleam_stdlib:println(_pipe@1);
false ->
gleam_stdlib:println(Text)
end;
json ->
_pipe@2 = Json_value,
_pipe@3 = gleam@json:to_string(_pipe@2),
gleam_stdlib:println(_pipe@3)
end.
-file("src/gleamdoc.gleam", 384).
-spec fail(format(), binary()) -> nil.
fail(Format, Message) ->
case Format of
text ->
case gleamdoc_ffi:stderr_supports_color() of
true ->
_pipe = Message,
_pipe@1 = gleamdoc@output:error(_pipe),
gleam_stdlib:println_error(_pipe@1);
false ->
gleam_stdlib:println_error(Message)
end;
json ->
_pipe@2 = gleam@json:object(
[{<<"schema_version"/utf8>>, gleam@json:int(1)},
{<<"error"/utf8>>, gleam@json:string(Message)},
{<<"results"/utf8>>, gleam@json:preprocessed_array([])}]
),
_pipe@3 = gleam@json:to_string(_pipe@2),
gleam_stdlib:println(_pipe@3)
end,
gleamdoc_ffi:exit_status(1).
-file("src/gleamdoc.gleam", 348).
-spec select_packages(list(gleam@package_interface:package()), scope()) -> list(gleam@package_interface:package()).
select_packages(Packages, Scope) ->
{scope, Package, Dependencies} = Scope,
Packages@1 = case Dependencies of
true ->
Packages;
false ->
gleam@list:take(Packages, 1)
end,
case Package of
none ->
Packages@1;
{some, Wanted} ->
_pipe = Packages@1,
gleam@list:filter(
_pipe,
fun(Package@1) ->
{package, Name, _, _, _} = Package@1,
Name =:= Wanted
end
)
end.
-file("src/gleamdoc.gleam", 333).
-spec scope_error(list(gleam@package_interface:package()), scope()) -> gleam@option:option(binary()).
scope_error(Packages, Scope) ->
{scope, Package, _} = Scope,
case Package of
none ->
none;
{some, Wanted} ->
case select_packages(Packages, Scope) of
[] ->
{some,
<<<<"Package `"/utf8, Wanted/binary>>/binary,
"` is not indexed in this scope."/utf8>>};
_ ->
none
end
end.
-file("src/gleamdoc.gleam", 257).
-spec execute_with_packages(action(), list(gleam@package_interface:package())) -> nil.
execute_with_packages(Action, All_packages) ->
case Action of
{lookup, Query, Format, Scope} ->
case scope_error(All_packages, Scope) of
{some, Message} ->
fail(Format, Message);
none ->
Packages = select_packages(All_packages, Scope),
case gleamdoc@interface:lookup_packages(Packages, Query) of
[] ->
fail(
Format,
<<<<"No public symbol found for `"/utf8,
Query/binary>>/binary,
"`."/utf8>>
);
Entries ->
print(
Format,
gleamdoc@interface:render_all(Entries),
gleamdoc@interface:entries_json(Entries),
documentation
)
end
end;
{search, Query@1, Format@1, Scope@1, Limit, Kind, Target} ->
case scope_error(All_packages, Scope@1) of
{some, Message@1} ->
fail(Format@1, Message@1);
none ->
Packages@1 = select_packages(All_packages, Scope@1),
case gleamdoc@interface:search_packages_filtered(
Packages@1,
Query@1,
Limit,
Kind,
Target
) of
[] ->
fail(
Format@1,
<<<<"No public symbols matched `"/utf8,
Query@1/binary>>/binary,
"`."/utf8>>
);
Entries@1 ->
print(
Format@1,
gleamdoc@interface:render_search_results(
Entries@1
),
gleamdoc@interface:entries_json(Entries@1),
search_results
)
end
end;
{packages, Format@2, Dependencies} ->
Packages@2 = case Dependencies of
true ->
All_packages;
false ->
gleam@list:take(All_packages, 1)
end,
print(
Format@2,
gleamdoc@interface:render_packages(Packages@2),
gleamdoc@interface:packages_json(Packages@2),
packages
);
{index, Format@3, _} ->
Packages@3 = All_packages,
print(
Format@3,
<<<<<<"Indexed "/utf8,
(erlang:integer_to_binary(erlang:length(Packages@3)))/binary>>/binary,
" package interfaces.\n\n"/utf8>>/binary,
(gleamdoc@interface:render_packages(Packages@3))/binary>>,
gleamdoc@interface:packages_json(Packages@3),
index_result
)
end.
-file("src/gleamdoc.gleam", 248).
-spec action_format(action()) -> format().
action_format(Action) ->
case Action of
{lookup, _, Format, _} ->
Format;
{search, _, Format@1, _, _, _, _} ->
Format@1;
{packages, Format@2, _} ->
Format@2;
{index, Format@3, _} ->
Format@3
end.
-file("src/gleamdoc.gleam", 429).
-spec load_package_file(binary()) -> {ok, gleam@package_interface:package()} |
{error, binary()}.
load_package_file(Path) ->
gleam@result:'try'(
begin
_pipe = simplifile:read(Path),
gleam@result:map_error(
_pipe,
fun(_) ->
<<<<"Could not read "/utf8, Path/binary>>/binary, "."/utf8>>
end
)
end,
fun(Source) ->
_pipe@1 = gleam@json:parse(
Source,
gleam@package_interface:decoder()
),
gleam@result:map_error(
_pipe@1,
fun(_) ->
<<<<"The generated package interface at "/utf8,
Path/binary>>/binary,
" was invalid."/utf8>>
end
)
end
).
-file("src/gleamdoc.gleam", 416).
-spec load_package_files(
list(binary()),
list(gleam@package_interface:package())
) -> {ok, list(gleam@package_interface:package())} | {error, binary()}.
load_package_files(Paths, Packages) ->
case Paths of
[] ->
{ok, lists:reverse(Packages)};
[Path | Rest] ->
gleam@result:'try'(
load_package_file(Path),
fun(Package) ->
load_package_files(Rest, [Package | Packages])
end
)
end.
-file("src/gleamdoc.gleam", 403).
-spec load_packages(scope(), boolean()) -> {ok,
list(gleam@package_interface:package())} |
{error, binary()}.
load_packages(Scope, Refresh) ->
{scope, Package, Dependencies} = Scope,
gleam@result:'try'(
gleamdoc@index:package_interface_paths(
Dependencies,
gleam@option:unwrap(Package, <<""/utf8>>),
Refresh
),
fun(Paths) -> load_package_files(Paths, []) end
).
-file("src/gleamdoc.gleam", 240).
-spec lookup_load_scope(scope(), binary()) -> scope().
lookup_load_scope(Scope, Query) ->
{scope, Package, Dependencies} = Scope,
case {Package, gleam@string:split_once(Query, <<":"/utf8>>)} of
{none, {ok, {Package@1, _}}} ->
{scope, {some, Package@1}, Dependencies};
{_, _} ->
Scope
end.
-file("src/gleamdoc.gleam", 228).
-spec load_options(action()) -> {scope(), boolean()}.
load_options(Action) ->
case Action of
{lookup, Query, _, Scope} ->
{lookup_load_scope(Scope, Query), false};
{search, _, _, Scope@1, _, _, _} ->
{Scope@1, false};
{packages, _, Dependencies} ->
{{scope, none, Dependencies}, false};
{index, _, Scope@2} ->
{Scope@2, true}
end.
-file("src/gleamdoc.gleam", 220).
-spec execute(action()) -> nil.
execute(Action) ->
{Scope, Refresh} = load_options(Action),
case load_packages(Scope, Refresh) of
{error, Message} ->
fail(action_format(Action), <<"error: "/utf8, Message/binary>>);
{ok, All_packages} ->
execute_with_packages(Action, All_packages)
end.
-file("src/gleamdoc.gleam", 213).
-spec optional_package(binary()) -> gleam@option:option(binary()).
optional_package(Package) ->
case gleam@string:trim(Package) of
<<""/utf8>> ->
none;
Package@1 ->
{some, Package@1}
end.
-file("src/gleamdoc.gleam", 206).
-spec output_format(boolean()) -> format().
output_format(Json) ->
case Json of
true ->
json;
false ->
text
end.
-file("src/gleamdoc.gleam", 158).
-spec no_deps_flag() -> glint:flag(boolean()).
no_deps_flag() ->
_pipe = glint:bool_flag(<<"no-deps"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, false),
glint:flag_help(_pipe@1, <<"Only inspect the current project."/utf8>>).
-file("src/gleamdoc.gleam", 152).
-spec package_flag() -> glint:flag(binary()).
package_flag() ->
_pipe = glint:string_flag(<<"package"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, <<""/utf8>>),
glint:flag_help(
_pipe@1,
<<"Restrict lookup or search to one package."/utf8>>
).
-file("src/gleamdoc.gleam", 146).
-spec json_flag() -> glint:flag(boolean()).
json_flag() ->
_pipe = glint:bool_flag(<<"json"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, false),
glint:flag_help(_pipe@1, <<"Emit machine-readable JSON."/utf8>>).
-file("src/gleamdoc.gleam", 127).
-spec index_command() -> glint:command(action()).
index_command() ->
glint:command_help(
<<"Generate package-interface caches used by lookup and search commands."/utf8>>,
fun() ->
glint:flag(
json_flag(),
fun(Json) ->
glint:flag(
package_flag(),
fun(Package) ->
glint:flag(
no_deps_flag(),
fun(No_deps) ->
glint:unnamed_args(
{eq_args, 0},
fun() ->
glint:command(
fun(_, _, Flags) ->
Json@2 = case Json(Flags) of
{ok, Json@1} -> Json@1;
_assert_fail ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"index_command"/utf8>>,
line => 136,
value => _assert_fail,
start => 3778,
'end' => 3811,
pattern_start => 3789,
pattern_end => 3797}
)
end,
Package@2 = case Package(
Flags
) of
{ok, Package@1} -> Package@1;
_assert_fail@1 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"index_command"/utf8>>,
line => 137,
value => _assert_fail@1,
start => 3814,
'end' => 3853,
pattern_start => 3825,
pattern_end => 3836}
)
end,
No_deps@2 = case No_deps(
Flags
) of
{ok, No_deps@1} -> No_deps@1;
_assert_fail@2 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"index_command"/utf8>>,
line => 138,
value => _assert_fail@2,
start => 3856,
'end' => 3895,
pattern_start => 3867,
pattern_end => 3878}
)
end,
{index,
output_format(Json@2),
{scope,
optional_package(
Package@2
),
not No_deps@2}}
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/gleamdoc.gleam", 115).
-spec packages_command() -> glint:command(action()).
packages_command() ->
glint:command_help(
<<"List indexed packages and module counts."/utf8>>,
fun() ->
glint:flag(
json_flag(),
fun(Json) ->
glint:flag(
no_deps_flag(),
fun(No_deps) ->
glint:unnamed_args(
{eq_args, 0},
fun() ->
glint:command(
fun(_, _, Flags) ->
Json@2 = case Json(Flags) of
{ok, Json@1} -> Json@1;
_assert_fail ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"packages_command"/utf8>>,
line => 121,
value => _assert_fail,
start => 3276,
'end' => 3309,
pattern_start => 3287,
pattern_end => 3295}
)
end,
No_deps@2 = case No_deps(Flags) of
{ok, No_deps@1} -> No_deps@1;
_assert_fail@1 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"packages_command"/utf8>>,
line => 122,
value => _assert_fail@1,
start => 3312,
'end' => 3351,
pattern_start => 3323,
pattern_end => 3334}
)
end,
{packages,
output_format(Json@2),
not No_deps@2}
end
)
end
)
end
)
end
)
end
).
-file("src/gleamdoc.gleam", 194).
-spec target_flag() -> glint:flag(binary()).
target_flag() ->
_pipe = glint:string_flag(<<"target"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, <<""/utf8>>),
_pipe@2 = glint:flag_constraint(
_pipe@1,
fun(Target) ->
case gleam@list:contains(
[<<""/utf8>>, <<"erlang"/utf8>>, <<"javascript"/utf8>>],
Target
) of
true ->
{ok, Target};
false ->
snag:error(<<"--target must be erlang or javascript"/utf8>>)
end
end
),
glint:flag_help(
_pipe@2,
<<"Restrict search to functions and constants for a target."/utf8>>
).
-file("src/gleamdoc.gleam", 176).
-spec kind_flag() -> glint:flag(binary()).
kind_flag() ->
_pipe = glint:string_flag(<<"kind"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, <<""/utf8>>),
_pipe@2 = glint:flag_constraint(
_pipe@1,
fun(Kind) ->
case gleam@list:contains(
[<<""/utf8>>,
<<"module"/utf8>>,
<<"fn"/utf8>>,
<<"const"/utf8>>,
<<"type"/utf8>>,
<<"variant"/utf8>>,
<<"alias"/utf8>>],
Kind
) of
true ->
{ok, Kind};
false ->
snag:error(
<<"--kind must be module, fn, const, type, variant, or alias"/utf8>>
)
end
end
),
glint:flag_help(_pipe@2, <<"Restrict search to one symbol kind."/utf8>>).
-file("src/gleamdoc.gleam", 164).
-spec limit_flag() -> glint:flag(integer()).
limit_flag() ->
_pipe = glint:int_flag(<<"limit"/utf8>>),
_pipe@1 = glint:flag_default(_pipe, 50),
_pipe@2 = glint:flag_constraint(_pipe@1, fun(Limit) -> case Limit > 0 of
true ->
{ok, Limit};
false ->
snag:error(<<"--limit must be greater than zero"/utf8>>)
end end),
glint:flag_help(_pipe@2, <<"Maximum number of search results."/utf8>>).
-file("src/gleamdoc.gleam", 86).
-spec search_command() -> glint:command(action()).
search_command() ->
glint:command_help(
<<"Search symbol names, modules, packages, signatures, and documentation."/utf8>>,
fun() ->
glint:flag(
json_flag(),
fun(Json) ->
glint:flag(
limit_flag(),
fun(Limit) ->
glint:flag(
kind_flag(),
fun(Kind) ->
glint:flag(
target_flag(),
fun(Target) ->
glint:flag(
package_flag(),
fun(Package) ->
glint:flag(
no_deps_flag(),
fun(No_deps) ->
glint:unnamed_args(
{min_args, 1},
fun() ->
glint:command(
fun(
_,
Terms,
Flags
) ->
Json@2 = case Json(
Flags
) of
{ok,
Json@1} -> Json@1;
_assert_fail ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"search_command"/utf8>>,
line => 98,
value => _assert_fail,
start => 2575,
'end' => 2608,
pattern_start => 2586,
pattern_end => 2594}
)
end,
Limit@2 = case Limit(
Flags
) of
{ok,
Limit@1} -> Limit@1;
_assert_fail@1 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"search_command"/utf8>>,
line => 99,
value => _assert_fail@1,
start => 2611,
'end' => 2646,
pattern_start => 2622,
pattern_end => 2631}
)
end,
Kind@2 = case Kind(
Flags
) of
{ok,
Kind@1} -> Kind@1;
_assert_fail@2 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"search_command"/utf8>>,
line => 100,
value => _assert_fail@2,
start => 2649,
'end' => 2682,
pattern_start => 2660,
pattern_end => 2668}
)
end,
Target@2 = case Target(
Flags
) of
{ok,
Target@1} -> Target@1;
_assert_fail@3 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"search_command"/utf8>>,
line => 101,
value => _assert_fail@3,
start => 2685,
'end' => 2722,
pattern_start => 2696,
pattern_end => 2706}
)
end,
Package@2 = case Package(
Flags
) of
{ok,
Package@1} -> Package@1;
_assert_fail@4 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"search_command"/utf8>>,
line => 102,
value => _assert_fail@4,
start => 2725,
'end' => 2764,
pattern_start => 2736,
pattern_end => 2747}
)
end,
No_deps@2 = case No_deps(
Flags
) of
{ok,
No_deps@1} -> No_deps@1;
_assert_fail@5 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"search_command"/utf8>>,
line => 103,
value => _assert_fail@5,
start => 2767,
'end' => 2806,
pattern_start => 2778,
pattern_end => 2789}
)
end,
{search,
gleam@string:join(
Terms,
<<" "/utf8>>
),
output_format(
Json@2
),
{scope,
optional_package(
Package@2
),
not No_deps@2},
Limit@2,
Kind@2,
Target@2}
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/gleamdoc.gleam", 65).
-spec lookup_command() -> glint:command(action()).
lookup_command() ->
glint:command_help(
<<"Look up an exact public module, function, constant, type, variant, or alias."/utf8>>,
fun() ->
glint:named_arg(
<<"query"/utf8>>,
fun(Query) ->
glint:flag(
json_flag(),
fun(Json) ->
glint:flag(
package_flag(),
fun(Package) ->
glint:flag(
no_deps_flag(),
fun(No_deps) ->
glint:unnamed_args(
{eq_args, 0},
fun() ->
glint:command(
fun(Named, _, Flags) ->
Json@2 = case Json(
Flags
) of
{ok, Json@1} -> Json@1;
_assert_fail ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"lookup_command"/utf8>>,
line => 75,
value => _assert_fail,
start => 1832,
'end' => 1865,
pattern_start => 1843,
pattern_end => 1851}
)
end,
Package@2 = case Package(
Flags
) of
{ok, Package@1} -> Package@1;
_assert_fail@1 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"lookup_command"/utf8>>,
line => 76,
value => _assert_fail@1,
start => 1868,
'end' => 1907,
pattern_start => 1879,
pattern_end => 1890}
)
end,
No_deps@2 = case No_deps(
Flags
) of
{ok, No_deps@1} -> No_deps@1;
_assert_fail@2 ->
erlang:error(
#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleamdoc"/utf8>>,
function => <<"lookup_command"/utf8>>,
line => 77,
value => _assert_fail@2,
start => 1910,
'end' => 1949,
pattern_start => 1921,
pattern_end => 1932}
)
end,
{lookup,
Query(Named),
output_format(
Json@2
),
{scope,
optional_package(
Package@2
),
not No_deps@2}}
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/gleamdoc.gleam", 53).
-spec cli() -> glint:glint(action()).
cli() ->
_pipe = glint:new(),
_pipe@1 = glint:with_name(_pipe, <<"gleamdoc"/utf8>>),
_pipe@2 = glint:global_help(
_pipe@1,
<<"Sparse, terminal-first documentation lookup for Gleam packages."/utf8>>
),
_pipe@3 = glint:add(_pipe@2, [], lookup_command()),
_pipe@4 = glint:add(_pipe@3, [<<"search"/utf8>>], search_command()),
_pipe@5 = glint:add(_pipe@4, [<<"packages"/utf8>>], packages_command()),
glint:add(_pipe@5, [<<"index"/utf8>>], index_command()).
-file("src/gleamdoc.gleam", 45).
?DOC(" Runs the Gleamdoc command-line application.\n").
-spec main() -> nil.
main() ->
case erlang:element(4, argv:load()) of
[<<"--version"/utf8>>] ->
gleam_stdlib:println(<<"gleamdoc "/utf8, "0.2.0"/utf8>>);
[<<"-v"/utf8>>] ->
gleam_stdlib:println(<<"gleamdoc "/utf8, "0.2.0"/utf8>>);
Arguments ->
glint:run_and_handle(cli(), Arguments, fun execute/1)
end.