This small library provides a facility to display simple progress-bars in the REPL or command-line app.
The progress bar is hidden by default and you need to set a variable to make it rendered. This can be useful in apps which can be running as a part of the UNIX pipeline.
In this small example, I create a progress bar and update it in a loop:
POFTHEDAY> (cl-progress-bar:with-progress-bar
(100 "Testing the progressbar")
(loop for i from 1 upto 100
do (cl-progress-bar:update 1)
(sleep 0.1)))
Testing the progressbar
==================================================
Finished in 10.26 seconds
The renderer is very simple and can be ruined by any other output, your program produce during the loop:
POFTHEDAY> (cl-progress-bar:with-progress-bar
(100 "Testing the progressbar")
(loop for i from 1 upto 100
do (cl-progress-bar:update 1)
(when (zerop (mod i 10))
(format t "This is ~A-th iteration~%" i))
(sleep 0.1)))
Testing the progressbar
=====This is 10-th iteration
====This is 20-th iteration
=====This is 30-th iteration
======This is 40-th iteration
====This is 50-th iteration
=====This is 60-th iteration
======This is 70-th iteration
====This is 80-th iteration
=====This is 90-th iteration
======This is 100-th iteration
Finished in 10.28 seconds
It is interesting, is it possible to detect that some output was written to the standard-output and to rerender the progress bar in full length?
Also, it would be a nice feature to output estimated time and to support progress bars for an unknown number of items.
For inspiration, you can take a look at how Python library “tqdm” processes progress bars:
By the way, I found, this library uses documentation-utils and keeps it’s docstrings in a separate file. So, when you navigate to the function source, you will not see docstrings.
But if you hit C-c C-d C-d in Emacs, it will show you this nice description:
CL-PROGRESS-BAR:WITH-PROGRESS-BAR
[symbol]
WITH-PROGRESS-BAR names a macro:
Lambda-list: ((CL-PROGRESS-BAR::STEPS-COUNT
CL-PROGRESS-BAR::DESCRIPTION &REST
CL-PROGRESS-BAR::DESC-ARGS)
&BODY CL-PROGRESS-BAR::BODY)
Documentation:
Description:
Macro. Build active progress bar. Requires size
and description that will be printed out to
the REPL. If *progress-bar-endabled* is nil or
there is another progress bar active already
progress bar will not be shown.
Notes:
Because with-progress-bar handles cases where
another progress-bar is active it is generally
safe to nest code with this macro on call stack.
However, top level with-progress-bar should
contain correct steps-count.
Source file: /Users/art/poftheday/.qlot/...
I think this is inconvenient. What do you think about this way of keeping documentation for the code?
What if somebody create an extended defun macro which will make it possible to combine type annotations and documentation like that:
(defun* update ((unit-count (integer 1 *)
"How many steps has been finished?")
&optional
(progress-bar (or null cl-progress-bar.progress:progress-bar)
*progress-bar*
"Instance of progress-bar. Usually should be
left with default (namely: *progress-bar*)."))
-> null
(:doc "Notify progress bar about step completion."
:thread-safety "This function is thread safe.")
(when progress-bar
(bt:with-lock-held ((cl-progress-bar.progress:mutex progress-bar))
(cl-progress-bar.progress:update-progress progress-bar unit-count))))
In this example I moved all docstrings from the separate file into the function.