-module(glitzer@spinner). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/glitzer/spinner.gleam"). -export([frames_from_list/1, new_spinner/1, default_spinner/0, bar_up_down_spinner/0, pulsating_spinner/0, bar_left_right_spinner/0, spinning_spinner/0, with_left_text/2, with_frames/2, with_frame_transform/2, with_right_text/2, with_tick_rate/2, prideful_spinner/0, with_finish_text/2, tick/1, tick_by/2, finish/1, get_current_frame_string/1, print_spinner/1, spin/1]). -export_type([state/0, frames/0, spinner_style/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. -type state() :: {state, frames(), fun((binary()) -> binary()), binary(), binary(), integer(), boolean(), gleam@option:option(repeatedly:repeater(state()))}. -opaque frames() :: {frames, glearray:array(binary())}. -type spinner_style() :: {spinner_style, integer(), binary(), state()}. -file("src/glitzer/spinner.gleam", 59). ?DOC(" Convert a given list of `String` to `Frames`.\n"). -spec frames_from_list(list(binary())) -> frames(). frames_from_list(Frames) -> {frames, erlang:list_to_tuple(Frames)}. -file("src/glitzer/spinner.gleam", 64). ?DOC(" Create a new spinner from `Frames` with a 100ms tick rate.\n"). -spec new_spinner(frames()) -> spinner_style(). new_spinner(F) -> {spinner_style, 100, <<""/utf8>>, {state, F, fun gleam@function:identity/1, <<""/utf8>>, <<""/utf8>>, 0, false, none}}. -file("src/glitzer/spinner.gleam", 83). ?DOC(" The default spinner.\n"). -spec default_spinner() -> spinner_style(). default_spinner() -> Frames = [<<"|"/utf8>>, <<"/"/utf8>>, <<"-"/utf8>>, <<"\\"/utf8>>], new_spinner(frames_from_list(Frames)). -file("src/glitzer/spinner.gleam", 89). ?DOC(" A spinner with a bar that goes up and down.\n"). -spec bar_up_down_spinner() -> spinner_style(). bar_up_down_spinner() -> Frames = [<<"\x{2581}"/utf8>>, <<"\x{2582}"/utf8>>, <<"\x{2583}"/utf8>>, <<"\x{2584}"/utf8>>, <<"\x{2585}"/utf8>>, <<"\x{2586}"/utf8>>, <<"\x{2587}"/utf8>>, <<"\x{2588}"/utf8>>, <<"\x{2587}"/utf8>>, <<"\x{2586}"/utf8>>, <<"\x{2585}"/utf8>>, <<"\x{2584}"/utf8>>, <<"\x{2583}"/utf8>>, <<"\x{2582}"/utf8>>], new_spinner(frames_from_list(Frames)). -file("src/glitzer/spinner.gleam", 99). ?DOC(" A spinner that pulsates.\n"). -spec pulsating_spinner() -> spinner_style(). pulsating_spinner() -> Frames = [<<"\x{2591}"/utf8>>, <<"\x{2592}"/utf8>>, <<"\x{2593}"/utf8>>, <<"\x{2588}"/utf8>>, <<"\x{2593}"/utf8>>, <<"\x{2592}"/utf8>>], new_spinner(frames_from_list(Frames)). -file("src/glitzer/spinner.gleam", 107). ?DOC(" A spinner that goes from left to right and back.\n"). -spec bar_left_right_spinner() -> spinner_style(). bar_left_right_spinner() -> Frames = [<<"\x{258f}"/utf8>>, <<"\x{258e}"/utf8>>, <<"\x{258d}"/utf8>>, <<"\x{258c}"/utf8>>, <<"\x{258b}"/utf8>>, <<"\x{258a}"/utf8>>, <<"\x{2589}"/utf8>>, <<"\x{2588}"/utf8>>, <<"\x{2589}"/utf8>>, <<"\x{258a}"/utf8>>, <<"\x{258b}"/utf8>>, <<"\x{258c}"/utf8>>, <<"\x{258d}"/utf8>>, <<"\x{258e}"/utf8>>], new_spinner(frames_from_list(Frames)). -file("src/glitzer/spinner.gleam", 117). ?DOC(" A spinner that actually spins.\n"). -spec spinning_spinner() -> spinner_style(). spinning_spinner() -> Frames = [<<"\x{28fe}"/utf8>>, <<"\x{28f7}"/utf8>>, <<"\x{28ef}"/utf8>>, <<"\x{28df}"/utf8>>, <<"\x{287f}"/utf8>>, <<"\x{28bf}"/utf8>>, <<"\x{28fb}"/utf8>>, <<"\x{28fd}"/utf8>>], new_spinner(frames_from_list(Frames)). -file("src/glitzer/spinner.gleam", 162). ?DOC(" Set the left text of the spinner.\n"). -spec with_left_text(spinner_style(), binary()) -> spinner_style(). with_left_text(S, T) -> S@1 = begin _record = S, {spinner_style, erlang:element(2, _record), erlang:element(3, _record), begin _record@1 = erlang:element(4, S), {state, erlang:element(2, _record@1), erlang:element(3, _record@1), T, erlang:element(5, _record@1), erlang:element(6, _record@1), erlang:element(7, _record@1), erlang:element(8, _record@1)} end} end, case erlang:element(8, erlang:element(4, S@1)) of {some, Repeater} -> repeatedly:set_state(Repeater, erlang:element(4, S@1)); none -> nil end, S@1. -file("src/glitzer/spinner.gleam", 173). ?DOC( " Set the frames of the spinner. Useful if you want to update the frames of\n" " an already running spinner.\n" ). -spec with_frames(spinner_style(), frames()) -> spinner_style(). with_frames(S, F) -> S@1 = begin _record = S, {spinner_style, erlang:element(2, _record), erlang:element(3, _record), begin _record@1 = erlang:element(4, S), {state, F, erlang:element(3, _record@1), erlang:element(4, _record@1), erlang:element(5, _record@1), erlang:element(6, _record@1), erlang:element(7, _record@1), erlang:element(8, _record@1)} end} end, case erlang:element(8, erlang:element(4, S@1)) of {some, Repeater} -> repeatedly:set_state(Repeater, erlang:element(4, S@1)); none -> nil end, S@1. -file("src/glitzer/spinner.gleam", 210). ?DOC( " Set a transformation function that will be applied for each frame. This can\n" " be every function with the signature `fn(String) -> String`.\n" "\n" "
\n" " Example:\n" "\n" " ```gleam\n" " import glitzer/spinner\n" " import gleam_community/ansi\n" "\n" " fn example() {\n" " let s =\n" " spinner.default_spinner()\n" " |> spinner.with_frame_transform(ansi.pink) // make all frames pink\n" " |> spinner.spin\n" "\n" " // do some cool stuff\n" "\n" " // update the spinner color and the spinner frames\n" " spinner.with_frame_transform(s, ansi.green)\n" " |> spinner.with_frames(spinner.frames_from_list([\"a\", \"s\", \"d\", \"f\"]))\n" "\n" " // do some other stuff\n" " \n" " spinner.finish(s)\n" " }\n" " ```\n" "
\n" ). -spec with_frame_transform(spinner_style(), fun((binary()) -> binary())) -> spinner_style(). with_frame_transform(S, Fun) -> S@1 = begin _record = S, {spinner_style, erlang:element(2, _record), erlang:element(3, _record), begin _record@1 = erlang:element(4, S), {state, erlang:element(2, _record@1), Fun, erlang:element(4, _record@1), erlang:element(5, _record@1), erlang:element(6, _record@1), erlang:element(7, _record@1), erlang:element(8, _record@1)} end} end, case erlang:element(8, erlang:element(4, S@1)) of {some, Repeater} -> repeatedly:set_state(Repeater, erlang:element(4, S@1)); none -> nil end, S@1. -file("src/glitzer/spinner.gleam", 223). ?DOC(" Set the right text of the spinner.\n"). -spec with_right_text(spinner_style(), binary()) -> spinner_style(). with_right_text(S, T) -> S@1 = begin _record = S, {spinner_style, erlang:element(2, _record), erlang:element(3, _record), begin _record@1 = erlang:element(4, S), {state, erlang:element(2, _record@1), erlang:element(3, _record@1), erlang:element(4, _record@1), T, erlang:element(6, _record@1), erlang:element(7, _record@1), erlang:element(8, _record@1)} end} end, case erlang:element(8, erlang:element(4, S@1)) of {some, Repeater} -> repeatedly:set_state(Repeater, erlang:element(4, S@1)); none -> nil end, S@1. -file("src/glitzer/spinner.gleam", 233). ?DOC(" Set the spinners tick rate in milliseconds.\n"). -spec with_tick_rate(spinner_style(), integer()) -> spinner_style(). with_tick_rate(S, Ms) -> _record = S, {spinner_style, Ms, erlang:element(3, _record), erlang:element(4, _record)}. -file("src/glitzer/spinner.gleam", 128). ?DOC( " A very colorful spinner with the colors from the progress pride flag :3\n" " Note that this spinner has a tick rate of 200 instead of 100 to not flash\n" " to fast.\n" ). -spec prideful_spinner() -> spinner_style(). prideful_spinner() -> Black@1 = case gleam_community@colour:from_rgb255(0, 0, 0) of {ok, Black} -> Black; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 129, value => _assert_fail, start => 3434, 'end' => 3484, pattern_start => 3445, pattern_end => 3454}) end, Brown@1 = case gleam_community@colour:from_rgb255(97, 57, 21) of {ok, Brown} -> Brown; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 130, value => _assert_fail@1, start => 3487, 'end' => 3540, pattern_start => 3498, pattern_end => 3507}) end, Blue@1 = case gleam_community@colour:from_rgb255(116, 215, 238) of {ok, Blue} -> Blue; _assert_fail@2 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 131, value => _assert_fail@2, start => 3543, 'end' => 3598, pattern_start => 3554, pattern_end => 3562}) end, Pink@1 = case gleam_community@colour:from_rgb255(255, 175, 200) of {ok, Pink} -> Pink; _assert_fail@3 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 132, value => _assert_fail@3, start => 3601, 'end' => 3656, pattern_start => 3612, pattern_end => 3620}) end, White@1 = case gleam_community@colour:from_rgb255(255, 255, 255) of {ok, White} -> White; _assert_fail@4 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 133, value => _assert_fail@4, start => 3659, 'end' => 3715, pattern_start => 3670, pattern_end => 3679}) end, Violet@1 = case gleam_community@colour:from_rgb255(115, 41, 130) of {ok, Violet} -> Violet; _assert_fail@5 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 134, value => _assert_fail@5, start => 3718, 'end' => 3774, pattern_start => 3729, pattern_end => 3739}) end, Indigo@1 = case gleam_community@colour:from_rgb255(36, 64, 142) of {ok, Indigo} -> Indigo; _assert_fail@6 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 135, value => _assert_fail@6, start => 3777, 'end' => 3832, pattern_start => 3788, pattern_end => 3798}) end, Green@1 = case gleam_community@colour:from_rgb255(0, 128, 38) of {ok, Green} -> Green; _assert_fail@7 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 136, value => _assert_fail@7, start => 3835, 'end' => 3888, pattern_start => 3846, pattern_end => 3855}) end, Yellow@1 = case gleam_community@colour:from_rgb255(255, 237, 0) of {ok, Yellow} -> Yellow; _assert_fail@8 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 137, value => _assert_fail@8, start => 3891, 'end' => 3946, pattern_start => 3902, pattern_end => 3912}) end, Orange@1 = case gleam_community@colour:from_rgb255(255, 140, 0) of {ok, Orange} -> Orange; _assert_fail@9 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 138, value => _assert_fail@9, start => 3949, 'end' => 4004, pattern_start => 3960, pattern_end => 3970}) end, Red@1 = case gleam_community@colour:from_rgb255(228, 3, 3) of {ok, Red} -> Red; _assert_fail@10 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"glitzer/spinner"/utf8>>, function => <<"prideful_spinner"/utf8>>, line => 139, value => _assert_fail@10, start => 4007, 'end' => 4057, pattern_start => 4018, pattern_end => 4025}) end, Frames = [gleam_community@ansi:color(<<"\x{2591}"/utf8>>, Black@1), gleam_community@ansi:color(<<"\x{2592}"/utf8>>, Brown@1), gleam_community@ansi:color(<<"\x{2593}"/utf8>>, Blue@1), gleam_community@ansi:color(<<"\x{2588}"/utf8>>, Pink@1), gleam_community@ansi:color(<<"\x{2593}"/utf8>>, White@1), gleam_community@ansi:color(<<"\x{2592}"/utf8>>, Violet@1), gleam_community@ansi:color(<<"\x{2591}"/utf8>>, Indigo@1), gleam_community@ansi:color(<<"\x{2592}"/utf8>>, Green@1), gleam_community@ansi:color(<<"\x{2593}"/utf8>>, Yellow@1), gleam_community@ansi:color(<<"\x{2588}"/utf8>>, Orange@1), gleam_community@ansi:color(<<"\x{2593}"/utf8>>, Red@1)], _pipe = new_spinner(frames_from_list(Frames)), with_tick_rate(_pipe, 200). -file("src/glitzer/spinner.gleam", 238). ?DOC(" Set the spinners finish text.\n"). -spec with_finish_text(spinner_style(), binary()) -> spinner_style(). with_finish_text(S, T) -> _record = S, {spinner_style, erlang:element(2, _record), T, erlang:element(4, _record)}. -file("src/glitzer/spinner.gleam", 243). ?DOC(" Progress the spinner by one.\n"). -spec tick(spinner_style()) -> spinner_style(). tick(S) -> S@1 = begin _record = S, {spinner_style, erlang:element(2, _record), erlang:element(3, _record), begin _record@1 = erlang:element(4, S), {state, erlang:element(2, _record@1), erlang:element(3, _record@1), erlang:element(4, _record@1), erlang:element(5, _record@1), erlang:element(6, erlang:element(4, S)) + 1, erlang:element(7, _record@1), erlang:element(8, _record@1)} end} end, case erlang:element(8, erlang:element(4, S@1)) of {some, Repeater} -> repeatedly:set_state(Repeater, erlang:element(4, S@1)); none -> nil end, S@1. -file("src/glitzer/spinner.gleam", 254). ?DOC(" Progress the spinner by `i`.\n"). -spec tick_by(spinner_style(), integer()) -> spinner_style(). tick_by(S, I) -> S@1 = begin _record = S, {spinner_style, erlang:element(2, _record), erlang:element(3, _record), begin _record@1 = erlang:element(4, S), {state, erlang:element(2, _record@1), erlang:element(3, _record@1), erlang:element(4, _record@1), erlang:element(5, _record@1), erlang:element(6, erlang:element(4, S)) + I, erlang:element(7, _record@1), erlang:element(8, _record@1)} end} end, case erlang:element(8, erlang:element(4, S@1)) of {some, Repeater} -> repeatedly:set_state(Repeater, erlang:element(4, S@1)); none -> nil end, S@1. -file("src/glitzer/spinner.gleam", 296). ?DOC( " Finish a spinner. If it was countinously ticking, the ticking will be\n" " stopped. The line will be cleared and the finish text will be printed if\n" " the spinner had some.\n" ). -spec finish(spinner_style()) -> spinner_style(). finish(S) -> case erlang:element(8, erlang:element(4, S)) of {some, Repeater} -> repeatedly_ffi:stop(Repeater); none -> nil end, gleam_stdlib:println( <<<<<<(<<"\x{001b}[?25h"/utf8>>)/binary, (<<"\x{001b}[2K"/utf8>>)/binary>>/binary, (<<"\r"/utf8>>)/binary>>/binary, (erlang:element(3, S))/binary>> ), _record = S, {spinner_style, erlang:element(2, _record), erlang:element(3, _record), begin _record@1 = erlang:element(4, S), {state, erlang:element(2, _record@1), erlang:element(3, _record@1), erlang:element(4, _record@1), erlang:element(5, _record@1), erlang:element(6, _record@1), true, erlang:element(8, _record@1)} end}. -file("src/glitzer/spinner.gleam", 323). -spec get_current_frame_string(spinner_style()) -> binary(). get_current_frame_string(S) -> case glearray_ffi:get( erlang:element(2, erlang:element(2, erlang:element(4, S))), case erlang:tuple_size( erlang:element(2, erlang:element(2, erlang:element(4, S))) ) of 0 -> 0; Gleam@denominator -> erlang:element(6, erlang:element(4, S)) rem Gleam@denominator end ) of {ok, F} -> (erlang:element(3, erlang:element(4, S)))(F); {error, _} -> <<""/utf8>> end. -file("src/glitzer/spinner.gleam", 312). ?DOC( " Print the spinner. This is useful if you need/want manual control over your\n" " spinner ticks and prints.\n" ). -spec print_spinner(spinner_style()) -> nil. print_spinner(S) -> gleam_stdlib:print( <<<<<<<<<<(<<"\x{001b}[?25l"/utf8>>)/binary, (<<"\x{001b}[2K"/utf8>>)/binary>>/binary, (<<"\r"/utf8>>)/binary>>/binary, (erlang:element(4, erlang:element(4, S)))/binary>>/binary, (get_current_frame_string(S))/binary>>/binary, (erlang:element(5, erlang:element(4, S)))/binary>> ). -file("src/glitzer/spinner.gleam", 280). ?DOC( " Continuously tick and print the spinner. Note that this **does not** update\n" " the tick value of your spinner reference!\n" "\n" "
\n" " Example:\n" "\n" " ```gleam\n" " import glitzer/spinner\n" "\n" " fn example() {\n" " spinner.default_spinner()\n" " |> spinner.spin\n" " }\n" " ```\n" "\n" "
\n" ). -spec spin(spinner_style()) -> spinner_style(). spin(S) -> Repeater = repeatedly_ffi:call( erlang:element(2, S), erlang:element(4, S), fun(State, _) -> S@1 = begin _record = S, {spinner_style, erlang:element(2, _record), erlang:element(3, _record), State} end, _pipe = tick(S@1), print_spinner(_pipe), State end ), _pipe@1 = begin _record@1 = S, {spinner_style, erlang:element(2, _record@1), erlang:element(3, _record@1), begin _record@2 = erlang:element(4, S), {state, erlang:element(2, _record@2), erlang:element(3, _record@2), erlang:element(4, _record@2), erlang:element(5, _record@2), erlang:element(6, _record@2), erlang:element(7, _record@2), {some, Repeater}} end} end, tick(_pipe@1).