Current section

Files

Jump to
glint src glint.erl
Raw

src/glint.erl

-module(glint).
-compile(no_auto_import).
-export([add_command_from_stub/2, new/0, add_command/6, execute/2, run/2, help_flag/0]).
-export_type([command_input/0, description/0, contents/1, command/1, stub/1, out/1]).
-type command_input() :: {command_input,
list(binary()),
gleam@map:map_(binary(), glint@flag:contents())}.
-type description() :: {description, binary(), binary()}.
-type contents(EON) :: {contents,
fun((command_input()) -> EON),
gleam@map:map_(binary(), glint@flag:contents()),
description()}.
-opaque command(EOO) :: {command,
gleam@option:option(contents(EOO)),
gleam@map:map_(binary(), command(EOO))}.
-type stub(EOP) :: {stub,
list(binary()),
fun((command_input()) -> EOP),
list({binary(), glint@flag:contents()}),
binary(),
binary()}.
-type out(EOQ) :: {out, EOQ} | {help, binary()}.
-spec add_command_from_stub(command(EPM), stub(EPM)) -> command(EPM).
add_command_from_stub(Root, Stub) ->
add_command(
Root,
erlang:element(2, Stub),
erlang:element(3, Stub),
erlang:element(4, Stub),
erlang:element(5, Stub),
erlang:element(6, Stub)
).
-spec new() -> command(any()).
new() ->
{command, none, gleam@map:new()}.
-spec sanitize_path(list(binary())) -> list(binary()).
sanitize_path(Path) ->
_pipe = Path,
_pipe@1 = gleam@list:map(_pipe, fun gleam@string:trim/1),
gleam@list:filter(_pipe@1, fun is_not_empty/1).
-spec add_command(
command(EPU),
list(binary()),
fun((command_input()) -> EPU),
list({binary(), glint@flag:contents()}),
binary(),
binary()
) -> command(EPU).
add_command(Root, Path, F, Flags, Description, Usage) ->
_pipe = Path,
_pipe@1 = sanitize_path(_pipe),
do_add_command(
Root,
_pipe@1,
{contents,
F,
glint@flag:build_map(Flags),
{description, Description, Usage}}
).
-spec do_add_command(command(EQA), list(binary()), contents(EQA)) -> command(EQA).
do_add_command(Root, Path, Contents) ->
case Path of
[] ->
erlang:setelement(2, Root, {some, Contents});
[X | Xs] ->
Update_subcommand = fun(Node) ->
_pipe = Node,
_pipe@1 = gleam@option:lazy_unwrap(_pipe, fun new/0),
do_add_command(_pipe@1, Xs, Contents)
end,
erlang:setelement(
3,
Root,
gleam@map:update(erlang:element(3, Root), X, Update_subcommand)
)
end.
-spec execute_root(command(EQF), list(binary()), list(binary())) -> {ok,
out(EQF)} |
{error, snag:snag()}.
execute_root(Cmd, Args, Flags) ->
case erlang:element(2, Cmd) of
{some, Contents} ->
case begin
_pipe = Flags,
_pipe@1 = gleam@list:try_fold(
_pipe,
erlang:element(3, Contents),
fun glint@flag:update_flags/2
),
snag:context(_pipe@1, <<"failed to run command"/utf8>>)
end of
{error, _try} -> {error, _try};
{ok, New_flags} ->
_pipe@2 = Args,
_pipe@3 = {command_input, _pipe@2, New_flags},
_pipe@4 = (erlang:element(2, Contents))(_pipe@3),
_pipe@5 = {out, _pipe@4},
{ok, _pipe@5}
end;
none ->
_pipe@6 = snag:error(<<"command not found"/utf8>>),
snag:context(_pipe@6, <<"failed to run command"/utf8>>)
end.
-spec execute(command(EQK), list(binary())) -> {ok, out(EQK)} |
{error, snag:snag()}.
execute(Cmd, Args) ->
Help_flag = help_flag(),
{Help, Args@2} = case gleam@list:pop(Args, fun(S) -> S =:= Help_flag end) of
{ok, {_@1, Args@1}} ->
{true, Args@1};
_@2 ->
{false, Args}
end,
{Flags, Args@3} = gleam@list:partition(
Args@2,
fun(_capture) -> gleam@string:starts_with(_capture, <<"--"/utf8>>) end
),
do_execute(Cmd, Args@3, Flags, Help, []).
-spec do_execute(
command(EQO),
list(binary()),
list(binary()),
boolean(),
list(binary())
) -> {ok, out(EQO)} | {error, snag:snag()}.
do_execute(Cmd, Args, Flags, Help, Command_path) ->
case Args of
[] when Help ->
_pipe = Command_path,
_pipe@1 = cmd_help(_pipe, Cmd),
_pipe@2 = {help, _pipe@1},
{ok, _pipe@2};
[] ->
execute_root(Cmd, [], Flags);
[Arg | Rest] ->
case gleam@map:get(erlang:element(3, Cmd), Arg) of
{ok, Cmd@1} ->
do_execute(Cmd@1, Rest, Flags, Help, [Arg | Command_path]);
_@1 when Help ->
_pipe@3 = Command_path,
_pipe@4 = cmd_help(_pipe@3, Cmd),
_pipe@5 = {help, _pipe@4},
{ok, _pipe@5};
_@2 ->
execute_root(Cmd, Args, Flags)
end
end.
-spec run(command(any()), list(binary())) -> nil.
run(Cmd, Args) ->
case execute(Cmd, Args) of
{error, Err} ->
_pipe = Err,
_pipe@1 = snag:pretty_print(_pipe),
gleam@io:println(_pipe@1);
{ok, {help, Help}} ->
gleam@io:println(Help);
_@1 ->
nil
end.
-spec is_not_empty(binary()) -> boolean().
is_not_empty(S) ->
S /= <<""/utf8>>.
-spec help_flag() -> binary().
help_flag() ->
gleam@string:append(<<"--"/utf8>>, <<"help"/utf8>>).
-spec cmd_help(list(binary()), command(any())) -> binary().
cmd_help(Path, Command) ->
Name = begin
_pipe = Path,
_pipe@1 = gleam@list:reverse(_pipe),
gleam@string:join(_pipe@1, <<" "/utf8>>)
end,
{Flags@2, Description, Usage@1} = case erlang:element(2, Command) of
none ->
{<<""/utf8>>, <<""/utf8>>, <<""/utf8>>};
{some, {contents, _@1, Flags, Desc}} ->
Flags@1 = begin
_pipe@2 = Flags,
_pipe@3 = glint@flag:flags_help(_pipe@2),
_pipe@4 = append_if_msg_not_empty(<<"\n\t"/utf8>>, _pipe@3),
_pipe@5 = gleam@string:append(
<<"--help\t\t\tPrint help information"/utf8>>,
_pipe@4
),
gleam@string:append(<<"FLAGS:\n\t"/utf8>>, _pipe@5)
end,
Usage = append_if_msg_not_empty(
<<"USAGE:\n\t"/utf8>>,
erlang:element(3, Desc)
),
{Flags@1, erlang:element(2, Desc), Usage}
end,
Header_items = begin
_pipe@6 = [Name, Description],
_pipe@7 = gleam@list:filter(_pipe@6, fun is_not_empty/1),
gleam@string:join(_pipe@7, <<"\n"/utf8>>)
end,
Subcommands = begin
_pipe@8 = erlang:element(3, Command),
_pipe@9 = subcommands_help(_pipe@8),
append_if_msg_not_empty(<<"SUBCOMMANDS:\n\t"/utf8>>, _pipe@9)
end,
_pipe@10 = [Header_items, Usage@1, Flags@2, Subcommands],
_pipe@11 = gleam@list:filter(_pipe@10, fun is_not_empty/1),
gleam@string:join(_pipe@11, <<"\n\n"/utf8>>).
-spec append_if_msg_not_empty(binary(), binary()) -> binary().
append_if_msg_not_empty(Prefix, Message) ->
case Message of
<<""/utf8>> ->
<<""/utf8>>;
_@1 ->
gleam@string:append(Prefix, Message)
end.
-spec subcommands_help(gleam@map:map_(binary(), command(any()))) -> binary().
subcommands_help(Cmds) ->
_pipe = Cmds,
_pipe@1 = gleam@map:map_values(_pipe, fun subcommand_help/2),
_pipe@2 = gleam@map:values(_pipe@1),
_pipe@3 = gleam@list:sort(_pipe@2, fun gleam@string:compare/2),
gleam@string:join(_pipe@3, <<"\n\t"/utf8>>).
-spec subcommand_help(binary(), command(any())) -> binary().
subcommand_help(Name, Cmd) ->
case erlang:element(2, Cmd) of
none ->
Name;
{some, {contents, _@1, _@2, {description, Desc, _@3}}} ->
gleam@string:concat([Name, <<"\t\t"/utf8>>, Desc])
end.