;;; isearch.el --- incremental search minor mode
-;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1999, 2000, 01, 2003, 2004
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1999,
+;; 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
;; Maintainer: FSF
;; keep the behavior. No point in forcing nonincremental search until
;; the last possible moment.
-;; TODO
-;; - Integrate the emacs 19 generalized command history.
-;; - Think about incorporating query-replace.
-;; - Hooks and options for failed search.
-
-;;; Change Log:
-
-;; Changes before those recorded in ChangeLog:
-
-;; Revision 1.4 92/09/14 16:26:02 liberte
-;; Added prefix args to isearch-forward, etc. to switch between
-;; string and regular expression searching.
-;; Added some support for lemacs.
-;; Added general isearch-highlight option - but only for lemacs so far.
-;; Added support for frame switching in emacs 19.
-;; Added word search option to isearch-edit-string.
-;; Renamed isearch-quit to isearch-abort.
-;; Numerous changes to comments and doc strings.
-;;
-;; Revision 1.3 92/06/29 13:10:08 liberte
-;; Moved modal isearch-mode handling into isearch-mode.
-;; Got rid of buffer-local isearch variables.
-;; isearch-edit-string used by ring adjustments, completion, and
-;; nonincremental searching. C-s and C-r are additional exit commands.
-;; Renamed all regex to regexp.
-;; Got rid of found-start and found-point globals.
-;; Generalized handling of upper-case chars.
-
-;; Revision 1.2 92/05/27 11:33:57 liberte
-;; Emacs version 19 has a search ring, which is supported here.
-;; Other fixes found in the version 19 isearch are included here.
-;;
-;; Also see variables search-caps-disable-folding,
-;; search-nonincremental-instead, search-whitespace-regexp, and
-;; commands isearch-toggle-regexp, isearch-edit-string.
-;;
-;; semi-modal isearching is supported.
-
-;; Changes for 1.1
-;; 3/18/92 Fixed invalid-regexp.
-;; 3/18/92 Fixed yanking in regexps.
-
;;; Code:
\f
:type 'boolean
:group 'isearch)
-(defcustom search-whitespace-regexp "\\(?:\\s-+\\)"
+(defcustom search-whitespace-regexp "\\s-+"
"*If non-nil, regular expression to match a sequence of whitespace chars.
This applies to regular expression incremental search.
+When you put a space or spaces in the incremental regexp, it stands for
+this, unless it is inside of a regexp construct such as [...] or *, + or ?.
You might want to use something like \"[ \\t\\r\\n]+\" instead.
In the Customization buffer, that is `[' followed by a space,
a tab, a carriage return (control-M), a newline, and `]+'."
:type 'boolean
:group 'isearch)
-(defcustom isearch-resume-enabled t
- "*If non-nil, `isearch-resume' commands are added to the command history."
+(defcustom isearch-resume-in-command-history nil
+ "*If non-nil, `isearch-resume' commands are added to the command history.
+This allows you to resume earlier isearch sessions through the
+command history."
:type 'boolean
:group 'isearch)
(defvar isearch-mode-end-hook nil
"Function(s) to call after terminating an incremental search.")
+(defvar isearch-wrap-function nil
+ "Function to call to wrap the search when search is failed.
+If nil, move point to the beginning of the buffer for a forward search,
+or to the end of the buffer for a backward search.")
+
+(defvar isearch-push-state-function nil
+ "Function to save a function restoring the mode-specific isearch state
+to the search status stack.")
+
;; Search ring.
(defvar search-ring nil
(define-key map "\r" 'isearch-exit)
(define-key map "\C-j" 'isearch-printing-char)
(define-key map "\t" 'isearch-printing-char)
- (define-key map " " 'isearch-whitespace-chars)
- (define-key map [?\S-\ ] 'isearch-whitespace-chars)
(define-key map "\C-w" 'isearch-yank-word-or-char)
(define-key map "\M-\C-w" 'isearch-del-char)
(define-key map "\M-\C-y" 'isearch-yank-char)
(define-key map "\C-y" 'isearch-yank-line)
- ;; Define keys for regexp chars * ? |.
+ ;; Define keys for regexp chars * ? } |.
;; Nothing special for + because it matches at least once.
(define-key map "*" 'isearch-*-char)
(define-key map "?" 'isearch-*-char)
- (define-key map "{" 'isearch-{-char)
+ (define-key map "}" 'isearch-}-char)
(define-key map "|" 'isearch-|-char)
;; Turned off because I find I expect to get the global definition--rms.
(define-key map "\M-r" 'isearch-toggle-regexp)
(define-key map "\M-e" 'isearch-edit-string)
- (define-key map (kbd "M-%") 'isearch-query-replace)
- (define-key map (kbd "C-M-%") 'isearch-query-replace-regexp)
+ (define-key map [?\M-%] 'isearch-query-replace)
+ (define-key map [?\C-\M-%] 'isearch-query-replace-regexp)
map)
"Keymap for `isearch-mode'.")
(defvar isearch-cmds nil
"Stack of search status sets.
-Each set is a list of the form:
- (STRING MESSAGE POINT SUCCESS FORWARD OTHER-END WORD
- INVALID-REGEXP WRAPPED BARRIER WITHIN-BRACKETS CASE-FOLD-SEARCH)")
+Each set is a vector of the form:
+ [STRING MESSAGE POINT SUCCESS FORWARD OTHER-END WORD
+ INVALID-REGEXP WRAPPED BARRIER WITHIN-BRACKETS CASE-FOLD-SEARCH]")
(defvar isearch-string "") ; The current search string.
(defvar isearch-message "") ; text-char-description version of isearch-string
Do incremental search forward for regular expression.
With a prefix argument, do a regular string search instead.
Like ordinary incremental search except that your input
-is treated as a regexp. See \\[isearch-forward] for more info."
+is treated as a regexp. See \\[isearch-forward] for more info.
+
+In regexp incremental searches, a space or spaces normally matches
+any whitespace (the variable `search-whitespace-regexp' controls
+precisely what that means). If you want to search for a literal space
+and nothing else, enter `[ ]'."
(interactive "P\np")
(isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
(setq disable-point-adjustment t))
(defun isearch-done (&optional nopush edit)
- (if isearch-resume-enabled
+ (if isearch-resume-in-command-history
(let ((command `(isearch-resume ,isearch-string ,isearch-regexp
,isearch-word ,isearch-forward
,isearch-message
(if isearch-small-window
(goto-char found-point)
;; Exiting the save-window-excursion clobbers window-start; restore it.
- (set-window-start (selected-window) found-start t))
-
- ;; If there was movement, mark the starting position.
- ;; Maybe should test difference between and set mark iff > threshold.
- (if (/= (point) isearch-opoint)
- (or (and transient-mark-mode mark-active)
- (progn
- (push-mark isearch-opoint t)
- (or executing-kbd-macro (> (minibuffer-depth) 0)
- (message "Mark saved where search started"))))))
+ (set-window-start (selected-window) found-start t)))
(setq isearch-mode nil)
(if isearch-input-method-local-p
(isearch-update-ring isearch-string isearch-regexp))
(run-hooks 'isearch-mode-end-hook)
+
+ ;; If there was movement, mark the starting position.
+ ;; Maybe should test difference between and set mark iff > threshold.
+ (if (/= (point) isearch-opoint)
+ (or (and transient-mark-mode mark-active)
+ (progn
+ (push-mark isearch-opoint t)
+ (or executing-kbd-macro (> (minibuffer-depth) 0)
+ (message "Mark saved where search started")))))
+
(and (not edit) isearch-recursive-edit (exit-recursive-edit)))
(defun isearch-update-ring (string &optional regexp)
;; (isearch-clean-overlays)
;; (handle-switch-frame (car (cdr last-command-char))))
+\f
+;; The search status structure and stack.
+
+(defsubst isearch-string-state (frame)
+ "Return the search string in FRAME."
+ (aref frame 0))
+(defsubst isearch-message-state (frame)
+ "Return the search string to display to the user in FRAME."
+ (aref frame 1))
+(defsubst isearch-point-state (frame)
+ "Return the point in FRAME."
+ (aref frame 2))
+(defsubst isearch-success-state (frame)
+ "Return the success flag in FRAME."
+ (aref frame 3))
+(defsubst isearch-forward-state (frame)
+ "Return the searching-forward flag in FRAME."
+ (aref frame 4))
+(defsubst isearch-other-end-state (frame)
+ "Return the other end of the match in FRAME."
+ (aref frame 5))
+(defsubst isearch-word-state (frame)
+ "Return the search-by-word flag in FRAME."
+ (aref frame 6))
+(defsubst isearch-invalid-regexp-state (frame)
+ "Return the regexp error message in FRAME, or nil if its regexp is valid."
+ (aref frame 7))
+(defsubst isearch-wrapped-state (frame)
+ "Return the search-wrapped flag in FRAME."
+ (aref frame 8))
+(defsubst isearch-barrier-state (frame)
+ "Return the barrier value in FRAME."
+ (aref frame 9))
+(defsubst isearch-within-brackets-state (frame)
+ "Return the in-character-class flag in FRAME."
+ (aref frame 10))
+(defsubst isearch-case-fold-search-state (frame)
+ "Return the case-folding flag in FRAME."
+ (aref frame 11))
+(defsubst isearch-pop-fun-state (frame)
+ "Return the function restoring the mode-specific isearch state in FRAME."
+ (aref frame 12))
+
+(defun isearch-top-state ()
+ (let ((cmd (car isearch-cmds)))
+ (setq isearch-string (isearch-string-state cmd)
+ isearch-message (isearch-message-state cmd)
+ isearch-success (isearch-success-state cmd)
+ isearch-forward (isearch-forward-state cmd)
+ isearch-other-end (isearch-other-end-state cmd)
+ isearch-word (isearch-word-state cmd)
+ isearch-invalid-regexp (isearch-invalid-regexp-state cmd)
+ isearch-wrapped (isearch-wrapped-state cmd)
+ isearch-barrier (isearch-barrier-state cmd)
+ isearch-within-brackets (isearch-within-brackets-state cmd)
+ isearch-case-fold-search (isearch-case-fold-search-state cmd))
+ (if (functionp (isearch-pop-fun-state cmd))
+ (funcall (isearch-pop-fun-state cmd) cmd))
+ (goto-char (isearch-point-state cmd))))
+
+(defun isearch-pop-state ()
+ (setq isearch-cmds (cdr isearch-cmds))
+ (isearch-top-state))
+
+(defun isearch-push-state ()
+ (setq isearch-cmds
+ (cons (vector isearch-string isearch-message (point)
+ isearch-success isearch-forward isearch-other-end
+ isearch-word
+ isearch-invalid-regexp isearch-wrapped isearch-barrier
+ isearch-within-brackets isearch-case-fold-search
+ (if isearch-push-state-function
+ (funcall isearch-push-state-function)))
+ isearch-cmds)))
+
\f
;; Commands active while inside of the isearch minor mode.
(defun isearch-cancel ()
"Terminate the search and go back to the starting point."
(interactive)
+ (if (functionp (isearch-pop-fun-state (car (last isearch-cmds))))
+ (funcall (isearch-pop-fun-state (car (last isearch-cmds)))
+ (car (last isearch-cmds))))
(goto-char isearch-opoint)
- (isearch-done t)
+ (isearch-done t) ; exit isearch
(isearch-clean-overlays)
- (signal 'quit nil)) ; and pass on quit signal
+ (signal 'quit nil)) ; and pass on quit signal
(defun isearch-abort ()
"Abort incremental search mode if searching is successful, signaling quit.
(if isearch-success
;; If search is successful, move back to starting point
;; and really do quit.
- (progn (goto-char isearch-opoint)
- (setq isearch-success nil)
- (isearch-done t) ; exit isearch
- (isearch-clean-overlays)
- (signal 'quit nil)) ; and pass on quit signal
+ (progn
+ (setq isearch-success nil)
+ (isearch-cancel))
;; If search is failing, or has an incomplete regexp,
;; rub out until it is once more successful.
(while (or (not isearch-success) isearch-invalid-regexp)
;; If already have what to search for, repeat it.
(or isearch-success
(progn
- (goto-char (if isearch-forward (point-min) (point-max)))
+ (if isearch-wrap-function
+ (funcall isearch-wrap-function)
+ (goto-char (if isearch-forward (point-min) (point-max))))
(setq isearch-wrapped t))))
;; C-s in reverse or C-r in forward, change direction.
(setq isearch-forward (not isearch-forward)))
(interactive)
(setq isearch-regexp (not isearch-regexp))
(if isearch-regexp (setq isearch-word nil))
+ (setq isearch-success t isearch-adjusted t)
(isearch-update))
(defun isearch-toggle-case-fold ()
(isearch-message-prefix nil nil isearch-nonincremental)
isearch-message
(if isearch-case-fold-search "in" "")))
- (setq isearch-adjusted t)
+ (setq isearch-success t isearch-adjusted t)
(sit-for 1)
(isearch-update))
-(defun isearch-query-replace ()
+(defun isearch-query-replace (&optional regexp-flag)
"Start query-replace with string to replace from last search string."
(interactive)
- (let ((query-replace-interactive 'initial)
- (case-fold-search isearch-case-fold-search))
- ;; Put search string into the right ring
- (setq isearch-regexp nil)
+ (barf-if-buffer-read-only)
+ (if regexp-flag (setq isearch-regexp t))
+ (let ((case-fold-search isearch-case-fold-search))
(isearch-done)
(isearch-clean-overlays)
- (and isearch-forward isearch-other-end (goto-char isearch-other-end))
- (call-interactively 'query-replace)))
+ (if (and (< isearch-other-end (point))
+ (not (and transient-mark-mode mark-active
+ (< isearch-opoint (point)))))
+ (goto-char isearch-other-end))
+ (set query-replace-from-history-variable
+ (cons isearch-string
+ (symbol-value query-replace-from-history-variable)))
+ (perform-replace
+ isearch-string
+ (query-replace-read-to
+ isearch-string
+ (if isearch-regexp "Query replace regexp" "Query replace")
+ isearch-regexp)
+ t isearch-regexp isearch-word nil nil
+ (if (and transient-mark-mode mark-active) (region-beginning))
+ (if (and transient-mark-mode mark-active) (region-end)))))
(defun isearch-query-replace-regexp ()
"Start query-replace-regexp with string to replace from last search string."
(interactive)
- (let ((query-replace-interactive 'initial)
- (case-fold-search isearch-case-fold-search))
- ;; Put search string into the right ring
- (setq isearch-regexp t)
- (isearch-done)
- (isearch-clean-overlays)
- (and isearch-forward isearch-other-end (goto-char isearch-other-end))
- (call-interactively 'query-replace-regexp)))
+ (isearch-query-replace t))
\f
(defun isearch-delete-char ()
(defun isearch-yank-line ()
"Pull rest of line from buffer into search string."
(interactive)
- (isearch-yank-internal 'line-end-position))
-
+ (isearch-yank-internal
+ (lambda () (line-end-position (if (eolp) 2 1)))))
(defun isearch-search-and-update ()
;; Do the search and update the display.
(isearch-update))
-(defun isearch-{-char ()
- "Handle \{ specially in regexps."
- (interactive)
- (isearch-*-char t))
-
-;; *, ?, and | chars can make a regexp more liberal.
+;; *, ?, }, and | chars can make a regexp more liberal.
;; They can make a regexp match sooner or make it succeed instead of failing.
;; So go back to place last successful search started
;; or to the last ^S/^R (barrier), whichever is nearer.
;; + needs no special handling because the string must match at least once.
-(defun isearch-*-char (&optional want-backslash)
- "Handle * and ? specially in regexps.
-When WANT-BACKSLASH is non-nil, do special handling for \{."
- (interactive)
- (if isearch-regexp
- (let ((idx (length isearch-string)))
- (while (and (> idx 0)
- (eq (aref isearch-string (1- idx)) ?\\))
- (setq idx (1- idx)))
- ;; * and ? are special when not preceded by \.
- ;; { is special when it is preceded by \.
- (when (= (mod (- (length isearch-string) idx) 2)
- (if want-backslash 1 0))
- (setq isearch-adjusted t)
- ;; Get the isearch-other-end from before the last search.
- ;; We want to start from there,
- ;; so that we don't retreat farther than that.
- ;; (car isearch-cmds) is after last search;
- ;; (car (cdr isearch-cmds)) is from before it.
- (let ((cs (nth 5 (car (cdr isearch-cmds)))))
- (setq cs (or cs isearch-barrier))
- (goto-char
- (if isearch-forward
- (max cs isearch-barrier)
- (min cs isearch-barrier)))))))
+(defun isearch-backslash (str)
+ "Return t if STR ends in an odd number of backslashes."
+ (= (mod (- (length str) (string-match "\\\\*\\'" str)) 2) 1))
+
+(defun isearch-fallback (want-backslash &optional allow-invalid to-barrier)
+ "Return point to previous successful match to allow regexp liberalization.
+\\<isearch-mode-map>
+Respects \\[isearch-repeat-forward] and \\[isearch-repeat-backward] by
+stopping at `isearch-barrier' as needed.
+
+Do nothing if a backslash is escaping the liberalizing character. If
+WANT-BACKSLASH is non-nil, invert this behavior (for \\} and \\|).
+
+Do nothing if regexp has recently been invalid unless optional ALLOW-INVALID
+non-nil.
+
+If optional TO-BARRIER non-nil, ignore previous matches and go exactly to the
+barrier."
+ ;; (eq (not a) (not b)) makes all non-nil values equivalent
+ (when (and isearch-regexp (eq (not (isearch-backslash isearch-string))
+ (not want-backslash))
+ ;; We have to check 2 stack frames because the last might be
+ ;; invalid just because of a backslash.
+ (or (not isearch-invalid-regexp)
+ (not (isearch-invalid-regexp-state (cadr isearch-cmds)))
+ allow-invalid))
+ (if to-barrier
+ (progn (goto-char isearch-barrier)
+ (setq isearch-adjusted t))
+ (let* ((stack isearch-cmds)
+ (previous (cdr stack)) ; lookbelow in the stack
+ (frame (car stack)))
+ ;; Walk down the stack looking for a valid regexp (as of course only
+ ;; they can be the previous successful match); this conveniently
+ ;; removes all bracket-sets and groups that might be in the way, as
+ ;; well as partial \{\} constructs that the code below leaves behind.
+ ;; Also skip over postfix operators -- though horrid,
+ ;; 'ab?\{5,6\}+\{1,2\}*' is perfectly legal.
+ (while (and previous
+ (or (isearch-invalid-regexp-state frame)
+ (let* ((string (isearch-string-state frame))
+ (lchar (aref string (1- (length string)))))
+ ;; The operators aren't always operators; check
+ ;; backslashes. This doesn't handle the case of
+ ;; operators at the beginning of the regexp not
+ ;; being special, but then we should fall back to
+ ;; the barrier anyway because it's all optional.
+ (if (isearch-backslash
+ (isearch-string-state (car previous)))
+ (eq lchar ?\})
+ (memq lchar '(?* ?? ?+))))))
+ (setq stack previous previous (cdr previous) frame (car stack)))
+ (when stack
+ ;; `stack' now refers the most recent valid regexp that is not at
+ ;; all optional in its last term. Now dig one level deeper and find
+ ;; what matched before that.
+ (let ((last-other-end (or (isearch-other-end-state (car previous))
+ isearch-barrier)))
+ (goto-char (if isearch-forward
+ (max last-other-end isearch-barrier)
+ (min last-other-end isearch-barrier)))
+ (setq isearch-adjusted t))))))
(isearch-process-search-char last-command-char))
+;; * and ? are special when not preceded by \.
+(defun isearch-*-char ()
+ "Maybe back up to handle * and ? specially in regexps."
+ (interactive)
+ (isearch-fallback nil))
+
+;; } is special when it is preceded by \.
+(defun isearch-}-char ()
+ "Handle \\} specially in regexps."
+ (interactive)
+ (isearch-fallback t t))
+;; | is special when it is preceded by \.
(defun isearch-|-char ()
- "If in regexp search, jump to the barrier."
+ "If in regexp search, jump to the barrier unless in a group."
(interactive)
- (if isearch-regexp
- (progn
- (setq isearch-adjusted t)
- (goto-char isearch-barrier)))
- (isearch-process-search-char last-command-char))
+ (isearch-fallback t nil t))
(defun isearch-unread-key-sequence (keylist)
"Unread the given key-sequence KEYLIST.
(let ((ab-bel (isearch-string-out-of-window isearch-point)))
(if ab-bel
(isearch-back-into-window (eq ab-bel 'above) isearch-point)
- (or (eq (point) isearch-point)
- (goto-char isearch-point))))
+ (goto-char isearch-point)))
(isearch-update))
(search-exit-option
(let (window)
;; Assume character codes 0200 - 0377 stand for characters in some
;; single-byte character set, and convert them to Emacs
;; characters.
- (and enable-multibyte-characters
- (>= char ?\200)
- (<= char ?\377)
- (setq char (unibyte-char-to-multibyte char)))
- (isearch-process-search-char char)))
+ (if (and isearch-regexp (= char ?\ ))
+ (if (subregexp-context-p isearch-string pos)
+ (isearch-process-search-string "[ ]" " ")
+ (isearch-process-search-char char))
+ (and enable-multibyte-characters
+ (>= char ?\200)
+ (<= char ?\377)
+ (setq char (unibyte-char-to-multibyte char)))
+ (isearch-process-search-char char))))
(defun isearch-return-char ()
"Convert return into newline for incremental search.
(isearch-process-search-multibyte-characters char)
(isearch-process-search-char char)))))
-(defun isearch-whitespace-chars ()
- "Match all whitespace chars, if in regexp mode.
-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)
- (not isearch-invalid-regexp))
- (isearch-process-search-string search-whitespace-regexp " ")
- (isearch-printing-char))
- (progn
- ;; This way of doing word search doesn't correctly extend current search.
- ;; (setq isearch-word t)
- ;; (setq isearch-adjusted t)
- ;; (goto-char isearch-barrier)
- (isearch-printing-char))))
-
(defun isearch-process-search-char (char)
;; Append the char to the search string, update the message and re-search.
(isearch-process-search-string
(delete-field)
(insert isearch-string))))
-\f
-;; The search status stack (and isearch window-local variables, not used).
-;; Need a structure for this.
-
-(defun isearch-top-state ()
- (let ((cmd (car isearch-cmds)))
- (setq isearch-string (car cmd)
- isearch-message (car (cdr cmd))
- isearch-success (nth 3 cmd)
- isearch-forward (nth 4 cmd)
- isearch-other-end (nth 5 cmd)
- isearch-word (nth 6 cmd)
- isearch-invalid-regexp (nth 7 cmd)
- isearch-wrapped (nth 8 cmd)
- isearch-barrier (nth 9 cmd)
- isearch-within-brackets (nth 10 cmd)
- isearch-case-fold-search (nth 11 cmd))
- (goto-char (car (cdr (cdr cmd))))))
-
-(defun isearch-pop-state ()
- (setq isearch-cmds (cdr isearch-cmds))
- (isearch-top-state))
-
-(defun isearch-push-state ()
- (setq isearch-cmds
- (cons (list isearch-string isearch-message (point)
- isearch-success isearch-forward isearch-other-end
- isearch-word
- isearch-invalid-regexp isearch-wrapped isearch-barrier
- isearch-within-brackets isearch-case-fold-search)
- isearch-cmds)))
-
\f
;; Message string
;; If currently failing, display no ellipsis.
(or isearch-success (setq ellipsis nil))
(let ((m (concat (if isearch-success "" "failing ")
+ (if isearch-adjusted "pending " "")
(if (and isearch-wrapped
+ (not isearch-wrap-function)
(if isearch-forward
(> (point) isearch-opoint)
(< (point) isearch-opoint)))
(let ((inhibit-point-motion-hooks search-invisible)
(inhibit-quit nil)
(case-fold-search isearch-case-fold-search)
+ (search-spaces-regexp search-whitespace-regexp)
(retry t))
(if isearch-regexp (setq isearch-invalid-regexp nil))
(setq isearch-within-brackets nil)
(if isearch-success
nil
;; Ding if failed this time after succeeding last time.
- (and (nth 3 (car isearch-cmds))
+ (and (isearch-success-state (car isearch-cmds))
(ding))
- (goto-char (nth 2 (car isearch-cmds)))))
+ (if (functionp (isearch-pop-fun-state (car isearch-cmds)))
+ (funcall (isearch-pop-fun-state (car isearch-cmds)) (car isearch-cmds)))
+ (goto-char (isearch-point-state (car isearch-cmds)))))
;; Called when opening an overlay, and we are still in isearch.
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)))))
+ (unless (equal isearch-string "")
+ (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))
+ (let ((case-fold-search isearch-case-fold-search)
+ (search-spaces-regexp search-whitespace-regexp))
(funcall (isearch-search-fun)
isearch-string
(if isearch-forward
(let ((mb (match-beginning 0))
(me (match-end 0)))
(if (= mb me) ;zero-length match
- (forward-char 1)
+ (if isearch-forward
+ (if (= mb (if isearch-lazy-highlight-wrapped
+ isearch-lazy-highlight-start
+ (window-end)))
+ (setq found nil)
+ (forward-char 1))
+ (if (= mb (if isearch-lazy-highlight-wrapped
+ isearch-lazy-highlight-end
+ (window-start)))
+ (setq found nil)
+ (forward-char -1)))
;; non-zero-length match
(let ((ov (make-overlay mb me)))
(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)))))))
+ (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-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-case-fold-search case-fold)
(isearch-search))
-;;; arch-tag: 74850515-f7d8-43a6-8a2c-ca90a4c1e675
+;; arch-tag: 74850515-f7d8-43a6-8a2c-ca90a4c1e675
;;; isearch.el ends here