Current section

Files

Jump to
glint src glint@flag.erl
Raw

src/glint@flag.erl

-module(glint@flag).
-compile(no_auto_import).
-export([int/3, ints/3, float/3, floats/3, string/3, strings/3, bool/3, build_map/1, update_flags/2, get/2, flag_type_help/1, flags_help/1]).
-export_type([value/0, contents/0]).
-type value() :: {b, boolean()} |
{i, integer()} |
{li, list(integer())} |
{f, float()} |
{lf, list(float())} |
{s, binary()} |
{ls, list(binary())}.
-opaque contents() :: {contents, value(), binary()}.
-spec int(binary(), integer(), binary()) -> {binary(), contents()}.
int(Name, Value, Description) ->
{Name, {contents, {i, Value}, Description}}.
-spec ints(binary(), list(integer()), binary()) -> {binary(), contents()}.
ints(Name, Value, Description) ->
{Name, {contents, {li, Value}, Description}}.
-spec float(binary(), float(), binary()) -> {binary(), contents()}.
float(Name, Value, Description) ->
{Name, {contents, {f, Value}, Description}}.
-spec floats(binary(), list(float()), binary()) -> {binary(), contents()}.
floats(Name, Value, Description) ->
{Name, {contents, {lf, Value}, Description}}.
-spec string(binary(), binary(), binary()) -> {binary(), contents()}.
string(Name, Value, Description) ->
{Name, {contents, {s, Value}, Description}}.
-spec strings(binary(), list(binary()), binary()) -> {binary(), contents()}.
strings(Name, Value, Description) ->
{Name, {contents, {ls, Value}, Description}}.
-spec bool(binary(), boolean(), binary()) -> {binary(), contents()}.
bool(Name, Value, Description) ->
{Name, {contents, {b, Value}, Description}}.
-spec build_map(list({binary(), contents()})) -> gleam@map:map_(binary(), contents()).
build_map(Flags) ->
gleam@map:from_list(Flags).
-spec update_flags(gleam@map:map_(binary(), contents()), binary()) -> {ok,
gleam@map:map_(binary(), contents())} |
{error, snag:snag()}.
update_flags(Flags, Flag_input) ->
Flag_input@1 = gleam@string:drop_left(
Flag_input,
gleam@string:length(<<"--"/utf8>>)
),
case gleam@string:split_once(Flag_input@1, <<"="/utf8>>) of
{ok, Data} ->
update_flag_value(Flags, Data);
{error, _@1} ->
attempt_toggle_flag(Flags, Flag_input@1)
end.
-spec update_flag_value(
gleam@map:map_(binary(), contents()),
{binary(), binary()}
) -> {ok, gleam@map:map_(binary(), contents())} | {error, snag:snag()}.
update_flag_value(Flags, Data) ->
{Key, Value} = Data,
case access(Flags, Key) of
{error, _try} -> {error, _try};
{ok, {contents, Default, Desc}} ->
_pipe = Default,
_pipe@1 = compute_flag(Key, Value, _pipe),
_pipe@2 = gleam@result:map(
_pipe@1,
fun(_capture) -> {contents, _capture, Desc} end
),
gleam@result:map(
_pipe@2,
fun(_capture@1) -> gleam@map:insert(Flags, Key, _capture@1) end
)
end.
-spec attempt_toggle_flag(gleam@map:map_(binary(), contents()), binary()) -> {ok,
gleam@map:map_(binary(), contents())} |
{error, snag:snag()}.
attempt_toggle_flag(Flags, Key) ->
case access(Flags, Key) of
{error, _try} -> {error, _try};
{ok, {contents, Default, Desc}} ->
case Default of
{b, Val} ->
_pipe = not Val,
_pipe@1 = {b, _pipe},
_pipe@2 = {contents, _pipe@1, Desc},
_pipe@3 = gleam@map:insert(Flags, Key, _pipe@2),
{ok, _pipe@3};
_@1 ->
{error, no_value_flag_err(Key)}
end
end.
-spec get(gleam@map:map_(binary(), contents()), binary()) -> {ok, value()} |
{error, nil}.
get(Flags, Name) ->
case gleam@map:get(Flags, Name) of
{error, _try} -> {error, _try};
{ok, Contents} ->
{ok, erlang:element(2, Contents)}
end.
-spec access(gleam@map:map_(binary(), contents()), binary()) -> {ok, contents()} |
{error, snag:snag()}.
access(Flags, Name) ->
_pipe = gleam@map:get(Flags, Name),
gleam@result:replace_error(_pipe, undefined_flag_err(Name)).
-spec compute_flag(binary(), binary(), value()) -> {ok, value()} |
{error, snag:snag()}.
compute_flag(Name, Input, Default) ->
Parse = case Default of
{i, _@1} ->
fun parse_int/2;
{li, _@2} ->
fun parse_int_list/2;
{f, _@3} ->
fun parse_float/2;
{lf, _@4} ->
fun parse_float_list/2;
{s, _@5} ->
fun parse_string/2;
{ls, _@6} ->
fun parse_string_list/2;
{b, _@7} ->
fun parse_bool/2
end,
Parse(Name, Input).
-spec parse_int(binary(), binary()) -> {ok, value()} | {error, snag:snag()}.
parse_int(Key, Value) ->
_pipe = parse_flag(
Value,
fun gleam@int:parse/1,
fun(Field@0) -> {i, Field@0} end
),
gleam@result:replace_error(_pipe, cannot_parse(Key, Value, <<"int"/utf8>>)).
-spec parse_int_list(binary(), binary()) -> {ok, value()} | {error, snag:snag()}.
parse_int_list(Key, Value) ->
_pipe = parse_list_flag(
Value,
fun gleam@int:parse/1,
fun(Field@0) -> {li, Field@0} end
),
gleam@result:replace_error(
_pipe,
cannot_parse(Key, Value, <<"int list"/utf8>>)
).
-spec parse_float(binary(), binary()) -> {ok, value()} | {error, snag:snag()}.
parse_float(Key, Value) ->
_pipe = parse_flag(
Value,
fun gleam@float:parse/1,
fun(Field@0) -> {f, Field@0} end
),
gleam@result:replace_error(
_pipe,
cannot_parse(Key, Value, <<"float"/utf8>>)
).
-spec parse_float_list(binary(), binary()) -> {ok, value()} |
{error, snag:snag()}.
parse_float_list(Key, Value) ->
_pipe = parse_list_flag(
Value,
fun gleam@float:parse/1,
fun(Field@0) -> {lf, Field@0} end
),
gleam@result:replace_error(
_pipe,
cannot_parse(Key, Value, <<"float list"/utf8>>)
).
-spec parse_bool(binary(), binary()) -> {ok, value()} | {error, snag:snag()}.
parse_bool(Key, Value) ->
case Value of
<<"true"/utf8>> ->
{ok, {b, true}};
<<"false"/utf8>> ->
{ok, {b, false}};
_@1 ->
{error, cannot_parse(Key, Value, <<"bool"/utf8>>)}
end.
-spec parse_string(binary(), binary()) -> {ok, value()} | {error, snag:snag()}.
parse_string(_, Value) ->
parse_flag(
Value,
fun(Field@0) -> {ok, Field@0} end,
fun(Field@0) -> {s, Field@0} end
).
-spec parse_string_list(binary(), binary()) -> {ok, value()} |
{error, snag:snag()}.
parse_string_list(_, Value) ->
parse_list_flag(
Value,
fun(Field@0) -> {ok, Field@0} end,
fun(Field@0) -> {ls, Field@0} end
).
-spec parse_flag(
binary(),
fun((binary()) -> {ok, FHY} | {error, FHZ}),
fun((FHY) -> value())
) -> {ok, value()} | {error, FHZ}.
parse_flag(Value, Parse, Construct) ->
_pipe = Value,
_pipe@1 = Parse(_pipe),
gleam@result:map(_pipe@1, Construct).
-spec parse_list_flag(
binary(),
fun((binary()) -> {ok, FIE} | {error, FIF}),
fun((list(FIE)) -> value())
) -> {ok, value()} | {error, FIF}.
parse_list_flag(Value, Parse, Construct) ->
_pipe = Value,
_pipe@1 = gleam@string:split(_pipe, <<","/utf8>>),
_pipe@2 = gleam@list:try_map(_pipe@1, Parse),
gleam@result:map(_pipe@2, Construct).
-spec layer_invalid_flag(snag:snag(), binary()) -> snag:snag().
layer_invalid_flag(Err, Flag) ->
_pipe = <<<<"invalid flag '"/utf8, Flag/binary>>/binary, "'"/utf8>>,
snag:layer(Err, _pipe).
-spec no_value_flag_err(binary()) -> snag:snag().
no_value_flag_err(Flag_input) ->
_pipe = <<<<"flag '"/utf8, Flag_input/binary>>/binary,
"' has no assigned value"/utf8>>,
_pipe@1 = snag:new(_pipe),
layer_invalid_flag(_pipe@1, Flag_input).
-spec undefined_flag_err(binary()) -> snag:snag().
undefined_flag_err(Key) ->
_pipe = <<"flag provided but not defined"/utf8>>,
_pipe@1 = snag:new(_pipe),
layer_invalid_flag(_pipe@1, Key).
-spec cannot_parse(binary(), binary(), binary()) -> snag:snag().
cannot_parse(Key, Value, Kind) ->
_pipe = <<<<<<<<<<"cannot parse flag '"/utf8, Key/binary>>/binary,
"' value '"/utf8>>/binary,
Value/binary>>/binary,
"' as "/utf8>>/binary,
Kind/binary>>,
_pipe@1 = snag:new(_pipe),
layer_invalid_flag(_pipe@1, Key).
-spec flag_type_help({binary(), contents()}) -> binary().
flag_type_help(Flag) ->
{Name, Contents} = Flag,
Kind = case erlang:element(2, Contents) of
{i, _@1} ->
<<"INT"/utf8>>;
{b, _@2} ->
<<"BOOL"/utf8>>;
{f, _@3} ->
<<"FLOAT"/utf8>>;
{lf, _@4} ->
<<"FLOAT_LIST"/utf8>>;
{li, _@5} ->
<<"INT_LIST"/utf8>>;
{ls, _@6} ->
<<"STRING_LIST"/utf8>>;
{s, _@7} ->
<<"STRING"/utf8>>
end,
<<<<<<<<<<"--"/utf8, Name/binary>>/binary, "="/utf8>>/binary, "<"/utf8>>/binary,
Kind/binary>>/binary,
">"/utf8>>.
-spec flag_help({binary(), contents()}) -> binary().
flag_help(Flag) ->
<<<<(flag_type_help(Flag))/binary, "\t\t"/utf8>>/binary,
(erlang:element(3, erlang:element(2, Flag)))/binary>>.
-spec flags_help(gleam@map:map_(binary(), contents())) -> binary().
flags_help(Flags) ->
_pipe = Flags,
_pipe@1 = gleam@map:to_list(_pipe),
_pipe@2 = gleam@list:map(_pipe@1, fun flag_help/1),
_pipe@3 = gleam@list:sort(_pipe@2, fun gleam@string:compare/2),
gleam@string:join(_pipe@3, <<"\n\t"/utf8>>).