Skip to content

1. A first bar ​

march with its first progress bar

march advances its solution for 50 time steps, and each step takes a while: long enough for whoever runs it to wonder how far it has come. A progress bar answers, in three steps: initialize the bar, start it, update it at every time step.

f90
program march
!< Tutorial, chapter 1: a first progress bar.
use, intrinsic :: iso_fortran_env, only : I8P=>int64, R8P=>real64
use forbear, only : bar_object
implicit none
type(bar_object) :: bar   ! the progress bar
integer          :: steps ! time steps
integer          :: step  ! current time step

steps = 50
call bar%initialize(max_value=real(steps, R8P))    ! 1. initialize
call bar%start                                     ! 2. start
do step = 1, steps
   call advance                                    ! the real work
   call bar%update(current=real(step, R8P))        ! 3. update
enddo
print '(A,I0,A)', 'march: ', steps, ' time steps done'

contains
   subroutine advance
   !< Advance the solution of one time step (here: wait 40 ms, as a real computation would take).
   integer(I8P) :: start ! clock at the start
   integer(I8P) :: now   ! clock now
   integer(I8P) :: rate  ! clock counts per second
   call system_clock(start, rate)
   do
      call system_clock(now)
      if (now - start >= rate / 25) exit
   enddo
   endsubroutine advance
endprogram march
  • initialize sets up the bar: here only its range, from min_value (default 0) to max_value. Everything not passed takes its default: a bar 32 characters wide, * for the done part and - for the rest.
  • start draws the empty bar (0%) and takes over the terminal line.
  • update takes the current value, between min_value and max_value, as a real(real64), and redraws the line.

Running it ​

While running, at step 25 of 50:

$ march
****************----------------

At the end:

$ march
********************************
march: 50 time steps done

Each update rewrites the same line: it ends with a carriage return instead of a new line, so the next one overwrites it; a fast loop is not slowed down by its bar, which is drawn at most ten times a second. When the progress reaches 100%, update ends the line and the program prints below it as usual: the message after the loop needs no special care.

The range ​

The progress is the fraction of the range done, in percent, truncated to an integer: the bar shows 100% only when current reaches max_value. With the default range [0, 1] you pass the fraction done; with max_value=real(steps, R8P) you pass the step itself; with min_value too, a counter that does not start at 1 (see A loop of many iterations). A value outside the range is clamped, and once the bar has reached 100% further updates do nothing.

What you learned

The three steps initialize, start, update; the range of the bar. Reference: The bar object.

Next: 2. The look of the bar.

Released under the GPL v3, BSD 2-Clause, BSD 3-Clause or MIT License.