elisp: Progress

 
 37.4.2 Reporting Operation Progress
 -----------------------------------
 
 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:
 
      (let ((progress-reporter
             (make-progress-reporter "Collecting mana for Emacs..."
                                     0  500)))
        (dotimes (k 500)
          (sit-for 0.01)
          (progress-reporter-update progress-reporter k))
        (progress-reporter-done progress-reporter))
 
  -- 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.
 
      The arguments MIN-VALUE and 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
      ‘point-min’ and ‘point-max’ correspondingly.  MAX-VALUE should be
      greater than MIN-VALUE.
 
      Alternatively, you can set MIN-VALUE and MAX-VALUE to ‘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.
 
      If MIN-VALUE and MAX-VALUE are numbers, you can give the argument
      CURRENT-VALUE a numerical value specifying the initial progress; if
      omitted, this defaults to MIN-VALUE.
 
      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
      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-CHANGE and MIN-TIME arguments,
      then it is omitted from the output.
 
      REPORTER must be the result of a call to ‘make-progress-reporter’.
      VALUE specifies the current state of your operation and must be
      between MIN-VALUE and 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 ‘point’.
 
      This function respects MIN-CHANGE and 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
      This function is similar to ‘progress-reporter-update’ except that
      it prints a message in the echo area unconditionally.
 
      The first two arguments have the same meaning as for
      ‘progress-reporter-update’.  Optional 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]) 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.
 
      You can rewrite the example in the beginning of this node using
      this macro this way:
 
           (dotimes-with-progress-reporter
               (k 500)
               "Collecting some mana for Emacs..."
             (sit-for 0.01))