(defgroup isearch nil
"Incremental search minor mode."
:link '(emacs-commentary-link "isearch")
:link '(custom-manual "(emacs)Incremental Search")
:prefix "isearch-"
:prefix "search-"
:group 'matching)
(defcustom search-exit-option t
"*Non-nil means random control characters terminate incremental search."
:type 'boolean
:group 'isearch)
(defcustom search-slow-window-lines 1
"*Number of lines in slow search display windows.
These are the short windows used during incremental search on slow terminals.
Negative means put the slow search window at the top (normally it's at bottom)
and the value is minus the number of lines."
:type 'integer
:group 'isearch)
(defcustom search-slow-speed 1200
"*Highest terminal speed at which to use \"slow\" style incremental search.
This is the style where a one-line window is created to show the line
that the search has reached."
:type 'integer
:group 'isearch)
(defcustom search-upper-case 'not-yanks
"*If non-nil, upper case chars disable case fold searching.
That is, upper and lower case chars must match exactly.
This applies no matter where the chars come from, but does not
apply to chars in regexps that are prefixed with `\\'.
If this value is `not-yanks', yanked text is always downcased."
:type '(choice (const :tag "off" nil)
(const not-yanks)
(other :tag "on" t))
:group 'isearch)
(defcustom search-nonincremental-instead t
"*If non-nil, do a nonincremental search instead if exiting immediately.
Actually, `isearch-edit-string' is called to let you enter the search
string, and RET terminates editing and does a nonincremental search."
:type 'boolean
:group 'isearch)
(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 `]+'.
When this is nil, each space you type matches literally, against one space."
:type '(choice (const :tag "Find Spaces Literally" nil)
regexp)
:group 'isearch)
(defcustom search-invisible 'open
"If t incremental search can match hidden text.
A nil value means don't match invisible text.
When the value is `open', if the text matched is made invisible by
an overlay having an `invisible' property and that overlay has a property
`isearch-open-invisible', then incremental search will show the contents.
\(This applies when using `outline.el' and `hideshow.el'.)
See also `reveal-mode' if you want overlays to automatically be opened
whenever point is in one of them."
:type '(choice (const :tag "Match hidden text" t)
(const :tag "Open overlays" open)
(const :tag "Don't match hidden text" nil))
:group 'isearch)
(defcustom isearch-hide-immediately t
"If non-nil, re-hide an invisible match right away.
This variable makes a difference when `search-invisible' is set to `open'.
It means that after search makes some invisible text visible
to show the match, it makes the text invisible again when the match moves.
Ordinarily the text becomes invisible again at the end of the search."
:type 'boolean
:group 'isearch)
(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-hook nil
"Function(s) to call after starting up an incremental search.")
(defvar isearch-mode-end-hook nil
"Function(s) to call after terminating an incremental search.
When these functions are called, `isearch-mode-end-hook-quit'
is non-nil if the user quit the search.")
(defvar isearch-mode-end-hook-quit nil
"Non-nil while running `isearch-mode-end-hook' if user quit the 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.")
(defvar search-ring nil
"List of search string sequences.")
(defvar regexp-search-ring nil
"List of regular expression search string sequences.")
(defcustom search-ring-max 16
"*Maximum length of search ring before oldest elements are thrown away."
:type 'integer
:group 'isearch)
(defcustom regexp-search-ring-max 16
"*Maximum length of regexp search ring before oldest elements are thrown away."
:type 'integer
:group 'isearch)
(defvar search-ring-yank-pointer nil
"Index in `search-ring' of last string reused.
It is nil if none yet.")
(defvar regexp-search-ring-yank-pointer nil
"Index in `regexp-search-ring' of last string reused.
It is nil if none yet.")
(defcustom search-ring-update nil
"*Non-nil if advancing or retreating in the search ring should cause search.
Default value, nil, means edit the string instead."
:type 'boolean
:group 'isearch)
(defcustom search-highlight t
"*Non-nil means incremental search highlights the current match."
:type 'boolean
:group 'isearch)
(defface isearch
'((((class color) (min-colors 88) (background light))
(:background "magenta3" :foreground "lightskyblue1"))
(((class color) (min-colors 88) (background dark))
(:background "palevioletred2" :foreground "brown4"))
(((class color) (min-colors 16))
(:background "magenta4" :foreground "cyan1"))
(((class color) (min-colors 8))
(:background "magenta4" :foreground "cyan1"))
(t (:inverse-video t)))
"Face for highlighting Isearch matches."
:group 'isearch
:group 'basic-faces)
(defvar isearch '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
string is highlighted lazily (see `lazy-highlight-initial-delay'
and `lazy-highlight-interval')."
:type 'boolean
:group 'lazy-highlight
:group 'isearch)
(defgroup lazy-highlight nil
"Lazy highlighting feature for matching strings."
:prefix "lazy-highlight-"
:version "21.1"
:group 'isearch
:group 'matching)
(defcustom lazy-highlight-cleanup t
"*Controls whether to remove extra highlighting after a search.
If this is nil, extra highlighting can be \"manually\" removed with
\\[lazy-highlight-cleanup]."
:type 'boolean
:group 'lazy-highlight)
(define-obsolete-variable-alias 'isearch-lazy-highlight-cleanup
'lazy-highlight-cleanup
"22.1")
(defcustom lazy-highlight-initial-delay 0.25
"*Seconds to wait before beginning to lazily highlight all matches."
:type 'number
:group 'lazy-highlight)
(define-obsolete-variable-alias 'isearch-lazy-highlight-initial-delay
'lazy-highlight-initial-delay
"22.1")
(defcustom lazy-highlight-interval 0 "*Seconds between lazily highlighting successive matches."
:type 'number
:group 'lazy-highlight)
(define-obsolete-variable-alias 'isearch-lazy-highlight-interval
'lazy-highlight-interval
"22.1")
(defcustom lazy-highlight-max-at-a-time 20
"*Maximum matches to highlight at a time (for `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 'lazy-highlight)
(define-obsolete-variable-alias 'isearch-lazy-highlight-max-at-a-time
'lazy-highlight-max-at-a-time
"22.1")
(defface lazy-highlight
'((((class color) (min-colors 88) (background light))
(:background "paleturquoise"))
(((class color) (min-colors 88) (background dark))
(:background "paleturquoise4"))
(((class color) (min-colors 16))
(:background "turquoise3"))
(((class color) (min-colors 8))
(:background "turquoise3"))
(t (:underline t)))
"Face for lazy highlighting of matches other than the current one."
:group 'lazy-highlight
:group 'basic-faces)
(put 'isearch-lazy-highlight-face 'face-alias 'lazy-highlight)
(defvar lazy-highlight-face 'lazy-highlight)
(define-obsolete-variable-alias 'isearch-lazy-highlight-face
'lazy-highlight-face
"22.1")
(defvar isearch-mode-map
(let* ((i 0)
(map (make-keymap)))
(or (vectorp (nth 1 map))
(char-table-p (nth 1 map))
(error "The initialization of isearch-mode-map must be updated"))
(let ((l (generic-character-list))
(table (nth 1 map)))
(while l
(set-char-table-default table (car l) 'isearch-printing-char)
(setq l (cdr l))))
(define-key map [t] 'isearch-other-control-char)
(while (< i ?\s)
(define-key map (make-string 1 i) 'isearch-other-control-char)
(setq i (1+ i)))
(setq i ?\s)
(while (< i 256)
(define-key map (vector i) 'isearch-printing-char)
(setq i (1+ i)))
(let ((meta-map (make-sparse-keymap)))
(define-key map (char-to-string meta-prefix-char) meta-map)
(define-key map [escape] meta-map))
(define-key map (vector meta-prefix-char t) 'isearch-other-meta-char)
(define-key map "\C-s" 'isearch-repeat-forward)
(define-key map "\C-r" 'isearch-repeat-backward)
(define-key map "\M-\C-s" 'isearch-repeat-forward)
(define-key map "\M-\C-r" 'isearch-repeat-backward)
(define-key map "\177" 'isearch-delete-char)
(define-key map "\C-g" 'isearch-abort)
(or (= ?\e meta-prefix-char)
(error "Inconsistency in isearch.el"))
(define-key map "\e\e\e" 'isearch-cancel)
(define-key map [escape escape escape] 'isearch-cancel)
(define-key map "\C-q" 'isearch-quote-char)
(define-key map "\r" 'isearch-exit)
(define-key map "\C-j" 'isearch-printing-char)
(define-key map "\t" 'isearch-printing-char)
(define-key map [?\S-\ ] 'isearch-printing-char)
(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-key map "\M-n" 'isearch-ring-advance)
(define-key map "\M-p" 'isearch-ring-retreat)
(define-key map "\M-y" 'isearch-yank-kill)
(define-key map "\M-\t" 'isearch-complete)
(define-key map [switch-frame] nil)
(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)
(define-key map [language-change] nil)
(define-key map "\C-\\" 'isearch-toggle-input-method)
(define-key map "\C-^" 'isearch-toggle-specified-input-method)
(define-key map [mouse-2] #'isearch-mouse-2)
(define-key map [down-mouse-2] nil)
(define-key map "\M-c" 'isearch-toggle-case-fold)
(define-key map "\M-r" 'isearch-toggle-regexp)
(define-key map "\M-e" 'isearch-edit-string)
(define-key map [?\M-%] 'isearch-query-replace)
(define-key map [?\C-\M-%] 'isearch-query-replace-regexp)
map)
"Keymap for `isearch-mode'.")
(defvar minibuffer-local-isearch-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
(define-key map "\r" 'isearch-nonincremental-exit-minibuffer)
(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-f" 'isearch-yank-char-in-minibuffer)
(define-key map [right] 'isearch-yank-char-in-minibuffer)
map)
"Keymap for editing isearch strings in the minibuffer.")
(defvar isearch-forward nil) (defvar isearch-regexp nil) (defvar isearch-word nil) (defvar isearch-hidden nil)
(defvar isearch-cmds nil
"Stack of search status sets.
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 "") (defvar isearch-message "")
(defvar isearch-success t) (defvar isearch-error nil) (defvar isearch-other-end nil) (defvar isearch-wrapped nil) (defvar isearch-barrier 0)
(defvar isearch-just-started nil)
(defvar isearch-start-hscroll 0)
(defvar isearch-case-fold-search nil)
(defvar isearch-last-case-fold-search nil)
(defvar isearch-original-minibuffer-message-timeout nil)
(defvar isearch-adjusted nil)
(defvar isearch-slow-terminal-mode nil)
(defvar isearch-small-window nil)
(defvar isearch-opoint 0)
(defvar isearch-window-configuration nil)
(defvar isearch-yank-flag nil)
(defvar isearch-op-fun nil)
(defvar isearch-recursive-edit nil)
(defvar isearch-nonincremental nil)
(defvar isearch-new-forward nil)
(defvar isearch-opened-overlays nil)
(defvar isearch-input-method-function nil)
(defvar isearch-input-method-local-p nil)
(or (assq 'isearch-mode minor-mode-alist)
(nconc minor-mode-alist
(list '(isearch-mode isearch-mode))))
(defvar isearch-mode nil) (make-variable-buffer-local 'isearch-mode)
(define-key global-map "\C-s" 'isearch-forward)
(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)
(defun isearch-forward (&optional regexp-p no-recursive-edit)
"\
Do incremental search forward.
With a prefix argument, do an incremental regular expression search instead.
\\<isearch-mode-map>
As you type characters, they add to the search string and are found.
The following non-printing keys are bound in `isearch-mode-map'.
Type \\[isearch-delete-char] to cancel last input item from end of search string.
Type \\[isearch-exit] to exit, leaving point at location found.
Type LFD (C-j) to match end of line.
Type \\[isearch-repeat-forward] to search again forward,\
\\[isearch-repeat-backward] to search again backward.
Type \\[isearch-yank-word-or-char] to yank next word or character in buffer
onto the end of the search string, and search for it.
Type \\[isearch-del-char] to delete character from end of search string.
Type \\[isearch-yank-char] to yank char from buffer onto end of search\
string and search for it.
Type \\[isearch-yank-line] to yank rest of line onto end of search string\
and search for it.
Type \\[isearch-yank-kill] to yank the last string of killed text.
Type \\[isearch-quote-char] to quote control character to search for it.
\\[isearch-abort] while searching or when search has failed cancels input\
back to what has
been found successfully.
\\[isearch-abort] when search is successful aborts and moves point to\
starting point.
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-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 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 \\[apropos] on search-.* to find them.
Other control and meta characters terminate the search
and are then executed normally (depending on `search-exit-option').
Likewise for function keys and mouse button events.
If this function is called non-interactively, it does not return to
the calling function until the search is done."
(interactive "P\np")
(isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit)))
(defun isearch-forward-regexp (&optional not-regexp no-recursive-edit)
"\
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.
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 C-q SPC."
(interactive "P\np")
(isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
(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."
(interactive "P\np")
(isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit)))
(defun isearch-backward-regexp (&optional not-regexp 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."
(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))
(defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
"Start isearch minor mode. Called by `isearch-forward', etc.
\\{isearch-mode-map}"
(setq isearch-forward forward
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-cmds nil
isearch-success t
isearch-wrapped nil
isearch-barrier (point)
isearch-adjusted nil
isearch-yank-flag nil
isearch-error nil
isearch-slow-terminal-mode (and (<= baud-rate search-slow-speed)
(> (window-height)
(* 4
(abs search-slow-window-lines))))
isearch-other-end nil
isearch-small-window nil
isearch-just-started t
isearch-start-hscroll (window-hscroll)
isearch-opoint (point)
search-ring-yank-pointer nil
isearch-opened-overlays nil
isearch-input-method-function input-method-function
isearch-input-method-local-p (local-variable-p 'input-method-function)
regexp-search-ring-yank-pointer nil
isearch-original-minibuffer-message-timeout minibuffer-message-timeout
minibuffer-message-timeout nil)
(or isearch-input-method-local-p
(make-local-variable 'input-method-function))
(setq input-method-function nil)
(looking-at "")
(setq isearch-window-configuration
(if isearch-slow-terminal-mode (current-window-configuration) nil))
(let ((frame (window-frame (minibuffer-window))))
(unless (memq (frame-live-p frame) '(nil t))
(unless (frame-visible-p frame)
(make-frame-visible frame))
(if minibuffer-auto-raise
(raise-frame frame))))
(setq isearch-mode " Isearch") (force-mode-line-update)
(isearch-push-state)
(setq overriding-terminal-local-map isearch-mode-map)
(isearch-update)
(run-hooks 'isearch-mode-hook)
(add-hook 'mouse-leave-buffer-hook 'isearch-done)
(add-hook 'kbd-macro-termination-hook 'isearch-done)
(if recursive-edit
(let ((isearch-recursive-edit t))
(recursive-edit)))
isearch-success)
(defun isearch-update ()
(if (and (null unread-command-events)
(null executing-kbd-macro))
(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))
(let ((current-scroll (window-hscroll)))
(set-window-hscroll (selected-window) isearch-start-hscroll)
(unless (pos-visible-in-window-p)
(set-window-hscroll (selected-window) current-scroll))))
(if isearch-other-end
(if (< isearch-other-end (point)) (isearch-highlight isearch-other-end (point))
(isearch-highlight (point) isearch-other-end))
(isearch-dehighlight))
))
(setq isearch-adjusted nil
isearch-yank-flag nil)
(when isearch-lazy-highlight
(isearch-lazy-highlight-new-loop))
(setq disable-point-adjustment t))
(defun isearch-done (&optional nopush edit)
"Exit Isearch mode.
For successful search, pass no args.
For a failing search, NOPUSH is t.
For going to the minibuffer to edit the search string,
NOPUSH is t and EDIT is t."
(if isearch-resume-in-command-history
(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)
(setq overriding-terminal-local-map nil)
(setq minibuffer-message-timeout isearch-original-minibuffer-message-timeout)
(isearch-dehighlight)
(lazy-highlight-cleanup lazy-highlight-cleanup)
(let ((found-start (window-start (selected-window)))
(found-point (point)))
(when isearch-window-configuration
(set-window-configuration isearch-window-configuration)
(if isearch-small-window
(goto-char found-point)
(set-window-start (selected-window) found-start t))))
(setq isearch-mode nil)
(if isearch-input-method-local-p
(setq input-method-function isearch-input-method-function)
(kill-local-variable 'input-method-function))
(force-mode-line-update)
(let ((after (if (eobp) nil
(get-text-property (point) 'intangible)))
(before (if (bobp) nil
(get-text-property (1- (point)) 'intangible))))
(when (and before after (eq before after))
(if isearch-forward
(goto-char (next-single-property-change (point) 'intangible))
(goto-char (previous-single-property-change (point) 'intangible)))))
(if (and (> (length isearch-string) 0) (not nopush))
(isearch-update-ring isearch-string isearch-regexp))
(let ((isearch-mode-end-hook-quit (and nopush (not edit))))
(run-hooks 'isearch-mode-end-hook))
(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)
"Add STRING to the beginning of the search ring.
REGEXP if non-nil says use the regexp search ring."
(add-to-history
(if regexp 'regexp-search-ring 'search-ring)
string
(if regexp regexp-search-ring-max search-ring-max)))
(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-error-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-case-fold-search-state (frame)
"Return the case-folding flag in FRAME."
(aref frame 10))
(defsubst isearch-pop-fun-state (frame)
"Return the function restoring the mode-specific isearch state in FRAME."
(aref frame 11))
(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-error (isearch-error-state cmd)
isearch-wrapped (isearch-wrapped-state cmd)
isearch-barrier (isearch-barrier-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-error isearch-wrapped isearch-barrier
isearch-case-fold-search
(if isearch-push-state-function
(funcall isearch-push-state-function)))
isearch-cmds)))
(defun isearch-exit ()
"Exit search normally.
However, if this is the first command after starting incremental
search and `search-nonincremental-instead' is non-nil, do a
nonincremental search instead via `isearch-edit-string'."
(interactive)
(if (and search-nonincremental-instead
(= 0 (length isearch-string)))
(let ((isearch-nonincremental t))
(isearch-edit-string)))
(isearch-done)
(isearch-clean-overlays))
(defun isearch-edit-string ()
"Edit the search string in the minibuffer.
The following additional command keys are active while editing.
\\<minibuffer-local-isearch-map>
\\[exit-minibuffer] to resume incremental searching with the edited string.
\\[isearch-nonincremental-exit-minibuffer] to do one nonincremental search.
\\[isearch-forward-exit-minibuffer] to resume isearching forward.
\\[isearch-reverse-exit-minibuffer] to resume isearching backward.
\\[isearch-complete-edit] to complete the search string using the search ring.
\\<isearch-mode-map>
If first char entered is \\[isearch-yank-word-or-char], then do word search instead."
(interactive)
(condition-case err
(progn
(let ((isearch-nonincremental isearch-nonincremental)
(isearch-new-string isearch-string)
(isearch-new-message isearch-message)
(isearch-new-forward isearch-forward)
(isearch-new-word isearch-word)
(isearch-regexp isearch-regexp)
(isearch-op-fun isearch-op-fun)
(isearch-cmds isearch-cmds)
(isearch-success isearch-success)
(isearch-wrapped isearch-wrapped)
(isearch-barrier isearch-barrier)
(isearch-adjusted isearch-adjusted)
(isearch-yank-flag isearch-yank-flag)
(isearch-error isearch-error)
(isearch-opoint isearch-opoint)
(isearch-slow-terminal-mode isearch-slow-terminal-mode)
(isearch-small-window isearch-small-window)
(isearch-recursive-edit isearch-recursive-edit)
(isearch-window-configuration (current-window-configuration))
(minibuffer-message-timeout
isearch-original-minibuffer-message-timeout)
(isearch-original-minibuffer-message-timeout
isearch-original-minibuffer-message-timeout)
)
(condition-case err
(isearch-done t t)
(exit nil))
(isearch-message) (unwind-protect
(let* ( (e (let ((cursor-in-echo-area t))
(read-event)))
(minibuffer-history-symbol)
(message-log-max nil))
(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 isearch-new-word t)
(cancel-kbd-macro-events)
(isearch-unread e))
(setq cursor-in-echo-area nil)
(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)
nil t)
isearch-new-message
(mapconcat 'isearch-text-char-description
isearch-new-string "")))
(isearch-mode isearch-forward
isearch-regexp
isearch-op-fun
nil
isearch-word)
(setq isearch-string isearch-new-string
isearch-message isearch-new-message
isearch-forward isearch-new-forward
isearch-word isearch-new-word))
(if (= 0 (length isearch-string))
(setq isearch-string (or (car (if isearch-regexp
regexp-search-ring
search-ring))
"")
isearch-message
(mapconcat 'isearch-text-char-description
isearch-string ""))
))
(isearch-push-state)
(isearch-search)
(isearch-update)
(if isearch-nonincremental
(progn
(isearch-done)
(if (equal isearch-string "")
(message "")))))
(quit (isearch-abort) )))
(defun isearch-nonincremental-exit-minibuffer ()
(interactive)
(setq isearch-nonincremental t)
(exit-minibuffer))
(defun isearch-forward-exit-minibuffer ()
(interactive)
(setq isearch-new-forward t)
(exit-minibuffer))
(defun isearch-reverse-exit-minibuffer ()
(interactive)
(setq isearch-new-forward nil)
(exit-minibuffer))
(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-clean-overlays)
(signal 'quit nil))
(defun isearch-abort ()
"Abort incremental search mode if searching is successful, signaling quit.
Otherwise, revert to previous successful search and continue searching.
Use `isearch-exit' to quit without signaling."
(interactive)
(discard-input)
(if isearch-success
(progn
(setq isearch-success nil)
(isearch-cancel))
(while (or (not isearch-success) isearch-error)
(isearch-pop-state))
(isearch-update)))
(defun isearch-repeat (direction)
(if (eq isearch-forward (eq direction 'forward))
(if (equal isearch-string "")
(if (null (if isearch-regexp regexp-search-ring search-ring))
(setq isearch-error "No previous search string")
(setq isearch-string
(if isearch-regexp
(car regexp-search-ring)
(car search-ring))
isearch-message
(mapconcat 'isearch-text-char-description
isearch-string "")
isearch-case-fold-search isearch-last-case-fold-search))
(or isearch-success
(progn
(setq isearch-wrapped t)
(if isearch-wrap-function
(funcall isearch-wrap-function)
(goto-char (if isearch-forward (point-min) (point-max)))))))
(setq isearch-forward (not isearch-forward)
isearch-success t))
(setq isearch-barrier (point))
(if (equal isearch-string "")
(setq isearch-success t)
(if (and isearch-success
(equal (point) isearch-other-end)
(not isearch-just-started))
(if (if isearch-forward (eobp) (bobp))
(progn
(setq isearch-success nil)
(ding))
(forward-char (if isearch-forward 1 -1))
(isearch-search))
(isearch-search)))
(isearch-push-state)
(isearch-update))
(defun isearch-repeat-forward ()
"Repeat incremental search forwards."
(interactive)
(isearch-repeat 'forward))
(defun isearch-repeat-backward ()
"Repeat incremental search backwards."
(interactive)
(isearch-repeat 'backward))
(defun isearch-toggle-regexp ()
"Toggle regexp searching on or off."
(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 ()
"Toggle case folding in searching on or off."
(interactive)
(setq isearch-case-fold-search
(if isearch-case-fold-search nil 'yes))
(let ((message-log-max nil))
(message "%s%s [case %ssensitive]"
(isearch-message-prefix nil nil isearch-nonincremental)
isearch-message
(if isearch-case-fold-search "in" "")))
(setq isearch-success t isearch-adjusted t)
(sit-for 1)
(isearch-update))
(defun isearch-query-replace (&optional regexp-flag)
"Start query-replace with string to replace from last search string."
(interactive)
(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)
(if (and isearch-other-end
(< isearch-other-end (point))
(not (and transient-mark-mode mark-active
(< (mark) (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)
(isearch-query-replace t))
(defun isearch-delete-char ()
"Discard last input item and move point back.
If no previous match was done, just beep."
(interactive)
(if (null (cdr isearch-cmds))
(ding)
(isearch-pop-state))
(isearch-update))
(defun isearch-del-char (&optional arg)
"Delete character from end of search string and search again.
If search string is empty, just beep."
(interactive "p")
(if (= 0 (length isearch-string))
(ding)
(setq isearch-string (substring isearch-string 0 (- (or arg 1)))
isearch-message (mapconcat 'isearch-text-char-description
isearch-string "")
isearch-yank-flag t))
(isearch-search-and-update))
(defun isearch-yank-string (string)
"Pull STRING into search string."
(if (and isearch-case-fold-search
(eq 'not-yanks search-upper-case))
(setq string (downcase string)))
(if isearch-regexp (setq string (regexp-quote string)))
(setq isearch-string (concat isearch-string string)
isearch-message
(concat isearch-message
(mapconcat 'isearch-text-char-description
string ""))
isearch-yank-flag t)
(isearch-search-and-update))
(defun isearch-yank-kill ()
"Pull string from kill ring into search string."
(interactive)
(isearch-yank-string (current-kill 0)))
(defun isearch-yank-x-selection ()
"Pull current X selection into search string."
(interactive)
(isearch-yank-string (x-get-selection)))
(defun isearch-mouse-2 (click)
"Handle mouse-2 in Isearch mode.
For a click in the echo area, invoke `isearch-yank-x-selection'.
Otherwise invoke whatever the calling mouse-2 command sequence
is bound to outside of Isearch."
(interactive "e")
(let* ((w (posn-window (event-start click)))
(overriding-terminal-local-map nil)
(binding (key-binding (this-command-keys-vector) t)))
(if (and (window-minibuffer-p w)
(not (minibuffer-window-active-p w))) (isearch-yank-x-selection)
(when (functionp binding)
(call-interactively binding)))))
(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) (funcall jumpform)))))
(defun isearch-yank-char-in-minibuffer (&optional arg)
"Pull next character from buffer into end of search string in minibuffer."
(interactive "p")
(if (eobp)
(insert
(save-excursion
(set-buffer (cadr (buffer-list)))
(buffer-substring-no-properties
(point) (progn (forward-char arg) (point)))))
(forward-char arg)))
(defun isearch-yank-char (&optional arg)
"Pull next character from buffer into search string."
(interactive "p")
(isearch-yank-internal (lambda () (forward-char arg) (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-internal
(lambda () (let ((inhibit-field-text-motion t))
(line-end-position (if (eolp) 2 1))))))
(defun isearch-search-and-update ()
(when (or isearch-success
isearch-regexp
(prog1 isearch-hidden (setq isearch-hidden nil)))
(if (and (not isearch-forward) (not isearch-adjusted)
(condition-case ()
(let ((case-fold-search isearch-case-fold-search))
(if (and (eq case-fold-search t) search-upper-case)
(setq case-fold-search
(isearch-no-upper-case-p isearch-string isearch-regexp)))
(looking-at (if isearch-regexp isearch-string
(regexp-quote isearch-string))))
(error nil))
(or isearch-yank-flag
(<= (match-end 0)
(min isearch-opoint isearch-barrier))))
(progn
(setq isearch-success t
isearch-error nil
isearch-other-end (match-end 0))
(if (and (eq isearch-case-fold-search t) search-upper-case)
(setq isearch-case-fold-search
(isearch-no-upper-case-p isearch-string isearch-regexp))))
(if (and isearch-other-end (not isearch-adjusted))
(goto-char (if isearch-forward isearch-other-end
(min isearch-opoint
isearch-barrier
(1+ isearch-other-end)))))
(isearch-search)
))
(isearch-push-state)
(if isearch-op-fun (funcall isearch-op-fun))
(isearch-update))
(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."
(when (and isearch-regexp (eq (not (isearch-backslash isearch-string))
(not want-backslash))
(or (not isearch-error)
(not (isearch-error-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)) (frame (car stack)))
(while (and previous
(or (isearch-error-state frame)
(let* ((string (isearch-string-state frame))
(lchar (aref string (1- (length string)))))
(if (isearch-backslash
(isearch-string-state (car previous)))
(eq lchar ?\})
(memq lchar '(?* ?? ?+))))))
(setq stack previous previous (cdr previous) frame (car stack)))
(when stack
(let ((last-other-end
(or (and (car previous)
(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)))))))
(defun isearch-unread-key-sequence (keylist)
"Unread the given key-sequence KEYLIST.
Scroll-bar or mode-line events are processed appropriately."
(cancel-kbd-macro-events)
(apply 'isearch-unread keylist)
(if (and (> (length keylist) 1)
(symbolp (car keylist))
(listp (cadr keylist))
(not (numberp (posn-point
(event-start (cadr keylist) )))))
(pop unread-command-events)))
(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))
(put 'recenter 'isearch-scroll t)
(put 'reposition-window 'isearch-scroll t)
(put 'scroll-up 'isearch-scroll t)
(put 'scroll-down 'isearch-scroll t)
(put 'list-buffers 'isearch-scroll t)
(put 'scroll-other-window 'isearch-scroll t)
(put 'scroll-other-window-down 'isearch-scroll t)
(put 'beginning-of-buffer-other-window 'isearch-scroll t)
(put 'end-of-buffer-other-window 'isearch-scroll t)
(put 'delete-other-windows 'isearch-scroll t)
(put 'balance-windows 'isearch-scroll t)
(put 'split-window-vertically 'isearch-scroll t)
(put 'split-window-horizontally 'isearch-scroll t)
(put 'enlarge-window 'isearch-scroll t)
(put 'universal-argument 'isearch-scroll t)
(put 'negative-argument 'isearch-scroll t)
(put 'digit-argument 'isearch-scroll t)
(defcustom isearch-allow-scroll nil
"If non-nil, scrolling commands are allowed during incremental search."
:type 'boolean
:group 'isearch)
(defun isearch-string-out-of-window (isearch-point)
"Test whether the search string is currently outside of the window.
Return nil if it's completely visible, or if point is visible,
together with as much of the search string as will fit; the symbol
`above' if we need to scroll the text downwards; the symbol `below',
if upwards."
(let ((w-start (window-start))
(w-end (window-end nil t))
(w-L1 (save-excursion (move-to-window-line 1) (point)))
(w-L-1 (save-excursion (move-to-window-line -1) (point)))
start end) (if isearch-forward
(setq end isearch-point start (or isearch-other-end isearch-point))
(setq start isearch-point end (or isearch-other-end isearch-point)))
(cond ((or (and (>= start w-start) (<= end w-end))
(if isearch-forward
(and (>= isearch-point w-L-1) (< isearch-point w-end)) (and (>= isearch-point w-start) (< isearch-point w-L1)))) nil)
((and (< start w-start)
(< isearch-point w-L-1))
'above)
(t 'below))))
(defun isearch-back-into-window (above isearch-point)
"Scroll the window to bring the search string back into view.
Restore point to ISEARCH-POINT in the process. ABOVE is t when the
search string is above the top of the window, nil when it is beneath
the bottom."
(let (start end)
(if isearch-forward
(setq end isearch-point start (or isearch-other-end isearch-point))
(setq start isearch-point end (or isearch-other-end isearch-point)))
(if above
(progn
(goto-char start)
(recenter 0)
(when (>= isearch-point (window-end nil t))
(goto-char isearch-point)
(recenter -1)))
(goto-char end)
(recenter -1)
(when (< isearch-point (window-start))
(goto-char isearch-point)
(recenter 0))))
(goto-char isearch-point))
(defun isearch-reread-key-sequence-naturally (keylist)
"Reread key sequence KEYLIST with Isearch mode's keymap deactivated.
Return the key sequence as a string/vector."
(isearch-unread-key-sequence keylist)
(let (overriding-terminal-local-map)
(read-key-sequence nil)))
(defun isearch-lookup-scroll-key (key-seq)
"If KEY-SEQ is bound to a scrolling command, return it as a symbol.
Otherwise return nil."
(let* ((overriding-terminal-local-map nil)
(binding (key-binding key-seq)))
(and binding (symbolp binding) (commandp binding)
(eq (get binding 'isearch-scroll) t)
binding)))
(defalias 'isearch-other-control-char 'isearch-other-meta-char)
(defun isearch-other-meta-char (&optional arg)
"Process a miscellaneous key sequence in Isearch mode.
Try to convert the current key-sequence to something usable in Isearch
mode, either by converting it with `function-key-map', downcasing a
key with C-<upper case>, or finding a \"scrolling command\" bound to
it. \(In the last case, we may have to read more events.) If so,
either unread the converted sequence or execute the command.
Otherwise, if `search-exit-option' is non-nil (the default) unread the
key-sequence and exit the search normally. If it is the symbol
`edit', the search string is edited in the minibuffer and the meta
character is unread so that it applies to editing the string.
ARG is the prefix argument. It will be transmitted through to the
scrolling command or to the command whose key-sequence exits
Isearch mode."
(interactive "P")
(let* ((key (if current-prefix-arg (substring (this-command-keys) universal-argument-num-events)
(this-command-keys)))
(main-event (aref key 0))
(keylist (listify-key-sequence key))
scroll-command isearch-point)
(cond ((and (= (length key) 1)
(let ((lookup (lookup-key function-key-map key)))
(not (or (null lookup) (integerp lookup)
(keymapp lookup)))))
(cancel-kbd-macro-events)
(if (lookup-key global-map key)
(progn
(isearch-done)
(apply 'isearch-unread keylist))
(setq keylist
(listify-key-sequence (lookup-key function-key-map key)))
(while keylist
(setq key (car keylist))
(if (and (integerp key)
(>= key ?\s) (/= key 127) (< key 256))
(progn
(isearch-process-search-char key)
(setq keylist (cdr keylist)))
(apply 'isearch-unread keylist)
(setq keylist nil)))))
(
(let ((mods (event-modifiers main-event)))
(and (integerp main-event)
(memq 'shift mods)
(memq 'control mods)
(not (memq (lookup-key isearch-mode-map
(let ((copy (copy-sequence key)))
(aset copy 0
(- main-event
(- ?\C-\S-a ?\C-a)))
copy)
nil)
'(nil
isearch-other-control-char)))))
(setcar keylist (- main-event (- ?\C-\S-a ?\C-a)))
(cancel-kbd-macro-events)
(apply 'isearch-unread keylist))
((eq search-exit-option 'edit)
(apply 'isearch-unread keylist)
(isearch-edit-string))
((and isearch-allow-scroll
(progn (setq key (isearch-reread-key-sequence-naturally keylist))
(setq keylist (listify-key-sequence key))
(setq main-event (aref key 0))
(setq scroll-command (isearch-lookup-scroll-key key))))
(setq isearch-point (point))
(setq prefix-arg arg)
(command-execute scroll-command)
(let ((ab-bel (isearch-string-out-of-window isearch-point)))
(if ab-bel
(isearch-back-into-window (eq ab-bel 'above) isearch-point)
(goto-char isearch-point)))
(isearch-update))
(search-exit-option
(let (window)
(isearch-unread-key-sequence keylist)
(setq main-event (car unread-command-events))
(if (and (not isearch-mode)
(listp main-event)
(setq window (posn-window (event-start main-event)))
(windowp window)
(or (> (minibuffer-depth) 0)
(not (window-minibuffer-p window))))
(save-excursion
(set-buffer (window-buffer window))
(isearch-done)
(isearch-clean-overlays))
(isearch-done)
(isearch-clean-overlays)
(setq prefix-arg arg))))
(t (isearch-process-search-string key key)))))
(defun isearch-quote-char ()
"Quote special characters for incremental search."
(interactive)
(let ((char (read-quoted-char (isearch-message t))))
(if (and isearch-regexp (= char ?\s))
(if (subregexp-context-p isearch-string (length isearch-string))
(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."
(interactive)
(isearch-process-search-char ?\n))
(make-obsolete 'isearch-return-char 'isearch-printing-char)
(defun isearch-printing-char ()
"Add this ordinary printing character to the search string and search."
(interactive)
(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)))))
(defun isearch-process-search-char (char)
(cond
((memq char '(?* ??)) (isearch-fallback nil))
((eq char ?\}) (isearch-fallback t t))
((eq char ?|) (isearch-fallback t nil t)))
(isearch-process-search-string
(char-to-string char)
(if (>= char ?\200)
(char-to-string char)
(isearch-text-char-description char))))
(defun isearch-process-search-string (string message)
(setq isearch-string (concat isearch-string string)
isearch-message (concat isearch-message message))
(isearch-search-and-update))
(defun isearch-ring-adjust1 (advance)
(let* ((ring (if isearch-regexp regexp-search-ring search-ring))
(length (length ring))
(yank-pointer-name (if isearch-regexp
'regexp-search-ring-yank-pointer
'search-ring-yank-pointer))
(yank-pointer (eval yank-pointer-name)))
(if (zerop length)
()
(set yank-pointer-name
(setq yank-pointer
(mod (+ (or yank-pointer 0)
(if advance -1 1))
length)))
(setq isearch-string (nth yank-pointer ring)
isearch-message (mapconcat 'isearch-text-char-description
isearch-string "")))))
(defun isearch-ring-adjust (advance)
(isearch-ring-adjust1 advance)
(if search-ring-update
(progn
(isearch-search)
(isearch-update))
(isearch-edit-string)
)
(isearch-push-state))
(defun isearch-ring-advance ()
"Advance to the next search string in the ring."
(interactive)
(isearch-ring-adjust 'advance))
(defun isearch-ring-retreat ()
"Retreat to the previous search string in the ring."
(interactive)
(isearch-ring-adjust nil))
(defun isearch-complete1 ()
(let* ((ring (if isearch-regexp regexp-search-ring search-ring))
(completion-ignore-case case-fold-search)
(completion (try-completion isearch-string ring)))
(cond
((eq completion t)
t)
((or completion (= 0 (length isearch-string))) (if (equal completion isearch-string) (progn
(if completion-auto-help
(with-output-to-temp-buffer "*Isearch completions*"
(display-completion-list
(all-completions isearch-string ring))))
t)
(and completion
(setq isearch-string completion))))
(t
(message "No completion") nil))))
(defun isearch-complete ()
"Complete the search string from the strings on the search ring.
The completed string is then editable in the minibuffer.
If there is no completion possible, say so and continue searching."
(interactive)
(if (isearch-complete1)
(progn (setq isearch-message
(mapconcat 'isearch-text-char-description
isearch-string ""))
(isearch-edit-string))
(sit-for 1)
(isearch-update)))
(defun isearch-complete-edit ()
"Same as `isearch-complete' except in the minibuffer."
(interactive)
(setq isearch-string (field-string))
(if (isearch-complete1)
(progn
(delete-field)
(insert isearch-string))))
(defun isearch-message (&optional c-q-hack ellipsis)
(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)))))
(defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
(and isearch-error ellipsis
(condition-case ()
(progn (re-search-forward isearch-string (point) t)
(setq isearch-error nil))
(error nil)))
(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)))
"over")
(if isearch-wrapped "wrapped ")
(if isearch-word "word " "")
(if isearch-regexp "regexp " "")
(if nonincremental "search" "I-search")
(if isearch-forward "" " backward")
(if current-input-method
(concat " [" current-input-method-title "]: ")
": ")
)))
(propertize (concat (upcase (substring m 0 1)) (substring m 1))
'face 'minibuffer-prompt)))
(defun isearch-message-suffix (&optional c-q-hack ellipsis)
(concat (if c-q-hack "^Q" "")
(if isearch-error
(concat " [" isearch-error "]")
"")))
(defvar isearch-search-fun-function nil
"Override `isearch-search-fun'.
This function should return the search function for isearch to use.
It will call this function with three arguments
as if it were `search-forward'.")
(defun isearch-search-fun ()
"Return the function to use for the search.
Can be changed via `isearch-search-fun-function' for special needs."
(if isearch-search-fun-function
(funcall isearch-search-fun-function)
(cond
(isearch-word
(if isearch-forward 'word-search-forward 'word-search-backward))
(isearch-regexp
(if isearch-forward 're-search-forward 're-search-backward))
(t
(if isearch-forward 'search-forward 'search-backward)))))
(defun isearch-search-string (string bound noerror)
(let ((func (isearch-search-fun))
(len (length string))
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))))
(when translated
(save-match-data
(save-excursion
(if (setq pos2 (funcall func translated bound noerror))
(setq match-data (match-data t)))))
(when (and pos2
(or (not pos1)
(if isearch-forward (< pos2 pos1) (> pos2 pos1))))
(setq pos1 pos2)
(set-match-data match-data)))))
(if pos1
(goto-char pos1))
pos1))
(defun isearch-search ()
(isearch-message nil t)
(if (and (eq isearch-case-fold-search t) search-upper-case)
(setq isearch-case-fold-search
(isearch-no-upper-case-p isearch-string isearch-regexp)))
(condition-case lossage
(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))
(setq isearch-error nil)
(while retry
(setq isearch-success
(isearch-search-string isearch-string nil t))
(if (or (eq search-invisible t)
(not isearch-success)
(bobp) (eobp)
(= (match-beginning 0) (match-end 0))
(not (isearch-range-invisible
(match-beginning 0) (match-end 0))))
(setq retry nil)))
(setq isearch-just-started nil)
(if isearch-success
(setq isearch-other-end
(if isearch-forward (match-beginning 0) (match-end 0)))))
(quit (isearch-unread ?\C-g)
(setq isearch-success nil))
(invalid-regexp
(setq isearch-error (car (cdr lossage)))
(if (string-match
"\\`Premature \\|\\`Unmatched \\|\\`Invalid "
isearch-error)
(setq isearch-error "incomplete input")))
(search-failed
(setq isearch-success nil)
(setq isearch-error (nth 2 lossage)))
(error
(setq isearch-error (format "%s" lossage))))
(if isearch-success
nil
(and (isearch-success-state (car isearch-cmds))
(ding))
(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)))))
(defun isearch-open-overlay-temporary (ov)
(if (not (null (overlay-get ov 'isearch-open-invisible-temporary)))
(funcall (overlay-get ov 'isearch-open-invisible-temporary) ov nil)
(overlay-put ov 'isearch-invisible (overlay-get ov 'invisible))
(overlay-put ov 'isearch-intangible (overlay-get ov 'intangible))
(overlay-put ov 'invisible nil)
(overlay-put ov 'intangible nil)))
(defun isearch-open-necessary-overlays (ov)
(let ((inside-overlay (and (> (point) (overlay-start ov))
(< (point) (overlay-end ov))))
(fct-temp (overlay-get ov 'isearch-open-invisible-temporary)))
(when (or inside-overlay (not fct-temp))
(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))
(if inside-overlay
(funcall (overlay-get ov 'isearch-open-invisible) ov)
(if fct-temp
(funcall fct-temp ov t)))))
(defun isearch-clean-overlays ()
(when isearch-opened-overlays
(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))))
(defun isearch-close-unnecessary-overlays (begin end)
(let ((overlays isearch-opened-overlays))
(setq isearch-opened-overlays 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
(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."
(when (/= beg end)
(save-excursion
(goto-char beg)
(let ( (can-be-opened (eq search-invisible 'open))
(crt-overlays nil))
(when (and can-be-opened isearch-hide-immediately)
(isearch-close-unnecessary-overlays beg end))
(while (and (< (point) end)
(let ((prop
(get-char-property (point) 'invisible)))
(if (eq buffer-invisibility-spec t)
prop
(or (memq prop buffer-invisibility-spec)
(assq prop buffer-invisibility-spec)))))
(if (get-text-property (point) 'invisible)
(progn
(goto-char (next-single-property-change (point) 'invisible
nil end))
(setq can-be-opened nil))
(when can-be-opened
(let ((overlays (overlays-at (point)))
ov-list
o
invis-prop)
(while overlays
(setq o (car overlays)
invis-prop (overlay-get o 'invisible))
(if (if (eq buffer-invisibility-spec t)
invis-prop
(or (memq invis-prop buffer-invisibility-spec)
(assq invis-prop buffer-invisibility-spec)))
(if (overlay-get o 'isearch-open-invisible)
(setq ov-list (cons o ov-list))
(setq can-be-opened nil)))
(setq overlays (cdr overlays)))
(if can-be-opened
(setq crt-overlays (append ov-list crt-overlays)))))
(goto-char (next-overlay-change (point)))))
(if (>= (point) end)
(if (and can-be-opened (consp crt-overlays))
(progn
(setq isearch-opened-overlays
(append isearch-opened-overlays crt-overlays))
(mapc 'isearch-open-overlay-temporary crt-overlays)
nil)
(setq isearch-hidden t)))))))
(defun isearch-no-upper-case-p (string regexp-flag)
"Return t if there are no upper case chars in STRING.
If REGEXP-FLAG is non-nil, disregard letters preceded by `\\' (but not `\\\\')
since they have special meaning in a regexp."
(let (quote-flag (i 0) (len (length string)) found)
(while (and (not found) (< i len))
(let ((char (aref string i)))
(if (and regexp-flag (eq char ?\\))
(setq quote-flag (not quote-flag))
(if (and (not quote-flag) (not (eq char (downcase char))))
(setq found t))
(setq quote-flag nil)))
(setq i (1+ i)))
(not (or found
(and regexp-flag (string-match "\\[:\\(upp\\|low\\)er:]" string)
(condition-case err
(progn
(string-match (substring string 0 (match-beginning 0))
"")
nil)
(invalid-regexp
(equal "Unmatched [ or [^" (cadr err)))))))))
(defun isearch-text-char-description (c)
(cond
((< c ?\s) (format "^%c" (+ c 64)))
((= c ?\^?) "^?")
(t (char-to-string c))))
(defun isearch-unread (&rest char-or-events)
(mapc 'store-kbd-macro-event char-or-events)
(setq unread-command-events
(append char-or-events unread-command-events)))
(defvar isearch-overlay nil)
(defun isearch-highlight (beg end)
(if search-highlight
(if isearch-overlay
(move-overlay isearch-overlay beg end (current-buffer))
(setq isearch-overlay (make-overlay beg end))
(overlay-put isearch-overlay 'priority 1001)
(overlay-put isearch-overlay 'face isearch))))
(defun isearch-dehighlight ()
(when isearch-overlay
(delete-overlay isearch-overlay)))
(defvar isearch-lazy-highlight-overlays nil)
(defvar isearch-lazy-highlight-wrapped nil)
(defvar isearch-lazy-highlight-start-limit nil)
(defvar isearch-lazy-highlight-end-limit 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)
(defvar isearch-lazy-highlight-window nil)
(defvar isearch-lazy-highlight-window-start nil)
(defvar isearch-lazy-highlight-window-end nil)
(defvar isearch-lazy-highlight-case-fold-search nil)
(defvar isearch-lazy-highlight-regexp nil)
(defvar isearch-lazy-highlight-space-regexp nil)
(defun lazy-highlight-cleanup (&optional force)
"Stop lazy highlighting and remove extra highlighting from current buffer.
FORCE non-nil means do it whether or not `lazy-highlight-cleanup'
is nil. This function is called when exiting an incremental search if
`lazy-highlight-cleanup' is non-nil."
(interactive '(t))
(if (or force 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)))
(define-obsolete-function-alias 'isearch-lazy-highlight-cleanup
'lazy-highlight-cleanup
"22.1")
(defun isearch-lazy-highlight-new-loop (&optional beg end)
"Cleanup any previous `lazy-highlight' loop and begin a new one.
BEG and END specify the bounds within which highlighting should occur.
This is called when `isearch-update' is invoked (which can cause the
search string to change or the window to scroll). It is also used
by other Emacs features."
(when (and (null executing-kbd-macro)
(sit-for 0) (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))
(not (= (window-end) isearch-lazy-highlight-window-end))))
(lazy-highlight-cleanup t) (when (not isearch-error)
(setq isearch-lazy-highlight-start-limit beg
isearch-lazy-highlight-end-limit end)
(setq isearch-lazy-highlight-window (selected-window)
isearch-lazy-highlight-window-start (window-start)
isearch-lazy-highlight-window-end (window-end)
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
isearch-lazy-highlight-space-regexp search-whitespace-regexp)
(unless (equal isearch-string "")
(setq isearch-lazy-highlight-timer
(run-with-idle-timer 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-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))
(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))))
(defun isearch-lazy-highlight-update ()
"Update highlighting of other matches for current search."
(let ((max lazy-highlight-max-at-a-time)
(looping t)
nomore)
(with-local-quit
(save-selected-window
(if (and (window-live-p isearch-lazy-highlight-window)
(not (eq (selected-window) isearch-lazy-highlight-window)))
(select-window isearch-lazy-highlight-window))
(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) (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)))
(let ((ov (make-overlay mb me)))
(push ov isearch-lazy-highlight-overlays)
(overlay-put ov 'priority 1000)
(overlay-put ov 'face lazy-highlight-face)
(overlay-put ov 'window (selected-window))))
(if isearch-forward
(setq isearch-lazy-highlight-end (point))
(setq isearch-lazy-highlight-start (point)))))
(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 (max (or isearch-lazy-highlight-start-limit (point-min))
(window-start))))
(setq isearch-lazy-highlight-start (window-end))
(goto-char (min (or isearch-lazy-highlight-end-limit (point-max))
(window-end))))))))
(unless nomore
(setq isearch-lazy-highlight-timer
(run-at-time lazy-highlight-interval nil
'isearch-lazy-highlight-update)))))))))
(defun isearch-resume (search regexp word forward message case-fold)
"Resume an incremental search.
SEARCH is the string or regexp searched for.
REGEXP non-nil means the resumed search was a regexp search.
WORD non-nil means resume a word search.
FORWARD non-nil means resume a forward search.
MESSAGE is the echo-area message recorded for the search resumed.
CASE-FOLD non-nil means the search was case-insensitive."
(isearch-mode forward regexp nil nil word)
(setq isearch-string search
isearch-message message
isearch-case-fold-search case-fold)
(isearch-search))