aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2018-10-27 23:27:54 +0300
committerJuri Linkov2018-10-27 23:27:54 +0300
commit3dd16a89bf410d77e9ddc41cbfbbd4b343928d6d (patch)
treeb8ab1e8cce028a8e6726e669ec8766ed0a65a951
parent2df74ce79b910c977167e84d4cb37ede1053663f (diff)
downloademacs-3dd16a89bf410d77e9ddc41cbfbbd4b343928d6d.tar.gz
emacs-3dd16a89bf410d77e9ddc41cbfbbd4b343928d6d.zip
* lisp/isearch.el (lazy-highlight-buffer): New defcustom. (Bug#29360)
(lazy-highlight-buffer-max-at-a-time): New defcustom. (isearch-lazy-highlight-buffer): New defvar. (isearch-lazy-highlight-new-loop): Don't check changes in window boundaries when lazy-highlight-buffer is non-nil. Move code that extends start/end to match whole string at point here from isearch-lazy-highlight-search. (isearch-lazy-highlight-search): Add args string and bound like in other search functions. Move calculation of bound to isearch-lazy-highlight-update. (isearch-lazy-highlight-match): New function with code extracted from isearch-lazy-highlight-update to be called also from isearch-lazy-highlight-buffer-update. (isearch-lazy-highlight-update): Reuse the values returned from window-group-start and window-group-end. At the end schedule the timer to call isearch-lazy-highlight-buffer-update when isearch-lazy-highlight-buffer is non-nil. (isearch-lazy-highlight-buffer-update): New function.
-rw-r--r--etc/NEWS8
-rw-r--r--lisp/isearch.el185
2 files changed, 152 insertions, 41 deletions
diff --git a/etc/NEWS b/etc/NEWS
index be32ac6b9bb..57a83068bd2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -581,6 +581,14 @@ can now be searched via 'C-s'.
581 581
582** Search and Replace 582** Search and Replace
583 583
584*** lazy-highlight-buffer highlights matches in the full buffer.
585It is useful in combination with lazy-highlight-cleanup customized to nil
586to leave matches highlighted in the whole buffer after exiting isearch.
587Also when lazy-highlight-buffer prepares highlighting in the buffer,
588navigation through the matches without flickering is more smooth.
589lazy-highlight-buffer-max-at-a-time controls the number of matches to
590highlight in one iteration while processing the full buffer.
591
584+++ 592+++
585*** New isearch bindings. 593*** New isearch bindings.
586 594
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 38110d09984..580b3ac40a6 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -304,9 +304,9 @@ are `word-search-regexp' \(`\\[isearch-toggle-word]'), `isearch-symbol-regexp'
304 304
305(defcustom isearch-lazy-highlight t 305(defcustom isearch-lazy-highlight t
306 "Controls the lazy-highlighting during incremental search. 306 "Controls the lazy-highlighting during incremental search.
307When non-nil, all text in the buffer matching the current search 307When non-nil, all text currently visible on the screen
308string is highlighted lazily (see `lazy-highlight-initial-delay' 308matching the current search string is highlighted lazily
309and `lazy-highlight-interval'). 309(see `lazy-highlight-initial-delay' and `lazy-highlight-interval').
310 310
311When multiple windows display the current buffer, the 311When multiple windows display the current buffer, the
312highlighting is displayed only on the selected window, unless 312highlighting is displayed only on the selected window, unless
@@ -351,6 +351,27 @@ A value of nil means highlight all matches shown on the screen."
351 (integer :tag "Some")) 351 (integer :tag "Some"))
352 :group 'lazy-highlight) 352 :group 'lazy-highlight)
353 353
354(defcustom lazy-highlight-buffer-max-at-a-time 20
355 "Maximum matches to highlight at a time (for `lazy-highlight-buffer').
356Larger values may reduce Isearch's responsiveness to user input;
357smaller values make matches highlight slowly.
358A value of nil means highlight all matches in the buffer."
359 :type '(choice (const :tag "All" nil)
360 (integer :tag "Some"))
361 :group 'lazy-highlight
362 :version "27.1")
363
364(defcustom lazy-highlight-buffer nil
365 "Controls the lazy-highlighting of the full buffer.
366When non-nil, all text in the buffer matching the current search
367string is highlighted lazily (see `lazy-highlight-initial-delay',
368`lazy-highlight-interval' and `lazy-highlight-buffer-max-at-a-time').
369This is useful when `lazy-highlight-cleanup' is customized to nil
370and doesn't remove full-buffer highlighting after a search."
371 :type 'boolean
372 :group 'lazy-highlight
373 :version "27.1")
374
354(defface lazy-highlight 375(defface lazy-highlight
355 '((((class color) (min-colors 88) (background light)) 376 '((((class color) (min-colors 88) (background light))
356 (:background "paleturquoise")) 377 (:background "paleturquoise"))
@@ -3181,6 +3202,7 @@ since they have special meaning in a regexp."
3181(defvar isearch-lazy-highlight-window-group nil) 3202(defvar isearch-lazy-highlight-window-group nil)
3182(defvar isearch-lazy-highlight-window-start nil) 3203(defvar isearch-lazy-highlight-window-start nil)
3183(defvar isearch-lazy-highlight-window-end nil) 3204(defvar isearch-lazy-highlight-window-end nil)
3205(defvar isearch-lazy-highlight-buffer nil)
3184(defvar isearch-lazy-highlight-case-fold-search nil) 3206(defvar isearch-lazy-highlight-case-fold-search nil)
3185(defvar isearch-lazy-highlight-regexp nil) 3207(defvar isearch-lazy-highlight-regexp nil)
3186(defvar isearch-lazy-highlight-lax-whitespace nil) 3208(defvar isearch-lazy-highlight-lax-whitespace nil)
@@ -3229,10 +3251,12 @@ by other Emacs features."
3229 isearch-lax-whitespace)) 3251 isearch-lax-whitespace))
3230 (not (eq isearch-lazy-highlight-regexp-lax-whitespace 3252 (not (eq isearch-lazy-highlight-regexp-lax-whitespace
3231 isearch-regexp-lax-whitespace)) 3253 isearch-regexp-lax-whitespace))
3232 (not (= (window-group-start) 3254 (not (or lazy-highlight-buffer
3233 isearch-lazy-highlight-window-start)) 3255 (= (window-group-start)
3234 (not (= (window-group-end) ; Window may have been split/joined. 3256 isearch-lazy-highlight-window-start)))
3235 isearch-lazy-highlight-window-end)) 3257 (not (or lazy-highlight-buffer
3258 (= (window-group-end) ; Window may have been split/joined.
3259 isearch-lazy-highlight-window-end)))
3236 (not (eq isearch-forward 3260 (not (eq isearch-forward
3237 isearch-lazy-highlight-forward)) 3261 isearch-lazy-highlight-forward))
3238 ;; In case we are recovering from an error. 3262 ;; In case we are recovering from an error.
@@ -3250,6 +3274,7 @@ by other Emacs features."
3250 isearch-lazy-highlight-window-group (selected-window-group) 3274 isearch-lazy-highlight-window-group (selected-window-group)
3251 isearch-lazy-highlight-window-start (window-group-start) 3275 isearch-lazy-highlight-window-start (window-group-start)
3252 isearch-lazy-highlight-window-end (window-group-end) 3276 isearch-lazy-highlight-window-end (window-group-end)
3277 isearch-lazy-highlight-buffer lazy-highlight-buffer
3253 ;; Start lazy-highlighting at the beginning of the found 3278 ;; Start lazy-highlighting at the beginning of the found
3254 ;; match (`isearch-other-end'). If no match, use point. 3279 ;; match (`isearch-other-end'). If no match, use point.
3255 ;; One of the next two variables (depending on search direction) 3280 ;; One of the next two variables (depending on search direction)
@@ -3267,12 +3292,22 @@ by other Emacs features."
3267 isearch-lazy-highlight-regexp-lax-whitespace isearch-regexp-lax-whitespace 3292 isearch-lazy-highlight-regexp-lax-whitespace isearch-regexp-lax-whitespace
3268 isearch-lazy-highlight-regexp-function isearch-regexp-function 3293 isearch-lazy-highlight-regexp-function isearch-regexp-function
3269 isearch-lazy-highlight-forward isearch-forward) 3294 isearch-lazy-highlight-forward isearch-forward)
3295 ;; Extend start/end to match whole string at point (bug#19353)
3296 (if isearch-lazy-highlight-forward
3297 (setq isearch-lazy-highlight-start
3298 (min (+ isearch-lazy-highlight-start
3299 (1- (length isearch-lazy-highlight-last-string)))
3300 (point-max)))
3301 (setq isearch-lazy-highlight-end
3302 (max (- isearch-lazy-highlight-end
3303 (1- (length isearch-lazy-highlight-last-string)))
3304 (point-min))))
3270 (unless (equal isearch-string "") 3305 (unless (equal isearch-string "")
3271 (setq isearch-lazy-highlight-timer 3306 (setq isearch-lazy-highlight-timer
3272 (run-with-idle-timer lazy-highlight-initial-delay nil 3307 (run-with-idle-timer lazy-highlight-initial-delay nil
3273 'isearch-lazy-highlight-start))))) 3308 'isearch-lazy-highlight-start)))))
3274 3309
3275(defun isearch-lazy-highlight-search () 3310(defun isearch-lazy-highlight-search (string bound)
3276 "Search ahead for the next or previous match, for lazy highlighting. 3311 "Search ahead for the next or previous match, for lazy highlighting.
3277Attempt to do the search exactly the way the pending Isearch would." 3312Attempt to do the search exactly the way the pending Isearch would."
3278 (condition-case nil 3313 (condition-case nil
@@ -3286,24 +3321,10 @@ Attempt to do the search exactly the way the pending Isearch would."
3286 (isearch-forward isearch-lazy-highlight-forward) 3321 (isearch-forward isearch-lazy-highlight-forward)
3287 (search-invisible nil) ; don't match invisible text 3322 (search-invisible nil) ; don't match invisible text
3288 (retry t) 3323 (retry t)
3289 (success nil) 3324 (success nil))
3290 (bound (if isearch-lazy-highlight-forward
3291 (min (or isearch-lazy-highlight-end-limit (point-max))
3292 (if isearch-lazy-highlight-wrapped
3293 (+ isearch-lazy-highlight-start
3294 ;; Extend bound to match whole string at point
3295 (1- (length isearch-lazy-highlight-last-string)))
3296 (window-group-end)))
3297 (max (or isearch-lazy-highlight-start-limit (point-min))
3298 (if isearch-lazy-highlight-wrapped
3299 (- isearch-lazy-highlight-end
3300 ;; Extend bound to match whole string at point
3301 (1- (length isearch-lazy-highlight-last-string)))
3302 (window-group-start))))))
3303 ;; Use a loop like in `isearch-search'. 3325 ;; Use a loop like in `isearch-search'.
3304 (while retry 3326 (while retry
3305 (setq success (isearch-search-string 3327 (setq success (isearch-search-string string bound t))
3306 isearch-lazy-highlight-last-string bound t))
3307 ;; Clear RETRY unless the search predicate says 3328 ;; Clear RETRY unless the search predicate says
3308 ;; to skip this search hit. 3329 ;; to skip this search hit.
3309 (if (or (not success) 3330 (if (or (not success)
@@ -3315,6 +3336,17 @@ Attempt to do the search exactly the way the pending Isearch would."
3315 success) 3336 success)
3316 (error nil))) 3337 (error nil)))
3317 3338
3339(defun isearch-lazy-highlight-match (mb me)
3340 (let ((ov (make-overlay mb me)))
3341 (push ov isearch-lazy-highlight-overlays)
3342 ;; 1000 is higher than ediff's 100+,
3343 ;; but lower than isearch main overlay's 1001
3344 (overlay-put ov 'priority 1000)
3345 (overlay-put ov 'face 'lazy-highlight)
3346 (unless (or (eq isearch-lazy-highlight 'all-windows)
3347 isearch-lazy-highlight-buffer)
3348 (overlay-put ov 'window (selected-window)))))
3349
3318(defun isearch-lazy-highlight-start () 3350(defun isearch-lazy-highlight-start ()
3319 "Start a new lazy-highlight updating loop." 3351 "Start a new lazy-highlight updating loop."
3320 (lazy-highlight-cleanup t) ;remove old overlays 3352 (lazy-highlight-cleanup t) ;remove old overlays
@@ -3324,19 +3356,32 @@ Attempt to do the search exactly the way the pending Isearch would."
3324 "Update highlighting of other matches for current search." 3356 "Update highlighting of other matches for current search."
3325 (let ((max lazy-highlight-max-at-a-time) 3357 (let ((max lazy-highlight-max-at-a-time)
3326 (looping t) 3358 (looping t)
3327 nomore) 3359 nomore window-start window-end)
3328 (with-local-quit 3360 (with-local-quit
3329 (save-selected-window 3361 (save-selected-window
3330 (if (and (window-live-p isearch-lazy-highlight-window) 3362 (if (and (window-live-p isearch-lazy-highlight-window)
3331 (not (memq (selected-window) isearch-lazy-highlight-window-group))) 3363 (not (memq (selected-window) isearch-lazy-highlight-window-group)))
3332 (select-window isearch-lazy-highlight-window)) 3364 (select-window isearch-lazy-highlight-window))
3365 (setq window-start (window-group-start))
3366 (setq window-end (window-group-end))
3333 (save-excursion 3367 (save-excursion
3334 (save-match-data 3368 (save-match-data
3335 (goto-char (if isearch-lazy-highlight-forward 3369 (goto-char (if isearch-lazy-highlight-forward
3336 isearch-lazy-highlight-end 3370 isearch-lazy-highlight-end
3337 isearch-lazy-highlight-start)) 3371 isearch-lazy-highlight-start))
3338 (while looping 3372 (while looping
3339 (let ((found (isearch-lazy-highlight-search))) 3373 (let* ((bound (if isearch-lazy-highlight-forward
3374 (min (or isearch-lazy-highlight-end-limit (point-max))
3375 (if isearch-lazy-highlight-wrapped
3376 isearch-lazy-highlight-start
3377 window-end))
3378 (max (or isearch-lazy-highlight-start-limit (point-min))
3379 (if isearch-lazy-highlight-wrapped
3380 isearch-lazy-highlight-end
3381 window-start))))
3382 (found (isearch-lazy-highlight-search
3383 isearch-lazy-highlight-last-string
3384 bound)))
3340 (when max 3385 (when max
3341 (setq max (1- max)) 3386 (setq max (1- max))
3342 (if (<= max 0) 3387 (if (<= max 0)
@@ -3348,24 +3393,17 @@ Attempt to do the search exactly the way the pending Isearch would."
3348 (if isearch-lazy-highlight-forward 3393 (if isearch-lazy-highlight-forward
3349 (if (= mb (if isearch-lazy-highlight-wrapped 3394 (if (= mb (if isearch-lazy-highlight-wrapped
3350 isearch-lazy-highlight-start 3395 isearch-lazy-highlight-start
3351 (window-group-end))) 3396 window-end))
3352 (setq found nil) 3397 (setq found nil)
3353 (forward-char 1)) 3398 (forward-char 1))
3354 (if (= mb (if isearch-lazy-highlight-wrapped 3399 (if (= mb (if isearch-lazy-highlight-wrapped
3355 isearch-lazy-highlight-end 3400 isearch-lazy-highlight-end
3356 (window-group-start))) 3401 window-start))
3357 (setq found nil) 3402 (setq found nil)
3358 (forward-char -1))) 3403 (forward-char -1)))
3359 3404
3360 ;; non-zero-length match 3405 ;; non-zero-length match
3361 (let ((ov (make-overlay mb me))) 3406 (isearch-lazy-highlight-match mb me))
3362 (push ov isearch-lazy-highlight-overlays)
3363 ;; 1000 is higher than ediff's 100+,
3364 ;; but lower than isearch main overlay's 1001
3365 (overlay-put ov 'priority 1000)
3366 (overlay-put ov 'face 'lazy-highlight)
3367 (unless (eq isearch-lazy-highlight 'all-windows)
3368 (overlay-put ov 'window (selected-window)))))
3369 ;; Remember the current position of point for 3407 ;; Remember the current position of point for
3370 ;; the next call of `isearch-lazy-highlight-update' 3408 ;; the next call of `isearch-lazy-highlight-update'
3371 ;; when `lazy-highlight-max-at-a-time' is too small. 3409 ;; when `lazy-highlight-max-at-a-time' is too small.
@@ -3381,17 +3419,82 @@ Attempt to do the search exactly the way the pending Isearch would."
3381 (setq isearch-lazy-highlight-wrapped t) 3419 (setq isearch-lazy-highlight-wrapped t)
3382 (if isearch-lazy-highlight-forward 3420 (if isearch-lazy-highlight-forward
3383 (progn 3421 (progn
3384 (setq isearch-lazy-highlight-end (window-group-start)) 3422 (setq isearch-lazy-highlight-end window-start)
3385 (goto-char (max (or isearch-lazy-highlight-start-limit (point-min)) 3423 (goto-char (max (or isearch-lazy-highlight-start-limit (point-min))
3386 (window-group-start)))) 3424 window-start)))
3387 (setq isearch-lazy-highlight-start (window-group-end)) 3425 (setq isearch-lazy-highlight-start window-end)
3388 (goto-char (min (or isearch-lazy-highlight-end-limit (point-max)) 3426 (goto-char (min (or isearch-lazy-highlight-end-limit (point-max))
3389 (window-group-end)))))))) 3427 window-end)))))))
3390 (unless nomore 3428 (if nomore
3429 (when isearch-lazy-highlight-buffer
3430 (if isearch-lazy-highlight-forward
3431 (setq isearch-lazy-highlight-end (point-min))
3432 (setq isearch-lazy-highlight-start (point-max)))
3433 (run-at-time lazy-highlight-interval nil
3434 'isearch-lazy-highlight-buffer-update))
3391 (setq isearch-lazy-highlight-timer 3435 (setq isearch-lazy-highlight-timer
3392 (run-at-time lazy-highlight-interval nil 3436 (run-at-time lazy-highlight-interval nil
3393 'isearch-lazy-highlight-update))))))))) 3437 'isearch-lazy-highlight-update)))))))))
3394 3438
3439(defun isearch-lazy-highlight-buffer-update ()
3440 "Update highlighting of other matches in the full buffer."
3441 (let ((max lazy-highlight-buffer-max-at-a-time)
3442 (looping t)
3443 nomore window-start window-end)
3444 (with-local-quit
3445 (save-selected-window
3446 (if (and (window-live-p isearch-lazy-highlight-window)
3447 (not (memq (selected-window) isearch-lazy-highlight-window-group)))
3448 (select-window isearch-lazy-highlight-window))
3449 (setq window-start (window-group-start))
3450 (setq window-end (window-group-end))
3451 (save-excursion
3452 (save-match-data
3453 (goto-char (if isearch-lazy-highlight-forward
3454 isearch-lazy-highlight-end
3455 isearch-lazy-highlight-start))
3456 (while looping
3457 (let* ((bound (if isearch-lazy-highlight-forward
3458 (or isearch-lazy-highlight-end-limit (point-max))
3459 (or isearch-lazy-highlight-start-limit (point-min))))
3460 (found (isearch-lazy-highlight-search
3461 isearch-lazy-highlight-last-string
3462 bound)))
3463 (when max
3464 (setq max (1- max))
3465 (if (<= max 0)
3466 (setq looping nil)))
3467 (if found
3468 (let ((mb (match-beginning 0))
3469 (me (match-end 0)))
3470 (if (= mb me) ;zero-length match
3471 (if isearch-lazy-highlight-forward
3472 (if (= mb (point-max))
3473 (setq found nil)
3474 (forward-char 1))
3475 (if (= mb (point-min))
3476 (setq found nil)
3477 (forward-char -1)))
3478 ;; Already highlighted by isearch-lazy-highlight-update
3479 (unless (and (>= mb window-start) (<= me window-end))
3480 ;; non-zero-length match
3481 (isearch-lazy-highlight-match mb me)))
3482 ;; Remember the current position of point for
3483 ;; the next call of `isearch-lazy-highlight-update'
3484 ;; when `lazy-highlight-buffer-max-at-a-time' is too small.
3485 (if isearch-lazy-highlight-forward
3486 (setq isearch-lazy-highlight-end (point))
3487 (setq isearch-lazy-highlight-start (point)))))
3488
3489 ;; not found or zero-length match at the search bound
3490 (if (not found)
3491 (setq looping nil
3492 nomore t))))
3493 (unless nomore
3494 (setq isearch-lazy-highlight-timer
3495 (run-at-time lazy-highlight-interval nil
3496 'isearch-lazy-highlight-buffer-update)))))))))
3497
3395(defun isearch-resume (string regexp word forward message case-fold) 3498(defun isearch-resume (string regexp word forward message case-fold)
3396 "Resume an incremental search. 3499 "Resume an incremental search.
3397STRING is the string or regexp searched for. 3500STRING is the string or regexp searched for.