;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
"Function to save a function restoring the mode-specific isearch state
to the search status stack.")
+(defvar isearch-success-function 'isearch-success-function-default
+ "Function to report whether the new search match is considered successful.
+The function has two arguments: the positions of start and end of text
+matched by the search. If this function returns nil, continue
+searching without stopping at this match.")
+
;; Search ring.
(defvar search-ring nil
:group 'basic-faces)
(defvar isearch 'isearch)
+(defface isearch-fail
+ '((((class color) (min-colors 88) (background light))
+ (:background "RosyBrown1"))
+ (((class color) (min-colors 88) (background dark))
+ (:background "red4"))
+ (((class color) (min-colors 16))
+ (:background "red"))
+ (((class color) (min-colors 8))
+ (:background "red"))
+ (((class color grayscale))
+ :foreground "grey")
+ (t (:inverse-video t)))
+ "Face for highlighting failed part in Isearch echo-area message."
+ :version "23.1"
+ :group 'isearch)
+
(defcustom isearch-lazy-highlight t
"*Controls the lazy-highlighting during incremental search.
When non-nil, all text in the buffer matching the current search
(define-obsolete-variable-alias 'isearch-lazy-highlight-face
'lazy-highlight-face
"22.1")
+\f
+;; Define isearch help map.
+
+(defvar isearch-help-map
+ (let ((i 0)
+ (map (make-sparse-keymap)))
+ (define-key map [t] 'isearch-other-control-char)
+ (define-key map (char-to-string help-char) 'isearch-help-for-help)
+ (define-key map [help] 'isearch-help-for-help)
+ (define-key map [f1] 'isearch-help-for-help)
+ (define-key map "?" 'isearch-help-for-help)
+ (define-key map "b" 'isearch-describe-bindings)
+ (define-key map "k" 'isearch-describe-key)
+ (define-key map "m" 'isearch-describe-mode)
+ (define-key map "q" 'help-quit)
+ map)
+ "Keymap for characters following the Help key for isearch mode.")
+
+(eval-when-compile (require 'help-macro))
+
+(make-help-screen isearch-help-for-help-internal
+ "Type a help option: [bkm] or ?"
+ "You have typed %THIS-KEY%, the help character. Type a Help option:
+\(Type \\<help-map>\\[help-quit] to exit the Help command.)
+
+b Display all isearch key bindings.
+k KEYS Display full documentation of isearch key sequence.
+m Display documentation of isearch mode.
+
+You can't type here other help keys available in the global help map,
+but outise of this help window when you type them in isearch mode,
+they exit isearch mode before displaying global help."
+ isearch-help-map)
+
+(defun isearch-help-for-help ()
+ "Display isearch help menu."
+ (interactive)
+ (let (same-window-buffer-names same-window-regexps)
+ (isearch-help-for-help-internal))
+ (isearch-update))
+
+(defun isearch-describe-bindings ()
+ "Show a list of all keys defined in isearch mode, and their definitions.
+This is like `describe-bindings', but displays only isearch keys."
+ (interactive)
+ (let (same-window-buffer-names same-window-regexps)
+ (with-help-window "*Help*"
+ (with-current-buffer standard-output
+ (princ "Isearch Mode Bindings:\n")
+ (princ (substitute-command-keys "\\{isearch-mode-map}"))))))
+
+(defun isearch-describe-key ()
+ "Display documentation of the function invoked by isearch key."
+ (interactive)
+ (let (same-window-buffer-names same-window-regexps)
+ (call-interactively 'describe-key))
+ (isearch-update))
+
+(defun isearch-describe-mode ()
+ "Display documentation of isearch mode."
+ (interactive)
+ (let (same-window-buffer-names same-window-regexps)
+ (describe-function 'isearch-forward))
+ (isearch-update))
+
+(defalias 'isearch-mode-help 'isearch-describe-mode)
+
\f
;; Define isearch-mode keymap.
(define-key map "\M-\C-y" 'isearch-yank-char)
(define-key map "\C-y" 'isearch-yank-line)
- ;; Turned off because I find I expect to get the global definition--rms.
- ;; ;; Instead bind C-h to special help command for isearch-mode.
- ;; (define-key map "\C-h" 'isearch-mode-help)
+ (define-key map "\C-h" isearch-help-map)
(define-key map "\M-n" 'isearch-ring-advance)
(define-key map "\M-p" 'isearch-ring-retreat)
(define-key map "\M-r" 'isearch-toggle-regexp)
(define-key map "\M-e" 'isearch-edit-string)
+ (define-key map "\M-sr" 'isearch-toggle-regexp)
+ (define-key map "\M-sw" 'isearch-toggle-word)
+
(define-key map [?\M-%] 'isearch-query-replace)
(define-key map [?\C-\M-%] 'isearch-query-replace-regexp)
(define-key map "\M-so" 'isearch-occur)
+ (define-key map "\M-shr" 'isearch-highlight-regexp)
map)
"Keymap for `isearch-mode'.")
(define-key map "\M-\t" 'isearch-complete-edit)
(define-key map "\C-s" 'isearch-forward-exit-minibuffer)
(define-key map "\C-r" 'isearch-reverse-exit-minibuffer)
+ (define-key map "\C-w" 'isearch-edit-string-set-word)
(define-key map "\C-f" 'isearch-yank-char-in-minibuffer)
(define-key map [right] 'isearch-yank-char-in-minibuffer)
map)
(defvar isearch-string "") ; The current search string.
(defvar isearch-message "") ; text-char-description version of isearch-string
+(defvar isearch-message-prefix-add nil) ; Additonal text for the message prefix
+(defvar isearch-message-suffix-add nil) ; Additonal text for the message suffix
+
(defvar isearch-success t) ; Searching is currently successful.
(defvar isearch-error nil) ; Error message for failed search.
(defvar isearch-other-end nil) ; Start (end) of match if forward (backward).
(define-key esc-map "\C-s" 'isearch-forward-regexp)
(define-key global-map "\C-r" 'isearch-backward)
(define-key esc-map "\C-r" 'isearch-backward-regexp)
+(define-key search-map "w" 'isearch-forward-word)
;; Entry points to isearch-mode.
If you try to exit with the search string still empty, it invokes
nonincremental search.
-Type \\[isearch-query-replace] to start `query-replace' with string to\
- replace from last search string.
-Type \\[isearch-query-replace-regexp] to start `query-replace-regexp'\
- with string to replace from last search string.
-
Type \\[isearch-toggle-case-fold] to toggle search case-sensitivity.
Type \\[isearch-toggle-regexp] to toggle regular-expression mode.
+Type \\[isearch-toggle-word] to toggle word 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.
ring.
Type \\[isearch-complete] to complete the search string using the search ring.
+Type \\[isearch-query-replace] to run `query-replace' with string to\
+ replace from last search string.
+Type \\[isearch-query-replace-regexp] to run `query-replace-regexp'\
+ with the last search string.
+Type \\[isearch-occur] to run `occur' that shows\
+ the last search string.
+Type \\[isearch-highlight-regexp] to run `highlight-regexp'\
+ that highlights the last search string.
+
+Type \\[isearch-describe-bindings] to display all isearch key bindings.
+Type \\[isearch-describe-key] to display documentation of isearch key.
+Type \\[isearch-describe-mode] to display documentation of isearch mode.
+
If an input method is turned on in the current buffer, that input
method is also active while you are typing characters to search. To
toggle the input method, type \\[isearch-toggle-input-method]. It
"\
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.
+Like ordinary incremental search except that your input is treated
+as a regexp. See the command `isearch-forward' for more information.
In regexp incremental searches, a space or spaces normally matches
any whitespace (the variable `search-whitespace-regexp' controls
(interactive "P\np")
(isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
+(defun isearch-forward-word (&optional not-word no-recursive-edit)
+ "\
+Do incremental search forward for a sequence of words.
+With a prefix argument, do a regular string search instead.
+Like ordinary incremental search except that your input is treated
+as a sequence of words without regard to how the words are separated.
+See the command `isearch-forward' for more information."
+ (interactive "P\np")
+ (isearch-mode t nil nil (not no-recursive-edit) (null not-word)))
+
(defun isearch-backward (&optional regexp-p no-recursive-edit)
"\
Do incremental search backward.
With a prefix argument, do a regular expression search instead.
-See \\[isearch-forward] for more information."
+See the command `isearch-forward' for more information."
(interactive "P\np")
(isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit)))
"\
Do incremental search backward 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."
+Like ordinary incremental search except that your input is treated
+as a regexp. See the command `isearch-forward' for more information."
(interactive "P\np")
(isearch-mode nil (null not-regexp) nil (not no-recursive-edit)))
-
-(defun isearch-mode-help ()
- (interactive)
- (describe-function 'isearch-forward)
- (isearch-update))
-
\f
;; isearch-mode only sets up incremental search for the minor mode.
;; All the work is done by the isearch-mode commands.
(defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
- "Start isearch minor mode. Called by `isearch-forward', etc.
-
-\\{isearch-mode-map}"
+ "Start isearch minor mode.
+It is called by the function `isearch-forward' and other related functions."
;; Initialize global vars.
(setq isearch-forward forward
;; that can change their values.
(setq old-point (point) old-other-end isearch-other-end)
- (isearch-message) ;; for read-char
(unwind-protect
- (let* (;; Why does following read-char echo?
- ;;(echo-keystrokes 0) ;; not needed with above message
- (e (let ((cursor-in-echo-area t))
- (read-event)))
+ (let* ((message-log-max nil)
;; Binding minibuffer-history-symbol to nil is a work-around
;; for some incompatibility with gmhist.
- (minibuffer-history-symbol)
- (message-log-max nil))
- ;; If the first character the user types when we prompt them
- ;; for a string is the yank-word character, then go into
- ;; word-search mode. Otherwise unread that character and
- ;; read a key the normal way.
- ;; Word search does not apply (yet) to regexp searches,
- ;; no check is made here.
- (message "%s" (isearch-message-prefix nil nil t))
- (if (memq (lookup-key isearch-mode-map (vector e))
- '(isearch-yank-word
- isearch-yank-word-or-char))
- (setq isearch-word t;; so message-prefix is right
- isearch-new-word t)
- (cancel-kbd-macro-events)
- (isearch-unread e))
- (setq cursor-in-echo-area nil)
+ (minibuffer-history-symbol))
(setq isearch-new-string
(read-from-minibuffer
(isearch-message-prefix nil nil isearch-nonincremental)
isearch-string
minibuffer-local-isearch-map nil
- (if isearch-regexp 'regexp-search-ring 'search-ring)
+ (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
;; Only the string actually used should be saved.
))
- ;; Push the state as of before this C-s.
- (isearch-push-state)
+ ;; This used to push the state as of before this C-s, but it adds
+ ;; an inconsistent state where part of variables are from the
+ ;; previous search (e.g. `isearch-success'), and part of variables
+ ;; are just entered from the minibuffer (e.g. `isearch-string').
+ ;; (isearch-push-state)
;; Reinvoke the pending search.
(isearch-search)
- (isearch-push-state)
+ (isearch-push-state) ; this pushes the correct state
(isearch-update)
(if isearch-nonincremental
(progn
(isearch-abort) ;; outside of let to restore outside global values
)))
+;; Obsolete usage of `C-s M-e C-w'. Remove after 23.1.
+(defvar isearch-new-word)
+(defun isearch-edit-string-set-word ()
+ "Do word search after exiting `isearch-edit-string'."
+ (interactive)
+ (message "This feature is obsolete since 23.1; use `M-s w' instead.")
+ (setq isearch-word t isearch-new-word t))
+
+
(defun isearch-nonincremental-exit-minibuffer ()
(interactive)
(setq isearch-nonincremental t)
(setq isearch-success t isearch-adjusted t)
(isearch-update))
+(defun isearch-toggle-word ()
+ "Toggle word searching on or off."
+ (interactive)
+ (setq isearch-word (not isearch-word))
+ (setq isearch-success t isearch-adjusted t)
+ (isearch-update))
+
(defun isearch-toggle-case-fold ()
"Toggle case folding in searching on or off."
(interactive)
(sit-for 1)
(isearch-update))
-(defun isearch-query-replace (&optional regexp-flag)
- "Start `query-replace' with string to replace from last search string."
- (interactive)
+(defun isearch-query-replace (&optional delimited regexp-flag)
+ "Start `query-replace' with string to replace from last search string.
+The arg DELIMITED (prefix arg if interactive), if non-nil, means replace
+only matches surrounded by word boundaries. Note that using the prefix arg
+is possible only when `isearch-allow-scroll' is non-nil, and it don't
+always provides the correct matches for `query-replace', so the preferred
+way to run word replacements from Isearch is `M-s w ... M-%'."
+ (interactive
+ (list current-prefix-arg))
(barf-if-buffer-read-only)
(if regexp-flag (setq isearch-regexp t))
(let ((case-fold-search isearch-case-fold-search)
;; set `search-upper-case' to nil to not call
;; `isearch-no-upper-case-p' in `perform-replace'
- (search-upper-case nil))
- (isearch-done)
+ (search-upper-case nil)
+ ;; Set `isearch-recursive-edit' to nil to prevent calling
+ ;; `exit-recursive-edit' in `isearch-done' that terminates
+ ;; the execution of this command when it is non-nil.
+ ;; We call `exit-recursive-edit' explicitly at the end below.
+ (isearch-recursive-edit nil))
+ (isearch-done nil t)
(isearch-clean-overlays)
(if (and isearch-other-end
(< isearch-other-end (point))
isearch-string
(query-replace-read-to
isearch-string
- (if isearch-regexp "Query replace regexp" "Query replace")
+ (concat "Query replace"
+ (if (or delimited isearch-word) " word" "")
+ (if isearch-regexp " regexp" "")
+ (if (and transient-mark-mode mark-active) " in region" ""))
isearch-regexp)
- t isearch-regexp isearch-word nil nil
+ t isearch-regexp (or delimited isearch-word) nil nil
(if (and transient-mark-mode mark-active) (region-beginning))
- (if (and transient-mark-mode mark-active) (region-end)))))
+ (if (and transient-mark-mode mark-active) (region-end))))
+ (and isearch-recursive-edit (exit-recursive-edit)))
-(defun isearch-query-replace-regexp ()
- "Start `query-replace-regexp' with string to replace from last search string."
- (interactive)
- (isearch-query-replace t))
+(defun isearch-query-replace-regexp (&optional delimited)
+ "Start `query-replace-regexp' with string to replace from last search string.
+See `isearch-query-replace' for more information."
+ (interactive
+ (list current-prefix-arg))
+ (isearch-query-replace delimited t))
(defun isearch-occur (regexp &optional nlines)
"Run `occur' with regexp to search from the current search string.
string. NLINES has the same meaning as in `occur'."
(interactive
(list
- (if isearch-regexp isearch-string (regexp-quote isearch-string))
+ (cond
+ (isearch-word (concat "\\b" (regexp-quote isearch-string) "\\b"))
+ (isearch-regexp isearch-string)
+ (t (regexp-quote isearch-string)))
(if current-prefix-arg (prefix-numeric-value current-prefix-arg))))
(let ((case-fold-search isearch-case-fold-search)
;; set `search-upper-case' to nil to not call
(search-upper-case nil))
(occur regexp nlines)))
+(declare-function hi-lock-regexp-okay "hi-lock" (regexp))
+(declare-function hi-lock-read-face-name "hi-lock" ())
+
+(defun isearch-highlight-regexp ()
+ "Run `highlight-regexp' with regexp from the current search string.
+It exits Isearch mode and calls `hi-lock-face-buffer' with its regexp
+argument from the last search regexp or a quoted search string,
+and reads its face argument using `hi-lock-read-face-name'."
+ (interactive)
+ (let (
+ ;; Set `isearch-recursive-edit' to nil to prevent calling
+ ;; `exit-recursive-edit' in `isearch-done' that terminates
+ ;; the execution of this command when it is non-nil.
+ ;; We call `exit-recursive-edit' explicitly at the end below.
+ (isearch-recursive-edit nil))
+ (isearch-done nil t)
+ (isearch-clean-overlays))
+ (require 'hi-lock nil t)
+ (let ((string (cond (isearch-regexp isearch-string)
+ ((if (and (eq isearch-case-fold-search t)
+ search-upper-case)
+ (isearch-no-upper-case-p
+ isearch-string isearch-regexp)
+ isearch-case-fold-search)
+ ;; Turn isearch-string into a case-insensitive
+ ;; regexp.
+ (mapconcat
+ (lambda (c)
+ (let ((s (string c)))
+ (if (string-match "[[:alpha:]]" s)
+ (format "[%s%s]" (upcase s) (downcase s))
+ (regexp-quote s))))
+ isearch-string ""))
+ (t (regexp-quote isearch-string)))))
+ (hi-lock-face-buffer string (hi-lock-read-face-name)))
+ (and isearch-recursive-edit (exit-recursive-edit)))
+
\f
(defun isearch-delete-char ()
"Discard last input item and move point back.
;; 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.
+ ;; 'ab?\{5,6\}+\{1,2\}*' is perfectly valid.
(while (and previous
(or (isearch-error-state frame)
(let* ((string (isearch-string-state frame))
;; Scroll-bar functions:
(if (fboundp 'scroll-bar-toolkit-scroll)
(put 'scroll-bar-toolkit-scroll 'isearch-scroll t))
-(if (fboundp 'mac-handle-scroll-bar-event)
- (put 'mac-handle-scroll-bar-event 'isearch-scroll t))
(if (fboundp 'w32-handle-scroll-bar-event)
(put 'w32-handle-scroll-bar-event 'isearch-scroll t))
;; Commands which scroll the window:
(put 'recenter 'isearch-scroll t)
+(put 'recenter-top-bottom 'isearch-scroll t)
(put 'reposition-window 'isearch-scroll t)
(put 'scroll-up 'isearch-scroll t)
(put 'scroll-down 'isearch-scroll t)
"Convert return into newline for incremental search."
(interactive)
(isearch-process-search-char ?\n))
-(make-obsolete 'isearch-return-char 'isearch-printing-char)
+(make-obsolete 'isearch-return-char 'isearch-printing-char "19.7")
(defun isearch-printing-char ()
"Add this ordinary printing character to the search string and search."
(let ((char last-command-char))
(if (= char ?\S-\ )
(setq char ?\s))
- (if (and enable-multibyte-characters
- (>= char ?\200)
- (<= char ?\377))
- (if (keyboard-coding-system)
- (isearch-process-search-multibyte-characters char)
- (isearch-process-search-char (unibyte-char-to-multibyte char)))
- (if current-input-method
- (isearch-process-search-multibyte-characters char)
- (isearch-process-search-char char)))))
+ (if current-input-method
+ (isearch-process-search-multibyte-characters char)
+ (isearch-process-search-char char))))
(defun isearch-process-search-char (char)
;; * and ? are special in regexps when not preceded by \.
(if search-ring-update
(progn
(isearch-search)
+ (isearch-push-state)
(isearch-update))
- (isearch-edit-string)
- )
- (isearch-push-state))
+ ;; Otherwise, edit the search string instead. Note that there is
+ ;; no need to push the search state after isearch-edit-string here
+ ;; since isearch-edit-string already pushes its state
+ (isearch-edit-string)))
(defun isearch-ring-advance ()
"Advance to the next search string in the ring."
(defun isearch-message (&optional c-q-hack ellipsis)
;; Generate and print the message string.
(let ((cursor-in-echo-area ellipsis)
- (m (concat
- (isearch-message-prefix c-q-hack ellipsis isearch-nonincremental)
- (if (and (not isearch-success)
- (string-match " +$" isearch-message))
- (concat
- (substring isearch-message 0 (match-beginning 0))
- (propertize (substring isearch-message (match-beginning 0))
- 'face 'trailing-whitespace))
- isearch-message)
- (isearch-message-suffix c-q-hack ellipsis)
- )))
- (if c-q-hack
- m
- (let ((message-log-max nil))
- (message "%s" m)))))
+ (m isearch-message)
+ (cmds isearch-cmds)
+ succ-msg)
+ (when (or (not isearch-success) isearch-error)
+ ;; Highlight failed part
+ (while (or (not (isearch-success-state (car cmds)))
+ (isearch-error-state (car cmds)))
+ (pop cmds))
+ (setq succ-msg (and cmds (isearch-message-state (car cmds)))
+ m (copy-sequence m))
+ (add-text-properties
+ (if (and (stringp succ-msg)
+ (< (length succ-msg) (length m))
+ (equal succ-msg (substring m 0 (length succ-msg))))
+ (length succ-msg)
+ 0)
+ (length m) '(face isearch-fail) m)
+ ;; Highlight failed trailing whitespace
+ (when (string-match " +$" m)
+ (add-text-properties (match-beginning 0) (match-end 0)
+ '(face trailing-whitespace) m)))
+ (setq m (concat
+ (isearch-message-prefix c-q-hack ellipsis isearch-nonincremental)
+ m
+ (isearch-message-suffix c-q-hack ellipsis)))
+ (if c-q-hack m (let ((message-log-max nil)) (message "%s" m)))))
(defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
;; If about to search, and previous search regexp was invalid,
(if isearch-wrapped "wrapped ")
(if isearch-word "word " "")
(if isearch-regexp "regexp " "")
+ (if multi-isearch-next-buffer-current-function "multi " "")
+ (or isearch-message-prefix-add "")
(if nonincremental "search" "I-search")
(if isearch-forward "" " backward")
(if current-input-method
(concat (if c-q-hack "^Q" "")
(if isearch-error
(concat " [" isearch-error "]")
- "")))
+ "")
+ (or isearch-message-suffix-add "")))
\f
;; Searching
(funcall isearch-search-fun-function)
(cond
(isearch-word
- (if isearch-forward 'word-search-forward 'word-search-backward))
+ ;; Use lax versions to not fail at the end of the word while the user
+ ;; adds and removes characters in the search string
+ (if (not (eq (length isearch-string)
+ (length (isearch-string-state (car isearch-cmds)))))
+ (if isearch-forward 'word-search-forward-lax 'word-search-backward-lax)
+ (if isearch-forward 'word-search-forward 'word-search-backward)))
(isearch-regexp
(if isearch-forward 're-search-forward 're-search-backward))
(t
pos1 pos2)
(setq pos1 (save-excursion (funcall func string bound noerror)))
(if (and (char-table-p translation-table-for-input)
- (> (string-bytes string) len))
- (let (translated match-data)
- (dotimes (i len)
- (let ((x (aref translation-table-for-input (aref string i))))
- (when x
- (or translated (setq translated (copy-sequence string)))
- (aset translated i x))))
+ (multibyte-string-p string)
+ ;; Minor optimization.
+ (string-match-p "[^[:ascii:]]" string))
+ (let ((translated
+ (apply 'string
+ (mapcar (lambda (c)
+ (or (aref translation-table-for-input c) c))
+ string)))
+ match-data)
(when translated
(save-match-data
(save-excursion
(when pos1
;; When using multiple buffers isearch, switch to the new buffer here,
;; because `save-excursion' above doesn't allow doing it inside funcall.
- (if (and isearch-buffers-next-buffer-function
- (buffer-live-p isearch-buffers-current-buffer))
- (switch-to-buffer isearch-buffers-current-buffer))
+ (if (and multi-isearch-next-buffer-current-function
+ (buffer-live-p multi-isearch-current-buffer))
+ (switch-to-buffer multi-isearch-current-buffer))
(goto-char pos1))
pos1))
(setq isearch-case-fold-search
(isearch-no-upper-case-p isearch-string isearch-regexp)))
(condition-case lossage
- (let ((inhibit-point-motion-hooks search-invisible)
+ (let ((inhibit-point-motion-hooks
+ (and (eq isearch-success-function 'isearch-success-function-default)
+ search-invisible))
(inhibit-quit nil)
(case-fold-search isearch-case-fold-search)
(search-spaces-regexp search-whitespace-regexp)
(isearch-search-string isearch-string nil t))
;; Clear RETRY unless we matched some invisible text
;; and we aren't supposed to do that.
- (if (or (eq search-invisible t)
- (not isearch-success)
+ (if (or (not isearch-success)
(bobp) (eobp)
(= (match-beginning 0) (match-end 0))
- (not (isearch-range-invisible
- (match-beginning 0) (match-end 0))))
+ (funcall isearch-success-function
+ (match-beginning 0) (match-end 0)))
(setq retry nil)))
(setq isearch-just-started nil)
(if isearch-success
nil)
(setq isearch-hidden t)))))))
+(defun isearch-success-function-default (beg end)
+ "Default function to report if the new search match is successful.
+Returns t if search can match hidden text, or otherwise checks if some
+text from BEG to END is visible."
+ (or (eq search-invisible t)
+ (not (isearch-range-invisible beg end))))
+
\f
;; General utilities
(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-lazy-highlight-case-fold-search)
- (isearch-regexp isearch-lazy-highlight-regexp)
- (search-spaces-regexp isearch-lazy-highlight-space-regexp))
- (condition-case nil
- (isearch-search-string
- isearch-lazy-highlight-last-string
- (if isearch-forward
- (min (or isearch-lazy-highlight-end-limit (point-max))
+ (condition-case nil
+ (let ((case-fold-search isearch-lazy-highlight-case-fold-search)
+ (isearch-regexp isearch-lazy-highlight-regexp)
+ (search-spaces-regexp isearch-lazy-highlight-space-regexp)
+ (search-invisible nil) ; don't match invisible text
+ (retry t)
+ (success nil)
+ (bound (if isearch-forward
+ (min (or isearch-lazy-highlight-end-limit (point-max))
+ (if isearch-lazy-highlight-wrapped
+ isearch-lazy-highlight-start
+ (window-end)))
+ (max (or isearch-lazy-highlight-start-limit (point-min))
(if isearch-lazy-highlight-wrapped
- isearch-lazy-highlight-start
- (window-end)))
- (max (or isearch-lazy-highlight-start-limit (point-min))
- (if isearch-lazy-highlight-wrapped
- isearch-lazy-highlight-end
- (window-start))))
- t)
- (error nil))))
+ isearch-lazy-highlight-end
+ (window-start))))))
+ ;; Use a loop like in `isearch-search'
+ (while retry
+ (setq success (isearch-search-string
+ isearch-lazy-highlight-last-string bound t))
+ (if (or (not success)
+ (funcall isearch-success-function
+ (match-beginning 0) (match-end 0)))
+ (setq retry nil)))
+ success)
+ (error nil)))
(defun isearch-lazy-highlight-update ()
"Update highlighting of other matches for current search."