When an operation can take a while to finish, you should inform the user about the progress it makes. This way the user can estimate remaining time and clearly see that Emacs is busy working, not hung. A convenient way to do this is to use a progress reporter.
Here is a working example that does nothing useful:
(make-progress-reporter "Collecting mana for Emacs..."
(dotimes (k 500)
(progress-reporter-update progress-reporter k))
function make-progress-reporter message \&optional min-value max-value current-value min-change min-time
This function creates and returns a progress reporter object, which you will use as an argument for the other functions listed below. The idea is to precompute as much data as possible to make progress reporting very fast.
When this progress reporter is subsequently used, it will display
message in the echo area, followed by progress percentage.
message is treated as a simple string. If you need it to depend on a filename, for instance, use
format-message before calling this function.
max-value should be numbers standing for the starting and final states of the operation. For instance, an operation that scans a buffer should set these to the results of
max-value should be greater than
Alternatively, you can set
nil. In that case, the progress reporter does not report process percentages; it instead displays a “spinner" that rotates a notch each time you update the progress reporter.
max-value are numbers, you can give the argument
current-value a numerical value specifying the initial progress; if omitted, this defaults to
The remaining arguments control the rate of echo area updates. The progress reporter will wait for at least
min-change more percents of the operation to be completed before printing next message; the default is one percent.
min-time specifies the minimum time in seconds to pass between successive prints; the default is 0.2 seconds. (On some operating systems, the progress reporter may handle fractions of seconds with varying precision).
This function calls
progress-reporter-update, so the first message is printed immediately.
function progress-reporter-update reporter \&optional value suffix
This function does the main work of reporting progress of your operation. It displays the message of
reporter, followed by progress percentage determined by
value. If percentage is zero, or close enough according to the
min-time arguments, then it is omitted from the output.
reporter must be the result of a call to
value specifies the current state of your operation and must be between
max-value (inclusive) as passed to
make-progress-reporter. For instance, if you scan a buffer, then
value should be the result of a call to
suffix is a string to be displayed after
reporter’s main message and progress text. If
reporter is a non-numerical reporter, then
value should be
nil, or a string to use instead of
This function respects
min-time as passed to
make-progress-reporter and so does not output new messages on every invocation. It is thus very fast and normally you should not try to reduce the number of calls to it: resulting overhead will most likely negate your effort.
function progress-reporter-force-update reporter \&optional value new-message suffix
This function is similar to
progress-reporter-update except that it prints a message in the echo area unconditionally.
suffix have the same meaning as for
new-message allows you to change the message of the
reporter. Since this function always updates the echo area, such a change will be immediately presented to the user.
function progress-reporter-done reporter
This function should be called when the operation is finished. It prints the message of
reporter followed by word ‘
done’ in the echo area.
You should always call this function and not hope for
progress-reporter-update to print ‘
100%’. Firstly, it may never print it, there are many good reasons for this not to happen. Secondly, ‘
done’ is more explicit.
macro dotimes-with-progress-reporter (var count [result]) reporter-or-message body…
This is a convenience macro that works the same way as
dotimes does, but also reports loop progress using the functions described above. It allows you to save some typing. The argument
reporter-or-message can be either a string or a progress reporter object.
You can rewrite the example in the beginning of this subsection using this macro as follows:
"Collecting some mana for Emacs..."
Using a reporter object as the
reporter-or-message argument is useful if you want to specify the optional arguments in
make-progress-reporter. For instance, you can write the previous example as follows:
(make-progress-reporter "Collecting some mana for Emacs..." 0 500 0 1 1.5)
macro dolist-with-progress-reporter (var count [result]) reporter-or-message body…
This is another convenience macro that works the same way as
dolist does, but also reports loop progress using the functions described above. As in
reporter-or-message can be a progress reporter or a string. You can rewrite the previous example with this macro as follows:
(k (number-sequence 0 500))
"Collecting some mana for Emacs..."