-module(glitzer@progress). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([char_from_string/1, string_from_char/1, default_bar/0, slim_bar/0, fancy_slim_bar/0, fancy_slim_arrow_bar/0, thick_bar/0, fancy_thick_bar/0, new_bar/0, with_left_text/2, with_right_text/2, with_empty/2, with_fill/2, with_fill_finished/2, with_fill_head/2, with_fill_head_finished/2, with_length/2, tick/1, tick_by/2, finish/1, print_bar/1, map_iterator/3, map2_iterator/4, each_iterator/3]). -export_type([char_/0, state/0, progress_style/0]). -opaque char_() :: {char, binary()}. -opaque state() :: {state, integer(), boolean()}. -opaque progress_style() :: {progress_style, binary(), binary(), char_(), char_(), gleam@option:option(char_()), gleam@option:option(char_()), gleam@option:option(char_()), integer(), state()}. -spec char_from_string(binary()) -> char_(). char_from_string(In) -> Len = gleam@string:length(In), case Len of 1 -> {char, In}; _ -> {char, <<"#"/utf8>>} end. -spec string_from_char(char_()) -> binary(). string_from_char(In) -> erlang:element(2, In). -spec default_bar() -> progress_style(). default_bar() -> {progress_style, <<"["/utf8>>, <<"]"/utf8>>, {char, <<" "/utf8>>}, {char, <<"#"/utf8>>}, none, none, none, 100, {state, 0, false}}. -spec slim_bar() -> progress_style(). slim_bar() -> Sym = <<"\x{2014}"/utf8>>, {progress_style, <<""/utf8>>, <<""/utf8>>, {char, <<" "/utf8>>}, {char, Sym}, none, none, none, 100, {state, 0, false}}. -spec fancy_slim_bar() -> progress_style(). fancy_slim_bar() -> Sym = <<"\x{2014}"/utf8>>, {progress_style, <<""/utf8>>, <<""/utf8>>, {char, gleam_community@ansi:blue(Sym)}, {char, gleam_community@ansi:red(Sym)}, {some, {char, gleam_community@ansi:green(Sym)}}, none, none, 100, {state, 0, false}}. -spec fancy_slim_arrow_bar() -> progress_style(). fancy_slim_arrow_bar() -> Sym = <<"\x{2014}"/utf8>>, Sym_head = <<"\x{2192}"/utf8>>, {progress_style, <<""/utf8>>, <<""/utf8>>, {char, gleam_community@ansi:blue(Sym)}, {char, gleam_community@ansi:red(Sym)}, {some, {char, gleam_community@ansi:green(Sym)}}, {some, {char, gleam_community@ansi:red(Sym_head)}}, {some, {char, gleam_community@ansi:green(Sym_head)}}, 100, {state, 0, false}}. -spec thick_bar() -> progress_style(). thick_bar() -> Sym = <<"\x{2588}"/utf8>>, Empty_sym = <<"\x{2592}"/utf8>>, {progress_style, <<""/utf8>>, <<""/utf8>>, {char, Empty_sym}, {char, Sym}, none, none, none, 100, {state, 0, false}}. -spec fancy_thick_bar() -> progress_style(). fancy_thick_bar() -> Sym = <<"\x{2588}"/utf8>>, Empty_sym = <<"\x{2592}"/utf8>>, {progress_style, <<""/utf8>>, <<""/utf8>>, {char, gleam_community@ansi:blue(Empty_sym)}, {char, gleam_community@ansi:red(Sym)}, {some, {char, gleam_community@ansi:green(Sym)}}, none, none, 100, {state, 0, false}}. -spec new_bar() -> progress_style(). new_bar() -> {progress_style, <<""/utf8>>, <<""/utf8>>, {char, <<" "/utf8>>}, {char, <<" "/utf8>>}, none, none, none, 0, {state, 0, false}}. -spec with_left_text(progress_style(), binary()) -> progress_style(). with_left_text(Bar, Text) -> erlang:setelement(2, Bar, Text). -spec with_right_text(progress_style(), binary()) -> progress_style(). with_right_text(Bar, Text) -> erlang:setelement(3, Bar, Text). -spec with_empty(progress_style(), char_()) -> progress_style(). with_empty(Bar, Char) -> erlang:setelement(4, Bar, Char). -spec with_fill(progress_style(), char_()) -> progress_style(). with_fill(Bar, Char) -> erlang:setelement(5, Bar, Char). -spec with_fill_finished(progress_style(), char_()) -> progress_style(). with_fill_finished(Bar, Char) -> erlang:setelement(6, Bar, {some, Char}). -spec with_fill_head(progress_style(), char_()) -> progress_style(). with_fill_head(Bar, Char) -> erlang:setelement(7, Bar, {some, Char}). -spec with_fill_head_finished(progress_style(), char_()) -> progress_style(). with_fill_head_finished(Bar, Char) -> erlang:setelement(8, Bar, {some, Char}). -spec with_length(progress_style(), integer()) -> progress_style(). with_length(Bar, Len) -> erlang:setelement(9, Bar, Len). -spec tick(progress_style()) -> progress_style(). tick(Bar) -> case erlang:element(2, erlang:element(10, Bar)) < (erlang:element(9, Bar) + 1) of true -> erlang:setelement( 10, Bar, erlang:setelement( 2, erlang:element(10, Bar), erlang:element(2, erlang:element(10, Bar)) + 1 ) ); false -> erlang:setelement( 10, Bar, {state, erlang:element(2, erlang:element(10, Bar)) + 1, true} ) end. -spec tick_by(progress_style(), integer()) -> progress_style(). tick_by(Bar, I) -> case I > 0 of true -> Bar@1 = tick(Bar), tick_by(Bar@1, I - 1); false -> Bar end. -spec finish(progress_style()) -> progress_style(). finish(Bar) -> erlang:setelement(10, Bar, {state, erlang:element(9, Bar) + 1, true}). -spec get_finished_head_fill( gleam@string_builder:string_builder(), progress_style() ) -> gleam@string_builder:string_builder(). get_finished_head_fill(Fill, Bar) -> case erlang:element(3, erlang:element(10, Bar)) of true -> gleam@string_builder:append( Fill, erlang:element( 2, gleam@option:unwrap( erlang:element(8, Bar), gleam@option:unwrap( erlang:element(7, Bar), gleam@option:unwrap( erlang:element(6, Bar), erlang:element(5, Bar) ) ) ) ) ); false -> gleam@string_builder:append( Fill, erlang:element( 2, gleam@option:unwrap( erlang:element(7, Bar), erlang:element(5, Bar) ) ) ) end. -spec get_finished_fill(gleam@string_builder:string_builder(), progress_style()) -> gleam@string_builder:string_builder(). get_finished_fill(Fill, Bar) -> case erlang:element(3, erlang:element(10, Bar)) of true -> gleam@string_builder:append( Fill, erlang:element( 2, gleam@option:unwrap( erlang:element(6, Bar), erlang:element(5, Bar) ) ) ); false -> gleam@string_builder:append( Fill, erlang:element(2, erlang:element(5, Bar)) ) end. -spec build_progress_fill( gleam@string_builder:string_builder(), progress_style(), integer(), integer() ) -> gleam@string_builder:string_builder(). build_progress_fill(Fill, Bar, Left_nonempty, Count) -> Fill@1 = case Left_nonempty > 0 of true -> case Left_nonempty =:= 1 of true -> get_finished_head_fill(Fill, Bar); false -> get_finished_fill(Fill, Bar) end; false -> gleam@string_builder:append( Fill, erlang:element(2, erlang:element(4, Bar)) ) end, case erlang:element(9, Bar) > Count of true -> build_progress_fill(Fill@1, Bar, Left_nonempty - 1, Count + 1); false -> Fill@1 end. -spec print_bar(progress_style()) -> nil. print_bar(Bar) -> Bar@1 = erlang:setelement( 10, Bar, erlang:setelement( 3, erlang:element(10, Bar), erlang:element(2, erlang:element(10, Bar)) >= erlang:element(9, Bar) ) ), Fill = begin _pipe = build_progress_fill( gleam@string_builder:new(), Bar@1, erlang:element(2, erlang:element(10, Bar@1)) + 1, 0 ), gleam@string_builder:to_string(_pipe) end, End = case erlang:element(3, erlang:element(10, Bar@1)) of true -> <<"\n"/utf8>>; false -> <<""/utf8>> end, gleam@io:print_error( <<<<<<<<<<<<(<<"\x{001b}[?25l"/utf8>>)/binary, (<<"\x{001b}[2K"/utf8>>)/binary>>/binary, (<<"\r"/utf8>>)/binary>>/binary, (erlang:element(2, Bar@1))/binary>>/binary, Fill/binary>>/binary, (erlang:element(3, Bar@1))/binary>>/binary, End/binary>> ). -spec tick_bar_by_i(progress_style(), integer()) -> progress_style(). tick_bar_by_i(Bar, I) -> case I > 0 of true -> tick_bar_by_i(tick(Bar), I - 1); false -> Bar end. -spec map_iterator( gleam@iterator:iterator(MQZ), progress_style(), fun((progress_style(), MQZ) -> MRB) ) -> gleam@iterator:iterator(MRB). map_iterator(I, Bar, Fun) -> _pipe = gleam@iterator:index(I), gleam@iterator:map( _pipe, fun(Pair) -> {El, I@1} = Pair, _pipe@1 = tick_bar_by_i(Bar, I@1), Fun(_pipe@1, El) end ). -spec map2_iterator( gleam@iterator:iterator(MRF), gleam@iterator:iterator(MRH), progress_style(), fun((progress_style(), MRF, MRH) -> MRJ) ) -> gleam@iterator:iterator(MRJ). map2_iterator(I1, I2, Bar, Fun) -> _pipe = gleam@iterator:zip(I1, I2), _pipe@1 = gleam@iterator:index(_pipe), gleam@iterator:map( _pipe@1, fun(Pair) -> {Pair@1, I} = Pair, {El1, El2} = Pair@1, _pipe@2 = tick_bar_by_i(Bar, I), Fun(_pipe@2, El1, El2) end ). -spec each_iterator( gleam@iterator:iterator(MRL), progress_style(), fun((progress_style(), MRL) -> any()) ) -> nil. each_iterator(I, Bar, Fun) -> _pipe = gleam@iterator:index(I), gleam@iterator:each( _pipe, fun(Pair) -> {El, I@1} = Pair, _pipe@1 = tick_bar_by_i(Bar, I@1), Fun(_pipe@1, El) end ).