-;;; isearch.el --- incremental search minor mode.
+;;; isearch.el --- incremental search minor mode
;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1999, 2000, 2001
;; Free Software Foundation, Inc.
:type 'boolean
:group 'isearch)
+(defcustom isearch-resume-enabled t
+ "*If non-nil, `isearch-resume' commands are added to the command history."
+ :type 'boolean
+ :group 'isearch)
+
(defvar isearch-mode-hook nil
"Function(s) to call after starting up an incremental search.")
(define-key map " " 'isearch-whitespace-chars)
(define-key map [?\S-\ ] 'isearch-whitespace-chars)
- (define-key map "\C-w" 'isearch-yank-word)
+ (define-key map "\C-w" 'isearch-yank-word-or-char)
(define-key map "\C-y" 'isearch-yank-line)
;; Define keys for regexp chars * ? |.
(define-key map [delete-frame] nil)
(define-key map [iconify-frame] nil)
(define-key map [make-frame-visible] nil)
+ (define-key map [mouse-movement] nil)
;; For searching multilingual text.
(define-key map "\C-\\" 'isearch-toggle-input-method)
(define-key map "\C-^" 'isearch-toggle-specified-input-method)
;; People expect to be able to paste with the mouse.
- (define-key map [mouse-2] #'isearch-mouse-yank)
+ (define-key map [mouse-2] #'isearch-mouse-2)
(define-key map [down-mouse-2] nil)
;; Some bindings you may want to put in your isearch-mode-hook.
; case in the search string is ignored.
(defvar isearch-case-fold-search nil)
+(defvar isearch-last-case-fold-search nil)
+
;; Used to save default value while isearch is active
(defvar isearch-original-minibuffer-message-timeout nil)
\\[isearch-abort] when search is successful aborts and moves point to\
starting point.
+Type \\[isearch-toggle-case-fold] to toggle search case-sensitivity.
+Type \\[isearch-toggle-regexp] to toggle regular-expression mode.
+Type \\[isearch-edit-string] to edit the search string in the minibuffer.
+
Also supported is a search ring of the previous 16 search strings.
Type \\[isearch-ring-advance] to search for the next item in the search ring.
Type \\[isearch-ring-retreat] to search for the previous item in the search\
ring.
Type \\[isearch-complete] to complete the search string using the search ring.
+If an input method is turned on in the current buffer, that input
+method is also active while you are typing a characters to search. To
+toggle the input method, type \\[isearch-toggle-input-method]. It
+also toggles the input method in the current buffer.
+
+To use a different input method for searching, type
+\\[isearch-toggle-specified-input-method], and specify an input method
+you want to use.
+
The above keys, bound in `isearch-mode-map', are often controlled by
options; do M-x apropos on search-.* to find them.
Other control and meta characters terminate the search
isearch-regexp regexp
isearch-word word-p
isearch-op-fun op-fun
+ isearch-last-case-fold-search isearch-case-fold-search
isearch-case-fold-search case-fold-search
isearch-string ""
isearch-message ""
isearch-within-brackets nil
isearch-slow-terminal-mode (and (<= baud-rate search-slow-speed)
(> (window-height)
- (* 4 search-slow-window-lines)))
+ (* 4
+ (abs search-slow-window-lines))))
isearch-other-end nil
isearch-small-window nil
isearch-just-started t
;; Called after each command to update the display.
(if (null unread-command-events)
(progn
- (if (not (input-pending-p))
- (isearch-message))
- (if (and isearch-slow-terminal-mode
- (not (or isearch-small-window
- (pos-visible-in-window-p))))
- (let ((found-point (point)))
- (setq isearch-small-window t)
- (move-to-window-line 0)
- (let ((window-min-height 1))
- (split-window nil (if (< search-slow-window-lines 0)
- (1+ (- search-slow-window-lines))
- (- (window-height)
- (1+ search-slow-window-lines)))))
- (if (< search-slow-window-lines 0)
- (progn (vertical-motion (- 1 search-slow-window-lines))
- (set-window-start (next-window) (point))
- (set-window-hscroll (next-window)
- (window-hscroll))
- (set-window-hscroll (selected-window) 0))
- (other-window 1))
- (goto-char found-point)))
- (if isearch-other-end
- (if (< isearch-other-end (point)) ; isearch-forward?
- (isearch-highlight isearch-other-end (point))
- (isearch-highlight (point) isearch-other-end))
- (isearch-dehighlight nil))
- ))
+ (if (not (input-pending-p))
+ (isearch-message))
+ (if (and isearch-slow-terminal-mode
+ (not (or isearch-small-window
+ (pos-visible-in-window-p))))
+ (let ((found-point (point)))
+ (setq isearch-small-window t)
+ (move-to-window-line 0)
+ (let ((window-min-height 1))
+ (split-window nil (if (< search-slow-window-lines 0)
+ (1+ (- search-slow-window-lines))
+ (- (window-height)
+ (1+ search-slow-window-lines)))))
+ (if (< search-slow-window-lines 0)
+ (progn (vertical-motion (- 1 search-slow-window-lines))
+ (set-window-start (next-window) (point))
+ (set-window-hscroll (next-window)
+ (window-hscroll))
+ (set-window-hscroll (selected-window) 0))
+ (other-window 1))
+ (goto-char found-point)))
+ (if isearch-other-end
+ (if (< isearch-other-end (point)) ; isearch-forward?
+ (isearch-highlight isearch-other-end (point))
+ (isearch-highlight (point) isearch-other-end))
+ (isearch-dehighlight nil))
+ ))
(setq ;; quit-flag nil not for isearch-mode
isearch-adjusted nil
isearch-yank-flag nil)
(setq disable-point-adjustment t))
(defun isearch-done (&optional nopush edit)
- (let ((command `(isearch-resume ,isearch-string ,isearch-regexp
- ,isearch-word ,isearch-forward
- ,isearch-message
- ,isearch-case-fold-search)))
- (unless (equal (car command-history) command)
- (setq command-history (cons command command-history))))
+ (if isearch-resume-enabled
+ (let ((command `(isearch-resume ,isearch-string ,isearch-regexp
+ ,isearch-word ,isearch-forward
+ ,isearch-message
+ ',isearch-case-fold-search)))
+ (unless (equal (car command-history) command)
+ (setq command-history (cons command command-history)))))
(remove-hook 'mouse-leave-buffer-hook 'isearch-done)
(remove-hook 'kbd-macro-termination-hook 'isearch-done)
-
(setq isearch-lazy-highlight-start nil)
;; Called by all commands that terminate isearch-mode.
"")
isearch-message
(mapconcat 'isearch-text-char-description
- isearch-string ""))
+ isearch-string "")
+ isearch-case-fold-search isearch-last-case-fold-search)
;; If already have what to search for, repeat it.
(or isearch-success
(progn
(isearch-update))
(defun isearch-delete-char ()
- "Discard last input item and move point back.
+ "Discard last input item and move point back.
If no previous match was done, just beep."
(interactive)
(if (null (cdr isearch-cmds))
(interactive)
(isearch-yank-string (x-get-selection)))
-(defun isearch-mouse-yank (click arg)
- "Yank with the mouse in Isearch mode.
+
+(defun isearch-mouse-2 (click arg)
+ "Handle mouse-2 in Isearch mode.
For a click in the echo area, invoke `isearch-yank-x-selection'.
-Otherwise invoke `mouse-yank-at-click'."
+Otherwise invoke whatever mouse-2 is bound to outside of Isearch."
(interactive "e\nP")
- (let ((w (posn-window (event-start click))))
+ (let* ((w (posn-window (event-start click)))
+ (overriding-terminal-local-map nil)
+ (key (vector (event-basic-type click)))
+ (binding (key-binding key)))
(if (and (window-minibuffer-p w)
(not (minibuffer-window-active-p w))) ; in echo area
(isearch-yank-x-selection)
- (mouse-yank-at-click click arg))))
-
-(defun isearch-yank-word ()
- "Pull next word from buffer into search string."
- (interactive)
+ (when binding
+ ;; Kluge to allow passing ARG to functions that support it,
+ ;; like mouse-yank-at-click.
+ (if (equal (cadr (interactive-form binding)) "e\nP")
+ (funcall binding click arg)
+ (funcall binding click))))))
+
+
+(defun isearch-yank-internal (jumpform)
+ "Pull the text from point to the point reached by JUMPFORM.
+JUMPFORM is a lambda expression that takes no arguments and returns a
+buffer position, possibly having moved point to that position. For
+example, it might move point forward by a word and return point, or it
+might return the position of the end of the line."
(isearch-yank-string
(save-excursion
(and (not isearch-forward) isearch-other-end
(goto-char isearch-other-end))
- (buffer-substring-no-properties
- (point) (progn (forward-word 1) (point))))))
+ (buffer-substring-no-properties (point) (funcall jumpform)))))
+
+(defun isearch-yank-char ()
+ "Pull next letter from buffer into search string."
+ (interactive)
+ (isearch-yank-internal (lambda () (forward-char 1) (point))))
+
+(defun isearch-yank-word-or-char ()
+ "Pull next character or word from buffer into search string."
+ (interactive)
+ (isearch-yank-internal (lambda ()
+ (if (or (= (char-syntax (or (char-after) 0)) ?w)
+ (= (char-syntax (or (char-after (1+ (point))) 0)) ?w))
+ (forward-word 1)
+ (forward-char 1)) (point))))
+
+(defun isearch-yank-word ()
+ "Pull next word from buffer into search string."
+ (interactive)
+ (isearch-yank-internal (lambda () (forward-word 1) (point))))
(defun isearch-yank-line ()
"Pull rest of line from buffer into search string."
(interactive)
- (isearch-yank-string
- (save-excursion
- (and (not isearch-forward) isearch-other-end
- (goto-char isearch-other-end))
- (buffer-substring-no-properties (point) (line-end-position)))))
+ (isearch-yank-internal (lambda () (line-end-position))))
(defun isearch-search-and-update ()
(let (window)
(cancel-kbd-macro-events)
(apply 'isearch-unread keylist)
- ;; Properly handle scroll-bar and mode-line clicks
- ;; for which a dummy prefix event was generated as (aref key 0).
- (and (> (length key) 1)
- (symbolp (aref key 0))
- (listp (aref key 1))
- (not (numberp (posn-point (event-start (aref key 1)))))
- ;; Convert the event back into its raw form,
- ;; with the dummy prefix implicit in the mouse event,
- ;; so it will get split up once again.
- (progn (setq unread-command-events
- (cdr unread-command-events))
- (setq main-event (car unread-command-events))
- (setcar (cdr (event-start main-event))
- (car (nth 1 (event-start main-event))))))
- ;; If we got a mouse click, maybe it was read with the buffer
+
+ ;; Properly handle scroll-bar and mode-line clicks for
+ ;; which a dummy prefix event was generated as (aref key
+ ;; 0). Note that we don't have to modify the event
+ ;; anymore in 21 because read_key_sequence no longer modifies
+ ;; events to produce fake prefix keys.
+ (when (and (> (length key) 1)
+ (symbolp (aref key 0))
+ (listp (aref key 1))
+ (not (numberp (posn-point
+ (event-start (aref key 1))))))
+ (pop unread-command-events)
+ (setq main-event (car unread-command-events)))
+
+ ;; If we got a mouse click event, that event contains the
+ ;; window clicked on. maybe it was read with the buffer
;; it was clicked on. If so, that buffer, not the current one,
;; is in isearch mode. So end the search in that buffer.
- (if (and (listp main-event)
+
+ ;; ??? I have no idea what this if checks for, but it's
+ ;; obviously wrong for the case that a down-mouse event
+ ;; on another window invokes this function. The event
+ ;; will contain the window clicked on and that window's
+ ;; buffer is certainaly not always in Isearch mode.
+ ;;
+ ;; Leave the code in, but check for current buffer not
+ ;; being in Isearch mode for now, until someone tells
+ ;; what it's really supposed to do.
+ ;;
+ ;; --gerd 2001-08-10.
+
+ (if (and (not isearch-mode)
+ (listp main-event)
(setq window (posn-window (event-start main-event)))
(windowp window)
(or (> (minibuffer-depth) 0)
(defun isearch-whitespace-chars ()
"Match all whitespace chars, if in regexp mode.
-If you want to search for just a space, type \\[quoted-insert] SPC."
+If you want to search for just a space, type \\<isearch-mode-map>\\[isearch-quote-char] SPC."
(interactive)
(if isearch-regexp
(if (and search-whitespace-regexp (not isearch-within-brackets)
(setq isearch-invalid-regexp "incomplete input")))
(error
;; stack overflow in regexp search.
- (setq isearch-invalid-regexp (car (cdr lossage)))))
+ (setq isearch-invalid-regexp (format "%s" lossage))))
(if isearch-success
nil
(mapc 'isearch-open-necessary-overlays isearch-opened-overlays)
(setq isearch-opened-overlays nil)))
+
+(defun isearch-intersects-p (start0 end0 start1 end1)
+ "Return t if regions START0..END0 and START1..END1 intersect."
+ (or (and (>= start0 start1) (< start0 end1))
+ (and (> end0 start1) (<= end0 end1))
+ (and (>= start1 start0) (< start1 end0))
+ (and (> end1 start0) (<= end1 end0))))
+
+
;;; Verify if the current match is outside of each element of
;;; `isearch-opened-overlays', if so close that overlay.
-(defun isearch-close-unecessary-overlays (begin end)
- (let ((ov-list isearch-opened-overlays)
- ov
- inside-overlay
- fct-temp)
+
+(defun isearch-close-unnecessary-overlays (begin end)
+ (let ((overlays isearch-opened-overlays))
(setq isearch-opened-overlays nil)
- (while ov-list
- (setq ov (car ov-list))
- (setq ov-list (cdr ov-list))
- (setq inside-overlay (or (and (> begin (overlay-start ov))
- (< begin (overlay-end ov)))
- (and (> end (overlay-start ov))
- (< end (overlay-end ov)))))
- ;; If this exists it means that the overlay was opened using
- ;; this function, not by us tweaking the overlay properties.
- (setq fct-temp (overlay-get ov 'isearch-open-invisible-temporary))
- (if inside-overlay
- (setq isearch-opened-overlays (cons ov isearch-opened-overlays))
- (if fct-temp
- (funcall fct-temp ov t)
- (overlay-put ov 'invisible (overlay-get ov 'isearch-invisible))
- (overlay-put ov 'intangible (overlay-get ov 'isearch-intangible))
- (overlay-put ov 'isearch-invisible nil)
- (overlay-put ov 'isearch-intangible nil))))))
+ (dolist (ov overlays)
+ (if (isearch-intersects-p begin end (overlay-start ov) (overlay-end ov))
+ (push ov isearch-opened-overlays)
+ (let ((fct-temp (overlay-get ov 'isearch-open-invisible-temporary)))
+ (if fct-temp
+ ;; If this exists it means that the overlay was opened
+ ;; using this function, not by us tweaking the overlay
+ ;; properties.
+ (funcall fct-temp ov t)
+ (overlay-put ov 'invisible (overlay-get ov 'isearch-invisible))
+ (overlay-put ov 'intangible (overlay-get ov 'isearch-intangible))
+ (overlay-put ov 'isearch-invisible nil)
+ (overlay-put ov 'isearch-intangible nil)))))))
+
(defun isearch-range-invisible (beg end)
"Return t if all the text from BEG to END is invisible."
;; the list of overlays that could be opened
(crt-overlays nil))
(when (and can-be-opened isearch-hide-immediately)
- (isearch-close-unecessary-overlays beg end))
+ (isearch-close-unnecessary-overlays beg end))
;; If the following character is currently invisible,
;; skip all characters with that same `invisible' property value.
;; Do that over and over.
(defvar isearch-overlay nil)
-(defsubst isearch-set-lazy-highlight-faces-at (pos face)
- "Set the face property of isearch lazy highlight overlays at POS to FACE.
-If POS is nil, nothing is done."
- (unless (null pos)
- (dolist (ov (overlays-at pos))
- (when (and (not (eq ov isearch-overlay))
- (memq ov isearch-lazy-highlight-overlays)
- (not (eq (overlay-get ov 'face) face)))
- (overlay-put ov 'face face)))))
-
(defun isearch-highlight (beg end)
- (unless (or (null search-highlight) (null (display-color-p)))
+ (unless (null search-highlight)
(cond (isearch-overlay
;; Overlay already exists, just move it.
-
- ;; Check to see if there are any lazy-isearch overlays at
- ;; the same position with their face property suppressed
- ;; (to avoid face clashes), and if so, give them their face
- ;; back.
- (isearch-set-lazy-highlight-faces-at (overlay-start isearch-overlay)
- isearch-lazy-highlight-face)
-
(move-overlay isearch-overlay beg end (current-buffer)))
(t
;; Overlay doesn't exist, create it.
(setq isearch-overlay (make-overlay beg end))
- (overlay-put isearch-overlay 'face isearch)))
-
- ;; Suppress the faces of any lazy-isearch overlays at the new position
- (isearch-set-lazy-highlight-faces-at beg nil)))
+ (overlay-put isearch-overlay 'face isearch)
+ (overlay-put isearch-overlay 'priority 1) ;higher than lazy overlays
+ ))))
(defun isearch-dehighlight (totally)
(when isearch-overlay
- ;; Check to see if there are any lazy-isearch overlays at the same
- ;; position with their face property suppressed (to avoid face
- ;; clashes), and if so, give them their face back.
- (isearch-set-lazy-highlight-faces-at (overlay-start isearch-overlay)
- isearch-lazy-highlight-face)
(delete-overlay isearch-overlay)))
;;; When active, *every* match for the current search string is
;;; highlighted: the current one using the normal isearch match color
-;;; and all the others using the unobtrusive `secondary-selection'
-;;; color. The extra highlighting makes it easier to anticipate where
-;;; the cursor will land each time you press C-s or C-r to repeat a
-;;; pending search. Highlighting of these additional matches happens
-;;; in a deferred fashion using "idle timers," so the cycles needed do
-;;; not rob isearch of its usual snappy response.
+;;; and all the others using `isearch-lazy-highlight-face'. The extra
+;;; highlighting makes it easier to anticipate where the cursor will
+;;; land each time you press C-s or C-r to repeat a pending search.
+;;; Highlighting of these additional matches happens in a deferred
+;;; fashion using "idle timers," so the cycles needed do not rob
+;;; isearch of its usual snappy response.
;;; IMPLEMENTATION NOTE: This depends on some isearch internals.
;;; Specifically:
;;; - `isearch-update' is expected to be called (at least) every time
-;;; the search string changes;
+;;; the search string or window-start changes;
;;; - `isearch-string' is expected to contain the current search
;;; string as entered by the user;
-;;; - `isearch-overlay' is expected to contain the overlay used for
-;;; primary isearch match-highlighting;
-;;; - `isearch-opoint' is expected to contain the location where the
-;;; current search began;
;;; - the type of the current search is expected to be given by
;;; `isearch-word' and `isearch-regexp';
;;; - the direction of the current search is expected to be given by
(defgroup isearch-lazy-highlight nil
"Lazy highlighting feature for incremental search."
:prefix "isearch-lazy-highlight-"
+ :version "21.1"
:group 'isearch)
(defcustom isearch-lazy-highlight t
:type 'number
:group 'isearch-lazy-highlight)
-(defcustom isearch-lazy-highlight-interval 0.0625
+(defcustom isearch-lazy-highlight-interval 0 ; 0.0625
"*Seconds between lazily highlighting successive matches."
:type 'number
:group 'isearch-lazy-highlight)
-(defcustom isearch-lazy-highlight-max 20
- "*Maximum number of matches to highlight."
+(defcustom isearch-lazy-highlight-max-at-a-time 20
+ "*Maximum matches to highlight at a time (for `isearch-lazy-highlight').
+Larger values may reduce isearch's responsiveness to user input;
+smaller values make matches highlight slowly.
+A value of nil means highlight all matches."
:type '(choice (const :tag "All" nil)
(integer :tag "Some"))
:group 'isearch-lazy-highlight)
'((((type tty pc) (class color))
(:background "magenta4" :foreground "cyan1"))
(((class color) (background light))
- (:background "magenta4" :foreground "lightskyblue1"))
+ ;; The background must not be too dark, for that means
+ ;; the character is hard to see when the cursor is there.
+ (:background "magenta2" :foreground "lightskyblue1"))
(((class color) (background dark))
(:background "palevioletred2" :foreground "brown4"))
(t (:inverse-video t)))
(defvar isearch-lazy-highlight-face 'isearch-lazy-highlight-face)
(defvar isearch-lazy-highlight-overlays nil)
-(defvar isearch-lazy-highlight-window nil)
+(defvar isearch-lazy-highlight-wrapped nil)
(defvar isearch-lazy-highlight-start nil)
(defvar isearch-lazy-highlight-end nil)
(defvar isearch-lazy-highlight-timer nil)
(defvar isearch-lazy-highlight-last-string nil)
-
-(defun isearch-lazy-highlight-cleanup (&optional remove)
- "Stop lazy highlighting and maybe remove existing highlighting.
-REMOVE non-nil means remove all the existing lazy highlighting.
-
-This function is called when exiting an incremental search."
+(defvar isearch-lazy-highlight-window nil)
+(defvar isearch-lazy-highlight-window-start nil)
+(defvar isearch-lazy-highlight-case-fold-search nil)
+(defvar isearch-lazy-highlight-regexp nil)
+
+(defun isearch-lazy-highlight-cleanup (&optional force)
+ "Stop lazy highlighting and remove extra highlighting from current buffer.
+FORCE non-nil means do it whether or not `isearch-lazy-highlight-cleanup'
+is nil. This function is called when exiting an incremental search if
+`isearch-lazy-highlight-cleanup' is non-nil."
(interactive '(t))
- (if remove
- (isearch-lazy-highlight-remove-overlays))
- (if isearch-lazy-highlight-timer
- (progn
- (cancel-timer isearch-lazy-highlight-timer)
- (setq isearch-lazy-highlight-timer nil))))
-
-(defun isearch-lazy-highlight-remove-overlays (&optional keep-start keep-end)
- "Remove lazy highlight overlays from the current buffer.
-With optional arguments KEEP-START and KEEP-END,
-preserve any overlays in that range."
- (let ((tem isearch-lazy-highlight-overlays))
- (while tem
- (if (or (null keep-start)
- (let ((pos (overlay-start (car tem))))
- (or (< pos keep-start) (> pos keep-end))))
- (progn
- (delete-overlay (car tem))
- (setq isearch-lazy-highlight-overlays
- (delq (car tem) isearch-lazy-highlight-overlays))))
- (setq tem (cdr tem)))))
+ (if (or force isearch-lazy-highlight-cleanup)
+ (while isearch-lazy-highlight-overlays
+ (delete-overlay (car isearch-lazy-highlight-overlays))
+ (setq isearch-lazy-highlight-overlays
+ (cdr isearch-lazy-highlight-overlays))))
+ (when isearch-lazy-highlight-timer
+ (cancel-timer isearch-lazy-highlight-timer)
+ (setq isearch-lazy-highlight-timer nil)))
(defun isearch-lazy-highlight-new-loop ()
- "Clear obsolete highlighting, and queue up to do new highlighting.
+ "Cleanup any previous `isearch-lazy-highlight' loop and begin a new one.
This happens when `isearch-update' is invoked (which can cause the
-search string to change)."
+search string to change or the window to scroll)."
(when (and isearch-lazy-highlight
- (not isearch-invalid-regexp)
- (not (equal isearch-string "")))
-
- ;; If the search string has changed, remove all old overlays.
- (unless (equal isearch-string isearch-lazy-highlight-last-string)
- (isearch-lazy-highlight-remove-overlays)
- (setq isearch-lazy-highlight-window nil))
-
- (if (and isearch-overlay
- (not (overlay-get isearch-overlay 'priority)))
- ;; Make sure the isearch-overlay takes priority
- ;; over any other matches.
- (overlay-put isearch-overlay 'priority 1))
-
- ;; Queue up to display other matches after a short pause.
- (setq isearch-lazy-highlight-timer
- (run-with-idle-timer isearch-lazy-highlight-initial-delay nil
- 'isearch-lazy-highlight-update))))
+ (sit-for 0) ;make sure (window-start) is credible
+ (or (not (equal isearch-string
+ isearch-lazy-highlight-last-string))
+ (not (eq (selected-window)
+ isearch-lazy-highlight-window))
+ (not (eq isearch-lazy-highlight-case-fold-search
+ isearch-case-fold-search))
+ (not (eq isearch-lazy-highlight-regexp
+ isearch-regexp))
+ (not (= (window-start)
+ isearch-lazy-highlight-window-start))))
+ ;; something important did indeed change
+ (isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays
+ (when (not isearch-invalid-regexp)
+ (setq isearch-lazy-highlight-window (selected-window)
+ isearch-lazy-highlight-window-start (window-start)
+ isearch-lazy-highlight-start (point)
+ isearch-lazy-highlight-end (point)
+ isearch-lazy-highlight-last-string isearch-string
+ isearch-lazy-highlight-case-fold-search isearch-case-fold-search
+ isearch-lazy-highlight-regexp isearch-regexp
+ isearch-lazy-highlight-wrapped nil)
+ (setq isearch-lazy-highlight-timer
+ (run-with-idle-timer isearch-lazy-highlight-initial-delay nil
+ 'isearch-lazy-highlight-update)))))
+
+(defun isearch-lazy-highlight-search ()
+ "Search ahead for the next or previous match, for lazy highlighting.
+Attempt to do the search exactly the way the pending isearch would."
+ (let ((case-fold-search isearch-case-fold-search)
+ (choices (cond (isearch-word
+ '(word-search-forward . word-search-backward))
+ (isearch-regexp
+ '(re-search-forward . re-search-backward))
+ (t
+ '(search-forward . search-backward)))))
+ (funcall (if isearch-forward
+ (car choices)
+ (cdr choices))
+ isearch-string
+ (if isearch-forward
+ (if isearch-lazy-highlight-wrapped
+ isearch-lazy-highlight-start
+ (window-end))
+ (if isearch-lazy-highlight-wrapped
+ isearch-lazy-highlight-end
+ (window-start)))
+ t)))
(defun isearch-lazy-highlight-update ()
- "Update highlighting of possible other matches for isearch."
- (unless (and (eq isearch-lazy-highlight-window (selected-window))
- (equal isearch-lazy-highlight-start (window-start)))
-
- ;; The search string or the visible window has changed.
-
- (setq isearch-lazy-highlight-window (selected-window)
- isearch-lazy-highlight-start (window-start)
- isearch-lazy-highlight-end (window-end nil t)
- isearch-lazy-highlight-last-string isearch-string)
-
- ;; If the string is the same, the old overlays are still usable
- ;; if they are still visible in the window.
- (isearch-lazy-highlight-remove-overlays (window-start)
- (window-end nil t))
-
- (when (or (null isearch-lazy-highlight-max)
- (< (length isearch-lazy-highlight-overlays)
- isearch-lazy-highlight-max))
- (save-excursion
- (save-match-data
- (let (found)
- (goto-char isearch-lazy-highlight-start)
- (while (let ((case-fold-search isearch-case-fold-search))
- (funcall (cond (isearch-word 'word-search-forward)
- (isearch-regexp 're-search-forward)
- (t 'search-forward))
- isearch-string
- isearch-lazy-highlight-end
- t))
- ;; Found the next match.
- (let ((ov (make-overlay (match-beginning 0)
- (match-end 0))))
- ;; If OV overlaps the current isearch overlay, suppress
- ;; its face property; otherwise, we sometimes get odd
- ;; looking face combinations.
- (unless (memq isearch-overlay
- (overlays-at (match-beginning 0)))
- (overlay-put ov 'face isearch-lazy-highlight-face))
-
- (overlay-put ov 'priority 0)
- ;; Don't highlight on any other windows.
- (overlay-put ov 'window isearch-lazy-highlight-window)
-
- (push ov isearch-lazy-highlight-overlays)))))))))
+ "Update highlighting of other matches for current search."
+ (let ((max isearch-lazy-highlight-max-at-a-time)
+ (looping t)
+ nomore)
+ (save-excursion
+ (save-match-data
+ (goto-char (if isearch-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
+ (forward-char 1)
+
+ ;; non-zero-length match
+ (let ((ov (make-overlay mb me)))
+ (overlay-put ov 'face isearch-lazy-highlight-face)
+ (overlay-put ov 'priority 0) ;lower than main overlay
+ (overlay-put ov 'window (selected-window))
+ (push ov isearch-lazy-highlight-overlays)))
+ (if isearch-forward
+ (setq isearch-lazy-highlight-end (point))
+ (setq isearch-lazy-highlight-start (point))))
+
+ ;; not found
+ (if isearch-lazy-highlight-wrapped
+ (setq looping nil
+ nomore t)
+ (setq isearch-lazy-highlight-wrapped t)
+ (if isearch-forward
+ (progn
+ (setq isearch-lazy-highlight-end (window-start))
+ (goto-char (window-start)))
+ (setq isearch-lazy-highlight-start (window-end))
+ (goto-char (window-end)))))))
+ (unless nomore
+ (setq isearch-lazy-highlight-timer
+ (run-at-time isearch-lazy-highlight-interval nil
+ 'isearch-lazy-highlight-update)))))))
(defun isearch-resume (search regexp word forward message case-fold)
"Resume an incremental search.