Current section
Files
Jump to
Current section
Files
src/birdie.erl
-module(birdie).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([main/0, snap/2]).
-export_type([error/0, new/0, accepted/0, snapshot/1, outcome/0, info_line/0, split/0, command/0, review_choice/0]).
-type error() :: snapshot_with_empty_title |
{cannot_create_snapshots_folder, simplifile:file_error()} |
{cannot_read_accepted_snapshot, simplifile:file_error(), binary()} |
{cannot_read_new_snapshot, simplifile:file_error(), binary()} |
{cannot_save_new_snapshot, simplifile:file_error(), binary(), binary()} |
{cannot_read_snapshots, simplifile:file_error(), binary()} |
{cannot_reject_snapshot, simplifile:file_error(), binary()} |
{cannot_accept_snapshot, simplifile:file_error(), binary()} |
cannot_read_user_input |
{corrupted_snapshot, binary()} |
{cannot_find_project_root, simplifile:file_error()} |
{cannot_get_titles, birdie@internal@titles:error()}.
-type new() :: any().
-type accepted() :: any().
-type snapshot(LLY) :: {snapshot,
binary(),
binary(),
gleam@option:option(birdie@internal@titles:test_info())} |
{gleam_phantom, LLY}.
-type outcome() :: {new_snapshot_created, snapshot(new()), binary()} |
{different, snapshot(accepted()), snapshot(new())} |
same.
-type info_line() :: {info_line_with_title, binary(), split(), binary()} |
{info_line_with_no_title, binary(), split()}.
-type split() :: do_not_split | split_words | truncate.
-type command() :: review | accept_all | reject_all | help.
-type review_choice() :: accept_snapshot | reject_snapshot | skip_snapshot.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 166).
-spec validate_snapshot_title(binary()) -> {ok, nil} | {error, error()}.
validate_snapshot_title(Title) ->
case gleam@string:trim(Title) of
<<""/utf8>> ->
{error, snapshot_with_empty_title};
_ ->
{ok, nil}
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 175).
-spec to_diff_lines(snapshot(accepted()), snapshot(new())) -> list(birdie@internal@diff:diff_line()).
to_diff_lines(Accepted, New) ->
{snapshot, _, Accepted_content, _} = Accepted,
{snapshot, _, New_content, _} = New,
birdie@internal@diff:histogram(Accepted_content, New_content).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 186).
-spec split_n(binary(), integer(), binary()) -> {ok, {list(binary()), binary()}} |
{error, nil}.
split_n(String, N, Separator) ->
case N =< 0 of
true ->
{ok, {[], String}};
false ->
gleam@result:'try'(
gleam@string:split_once(String, Separator),
fun(_use0) ->
{Line, Rest} = _use0,
gleam@result:'try'(
split_n(Rest, N - 1, Separator),
fun(_use0@1) ->
{Lines, Rest@1} = _use0@1,
{ok, {[Line | Lines], Rest@1}}
end
)
end
)
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 201).
-spec deserialise(binary()) -> {ok, snapshot(any())} | {error, nil}.
deserialise(Raw) ->
case split_n(Raw, 4, <<"\n"/utf8>>) of
{ok,
{[<<"---"/utf8>>,
<<"version: "/utf8, _/binary>>,
<<"title: "/utf8, Title/binary>>,
<<"---"/utf8>>],
Content}} ->
{ok, {snapshot, gleam@string:trim(Title), Content, none}};
{ok,
{[<<"---\r"/utf8>>,
<<"version: "/utf8, _/binary>>,
<<"title: "/utf8, Title/binary>>,
<<"---\r"/utf8>>],
Content}} ->
{ok, {snapshot, gleam@string:trim(Title), Content, none}};
{ok, _} ->
case split_n(Raw, 6, <<"\n"/utf8>>) of
{ok,
{[<<"---"/utf8>>,
<<"version: "/utf8, _/binary>>,
<<"title: "/utf8, Title@1/binary>>,
<<"file: "/utf8, File/binary>>,
<<"test_name: "/utf8, Test_name/binary>>,
<<"---"/utf8>>],
Content@1}} ->
{ok,
{snapshot,
gleam@string:trim(Title@1),
Content@1,
{some,
{test_info,
gleam@string:trim(File),
gleam@string:trim(Test_name)}}}};
{ok,
{[<<"---\r"/utf8>>,
<<"version: "/utf8, _/binary>>,
<<"title: "/utf8, Title@1/binary>>,
<<"file: "/utf8, File/binary>>,
<<"test_name: "/utf8, Test_name/binary>>,
<<"---\r"/utf8>>],
Content@1}} ->
{ok,
{snapshot,
gleam@string:trim(Title@1),
Content@1,
{some,
{test_info,
gleam@string:trim(File),
gleam@string:trim(Test_name)}}}};
{ok, _} ->
{error, nil};
{error, _} ->
{error, nil}
end;
{error, _} ->
case split_n(Raw, 6, <<"\n"/utf8>>) of
{ok,
{[<<"---"/utf8>>,
<<"version: "/utf8, _/binary>>,
<<"title: "/utf8, Title@1/binary>>,
<<"file: "/utf8, File/binary>>,
<<"test_name: "/utf8, Test_name/binary>>,
<<"---"/utf8>>],
Content@1}} ->
{ok,
{snapshot,
gleam@string:trim(Title@1),
Content@1,
{some,
{test_info,
gleam@string:trim(File),
gleam@string:trim(Test_name)}}}};
{ok,
{[<<"---\r"/utf8>>,
<<"version: "/utf8, _/binary>>,
<<"title: "/utf8, Title@1/binary>>,
<<"file: "/utf8, File/binary>>,
<<"test_name: "/utf8, Test_name/binary>>,
<<"---\r"/utf8>>],
Content@1}} ->
{ok,
{snapshot,
gleam@string:trim(Title@1),
Content@1,
{some,
{test_info,
gleam@string:trim(File),
gleam@string:trim(Test_name)}}}};
{ok, _} ->
{error, nil};
{error, _} ->
{error, nil}
end
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 295).
-spec read_accepted(binary()) -> {ok, gleam@option:option(snapshot(accepted()))} |
{error, error()}.
read_accepted(Source) ->
case simplifile:read(Source) of
{ok, Content} ->
case deserialise(Content) of
{ok, Snapshot} ->
{ok, {some, Snapshot}};
{error, nil} ->
{error, {corrupted_snapshot, Source}}
end;
{error, enoent} ->
{ok, none};
{error, Reason} ->
{error, {cannot_read_accepted_snapshot, Reason, Source}}
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 315).
-spec read_new(binary()) -> {ok, snapshot(new())} | {error, error()}.
read_new(Source) ->
case simplifile:read(Source) of
{ok, Content} ->
gleam@result:replace_error(
deserialise(Content),
{corrupted_snapshot, Source}
);
{error, Reason} ->
{error, {cannot_read_new_snapshot, Reason, Source}}
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 326).
-spec list_new_snapshots(binary()) -> {ok, list(binary())} | {error, error()}.
list_new_snapshots(Folder) ->
case simplifile_erl:read_directory(Folder) of
{error, Reason} ->
{error, {cannot_read_snapshots, Reason, Folder}};
{ok, Files} ->
{ok,
(gleam@list:filter_map(
Files,
fun(File) -> case filepath:extension(File) of
{ok, <<"new"/utf8>>} ->
{ok, filepath:join(Folder, File)};
_ ->
{error, nil}
end end
))}
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 388).
-spec reject_snapshot(binary()) -> {ok, nil} | {error, error()}.
reject_snapshot(New_snapshot_path) ->
_pipe = simplifile_erl:delete(New_snapshot_path),
gleam@result:map_error(
_pipe,
fun(_capture) ->
{cannot_reject_snapshot, _capture, New_snapshot_path}
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 398).
-spec file_name(binary()) -> binary().
file_name(Title) ->
_pipe = gleam@string:replace(Title, <<"/"/utf8>>, <<" "/utf8>>),
_pipe@1 = gleam@string:replace(_pipe, <<"\\"/utf8>>, <<" "/utf8>>),
_pipe@2 = gleam@string:replace(_pipe@1, <<"\n"/utf8>>, <<" "/utf8>>),
_pipe@3 = gleam@string:replace(_pipe@2, <<"\t"/utf8>>, <<" "/utf8>>),
_pipe@4 = gleam@string:replace(_pipe@3, <<"\r"/utf8>>, <<" "/utf8>>),
_pipe@5 = gleam@string:replace(_pipe@4, <<"."/utf8>>, <<" "/utf8>>),
_pipe@6 = gleam@string:replace(_pipe@5, <<":"/utf8>>, <<" "/utf8>>),
justin:snake_case(_pipe@6).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 411).
-spec new_destination(snapshot(new()), binary()) -> binary().
new_destination(Snapshot, Folder) ->
<<(filepath:join(Folder, file_name(erlang:element(2, Snapshot))))/binary,
".new"/utf8>>.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 418).
-spec to_accepted_path(binary()) -> binary().
to_accepted_path(File) ->
<<(filepath:strip_extension(File))/binary, ".accepted"/utf8>>.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 524).
-spec to_function_name(binary(), binary()) -> binary().
to_function_name(File, Function_name) ->
Module_name = case File of
<<"./test/"/utf8, Rest/binary>> ->
filepath:strip_extension(Rest);
_ ->
filepath:strip_extension(File)
end,
<<<<<<Module_name/binary, ".{"/utf8>>/binary, Function_name/binary>>/binary,
"}"/utf8>>.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 425).
-spec explain(error()) -> binary().
explain(Error) ->
Heading = fun(Reason) ->
<<<<"["/utf8,
(gleam_community@ansi:bold(gleam@string:inspect(Reason)))/binary>>/binary,
"] "/utf8>>
end,
Message = case Error of
snapshot_with_empty_title ->
<<"A snapshot cannot have the empty string as a title."/utf8>>;
{cannot_create_snapshots_folder, Reason@1} ->
<<(Heading(Reason@1))/binary,
"I couldn't create the snapshots folder."/utf8>>;
{cannot_read_accepted_snapshot, Reason@2, Source} ->
<<<<(Heading(Reason@2))/binary,
"I couldn't read the accepted snapshot from "/utf8>>/binary,
(gleam_community@ansi:italic(
<<<<"\""/utf8, Source/binary>>/binary, "\"."/utf8>>
))/binary>>;
{cannot_read_new_snapshot, Reason@3, Source@1} ->
<<<<(Heading(Reason@3))/binary,
"I couldn't read the new snapshot from "/utf8>>/binary,
(gleam_community@ansi:italic(
<<<<"\""/utf8, Source@1/binary>>/binary, "\"."/utf8>>
))/binary>>;
{cannot_save_new_snapshot, Reason@4, Title, Destination} ->
<<<<<<<<(Heading(Reason@4))/binary,
"I couldn't save the snapshot "/utf8>>/binary,
(gleam_community@ansi:italic(
<<<<"\""/utf8, Title/binary>>/binary, "\" "/utf8>>
))/binary>>/binary,
"to "/utf8>>/binary,
(gleam_community@ansi:italic(
<<<<"\""/utf8, Destination/binary>>/binary, "\"."/utf8>>
))/binary>>;
{cannot_read_snapshots, Reason@5, _} ->
<<(Heading(Reason@5))/binary,
"I couldn't read the snapshots folder's contents."/utf8>>;
{cannot_reject_snapshot, Reason@6, Snapshot} ->
<<<<(Heading(Reason@6))/binary,
"I couldn't reject the snapshot "/utf8>>/binary,
(gleam_community@ansi:italic(
<<<<"\""/utf8, Snapshot/binary>>/binary, "\"."/utf8>>
))/binary>>;
{cannot_accept_snapshot, Reason@7, Snapshot@1} ->
<<<<(Heading(Reason@7))/binary,
"I couldn't accept the snapshot "/utf8>>/binary,
(gleam_community@ansi:italic(
<<<<"\""/utf8, Snapshot@1/binary>>/binary, "\"."/utf8>>
))/binary>>;
cannot_read_user_input ->
<<"I couldn't read the user input."/utf8>>;
{corrupted_snapshot, Source@2} ->
<<<<<<<<"It looks like "/utf8,
(gleam_community@ansi:italic(
<<<<"\""/utf8, Source@2/binary>>/binary,
"\"\n"/utf8>>
))/binary>>/binary,
"is not a valid snapshot.\n"/utf8>>/binary,
"This might happen when someone modifies its content.\n"/utf8>>/binary,
"Try deleting the snapshot and recreating it."/utf8>>;
{cannot_find_project_root, Reason@8} ->
<<<<(Heading(Reason@8))/binary,
"I couldn't locate the project's root where the snapshot's"/utf8>>/binary,
" folder should be."/utf8>>;
{cannot_get_titles, {cannot_find_project_root, Reason@8}} ->
<<<<(Heading(Reason@8))/binary,
"I couldn't locate the project's root where the snapshot's"/utf8>>/binary,
" folder should be."/utf8>>;
{cannot_get_titles, {cannot_read_test_directory, Reason@9}} ->
<<(Heading(Reason@9))/binary,
"I couldn't list the contents of the test folder."/utf8>>;
{cannot_get_titles, {cannot_read_test_file, Reason@10, File}} ->
<<<<(Heading(Reason@10))/binary,
"I couldn't read the test file "/utf8>>/binary,
(gleam_community@ansi:italic(
<<<<"\""/utf8, File/binary>>/binary, "\"\n"/utf8>>
))/binary>>;
{cannot_get_titles,
{duplicate_literal_titles,
Title@1,
{test_info, One_file, One_test_name},
{test_info, Other_file, Other_test_name}}} ->
Same_file = One_file =:= Other_file,
Same_function = One_test_name =:= Other_test_name,
Location = case {Same_file, Same_function} of
{true, true} ->
<<"Both tests are defined in:\n\n "/utf8,
(gleam_community@ansi:italic(
to_function_name(One_file, One_test_name)
))/binary>>;
{_, _} ->
<<<<<<"One test is defined in:\n\n "/utf8,
(gleam_community@ansi:italic(
to_function_name(One_file, One_test_name)
))/binary>>/binary,
"\n\nWhile the other is defined in:\n\n "/utf8>>/binary,
(gleam_community@ansi:italic(
to_function_name(Other_file, Other_test_name)
))/binary>>
end,
<<<<<<<<<<"It looks like there's some snapshot tests sharing the same title:
"/utf8,
(gleam_community@ansi:italic(
<<<<"\""/utf8, Title@1/binary>>/binary,
"\""/utf8>>
))/binary>>/binary,
"
Snapshot titles "/utf8>>/binary,
(gleam_community@ansi:bold(<<"must be unique"/utf8>>))/binary>>/binary,
" or you would run into strange diffs
when reviewing them, try changing one of those.
"/utf8>>/binary,
Location/binary>>;
{cannot_get_titles, {overlapping_prefixes, _, _, _, _}} ->
erlang:error(#{gleam_error => panic,
message => <<"Prefixes are not implemented yet"/utf8>>,
module => <<"birdie"/utf8>>,
function => <<"explain"/utf8>>,
line => 515});
{cannot_get_titles, {prefix_overlapping_with_literal_title, _, _, _}} ->
erlang:error(#{gleam_error => panic,
message => <<"Prefixes are not implemented yet"/utf8>>,
module => <<"birdie"/utf8>>,
function => <<"explain"/utf8>>,
line => 518})
end,
Message.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 544).
-spec snapshot_default_lines(snapshot(any())) -> list(info_line()).
snapshot_default_lines(Snapshot) ->
{snapshot, Title, _, Info} = Snapshot,
case Info of
none ->
[{info_line_with_title, Title, split_words, <<"title"/utf8>>}];
{some, {test_info, File, Test_name}} ->
[{info_line_with_title, Title, split_words, <<"title"/utf8>>},
{info_line_with_title, File, truncate, <<"file"/utf8>>},
{info_line_with_title, Test_name, truncate, <<"name"/utf8>>}]
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 658).
-spec pretty_diff_line(birdie@internal@diff:diff_line(), integer()) -> binary().
pretty_diff_line(Diff_line, Padding) ->
{diff_line, Number, Line, Kind} = Diff_line,
{Pretty_number, Pretty_line, Separator} = case Kind of
shared ->
{begin
_pipe = erlang:integer_to_binary(Number),
_pipe@1 = gleam@string:pad_start(
_pipe,
Padding - 1,
<<" "/utf8>>
),
gleam_community@ansi:dim(_pipe@1)
end,
gleam_community@ansi:dim(Line),
<<" │ "/utf8>>};
new ->
{begin
_pipe@2 = erlang:integer_to_binary(Number),
_pipe@3 = gleam@string:pad_start(
_pipe@2,
Padding - 1,
<<" "/utf8>>
),
_pipe@4 = gleam_community@ansi:green(_pipe@3),
gleam_community@ansi:bold(_pipe@4)
end,
gleam_community@ansi:green(Line),
gleam_community@ansi:green(<<" + "/utf8>>)};
old ->
Number@1 = begin
_pipe@5 = (<<" "/utf8,
(erlang:integer_to_binary(Number))/binary>>),
gleam@string:pad_end(_pipe@5, Padding - 1, <<" "/utf8>>)
end,
{gleam_community@ansi:red(Number@1),
gleam_community@ansi:red(Line),
gleam_community@ansi:red(<<" - "/utf8>>)}
end,
<<<<Pretty_number/binary, Separator/binary>>/binary, Pretty_line/binary>>.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 692).
-spec truncate(binary(), integer()) -> binary().
truncate(String, Max_length) ->
case string:length(String) > Max_length of
false ->
String;
true ->
_pipe = gleam@string:to_graphemes(String),
_pipe@1 = gleam@list:take(_pipe, Max_length - 3),
_pipe@2 = gleam@string:join(_pipe@1, <<""/utf8>>),
gleam@string:append(_pipe@2, <<"..."/utf8>>)
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 710).
-spec do_to_lines(
list(binary()),
binary(),
integer(),
list(binary()),
integer()
) -> list(binary()).
do_to_lines(Lines, Line, Line_length, Words, Max_length) ->
case Words of
[] ->
case Line =:= <<""/utf8>> of
true ->
lists:reverse(Lines);
false ->
lists:reverse([Line | Lines])
end;
[Word | Rest] ->
Word_length = string:length(Word),
New_line_length = (Word_length + Line_length) + 1,
case New_line_length > Max_length of
true ->
do_to_lines(
[Line | Lines],
<<""/utf8>>,
0,
Words,
Max_length
);
false ->
New_line = case Line of
<<""/utf8>> ->
Word;
_ ->
<<<<Line/binary, " "/utf8>>/binary, Word/binary>>
end,
do_to_lines(
Lines,
New_line,
New_line_length,
Rest,
Max_length
)
end
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 703).
-spec to_lines(binary(), integer()) -> list(binary()).
to_lines(String, Max_length) ->
gleam@list:flat_map(
gleam@string:split(String, <<"\n"/utf8>>),
fun(Line) ->
Words = gleam@string:split(Line, <<" "/utf8>>),
do_to_lines([], <<""/utf8>>, 0, Words, Max_length)
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 635).
-spec pretty_info_line(info_line(), integer()) -> binary().
pretty_info_line(Line, Width) ->
{Prefix, Prefix_length} = case Line of
{info_line_with_no_title, _, _} ->
{<<" "/utf8>>, 2};
{info_line_with_title, _, _, Title} ->
{<<" "/utf8,
(gleam_community@ansi:blue(<<Title/binary, ": "/utf8>>))/binary>>,
string:length(Title) + 4}
end,
case erlang:element(3, Line) of
truncate ->
<<Prefix/binary,
(truncate(erlang:element(2, Line), Width - Prefix_length))/binary>>;
do_not_split ->
<<Prefix/binary, (erlang:element(2, Line))/binary>>;
split_words ->
case to_lines(erlang:element(2, Line), Width - Prefix_length) of
[] ->
Prefix;
[Line@1 | Lines] ->
gleam@list:fold(
Lines,
<<Prefix/binary, Line@1/binary>>,
fun(Acc, Line@2) ->
<<<<<<Acc/binary, "\n"/utf8>>/binary,
(gleam@string:repeat(
<<" "/utf8>>,
Prefix_length
))/binary>>/binary,
Line@2/binary>>
end
)
end
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 751).
-spec command_to_string(command()) -> binary().
command_to_string(Command) ->
case Command of
review ->
<<"review"/utf8>>;
accept_all ->
<<"accept-all"/utf8>>;
reject_all ->
<<"reject-all"/utf8>>;
help ->
<<"help"/utf8>>
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 789).
-spec parse_command(list(binary())) -> {ok, command()} | {error, nil}.
parse_command(Arguments) ->
case Arguments of
[] ->
{ok, review};
[<<"review"/utf8>>] ->
{ok, review};
[<<"accept-all"/utf8>>] ->
{ok, accept_all};
[<<"accept"/utf8>>, <<"all"/utf8>>] ->
{ok, accept_all};
[<<"reject-all"/utf8>>] ->
{ok, reject_all};
[<<"reject"/utf8>>, <<"all"/utf8>>] ->
{ok, reject_all};
[<<"help"/utf8>>] ->
{ok, help};
_ ->
{error, nil}
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 828).
-spec closest_command(binary()) -> {ok, command()} | {error, nil}.
closest_command(String) ->
Distance = fun(C) -> _pipe = command_to_string(C),
edit_distance@levenshtein:distance(_pipe, String) end,
_pipe@1 = [review, accept_all, reject_all, help],
_pipe@2 = gleam@list:map(
_pipe@1,
fun(Command) -> {Command, Distance(Command)} end
),
_pipe@3 = gleam@list:filter(
_pipe@2,
fun(Command@1) -> erlang:element(2, Command@1) =< 3 end
),
_pipe@4 = gleam@list:sort(
_pipe@3,
fun(One, Other) ->
gleam@int:compare(erlang:element(2, One), erlang:element(2, Other))
end
),
_pipe@5 = gleam@list:first(_pipe@4),
gleam@result:map(_pipe@5, fun(Pair) -> erlang:element(1, Pair) end).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 1003).
-spec help_text() -> binary().
help_text() ->
<<<<<<<<<<<<<<<<<<<<(gleam_community@ansi:yellow(<<"USAGE:\n"/utf8>>))/binary,
" gleam run -m birdie [ <SUBCOMMAND> ]\n\n"/utf8>>/binary,
(gleam_community@ansi:yellow(
<<"SUBCOMMANDS:\n"/utf8>>
))/binary>>/binary,
(gleam_community@ansi:green(
<<" review "/utf8>>
))/binary>>/binary,
"Review all new snapshots one by one\n"/utf8>>/binary,
(gleam_community@ansi:green(
<<" accept-all "/utf8>>
))/binary>>/binary,
"Accept all new snapshots\n"/utf8>>/binary,
(gleam_community@ansi:green(<<" reject-all "/utf8>>))/binary>>/binary,
"Reject all new snapshots\n"/utf8>>/binary,
(gleam_community@ansi:green(<<" help "/utf8>>))/binary>>/binary,
"Show this help text\n"/utf8>>.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 1017).
-spec unexpected_subcommand(binary()) -> nil.
unexpected_subcommand(Subcommand) ->
Error_message = <<<<<<(gleam_community@ansi:bold(<<"Error: "/utf8>>))/binary,
"\""/utf8>>/binary,
Subcommand/binary>>/binary,
"\" isn't a valid subcommand."/utf8>>,
gleam_stdlib:println(
<<<<(gleam_community@ansi:red(Error_message))/binary, "\n\n"/utf8>>/binary,
(help_text())/binary>>
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 1024).
-spec more_than_one_command(list(binary())) -> nil.
more_than_one_command(Subcommands) ->
Error_message = <<<<(gleam_community@ansi:bold(<<"Error: "/utf8>>))/binary,
"I can only run one subcommand at a time, but more than one were provided: "/utf8>>/binary,
(gleam@string:join(
gleam@list:map(
Subcommands,
fun(S) -> <<<<"\""/utf8, S/binary>>/binary, "\""/utf8>> end
),
<<", "/utf8>>
))/binary>>,
gleam_stdlib:println(
<<<<(gleam_community@ansi:red(Error_message))/binary, "\n\n"/utf8>>/binary,
(help_text())/binary>>
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 1033).
-spec report_status({ok, nil} | {error, error()}) -> nil.
report_status(Result) ->
case Result of
{ok, nil} ->
gleam_stdlib:println(
gleam_community@ansi:green(<<"🐦⬛ Done!"/utf8>>)
);
{error, Error} ->
gleam_stdlib:println_error(<<"❌ "/utf8, (explain(Error))/binary>>)
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 937).
-spec ask_choice() -> {ok, review_choice()} | {error, error()}.
ask_choice() ->
gleam_stdlib:println(
<<<<<<<<<<<<<<<<(gleam_community@ansi:bold(
gleam_community@ansi:green(
<<" a"/utf8>>
)
))/binary,
" accept "/utf8>>/binary,
(gleam_community@ansi:dim(
<<"accept the new snapshot\n"/utf8>>
))/binary>>/binary,
(gleam_community@ansi:bold(
gleam_community@ansi:red(<<" r"/utf8>>)
))/binary>>/binary,
" reject "/utf8>>/binary,
(gleam_community@ansi:dim(
<<"reject the new snapshot\n"/utf8>>
))/binary>>/binary,
(gleam_community@ansi:bold(
gleam_community@ansi:yellow(<<" s"/utf8>>)
))/binary>>/binary,
" skip "/utf8>>/binary,
(gleam_community@ansi:dim(<<"skip the snapshot for now\n"/utf8>>))/binary>>
),
birdie_ffi_erl:clear_line(),
case gleam@result:map(
gleam_erlang_ffi:get_line(<<"> "/utf8>>),
fun gleam@string:trim/1
) of
{ok, <<"a"/utf8>>} ->
{ok, accept_snapshot};
{ok, <<"r"/utf8>>} ->
{ok, reject_snapshot};
{ok, <<"s"/utf8>>} ->
{ok, skip_snapshot};
{ok, _} ->
birdie_ffi_erl:cursor_up(5),
ask_choice();
{error, _} ->
{error, cannot_read_user_input}
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 1057).
-spec terminal_width() -> integer().
terminal_width() ->
gleam@result:unwrap(birdie_ffi_erl:terminal_width(), 80).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 596).
-spec pretty_box(
binary(),
list(birdie@internal@diff:diff_line()),
list(info_line())
) -> binary().
pretty_box(Title, Content_lines, Info_lines) ->
Width = terminal_width(),
_assert_subject = begin
Lines_count = erlang:length(Content_lines) + 1,
gleam@result:'try'(
gleam@int:digits(Lines_count, 10),
fun(Digits) -> {ok, (erlang:length(Digits) * 2) + 5} end
)
end,
{ok, Padding} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail,
module => <<"birdie"/utf8>>,
function => <<"pretty_box"/utf8>>,
line => 602})
end,
Title_length = string:length(Title),
Title_line_right = gleam@string:repeat(
<<"─"/utf8>>,
(Width - 5) - Title_length
),
Title_line = <<<<<<"── "/utf8, Title/binary>>/binary, " ─"/utf8>>/binary,
Title_line_right/binary>>,
Info_lines@1 = begin
_pipe = gleam@list:map(
Info_lines,
fun(_capture) -> pretty_info_line(_capture, Width) end
),
gleam@string:join(_pipe, <<"\n"/utf8>>)
end,
Content = begin
_pipe@1 = gleam@list:map(
Content_lines,
fun(_capture@1) -> pretty_diff_line(_capture@1, Padding) end
),
gleam@string:join(_pipe@1, <<"\n"/utf8>>)
end,
Left_padding_line = gleam@string:repeat(<<"─"/utf8>>, Padding),
Right_padding_line = gleam@string:repeat(
<<"─"/utf8>>,
(Width - Padding) - 1
),
Open_line = <<<<Left_padding_line/binary, "┬"/utf8>>/binary,
Right_padding_line/binary>>,
Closed_line = <<<<Left_padding_line/binary, "┴"/utf8>>/binary,
Right_padding_line/binary>>,
_pipe@2 = [Title_line,
<<""/utf8>>,
Info_lines@1,
<<""/utf8>>,
Open_line,
Content,
Closed_line],
gleam@string:join(_pipe@2, <<"\n"/utf8>>).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 556).
-spec new_snapshot_box(snapshot(new()), list(info_line())) -> binary().
new_snapshot_box(Snapshot, Additional_info_lines) ->
{snapshot, _, Content, _} = Snapshot,
Content@1 = begin
_pipe = gleam@string:split(Content, <<"\n"/utf8>>),
gleam@list:index_map(
_pipe,
fun(Line, I) -> {diff_line, I + 1, Line, new} end
)
end,
pretty_box(
<<"new snapshot"/utf8>>,
Content@1,
gleam@list:flatten(
[snapshot_default_lines(Snapshot), Additional_info_lines]
)
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 575).
-spec diff_snapshot_box(
snapshot(accepted()),
snapshot(new()),
list(info_line())
) -> binary().
diff_snapshot_box(Accepted, New, Additional_info_lines) ->
pretty_box(
<<"mismatched snapshots"/utf8>>,
to_diff_lines(Accepted, New),
begin
_pipe = [snapshot_default_lines(Accepted),
Additional_info_lines,
[{info_line_with_no_title, <<""/utf8>>, do_not_split},
{info_line_with_no_title,
gleam_community@ansi:red(<<"- old snapshot"/utf8>>),
do_not_split},
{info_line_with_no_title,
gleam_community@ansi:green(<<"+ new snapshot"/utf8>>),
do_not_split}]],
gleam@list:flatten(_pipe)
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 244).
-spec serialise(snapshot(new())) -> binary().
serialise(Snapshot) ->
{snapshot, Title, Content, Info} = Snapshot,
Info_lines = case Info of
none ->
[];
{some, {test_info, File, Test_name}} ->
[<<"file: "/utf8, File/binary>>,
<<"test_name: "/utf8, Test_name/binary>>]
end,
_pipe = [[<<"---"/utf8>>,
<<"version: "/utf8, "1.2.5"/utf8>>,
<<"title: "/utf8,
(gleam@string:replace(Title, <<"\n"/utf8>>, <<"\\n"/utf8>>))/binary>>],
Info_lines,
[<<"---"/utf8>>, Content]],
_pipe@1 = gleam@list:flatten(_pipe),
gleam@string:join(_pipe@1, <<"\n"/utf8>>).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 275).
-spec save(snapshot(new()), binary()) -> {ok, nil} | {error, error()}.
save(Snapshot, Destination) ->
case gleam_stdlib:string_ends_with(Destination, <<".new"/utf8>>) of
false ->
erlang:error(#{gleam_error => panic,
message => <<"Looks like I've messed up something, all new snapshots should have the `.new` extension"/utf8>>,
module => <<"birdie"/utf8>>,
function => <<"save"/utf8>>,
line => 281});
true ->
_pipe = simplifile:write(Destination, serialise(Snapshot)),
gleam@result:map_error(
_pipe,
fun(_capture) ->
{cannot_save_new_snapshot,
_capture,
erlang:element(2, Snapshot),
Destination}
end
)
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 356).
-spec accept_snapshot(binary(), birdie@internal@titles:titles()) -> {ok, nil} |
{error, error()}.
accept_snapshot(New_snapshot_path, Titles) ->
gleam@result:'try'(
read_new(New_snapshot_path),
fun(Snapshot) ->
{snapshot, Title, Content, _} = Snapshot,
Accepted_snapshot_path = to_accepted_path(New_snapshot_path),
case birdie@internal@titles:find(Titles, Title) of
{ok, {literal, Info}} ->
Delete_new_snapshot = begin
_pipe = simplifile_erl:delete(New_snapshot_path),
gleam@result:map_error(
_pipe,
fun(_capture) ->
{cannot_accept_snapshot,
_capture,
New_snapshot_path}
end
)
end,
gleam@result:'try'(
Delete_new_snapshot,
fun(_) ->
_pipe@1 = {snapshot, Title, Content, {some, Info}},
_pipe@2 = serialise(_pipe@1),
_pipe@3 = simplifile:write(
Accepted_snapshot_path,
_pipe@2
),
gleam@result:map_error(
_pipe@3,
fun(_capture@1) ->
{cannot_accept_snapshot,
_capture@1,
Accepted_snapshot_path}
end
)
end
);
{ok, {prefix, Info, _}} ->
Delete_new_snapshot = begin
_pipe = simplifile_erl:delete(New_snapshot_path),
gleam@result:map_error(
_pipe,
fun(_capture) ->
{cannot_accept_snapshot,
_capture,
New_snapshot_path}
end
)
end,
gleam@result:'try'(
Delete_new_snapshot,
fun(_) ->
_pipe@1 = {snapshot, Title, Content, {some, Info}},
_pipe@2 = serialise(_pipe@1),
_pipe@3 = simplifile:write(
Accepted_snapshot_path,
_pipe@2
),
gleam@result:map_error(
_pipe@3,
fun(_capture@1) ->
{cannot_accept_snapshot,
_capture@1,
Accepted_snapshot_path}
end
)
end
);
{error, _} ->
_pipe@4 = simplifile_erl:rename_file(
New_snapshot_path,
Accepted_snapshot_path
),
gleam@result:map_error(
_pipe@4,
fun(_capture@2) ->
{cannot_accept_snapshot,
_capture@2,
New_snapshot_path}
end
)
end
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 871).
-spec do_review(
list(binary()),
birdie@internal@titles:titles(),
integer(),
integer()
) -> {ok, nil} | {error, error()}.
do_review(New_snapshot_paths, Titles, Current, Out_of) ->
case New_snapshot_paths of
[] ->
{ok, nil};
[New_snapshot_path | Rest] ->
birdie_ffi_erl:clear(),
gleam@result:'try'(
read_new(New_snapshot_path),
fun(New_snapshot) ->
New_snapshot_info = case birdie@internal@titles:find(
Titles,
erlang:element(2, New_snapshot)
) of
{ok, {prefix, Info, _}} ->
{some, Info};
{ok, {literal, Info}} ->
{some, Info};
{error, _} ->
none
end,
New_snapshot@1 = erlang:setelement(
4,
New_snapshot,
New_snapshot_info
),
Accepted_snapshot_path = to_accepted_path(New_snapshot_path),
gleam@result:'try'(
read_accepted(Accepted_snapshot_path),
fun(Accepted_snapshot) ->
Progress = <<<<<<(gleam_community@ansi:dim(
<<"Reviewing "/utf8>>
))/binary,
(gleam_community@ansi:bold(
gleam_community@ansi:yellow(
rank:ordinalise(Current)
)
))/binary>>/binary,
(gleam_community@ansi:dim(
<<" out of "/utf8>>
))/binary>>/binary,
(gleam_community@ansi:bold(
gleam_community@ansi:yellow(
erlang:integer_to_binary(Out_of)
)
))/binary>>,
Box = case Accepted_snapshot of
none ->
new_snapshot_box(New_snapshot@1, []);
{some, Accepted_snapshot@1} ->
diff_snapshot_box(
Accepted_snapshot@1,
New_snapshot@1,
[]
)
end,
gleam_stdlib:println(
<<<<<<Progress/binary, "\n\n"/utf8>>/binary,
Box/binary>>/binary,
"\n"/utf8>>
),
gleam@result:'try'(
ask_choice(),
fun(Choice) -> gleam@result:'try'(case Choice of
accept_snapshot ->
accept_snapshot(
New_snapshot_path,
Titles
);
reject_snapshot ->
reject_snapshot(
New_snapshot_path
);
skip_snapshot ->
{ok, nil}
end, fun(_) ->
do_review(
Rest,
Titles,
Current + 1,
Out_of
)
end) end
)
end
)
end
)
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 998).
-spec help() -> nil.
help() ->
Version = <<<<(gleam_community@ansi:green(<<"🐦⬛ birdie "/utf8>>))/binary,
"v"/utf8>>/binary,
"1.2.5"/utf8>>,
gleam_stdlib:println(
<<<<Version/binary, "\n\n"/utf8>>/binary, (help_text())/binary>>
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 345).
-spec find_snapshots_folder() -> {ok, binary()} | {error, error()}.
find_snapshots_folder() ->
Result = gleam@result:map_error(
birdie@internal@project:find_root(),
fun(Field@0) -> {cannot_find_project_root, Field@0} end
),
gleam@result:'try'(
Result,
fun(Project_root) ->
Snapshots_folder = filepath:join(
Project_root,
<<"birdie_snapshots"/utf8>>
),
case simplifile_erl:create_directory(Snapshots_folder) of
{ok, nil} ->
{ok, Snapshots_folder};
{error, eexist} ->
{ok, Snapshots_folder};
{error, Error} ->
{error, {cannot_create_snapshots_folder, Error}}
end
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 121).
-spec do_snap(binary(), binary()) -> {ok, outcome()} | {error, error()}.
do_snap(Content, Title) ->
gleam@result:'try'(
validate_snapshot_title(Title),
fun(_) ->
gleam@result:'try'(
find_snapshots_folder(),
fun(Folder) ->
New = {snapshot, Title, Content, none},
New_snapshot_path = new_destination(New, Folder),
Accepted_snapshot_path = to_accepted_path(New_snapshot_path),
gleam@result:'try'(
read_accepted(Accepted_snapshot_path),
fun(Accepted) -> case Accepted of
none ->
gleam@result:'try'(
save(New, New_snapshot_path),
fun(_) ->
{ok,
{new_snapshot_created,
New,
New_snapshot_path}}
end
);
{some, Accepted@1} ->
gleam@bool:guard(
erlang:element(3, Accepted@1) =:= erlang:element(
3,
New
),
{ok, same},
fun() ->
gleam@result:'try'(
save(New, New_snapshot_path),
fun(_) ->
{ok,
{different,
Accepted@1,
New}}
end
)
end
)
end end
)
end
)
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 839).
-spec review() -> {ok, nil} | {error, error()}.
review() ->
gleam@result:'try'(
find_snapshots_folder(),
fun(Snapshots_folder) ->
Get_titles = birdie@internal@titles:from_test_directory(),
gleam@result:'try'(
gleam@result:map_error(
Get_titles,
fun(Field@0) -> {cannot_get_titles, Field@0} end
),
fun(Titles) ->
gleam@result:'try'(
list_new_snapshots(Snapshots_folder),
fun(New_snapshots) ->
case erlang:length(New_snapshots) of
0 ->
gleam_stdlib:println(
<<"No new snapshots to review."/utf8>>
),
{ok, nil};
N ->
Result = do_review(
New_snapshots,
Titles,
1,
N
),
birdie_ffi_erl:clear(),
gleam@result:'try'(
Result,
fun(_) ->
gleam_stdlib:println(case N of
1 ->
<<"Reviewed one snapshot"/utf8>>;
N@1 ->
<<<<"Reviewed "/utf8,
(erlang:integer_to_binary(
N@1
))/binary>>/binary,
" snapshots"/utf8>>
end),
{ok, nil}
end
)
end
end
)
end
)
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 967).
-spec accept_all() -> {ok, nil} | {error, error()}.
accept_all() ->
gleam_stdlib:println(<<"Looking for new snapshots..."/utf8>>),
gleam@result:'try'(
find_snapshots_folder(),
fun(Snapshots_folder) ->
gleam@result:'try'(
list_new_snapshots(Snapshots_folder),
fun(New_snapshots) ->
Get_titles = birdie@internal@titles:from_test_directory(),
gleam@result:'try'(
gleam@result:map_error(
Get_titles,
fun(Field@0) -> {cannot_get_titles, Field@0} end
),
fun(Titles) ->
case erlang:length(New_snapshots) of
0 ->
gleam_stdlib:println(
<<"No new snapshots to accept."/utf8>>
);
1 ->
gleam_stdlib:println(
<<"Accepting one new snapshot."/utf8>>
);
N ->
gleam_stdlib:println(
<<<<"Accepting "/utf8,
(erlang:integer_to_binary(N))/binary>>/binary,
" new snapshots."/utf8>>
)
end,
gleam@list:try_each(
New_snapshots,
fun(_capture) ->
accept_snapshot(_capture, Titles)
end
)
end
)
end
)
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 984).
-spec reject_all() -> {ok, nil} | {error, error()}.
reject_all() ->
gleam_stdlib:println(<<"Looking for new snapshots..."/utf8>>),
gleam@result:'try'(
find_snapshots_folder(),
fun(Snapshots_folder) ->
gleam@result:'try'(
list_new_snapshots(Snapshots_folder),
fun(New_snapshots) ->
case erlang:length(New_snapshots) of
0 ->
gleam_stdlib:println(
<<"No new snapshots to reject."/utf8>>
);
1 ->
gleam_stdlib:println(
<<"Rejecting one new snapshot."/utf8>>
);
N ->
gleam_stdlib:println(
<<<<"Rejecting "/utf8,
(erlang:integer_to_binary(N))/binary>>/binary,
" new snapshots."/utf8>>
)
end,
gleam@list:try_each(New_snapshots, fun reject_snapshot/1)
end
)
end
).
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 799).
-spec run_command(command()) -> nil.
run_command(Command) ->
case Command of
review ->
report_status(review());
accept_all ->
report_status(accept_all());
reject_all ->
report_status(reject_all());
help ->
help()
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 808).
-spec suggest_run_command(binary(), command()) -> nil.
suggest_run_command(Invalid, Command) ->
Error_message = <<<<<<(gleam_community@ansi:bold(<<"Error: "/utf8>>))/binary,
"\""/utf8>>/binary,
Invalid/binary>>/binary,
"\" isn't a valid subcommand."/utf8>>,
gleam_stdlib:println(gleam_community@ansi:red(Error_message)),
Msg = <<<<"I think you misspelled `"/utf8,
(command_to_string(Command))/binary>>/binary,
"`, would you like me to run it instead? [Y/n] "/utf8>>,
case gleam_erlang_ffi:get_line(Msg) of
{error, _} ->
nil;
{ok, Line} ->
case begin
_pipe = string:lowercase(Line),
gleam@string:trim(_pipe)
end of
<<"yes"/utf8>> ->
run_command(Command);
<<"y"/utf8>> ->
run_command(Command);
<<""/utf8>> ->
run_command(Command);
_ ->
gleam_stdlib:println(<<"\n"/utf8, (help_text())/binary>>)
end
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 773).
-spec main() -> nil.
main() ->
Args = erlang:element(4, argv:load()),
case parse_command(Args) of
{ok, Command} ->
run_command(Command);
{error, _} ->
case Args of
[Subcommand] ->
case closest_command(Subcommand) of
{ok, Command@1} ->
suggest_run_command(Subcommand, Command@1);
{error, nil} ->
unexpected_subcommand(Subcommand)
end;
Subcommands ->
more_than_one_command(Subcommands)
end
end.
-file("/home/runner/work/birdie/birdie/src/birdie.gleam", 86).
-spec snap(binary(), binary()) -> nil.
snap(Content, Title) ->
case do_snap(Content, Title) of
{ok, same} ->
nil;
{ok, {new_snapshot_created, Snapshot, _}} ->
Hint_message = gleam_community@ansi:yellow(
<<"run `gleam run -m birdie` to review the snapshots"/utf8>>
),
Hint = {info_line_with_title,
Hint_message,
do_not_split,
<<"hint"/utf8>>},
Box = new_snapshot_box(Snapshot, [Hint]),
gleam_stdlib:println_error(
<<<<"\n\n"/utf8, Box/binary>>/binary, "\n"/utf8>>
),
erlang:error(#{gleam_error => panic,
message => <<"Birdie snapshot test failed"/utf8>>,
module => <<"birdie"/utf8>>,
function => <<"snap"/utf8>>,
line => 96});
{ok, {different, Accepted, New}} ->
Hint_message@1 = gleam_community@ansi:yellow(
<<"run `gleam run -m birdie` to review the snapshots"/utf8>>
),
Hint@1 = {info_line_with_title,
Hint_message@1,
do_not_split,
<<"hint"/utf8>>},
Box@1 = diff_snapshot_box(Accepted, New, [Hint@1]),
gleam_stdlib:println_error(
<<<<"\n\n"/utf8, Box@1/binary>>/binary, "\n"/utf8>>
),
erlang:error(#{gleam_error => panic,
message => <<"Birdie snapshot test failed"/utf8>>,
module => <<"birdie"/utf8>>,
function => <<"snap"/utf8>>,
line => 105});
{error, Error} ->
Panic_message = <<"Birdie snapshot test failed\n"/utf8,
(explain(Error))/binary>>,
erlang:error(#{gleam_error => panic,
message => Panic_message,
module => <<"birdie"/utf8>>,
function => <<"snap"/utf8>>,
line => 110})
end.