emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 4c0c9d23ab 1/2: Rewrite the minibuffer lazy highlight feature


From: Juri Linkov
Subject: master 4c0c9d23ab 1/2: Rewrite the minibuffer lazy highlight feature
Date: Sun, 10 Apr 2022 15:38:10 -0400 (EDT)

branch: master
commit 4c0c9d23abc28c7fa7eacf2f4d7a5aff02d84ab0
Author: Augusto Stoffel <arstoffel@gmail.com>
Commit: Juri Linkov <juri@linkov.net>

    Rewrite the minibuffer lazy highlight feature
    
    The new API was discussed in bug#53126.  It's more robust and easier
    to use in complex cases like that of 'query-replace'.
    
    * etc/NEWS: Amend the feature announcement
    * lisp/isearch.el (isearch-edit-string): Use new API.
    (minibuffer-lazy-highlight-transform,
    minibuffer-lazy-highlight--overlay, minibuffer-lazy-highlight--count,
    minibuffer-lazy-highlight--after-change,
    minibuffer-lazy-highlight--exit) Remove helper functions, which are
    now kept together with the lazy highlight configuration variables
    within a closure.
    (minibuffer-lazy-highlight-setup): This function now takes the lazy
    highlighting configuration variables as argument, and returns a
    closure that is intended to run as part of the minibuffer setup.
---
 etc/NEWS        |   5 +-
 lisp/isearch.el | 148 ++++++++++++++++++++++++++++++++------------------------
 2 files changed, 88 insertions(+), 65 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 2fac893cc5..2cddfcc8db 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1593,9 +1593,8 @@ the clipboard, and insert it into the buffer.
 
 ---
 ** New function 'minibuffer-lazy-highlight-setup'.
-This function is intended to be added to 'minibuffer-setup-hook'.
-It sets up the minibuffer for lazy highlighting of matches
-in the original window.
+This function allows to set up the minibuffer so that lazy
+highlighting of its content is applied in the original window.
 
 +++
 ** New text property 'inhibit-isearch'.
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 956b115ce4..168d71ada3 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1812,20 +1812,20 @@ The following additional command keys are active while 
editing.
          (minibuffer-history-symbol)
          ;; Search string might have meta information on text properties.
          (minibuffer-allow-text-properties t))
-     (when isearch-lazy-highlight
-       (add-hook 'minibuffer-setup-hook #'minibuffer-lazy-highlight-setup))
      (setq isearch-new-string
-          (read-from-minibuffer
-           (isearch-message-prefix nil isearch-nonincremental)
-           (cons isearch-string (1+ (or (isearch-fail-pos)
-                                        (length isearch-string))))
-           minibuffer-local-isearch-map nil
-           (if isearch-regexp
-               (cons 'regexp-search-ring
-                     (1+ (or regexp-search-ring-yank-pointer -1)))
-             (cons 'search-ring
-                   (1+ (or search-ring-yank-pointer -1))))
-           nil t)
+          (minibuffer-with-setup-hook
+               (minibuffer-lazy-highlight-setup)
+             (read-from-minibuffer
+             (isearch-message-prefix nil isearch-nonincremental)
+             (cons isearch-string (1+ (or (isearch-fail-pos)
+                                          (length isearch-string))))
+             minibuffer-local-isearch-map nil
+             (if isearch-regexp
+                 (cons 'regexp-search-ring
+                       (1+ (or regexp-search-ring-yank-pointer -1)))
+               (cons 'search-ring
+                     (1+ (or search-ring-yank-pointer -1))))
+             nil t))
           isearch-new-message
           (mapconcat 'isearch-text-char-description
                      isearch-new-string "")))))
@@ -4361,57 +4361,81 @@ Attempt to do the search exactly the way the pending 
Isearch would."
   :group 'lazy-count
   :version "29.1")
 
-(defvar minibuffer-lazy-highlight-transform #'identity
-  "Function to transform minibuffer text into a `isearch-string' for 
highlighting.")
-
-(defvar minibuffer-lazy-highlight--overlay nil
-  "Overlay for minibuffer prompt updates.")
-
-(defun minibuffer-lazy-highlight--count ()
-  "Display total match count in the minibuffer prompt."
-  (when minibuffer-lazy-highlight--overlay
-    (overlay-put minibuffer-lazy-highlight--overlay
-                 'before-string
-                 (and isearch-lazy-count-total
-                      (not isearch-error)
-                      (format minibuffer-lazy-count-format
-                              isearch-lazy-count-total)))))
-
-(defun minibuffer-lazy-highlight--after-change (_beg _end _len)
-  "Update lazy highlight state in minibuffer selected window."
-  (when isearch-lazy-highlight
-    (let ((inhibit-redisplay t) ;; Avoid cursor flickering
-          (string (minibuffer-contents)))
-      (with-minibuffer-selected-window
-        (setq isearch-string (funcall minibuffer-lazy-highlight-transform 
string))
-        (isearch-lazy-highlight-new-loop)))))
-
-(defun minibuffer-lazy-highlight--exit ()
-  "Unwind changes from `minibuffer-lazy-highlight-setup'."
-  (remove-hook 'after-change-functions
-               #'minibuffer-lazy-highlight--after-change)
-  (remove-hook 'lazy-count-update-hook #'minibuffer-lazy-highlight--count)
-  (remove-hook 'minibuffer-exit-hook #'minibuffer-lazy-highlight--exit)
-  (setq minibuffer-lazy-highlight--overlay nil)
-  (when lazy-highlight-cleanup
-    (lazy-highlight-cleanup)))
-
-(defun minibuffer-lazy-highlight-setup ()
+(cl-defun minibuffer-lazy-highlight-setup
+    (&key (highlight isearch-lazy-highlight)
+          (cleanup lazy-highlight-cleanup)
+          (transform #'identity)
+          (filter nil)
+          (regexp isearch-regexp)
+          (regexp-function isearch-regexp-function)
+          (case-fold isearch-case-fold-search)
+          (lax-whitespace (if regexp
+                              isearch-regexp-lax-whitespace
+                            isearch-lax-whitespace)))
   "Set up minibuffer for lazy highlight of matches in the original window.
 
-This function is intended to be added to `minibuffer-setup-hook'.
-Note that several other isearch variables influence the lazy
-highlighting, including `isearch-regexp',
-`isearch-lazy-highlight' and `isearch-lazy-count'."
-  (remove-hook 'minibuffer-setup-hook #'minibuffer-lazy-highlight-setup)
-  (add-hook 'after-change-functions
-            #'minibuffer-lazy-highlight--after-change)
-  (add-hook 'lazy-count-update-hook #'minibuffer-lazy-highlight--count)
-  (add-hook 'minibuffer-exit-hook #'minibuffer-lazy-highlight--exit)
-  (setq minibuffer-lazy-highlight--overlay
-        (and minibuffer-lazy-count-format
-             (make-overlay (point-min) (point-min) (current-buffer) t)))
-  (minibuffer-lazy-highlight--after-change nil nil nil))
+This function return a closure intended to be added to
+`minibuffer-setup-hook'.  It accepts the following keyword
+arguments, all of which have a default based on the current
+isearch settings.
+
+HIGHLIGHT: Whether to perform lazy highlight.
+CLEANUP: Whether to clean up the lazy highlight when the minibuffer
+exits.
+TRANSFORM: A function taking one argument, the minibuffer contents,
+and returning the `isearch-string' to use for lazy highlighting.
+FILTER: A function to add to `isearch-filter-predicate'.
+REGEXP: The value of `isearch-regexp' to use for lazy highlighting.
+REGEXP-FUNCTION: The value of `isearch-regexp-function' to use for
+lazy highlighting.
+CASE-FOLD: The value of `isearch-case-fold' to use for lazy
+highlighting.
+LAX-WHITESPACE: The value of `isearch-lax-whitespace' and
+`isearch-regexp-lax-whitespace' to use for lazy highlighting."
+  (if (not highlight)
+      #'ignore
+    (let ((unwind (make-symbol "minibuffer-lazy-highlight--unwind"))
+          (after-change (make-symbol 
"minibuffer-lazy-highlight--after-change"))
+          (display-count (make-symbol 
"minibuffer-lazy-highlight--display-count"))
+          overlay)
+      (fset unwind
+            (lambda ()
+              (remove-function isearch-filter-predicate filter)
+              (remove-hook 'lazy-count-update-hook display-count)
+              (when overlay (delete-overlay overlay))
+              (remove-hook 'after-change-functions after-change)
+              (remove-hook 'minibuffer-exit-hook unwind)
+              (let ((lazy-highlight-cleanup cleanup))
+                (lazy-highlight-cleanup))))
+      (fset after-change
+            (lambda (_beg _end _len)
+              (let ((inhibit-redisplay t) ;; Avoid cursor flickering
+                    (string (minibuffer-contents)))
+                (with-minibuffer-selected-window
+                  (let* ((isearch-forward t)
+                         (isearch-regexp regexp)
+                         (isearch-regexp-function regexp-function)
+                         (isearch-case-fold-search case-fold)
+                         (isearch-lax-whitespace lax-whitespace)
+                         (isearch-regexp-lax-whitespace lax-whitespace)
+                         (isearch-string (funcall transform string)))
+                    (isearch-lazy-highlight-new-loop))))))
+      (fset display-count
+            (lambda ()
+              (overlay-put overlay 'before-string
+                           (and isearch-lazy-count-total
+                                (not isearch-error)
+                                (format minibuffer-lazy-count-format
+                                        isearch-lazy-count-total)))))
+      (lambda ()
+        (add-hook 'minibuffer-exit-hook unwind)
+        (add-hook 'after-change-functions after-change)
+        (when minibuffer-lazy-count-format
+          (setq overlay (make-overlay (point-min) (point-min) (current-buffer) 
t))
+          (add-hook 'lazy-count-update-hook display-count))
+        (when filter
+          (add-function :after-while isearch-filter-predicate filter))
+        (funcall after-change nil nil nil)))))
 
 
 (defun isearch-resume (string regexp word forward message case-fold)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]