-module(glitzer@multi). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -define(FILEPATH, "src/glitzer/multi.gleam"). -export([new_same_line/0, insert_progress_inline/3, insert_spinner_inline/3, run_line/1, tick_inline/2, tick_by_inline/3]). -export_type([style_wrapper/0, line_state/0, same_line/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. -opaque style_wrapper() :: {progress, glitzer@progress:progress_style()} | {spinner, glitzer@spinner:spinner_style()}. -opaque line_state() :: {line_state, list({binary(), style_wrapper()})}. -opaque same_line() :: {same_line, integer(), gleam@option:option(repeatedly:repeater(line_state())), line_state()}. -file("src/glitzer/multi.gleam", 80). ?DOC( " Create a new `SameLine` that can print multiple spinners/progress bars on\n" " the same line.\n" ). -spec new_same_line() -> same_line(). new_same_line() -> {same_line, 100, none, {line_state, []}}. -file("src/glitzer/multi.gleam", 85). ?DOC(" Insert a `ProgressStyle` at the end of a given `SameLine`.\n"). -spec insert_progress_inline( same_line(), binary(), glitzer@progress:progress_style() ) -> same_line(). insert_progress_inline(L, N, P) -> _record = L, {same_line, erlang:element(2, _record), erlang:element(3, _record), {line_state, lists:append( erlang:element(2, erlang:element(4, L)), [{N, {progress, glitzer@progress:with_newline_on_finished(P, false)}}] )}}. -file("src/glitzer/multi.gleam", 101). ?DOC(" Insert a `SpinnerStyle` at the end of a given `SameLine`.\n"). -spec insert_spinner_inline( same_line(), binary(), glitzer@spinner:spinner_style() ) -> same_line(). insert_spinner_inline(L, N, S) -> _record = L, {same_line, erlang:element(2, _record), erlang:element(3, _record), {line_state, lists:append( erlang:element(2, erlang:element(4, L)), [{N, {spinner, S}}] )}}. -file("src/glitzer/multi.gleam", 174). -spec print_bar_inline(glitzer@progress:progress_style()) -> nil. print_bar_inline(P) -> gleam_stdlib:print_error( <<(glitzer@progress:get_raw_bar(P))/binary, " "/utf8>> ). -file("src/glitzer/multi.gleam", 178). -spec print_spinner_inline(glitzer@spinner:spinner_style()) -> nil. print_spinner_inline(S) -> gleam_stdlib:print_error( <<<<<<(erlang:element(4, erlang:element(4, S)))/binary, (glitzer@spinner:get_current_frame_string(S))/binary>>/binary, (erlang:element(5, erlang:element(4, S)))/binary>>/binary, " "/utf8>> ). -file("src/glitzer/multi.gleam", 130). ?DOC( " Run the line. This will print the whole line every `line.refresh_rate`\n" " milliseconds. It will also automatically tick all inline spinners with\n" " regard to their tick rate.\n" "\n" "
\n" " Example:\n" "\n" " ```gleam\n" " let multi =\n" " multi.new_same_line()\n" " |> multi.insert_spinner_inline(\"s1\", spinner.pulsating_spinner())\n" " |> multi.insert_spinner_inline(\n" " \"s2\",\n" " spinner.with_tick_rate(spinner.default_spinner(), 500),\n" " )\n" " |> multi.run_line\n" " ```\n" "
\n" ). -spec run_line(same_line()) -> same_line(). run_line(L) -> Repeater = repeatedly_ffi:call( erlang:element(2, L), erlang:element(4, L), fun(State, I) -> gleam_stdlib:print( <<<<(<<"\x{001b}[?25l"/utf8>>)/binary, (<<"\x{001b}[2K"/utf8>>)/binary>>/binary, (<<"\r"/utf8>>)/binary>> ), New_line = begin _pipe = gleam@yielder:from_list(erlang:element(2, State)), _pipe@1 = gleam@yielder:map( _pipe, fun(El) -> {Name, Value} = El, Value@1 = case Value of {progress, P} -> {progress, P}; {spinner, S} -> Time_gone_by = I * erlang:element(2, L), Spin_count = gleam@result:unwrap( gleam@int:floor_divide( Time_gone_by, erlang:element(2, S) ), 0 ), Left_to_tick = Spin_count - erlang:element( 6, erlang:element(4, S) ), {spinner, glitzer@spinner:tick_by(S, Left_to_tick)} end, {Name, Value@1} end ), gleam@yielder:to_list(_pipe@1) end, _pipe@2 = gleam@yielder:from_list(New_line), gleam@yielder:each( _pipe@2, fun(El@1) -> {_, Value@2} = El@1, case Value@2 of {progress, P@1} -> print_bar_inline(P@1); {spinner, S@1} -> print_spinner_inline(S@1) end end ), {line_state, New_line} end ), _record = L, {same_line, erlang:element(2, _record), {some, Repeater}, erlang:element(4, _record)}. -file("src/glitzer/multi.gleam", 189). ?DOC( " Tick a spinner or progress bar with the given name by 1. Does nothing if\n" " the spinner/progress bar doesn't exist.\n" ). -spec tick_inline(same_line(), binary()) -> same_line(). tick_inline(L, N) -> Value = gleam@list:key_find(erlang:element(2, erlang:element(4, L)), N), New_state = case Value of {ok, Value@1} -> case Value@1 of {progress, P} -> {line_state, gleam@list:key_set( erlang:element(2, erlang:element(4, L)), N, {progress, glitzer@progress:tick(P)} )}; {spinner, S} -> {line_state, gleam@list:key_set( erlang:element(2, erlang:element(4, L)), N, {spinner, glitzer@spinner:tick(S)} )} end; {error, _} -> erlang:element(4, L) end, case erlang:element(3, L) of {some, R} -> repeatedly:set_state(R, New_state); none -> nil end, _record = L, {same_line, erlang:element(2, _record), erlang:element(3, _record), New_state}. -file("src/glitzer/multi.gleam", 219). ?DOC( " Tick a spinner or progress bar with the given name by `i`. Does nothing if\n" " the spinner/progress bar doesn't exist.\n" ). -spec tick_by_inline(same_line(), binary(), integer()) -> same_line(). tick_by_inline(L, N, I) -> Value = gleam@list:key_find(erlang:element(2, erlang:element(4, L)), N), New_state = case Value of {ok, Value@1} -> case Value@1 of {progress, P} -> {line_state, gleam@list:key_set( erlang:element(2, erlang:element(4, L)), N, {progress, glitzer@progress:tick_by(P, I)} )}; {spinner, S} -> {line_state, gleam@list:key_set( erlang:element(2, erlang:element(4, L)), N, {spinner, glitzer@spinner:tick_by(S, I)} )} end; {error, _} -> erlang:element(4, L) end, case erlang:element(3, L) of {some, R} -> repeatedly:set_state(R, New_state); none -> nil end, _record = L, {same_line, erlang:element(2, _record), erlang:element(3, _record), New_state}.