10. Unknown ends

Every bar so far knew its end: max_value steps, and the bar completed when current reached it. Two common loops do not fit that. An iterative solver runs until its residual is small enough, and nobody knows in advance how many iterations that takes. A time loop of 50 steps may reach a steady state at step 30 and leave early. march does both:
call bar%initialize(template='solve {spinner:cyan} [{bar:20}] {count:yellow} iterations, {elapsed:blue}', &
indeterminate=.true., spinner_string='⠋', filled_char_string='#', empty_char_string='.')
residual = 1._R8P
iterations = 0
call bar%start
do while (residual > 1.e-6_R8P) ! how many iterations: unknown until done
call advance
residual = residual / 2._R8P
iterations = iterations + 1
call bar%update(current=real(iterations, R8P))
enddo
call bar%finishWhile the solver runs:
$ march
solve ⠇ [........#####.......] 8 iterations, hh:mm:ssindeterminate=.true.says that the total is unknown.currentcounts what is done, frommin_value, and the bar never completes by itself: a block goes back and forth along the track, one cell per drawing, as the spinner turns.{count}shows what is done (8), not8/max;{speed}, if you ask for it, is what is done per second.- With nothing to measure against, an indeterminate bar has no percent, ETA or scale: asking for one stops the program in
initialize, with a message. bar%finishends the bar: it draws the last update with the track full, ends the line and writes the summary, if asked.
Leaving a loop early
steps = 50
call bar%initialize(prefix_string='march ', bracket_left_string='[', bracket_right_string=']', &
filled_char_string='#', empty_char_string='.', add_progress_percent=.true., &
progress_percent_color_fg='yellow', message_color_fg='green', width=30, &
max_value=real(steps, R8P))
residual = 1._R8P
call bar%start
do step = 1, steps
call advance
residual = residual / 2._R8P
call bar%update(current=real(step, R8P))
if (residual < 1.e-9_R8P) exit ! steady state: the remaining steps are not needed
enddo
call bar%finish(message='steady state')At the end:
$ march
solve ⠙ [####################] 20 iterations, hh:mm:ss
march [##################............] 60% steady stateWithout finish, the exit would leave the bar running at 60%: on a terminal its line not ended and the cursor still hidden, the next output drawn over it. finish ends it where it is: the last update drawn, here with a message, the line ended, the cursor shown, the date and summary lines written if asked (the summary rate counts the 60% done). After finish, updates do nothing until the next start, as after 100%; on a bar not running, finish does nothing.
In a log, an indeterminate bar writes two lines, at the start and at the end: there is no 10% to wait for. A determinate bar finished early writes one last line, unless its last line already shows where it stopped.
For a livelier pulse, pulse_trail gives it a one-cell head and a fading trail, as a scanner: see Pulse trail.
What you learned
indeterminate bars, ended by finish; finish for a loop left before its end. Reference: finish.
Next: 11. A 1980s dashboard.