1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-23 07:19:15 +00:00

(make-progress-reporter, progress-reporter-update)

(progress-reporter-force-update, progress-reporter-do-update)
(progress-reporter-done): New functions.
This commit is contained in:
Eli Zaretskii 2004-10-08 17:23:40 +00:00
parent e42d647407
commit b4329caaf8
2 changed files with 133 additions and 0 deletions

View File

@ -1,3 +1,9 @@
2004-10-08 Paul Pogonyshev <pogonyshev@gmx.net>
* subr.el (make-progress-reporter, progress-reporter-update)
(progress-reporter-force-update, progress-reporter-do-update)
(progress-reporter-done): New functions.
2004-10-08 Alan Mackenzie <acm@muc.de>
* isearch.el (isearch-yank-line): C-y yanks to next EOL, not end

View File

@ -2652,5 +2652,132 @@ The properties used on SYMBOL are `composefunc', `sendfunc',
(put symbol 'abortfunc (or abortfunc 'kill-buffer))
(put symbol 'hookvar (or hookvar 'mail-send-hook)))
;; Standardized progress reporting
;; Progress reporter has the following structure:
;;
;; (NEXT-UPDATE-VALUE . [NEXT-UPDATE-TIME
;; MIN-VALUE
;; MAX-VALUE
;; MESSAGE
;; MIN-CHANGE
;; MIN-TIME])
;;
;; This weirdeness is for optimization reasons: we want
;; `progress-reporter-update' to be as fast as possible, so
;; `(car reporter)' is better than `(aref reporter 0)'.
;;
;; NEXT-UPDATE-TIME is a float. While `float-time' loses a couple
;; digits of precision, it doesn't really matter here. On the other
;; hand, it greatly simplifies the code.
(defun make-progress-reporter (message min-value max-value
&optional current-value
min-change min-time)
"Return an object suitable for reporting operation progress with `progress-reporter-update'.
MESSAGE is shown in the echo area. When at least 1% of operation
is complete, the exact percentage will be appended to the
MESSAGE. When you call `progress-reporter-done', word \"done\"
is printed after the MESSAGE. You can change MESSAGE of an
existing progress reporter with `progress-reporter-force-update'.
MIN-VALUE and MAX-VALUE designate starting (0% complete) and
final (100% complete) states of operation. The latter should be
larger; if this is not the case, then simply negate all values.
Optional CURRENT-VALUE specifies the progress by the moment you
call this function. You should omit it or set it to nil in most
cases since it defaults to MIN-VALUE.
Optional MIN-CHANGE determines the minimal change in percents to
report (default is 1%.) Optional MIN-TIME specifies the minimal
time before echo area updates (default is 0.2 seconds.) If
`float-time' function is not present, then time is not tracked
at all. If OS is not capable of measuring fractions of seconds,
then this parameter is effectively rounded up."
(unless min-time
(setq min-time 0.2))
(let ((reporter
(cons min-value ;; Force a call to `message' now
(vector (if (and (fboundp 'float-time)
(>= min-time 0.02))
(float-time) nil)
min-value
max-value
message
(if min-change (max (min min-change 50) 1) 1)
min-time))))
(progress-reporter-update reporter (or current-value min-value))
reporter))
(defsubst progress-reporter-update (reporter value)
"Report progress of an operation in the echo area.
However, if the change since last echo area update is too small
or not enough time has passed, then do nothing (see
`make-progress-reporter' for details).
First parameter, REPORTER, should be the result of a call to
`make-progress-reporter'. Second, VALUE, determines the actual
progress of operation; it must be between MIN-VALUE and MAX-VALUE
as passed to `make-progress-reporter'.
This function is very inexpensive, you may not bother how often
you call it."
(when (>= value (car reporter))
(progress-reporter-do-update reporter value)))
(defun progress-reporter-force-update (reporter value &optional new-message)
"Report progress of an operation in the echo area unconditionally.
First two parameters are the same as for
`progress-reporter-update'. Optional NEW-MESSAGE allows you to
change the displayed message."
(let ((parameters (cdr reporter)))
(when new-message
(aset parameters 3 new-message))
(when (aref parameters 0)
(aset parameters 0 (float-time)))
(progress-reporter-do-update reporter value)))
(defun progress-reporter-do-update (reporter value)
(let* ((parameters (cdr reporter))
(min-value (aref parameters 1))
(max-value (aref parameters 2))
(one-percent (/ (- max-value min-value) 100.0))
(percentage (truncate (/ (- value min-value) one-percent)))
(update-time (aref parameters 0))
(current-time (float-time))
(enough-time-passed
;; See if enough time has passed since the last update.
(or (not update-time)
(when (>= current-time update-time)
;; Calculate time for the next update
(aset parameters 0 (+ update-time (aref parameters 5)))))))
;;
;; Calculate NEXT-UPDATE-VALUE. If we are not going to print
;; message this time because not enough time has passed, then use
;; 1 instead of MIN-CHANGE. This makes delays between echo area
;; updates closer to MIN-TIME.
(setcar reporter
(min (+ min-value (* (+ percentage
(if enough-time-passed
(aref parameters 4) ;; MIN-CHANGE
1))
one-percent))
max-value))
(when (integerp value)
(setcar reporter (ceiling (car reporter))))
;;
;; Only print message if enough time has passed
(when enough-time-passed
(if (> percentage 0)
(message "%s%d%%" (aref parameters 3) percentage)
(message "%s" (aref parameters 3))))))
(defun progress-reporter-done (reporter)
"Print reporter's message followed by word \"done\" in echo area."
(message "%sdone" (aref (cdr reporter) 3)))
;; arch-tag: f7e0e6e5-70aa-4897-ae72-7a3511ec40bc
;;; subr.el ends here