Did you know ... Search Documentation:
Pack progress_bar -- prolog/progress_bar.pl
PublicShow source

progress_bar makes available a DCG rule (e.g. simple_progress_bar, simple_spinner) that is to be used as part of the prolog messaging system to print the progress of a used defined process (see https://www.swi-prolog.org/pldoc/man?section=printmsg). Note that the term 'process' denotes an abstract task a user wishes to complete (i.e. it doens't refer to a separate thread)

The message is meant to be called repeatedly while the user- process progresses (i.e. it is part of the user processing loop). To this end the DCG rule (e.g. simple_progress_bar) should be provided: the current state (=Index), with respect to the total denoting completion (=Total). Additional information may be provided to allow informing the user about the processing (see example below). Note the spinner//10 doesn't define a Total (it does define Index) and therefore it's progress with respect to completion is unknown. When the user-process finishes, the user should call spinner_end//0 to end the spinner.

Under the hood, the DCG rules formats the message according to a specific layout (see progress_bar//12, and spinner//10 for details). simple_progress_bar//2, default_progress_bar//4, fancy_progress_bar//7 are specialisations of progress_bar//12 defaulting some of its values (similarily for spinner). While the user-process progresses, the DCG rule is called repeatedly (i.e. as part of the user defined loop). Every message is prefixed with a 'carriage-return only' character ('\r'), which effectively resets the last printed message, and creates the animation effect.


The example below illustrates the use of simple_progress_bar//2 within user_defined_predicate to visually portray advancement whilte iterating elements within the forall/2 loop. Within the forall-loop print_message/2 calls the DGC rule my_application_does_stuff//2 to format to pre-process the message passed to default_progress_bar//4.

user_defined_predicate(...) :-
        forall(nth1(Index,Items,Item), (
                %  do something with Item

my_application_does_stuff(Index,Total) -->
        Percentage is (Index/Total) * 100,
- Joost Geurts
- MIT License
 simple_spinner(+Progress:int)// is det
renders a spinner message on the center of the screen-line
 default_spinner(+Progress:int, TextLeft:text)// is det
renders a text message followed by a spinner
 fancy_spinner(+Progress:int, +TextLeft:text, +TextRight:text)// is det
fancy_spinner renders a (dynamic) message on the left of the screen (including a spinner) and rights-aligned message
 spinner(+Progress:int, +SpinLeftLeft:atom, +TextLeft:text, SpinLeftRight:atom, +SpinCenterLeft:atom, +TextCenter:text, +SpinCenterRight:atom, +SpinRightLeft:atom, +TextRight:text, +SpinRightRight:atom)// is det
Generates a spinner message that is meant to be called repeatedly by a task to indicate its progress (while its completion cannot be determined ahead of timer, otherwise a progess bar would be more appropriate)

The layout of the spinner message is setup according to the following schema:


SLL stands for Spinner-Left-Left, TL stands for Text-Left, SLR stands for Spinner-Left-Right The other abreviation follow the same schema

  • Progress is an possitive integer that represents advancement of a task (it is assumed to grow 1 with every call)
  • TL is a left-aligned text,
  • TC is a center-aligned text,
  • TR is a right-aligned text
  • SLL, SLR, SCL,SCR,SRL and SRR are atoms represent a spinner Id (e.g. 'classic', 'dots', .. ). Noting 'none' denotes absence of a spinner

    As the termination of a spinner us unnknown a newline should be emmited when done, this can be done using end_spinner.

 spinner_end// is det
spinner_end ends the the spinner
 simple_progress_bar(+Index:int, +Total:int)// is det
simple_progress_bar renders a progress bar, and the percentage completed
 default_progress_bar(+Index:int, +Total:int, IntroText:text, OutroText:text)// is det
default_progress_bar renders a progress bar, including an IntroText, OutroText (that may be dynamically updated)
 fancy_progress_bar(+Index:int, +Total:int, IntroText:text, OutroText:text, StartText, TodoText:text, EndText:text)// is det
fancy_progress_bar renders a progress bar, including an IntroText, OutroText, StartText, TodoText and EndText (that may be dynamically updated)
 progress_bar(+Index:int, +Total:int, +IntroText:text, +OutroText:text, +StartMarker:char, +StartText:text, +DoneChar:char, +DoneText:text, +TodoText:text, +TodoChar:char, +EndText:text, +EndMarker:char)// is det
progress_bar renders the progress of a process using the full width of the terminal where Index represent the current advancement, and Total represent completion. (i.e. Index =< Total)

The layout of the bar is setup according to the following schema:

Intro [Start+++++++++++++++><---------End] Outro
  • IntroText ('Intro' in the schema) represents the text that is printed before the bar
  • StartMarker ('[') defined the character used to render the left boundary of the bar
  • StartText ('Start') is a text printed at the right side of the StartMarker, provided there is sufficient space
  • DoneChar ('+') is the charcater used to render the advancement completed
  • DoneText ('>') is a text that is printed (provided there is space) at the left side ('i.e done') of the current advancement
  • TodoText ('<') is a text that is printed (provided there is space) at the right side (i.e. todo') of the current advancement
  • TodoChar ('-') is the character used to render the advacement that remains to be made
  • EndText ('End') is a text printed at the left side of the EndMarker, provided there is sufficient space
  • EndMarker (']') defined the character used to render the right boundary of the bar
  • OutroText ('Outro') represents the text that is printed after the bar