bug-gnu-emacs
[Top][All Lists]
Advanced

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

bug#29360: 26.0; Add full-buffer choice for `isearch-lazy-highlight'


From: Juri Linkov
Subject: bug#29360: 26.0; Add full-buffer choice for `isearch-lazy-highlight'
Date: Sun, 21 Oct 2018 22:06:48 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (x86_64-pc-linux-gnu)

> In any case, yes, your suggestion of first doing what we do now
> (highlight the immediate area, using the current algorith), and
> then following that with highlighting the rest of the buffer,
> could be a good idea. Dunno how much that might change
> the existing code.

In the patch attached below, a new function isearch-lazy-highlight-buffer-update
is a copy of isearch-lazy-highlight-update with some changes specific
to highlighting the full buffer.  It seems making a duplicate function
is necessary because adding more full-buffer specific conditions to
the existing function isearch-lazy-highlight-update will make it
unmaintainable.

Only a part of the function (that highlights the match) is extracted
into a new function isearch-lazy-highlight-match and shared among these
aforementioned two functions.

diff --git a/lisp/isearch.el b/lisp/isearch.el
index 1e785a44c5..cb9e72526b 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -304,7 +304,7 @@ isearch-fail
 
 (defcustom isearch-lazy-highlight t
   "Controls the lazy-highlighting during incremental search.
-When non-nil, all text in the buffer matching the current search
+When non-nil, all text on the screen matching the current search
 string is highlighted lazily (see `lazy-highlight-initial-delay'
 and `lazy-highlight-interval').
 
@@ -316,6 +316,15 @@ isearch-lazy-highlight
   :group 'lazy-highlight
   :group 'isearch)
 
+(defcustom isearch-lazy-highlight-buffer nil
+  "Controls the lazy-highlighting of the whole buffer.
+When non-nil, all text in the buffer matching the current search
+string is highlighted lazily (see `lazy-highlight-initial-delay',
+`lazy-highlight-interval' and `lazy-highlight-buffer-max-at-a-time')."
+  :type 'boolean
+  :group 'lazy-highlight
+  :group 'isearch)
+
 ;;; Lazy highlight customization.
 
 (defgroup lazy-highlight nil
@@ -351,6 +360,15 @@ lazy-highlight-max-at-a-time
                 (integer :tag "Some"))
   :group 'lazy-highlight)
 
+(defcustom lazy-highlight-buffer-max-at-a-time 20
+  "Maximum matches to highlight at a time (for 
`isearch-lazy-highlight-buffer').
+Larger values may reduce Isearch's responsiveness to user input;
+smaller values make matches highlight slowly.
+A value of nil means highlight all matches shown in the buffer."
+  :type '(choice (const :tag "All" nil)
+                (integer :tag "Some"))
+  :group 'lazy-highlight)
+
 (defface lazy-highlight
   '((((class color) (min-colors 88) (background light))
      (:background "paleturquoise"))
@@ -3290,13 +3308,13 @@ isearch-lazy-highlight-search
                                (+ isearch-lazy-highlight-start
                                   ;; Extend bound to match whole string at 
point
                                   (1- (length 
isearch-lazy-highlight-last-string)))
-                             (window-group-end)))
+                             (if isearch-lazy-highlight-buffer (point-max) 
(window-group-end))))
                     (max (or isearch-lazy-highlight-start-limit (point-min))
                          (if isearch-lazy-highlight-wrapped
                              (- isearch-lazy-highlight-end
                                 ;; Extend bound to match whole string at point
                                 (1- (length 
isearch-lazy-highlight-last-string)))
-                           (window-group-start))))))
+                           (if isearch-lazy-highlight-buffer (point-min) 
(window-group-start)))))))
        ;; Use a loop like in `isearch-search'.
        (while retry
          (setq success (isearch-search-string
@@ -3317,6 +3335,20 @@ isearch-lazy-highlight-start
   (lazy-highlight-cleanup t) ;remove old overlays
   (isearch-lazy-highlight-update))
 
+(defvar isearch-lazy-highlight-match-function #'isearch-lazy-highlight-match
+  "Function that highlights the found match.
+The function accepts two arguments: the beginning and the end of the match.")
+
+(defun isearch-lazy-highlight-match (mb me)
+  (let ((ov (make-overlay mb me)))
+    (push ov isearch-lazy-highlight-overlays)
+    ;; 1000 is higher than ediff's 100+,
+    ;; but lower than isearch main overlay's 1001
+    (overlay-put ov 'priority 1000)
+    (overlay-put ov 'face 'lazy-highlight)
+    (unless (eq isearch-lazy-highlight 'all-windows)
+      (overlay-put ov 'window (selected-window)))))
+
 (defun isearch-lazy-highlight-update ()
   "Update highlighting of other matches for current search."
   (let ((max lazy-highlight-max-at-a-time)
@@ -3353,16 +3385,8 @@ isearch-lazy-highlight-update
                                        (window-group-start)))
                                (setq found nil)
                              (forward-char -1)))
-
                        ;; non-zero-length match
-                       (let ((ov (make-overlay mb me)))
-                         (push ov isearch-lazy-highlight-overlays)
-                         ;; 1000 is higher than ediff's 100+,
-                         ;; but lower than isearch main overlay's 1001
-                         (overlay-put ov 'priority 1000)
-                         (overlay-put ov 'face 'lazy-highlight)
-                         (unless (eq isearch-lazy-highlight 'all-windows)
-                            (overlay-put ov 'window (selected-window)))))
+                       (funcall isearch-lazy-highlight-match-function mb me))
                      ;; Remember the current position of point for
                      ;; the next call of `isearch-lazy-highlight-update'
                      ;; when `lazy-highlight-max-at-a-time' is too small.
@@ -3384,11 +3408,75 @@ isearch-lazy-highlight-update
                        (setq isearch-lazy-highlight-start (window-group-end))
                        (goto-char (min (or isearch-lazy-highlight-end-limit 
(point-max))
                                        (window-group-end))))))))
-           (unless nomore
+           (if nomore
+                (when isearch-lazy-highlight-buffer
+                  (setq isearch-lazy-highlight-start (window-group-start))
+                  (setq isearch-lazy-highlight-end (window-group-end))
+                  (setq isearch-lazy-highlight-wrapped nil)
+                  (run-at-time lazy-highlight-interval nil
+                              'isearch-lazy-highlight-buffer-update))
              (setq isearch-lazy-highlight-timer
                    (run-at-time lazy-highlight-interval nil
                                 'isearch-lazy-highlight-update)))))))))
 
+(defun isearch-lazy-highlight-buffer-update ()
+  "Update highlighting of other matches in the whole buffer."
+  (let ((max lazy-highlight-buffer-max-at-a-time)
+        (looping t)
+        nomore)
+    (with-local-quit
+      (save-excursion
+       (save-match-data
+         (goto-char (if isearch-lazy-highlight-forward
+                        isearch-lazy-highlight-end
+                      isearch-lazy-highlight-start))
+         (while looping
+           (let ((found (isearch-lazy-highlight-search)))
+             (when max
+               (setq max (1- max))
+               (if (<= max 0)
+                   (setq looping nil)))
+             (if found
+                 (let ((mb (match-beginning 0))
+                       (me (match-end 0)))
+                   (if (= mb me)       ;zero-length match
+                       (if isearch-lazy-highlight-forward
+                           (if (= mb (if isearch-lazy-highlight-wrapped
+                                         (window-group-start)
+                                       (point-max)))
+                               (setq found nil)
+                             (forward-char 1))
+                         (if (= mb (if isearch-lazy-highlight-wrapped
+                                       (window-group-end)
+                                     (point-min)))
+                             (setq found nil)
+                           (forward-char -1)))
+                     ;; non-zero-length match
+                     (funcall isearch-lazy-highlight-match-function mb me))
+                   ;; Remember the current position of point for
+                   ;; the next call of `isearch-lazy-highlight-update'
+                   ;; when `lazy-highlight-max-at-a-time' is too small.
+                   (if isearch-lazy-highlight-forward
+                       (setq isearch-lazy-highlight-end (point))
+                     (setq isearch-lazy-highlight-start (point)))))
+             ;; not found or zero-length match at the search bound
+             (if (not found)
+                 (if isearch-lazy-highlight-wrapped
+                     (setq looping nil
+                           nomore  t)
+                   (setq isearch-lazy-highlight-wrapped t)
+                   (if isearch-lazy-highlight-forward
+                       (progn
+                         (setq isearch-lazy-highlight-end (point-min))
+                         (goto-char (point-min)))
+                     (setq isearch-lazy-highlight-start (point-max))
+                     (goto-char (point-max)))))))
+         (if nomore
+              (message "Finished lazy-highlighting the buffer")
+           (setq isearch-lazy-highlight-timer
+                 (run-at-time lazy-highlight-interval nil
+                              'isearch-lazy-highlight-buffer-update))))))))
+
 (defun isearch-resume (string regexp word forward message case-fold)
   "Resume an incremental search.
 STRING is the string or regexp searched for.

reply via email to

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