From edb1f85a27817a3fac38bb85752671414819203b Mon Sep 17 00:00:00 2001 From: Tino Calancha Date: Sun, 17 Jun 2018 18:28:34 +0900 Subject: [PATCH] Add new macro dolist-with-progress-reporter * lisp/subr.el (dolist-with-progress-reporter): New macro (Bug#31697). * lisp/cus-edit.el (custom-group-value-create): Use it. * lisp/dabbrev.el (dabbrev--progress-reporter): Delete variable. (dabbrev--find-expansion): Use dotimes-with-progress-reporter. * doc/lispref/display.texi: Document the macro. ; * etc/NEWS: Announce it. --- doc/lispref/display.texi | 15 +++++++++++++++ etc/NEWS | 3 +++ lisp/cus-edit.el | 10 ++-------- lisp/dabbrev.el | 21 ++++++++------------- lisp/subr.el | 28 ++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 21 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 12c36bb08ff..feeb1caf197 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -497,6 +497,21 @@ For instance, you can write previous example as follows: @end example @end defmac +@defmac dolist-with-progress-reporter (var count [result]) reporter-or-message body@dots{} +This is another convenience macro that works the same way as @code{dolist} +does, but also reports loop progress using the functions described +above. As in @code{dotimes-with-progress-reporter}, @code{reporter-or-message} can be +a progress reporter or an string. +We can rewrite our previous example with this macro as follows: + +@example +(dolist-with-progress-reporter + (k (number-sequence 0 500)) + "Collecting some mana for Emacs..." + (sit-for 0.01)) +@end example +@end defmac + @node Logging Messages @subsection Logging Messages in @file{*Messages*} @cindex logging echo-area messages diff --git a/etc/NEWS b/etc/NEWS index a77be110ffa..b5d3d59320a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -616,6 +616,9 @@ manual for more details. * Lisp Changes in Emacs 27.1 ++++ +** New macro dolist-with-progress-reporter. + +++ ** New hook 'after-delete-frame-functions'. This works like 'delete-frame-functions', but runs after the frame to diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index ff6a4f6d33c..723cd5010df 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -4221,19 +4221,14 @@ If GROUPS-ONLY is non-nil, return only those members that are groups." custom-buffer-order-groups)) (prefixes (widget-get widget :custom-prefixes)) (custom-prefix-list (custom-prefix-add symbol prefixes)) - (len (length members)) - (count 0) - (reporter (make-progress-reporter - "Creating group entries..." 0 len)) (have-subtitle (and (not (eq symbol 'emacs)) (eq custom-buffer-order-groups 'last))) prev-type children) - (dolist (entry members) + (dolist-with-progress-reporter (entry members) "Creating group entries..." (unless (eq prev-type 'custom-group) (widget-insert "\n")) - (progress-reporter-update reporter (setq count (1+ count))) (let ((sym (nth 0 entry)) (type (nth 1 entry))) (when (and have-subtitle (eq type 'custom-group)) @@ -4255,8 +4250,7 @@ If GROUPS-ONLY is non-nil, return only those members that are groups." (setq children (nreverse children)) (mapc 'custom-magic-reset children) (widget-put widget :children children) - (custom-group-state-update widget) - (progress-reporter-done reporter)) + (custom-group-state-update widget)) ;; End line (let ((p (1+ (point)))) (insert "\n\n") diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el index 57ee9a526a9..4af22e61409 100644 --- a/lisp/dabbrev.el +++ b/lisp/dabbrev.el @@ -327,9 +327,6 @@ this list." ;; The regexp for recognizing a character in an abbreviation. (defvar dabbrev--abbrev-char-regexp nil) -;; The progress reporter for buffer-scanning progress. -(defvar dabbrev--progress-reporter nil) - ;;---------------------------------------------------------------- ;; Macros ;;---------------------------------------------------------------- @@ -739,21 +736,19 @@ of the start of the occurrence." ;; Put that list in dabbrev--friend-buffer-list. (unless dabbrev--friend-buffer-list (setq dabbrev--friend-buffer-list - (dabbrev--make-friend-buffer-list)) - (setq dabbrev--progress-reporter - (make-progress-reporter - "Scanning for dabbrevs..." - (- (length dabbrev--friend-buffer-list)) 0 0 1 1.5)))) + (dabbrev--make-friend-buffer-list)))) ;; Walk through the buffers till we find a match. (let (expansion) - (while (and (not expansion) dabbrev--friend-buffer-list) + (dolist-with-progress-reporter + (_ dabbrev--friend-buffer-list) + (make-progress-reporter + "Scanning for dabbrevs..." + 0 (length dabbrev--friend-buffer-list) 0 1 1.5) (setq dabbrev--last-buffer (pop dabbrev--friend-buffer-list)) (set-buffer dabbrev--last-buffer) - (progress-reporter-update dabbrev--progress-reporter - (- (length dabbrev--friend-buffer-list))) (setq dabbrev--last-expansion-location (point-min)) - (setq expansion (dabbrev--try-find abbrev nil 1 ignore-case))) - (progress-reporter-done dabbrev--progress-reporter) + (setq expansion (dabbrev--try-find abbrev nil 1 ignore-case)) + (unless expansion (setq dabbrev--friend-buffer-list '()))) expansion))))) ;; Compute the list of buffers to scan. diff --git a/lisp/subr.el b/lisp/subr.el index d4383f862af..dc946bd90b0 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -5068,6 +5068,34 @@ This macro is a convenience wrapper around `make-progress-reporter' and friends. (progress-reporter-done ,prep) (or ,@(cdr (cdr spec)) nil)))) +(defmacro dolist-with-progress-reporter (spec reporter-or-message &rest body) + "Loop over a list and report progress in the echo area. +Evaluate BODY with VAR bound to each car from LIST, in turn. +Then evaluate RESULT to get return value, default nil. + +REPORTER-OR-MESSAGE is a progress reporter object or a string. In the latter +case, use this string to create a progress reporter. + +At each iteration, print the reporter message followed by progress +percentage in the echo area. After the loop is finished, +print the reporter message followed by word \"done\". + +\(fn (VAR LIST [RESULT]) MESSAGE BODY...)" + (declare (indent 2) (debug ((symbolp form &optional form) form body))) + (let ((prep (make-symbol "--dolist-progress-reporter--")) + (count (make-symbol "--dolist-count--")) + (list (make-symbol "--dolist-list--"))) + `(let ((,prep ,reporter-or-message) + (,count 0) + (,list ,(cadr spec))) + (when (stringp ,prep) + (setq ,prep (make-progress-reporter ,prep 0 (1- (length ,list))))) + (dolist (,(car spec) ,list) + ,@body + (progress-reporter-update ,prep (setq ,count (1+ ,count)))) + (progress-reporter-done ,prep) + (or ,@(cdr (cdr spec)) nil)))) + ;;;; Comparing version strings. -- 2.39.5