-module(gleeam_code@list_cmd).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeam_code/list_cmd.gleam").
-export([parse_filters/1, apply_filters/2, run/3]).
-export_type([problem_entry/0, filter/0, option/0]).
-type problem_entry() :: {problem_entry,
integer(),
binary(),
binary(),
binary()}.
-type filter() :: {filter, list(binary()), option(), option()}.
-type option() :: on | off.
-file("src/gleeam_code/list_cmd.gleam", 25).
-spec do_parse_filters(list(binary()), filter()) -> filter().
do_parse_filters(Args, Acc) ->
case Args of
[] ->
Acc;
[<<"--easy"/utf8>> | Rest] ->
do_parse_filters(
Rest,
{filter,
[<<"Easy"/utf8>> | erlang:element(2, Acc)],
erlang:element(3, Acc),
erlang:element(4, Acc)}
);
[<<"--medium"/utf8>> | Rest@1] ->
do_parse_filters(
Rest@1,
{filter,
[<<"Medium"/utf8>> | erlang:element(2, Acc)],
erlang:element(3, Acc),
erlang:element(4, Acc)}
);
[<<"--hard"/utf8>> | Rest@2] ->
do_parse_filters(
Rest@2,
{filter,
[<<"Hard"/utf8>> | erlang:element(2, Acc)],
erlang:element(3, Acc),
erlang:element(4, Acc)}
);
[<<"--solved"/utf8>> | Rest@3] ->
do_parse_filters(
Rest@3,
{filter, erlang:element(2, Acc), on, erlang:element(4, Acc)}
);
[<<"--unsolved"/utf8>> | Rest@4] ->
do_parse_filters(
Rest@4,
{filter, erlang:element(2, Acc), erlang:element(3, Acc), on}
);
[_ | Rest@5] ->
do_parse_filters(Rest@5, Acc)
end.
-file("src/gleeam_code/list_cmd.gleam", 21).
-spec parse_filters(list(binary())) -> filter().
parse_filters(Args) ->
do_parse_filters(Args, {filter, [], off, off}).
-file("src/gleeam_code/list_cmd.gleam", 59).
-spec filter_by_difficulty(list(problem_entry()), list(binary())) -> list(problem_entry()).
filter_by_difficulty(Problems, Difficulties) ->
case Difficulties of
[] ->
Problems;
_ ->
gleam@list:filter(
Problems,
fun(P) ->
gleam@list:contains(Difficulties, erlang:element(4, P))
end
)
end.
-file("src/gleeam_code/list_cmd.gleam", 70).
-spec filter_by_status(list(problem_entry()), option(), option()) -> list(problem_entry()).
filter_by_status(Problems, Solved, Unsolved) ->
case {Solved, Unsolved} of
{on, off} ->
gleam@list:filter(
Problems,
fun(P) -> erlang:element(5, P) =:= <<"Accepted"/utf8>> end
);
{off, on} ->
gleam@list:filter(
Problems,
fun(P@1) -> erlang:element(5, P@1) /= <<"Accepted"/utf8>> end
);
{_, _} ->
Problems
end.
-file("src/gleeam_code/list_cmd.gleam", 50).
-spec apply_filters(list(problem_entry()), filter()) -> list(problem_entry()).
apply_filters(Problems, Filter) ->
_pipe = Problems,
_pipe@1 = filter_by_difficulty(_pipe, erlang:element(2, Filter)),
filter_by_status(
_pipe@1,
erlang:element(3, Filter),
erlang:element(4, Filter)
).
-file("src/gleeam_code/list_cmd.gleam", 153).
-spec extract_number(list(binary())) -> {ok, integer()} | {error, nil}.
extract_number(Lines) ->
case Lines of
[] ->
{error, nil};
[Line | Rest] ->
case gleam_stdlib:string_starts_with(Line, <<"//// Problem "/utf8>>) of
true ->
After = gleam@string:drop_start(
Line,
string:length(<<"//// Problem "/utf8>>)
),
case gleam@string:split_once(After, <<":"/utf8>>) of
{ok, {Num_str, _}} ->
_pipe = Num_str,
_pipe@1 = gleam@string:trim(_pipe),
_pipe@2 = gleam_stdlib:parse_int(_pipe@1),
gleam@result:replace_error(_pipe@2, nil);
{error, _} ->
{error, nil}
end;
false ->
extract_number(Rest)
end
end.
-file("src/gleeam_code/list_cmd.gleam", 171).
-spec extract_slug(binary()) -> binary().
extract_slug(Dir_name) ->
case gleam@string:split_once(Dir_name, <<"_"/utf8>>) of
{ok, {_, Rest}} ->
gleam@string:replace(Rest, <<"_"/utf8>>, <<"-"/utf8>>);
{error, _} ->
Dir_name
end.
-file("src/gleeam_code/list_cmd.gleam", 178).
-spec extract_difficulty(list(binary())) -> binary().
extract_difficulty(Lines) ->
case Lines of
[] ->
<<"?"/utf8>>;
[Line | Rest] ->
case gleam_stdlib:string_starts_with(
Line,
<<"//// Difficulty: "/utf8>>
) of
true ->
_pipe = gleam@string:drop_start(
Line,
string:length(<<"//// Difficulty: "/utf8>>)
),
gleam@string:trim(_pipe);
false ->
extract_difficulty(Rest)
end
end.
-file("src/gleeam_code/list_cmd.gleam", 191).
-spec read_status(binary()) -> binary().
read_status(Meta_path) ->
case gleeam_code@internal@file:read(Meta_path) of
{ok, Content} ->
gleeam_code@internal@meta:find_value(
gleam@string:split(Content, <<"\n"/utf8>>),
<<"status"/utf8>>
);
{error, _} ->
<<""/utf8>>
end.
-file("src/gleeam_code/list_cmd.gleam", 135).
-spec parse_solution_header(binary(), binary(), binary()) -> {ok,
problem_entry()} |
{error, nil}.
parse_solution_header(Content, Dir_name, Meta_path) ->
Lines = gleam@string:split(Content, <<"\n"/utf8>>),
gleam@result:'try'(
extract_number(Lines),
fun(Number) ->
Slug = extract_slug(Dir_name),
Difficulty = extract_difficulty(Lines),
Status = read_status(Meta_path),
{ok, {problem_entry, Number, Slug, Difficulty, Status}}
end
).
-file("src/gleeam_code/list_cmd.gleam", 123).
-spec parse_entry(binary(), binary()) -> {ok, problem_entry()} | {error, nil}.
parse_entry(Solutions_dir, Dir_name) ->
Solution_path = <<<<<<Solutions_dir/binary, "/"/utf8>>/binary,
Dir_name/binary>>/binary,
"/solution.gleam"/utf8>>,
Meta_path = <<<<<<Solutions_dir/binary, "/"/utf8>>/binary, Dir_name/binary>>/binary,
"/.glc_meta"/utf8>>,
case gleeam_code@internal@file:read(Solution_path) of
{ok, Content} ->
parse_solution_header(Content, Dir_name, Meta_path);
{error, _} ->
{error, nil}
end.
-file("src/gleeam_code/list_cmd.gleam", 212).
-spec format_status(binary()) -> binary().
format_status(Status) ->
case Status of
<<"Accepted"/utf8>> ->
<<"✓ Accepted"/utf8>>;
<<""/utf8>> ->
<<""/utf8>>;
Other ->
<<"✗ "/utf8, Other/binary>>
end.
-file("src/gleeam_code/list_cmd.gleam", 220).
-spec pad_right(binary(), integer()) -> binary().
pad_right(S, Width) ->
Len = string:length(S),
case Len >= Width of
true ->
S;
false ->
<<S/binary,
(gleam@string:repeat(<<" "/utf8>>, Width - Len))/binary>>
end.
-file("src/gleeam_code/list_cmd.gleam", 198).
-spec format_header() -> binary().
format_header() ->
<<<<<<(pad_right(<<"#"/utf8>>, 5))/binary,
(pad_right(<<"Slug"/utf8>>, 30))/binary>>/binary,
(pad_right(<<"Difficulty"/utf8>>, 12))/binary>>/binary,
"Status"/utf8>>.
-file("src/gleeam_code/list_cmd.gleam", 205).
-spec format_row(problem_entry()) -> binary().
format_row(Entry) ->
<<<<<<(pad_right(erlang:integer_to_binary(erlang:element(2, Entry)), 5))/binary,
(pad_right(erlang:element(3, Entry), 30))/binary>>/binary,
(pad_right(erlang:element(4, Entry), 12))/binary>>/binary,
(format_status(erlang:element(5, Entry)))/binary>>.
-file("src/gleeam_code/list_cmd.gleam", 82).
-spec run(binary(), list(binary()), fun((binary()) -> nil)) -> {ok, nil} |
{error, binary()}.
run(Base_dir, Args, Print) ->
Filter = parse_filters(Args),
Solutions_dir = <<Base_dir/binary, "/src/solutions"/utf8>>,
case gleeam_code@internal@file:dir_exists(Solutions_dir) of
false ->
Print(<<"No solutions found. Run `glc fetch` first."/utf8>>),
{ok, nil};
true ->
gleam@result:'try'(
begin
_pipe = gleeam_code@internal@file:list_directory(
Solutions_dir
),
gleam@result:map_error(
_pipe,
fun(Err) ->
<<"Failed to read solutions directory: "/utf8,
(gleeam_code@internal@file:describe_error(Err))/binary>>
end
)
end,
fun(Entries) ->
Problems = begin
_pipe@1 = Entries,
_pipe@2 = gleam@list:filter_map(
_pipe@1,
fun(Entry) -> parse_entry(Solutions_dir, Entry) end
),
_pipe@3 = gleam@list:sort(
_pipe@2,
fun(A, B) ->
gleam@int:compare(
erlang:element(2, A),
erlang:element(2, B)
)
end
),
apply_filters(_pipe@3, Filter)
end,
case Problems of
[] ->
Print(
<<"No solutions found. Run `glc fetch` first."/utf8>>
),
{ok, nil};
_ ->
Print(format_header()),
gleam@list:each(
Problems,
fun(P) -> Print(format_row(P)) end
),
{ok, nil}
end
end
)
end.