Function: with-isearch-suspended
with-isearch-suspended is a macro defined in isearch.el.gz.
Signature
(with-isearch-suspended &rest BODY)
Documentation
Exit Isearch mode, run BODY, and reinvoke the pending search.
You can update the global isearch variables by setting new values to
isearch-new-string, isearch-new-message, isearch-new-forward,
isearch-new-regexp-function, isearch-new-case-fold,
isearch-new-nonincremental.
Source Code
;; Defined in /usr/src/emacs/lisp/isearch.el.gz
(defmacro with-isearch-suspended (&rest body)
"Exit Isearch mode, run BODY, and reinvoke the pending search.
You can update the global isearch variables by setting new values to
`isearch-new-string', `isearch-new-message', `isearch-new-forward',
`isearch-new-regexp-function', `isearch-new-case-fold',
`isearch-new-nonincremental'."
;; This code is very hairy for several reasons, explained in the code.
;; Mainly, isearch-mode must be terminated while editing and then restarted.
;; If there were a way to catch any change of buffer from the minibuffer,
;; this could be simplified greatly.
;; Editing doesn't back up the search point. Should it?
`(condition-case nil
(progn
(let ((isearch-new-nonincremental isearch-nonincremental)
;; Locally bind all isearch global variables to protect them
;; from recursive isearching.
;; isearch-string -message and -forward are not bound
;; so they may be changed. Instead, save the values.
(isearch-new-string isearch-string)
(isearch-new-message isearch-message)
(isearch-new-forward isearch-forward)
(isearch-new-regexp-function isearch-regexp-function)
(isearch-new-case-fold isearch-case-fold-search)
(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-match-data isearch-match-data)
(multi-isearch-file-list-new multi-isearch-file-list)
(multi-isearch-buffer-list-new multi-isearch-buffer-list)
(multi-isearch-next-buffer-function multi-isearch-next-buffer-current-function)
(multi-isearch-current-buffer-new multi-isearch-current-buffer)
;;; Don't bind this. We want isearch-search, below, to set it.
;;; And the old value won't matter after that.
;;; (isearch-other-end isearch-other-end)
;;; Perhaps some of these other variables should be bound for a
;;; shorter period, ending before the next isearch-search.
;;; But there doesn't seem to be a real bug, so let's not risk it now.
(isearch-opoint isearch-opoint)
(isearch-slow-terminal-mode isearch-slow-terminal-mode)
(isearch-small-window isearch-small-window)
(isearch-recursive-edit isearch-recursive-edit)
;; Save current configuration so we can restore it here.
(isearch-window-configuration (current-window-configuration))
;; This could protect the index of the search rings,
;; but we can't reliably count the number of typed M-p
;; in `read-from-minibuffer' to adjust the index accordingly.
;; So when the following is commented out, `isearch-mode'
;; below resets the index to the predictable value nil.
;; (search-ring-yank-pointer search-ring-yank-pointer)
;; (regexp-search-ring-yank-pointer regexp-search-ring-yank-pointer)
;; Temporarily restore `minibuffer-message-timeout'.
(minibuffer-message-timeout
isearch-original-minibuffer-message-timeout)
(isearch-original-minibuffer-message-timeout
isearch-original-minibuffer-message-timeout)
old-point old-other-end)
(setq isearch-suspended t)
;; Actually terminate isearching until editing is done.
;; This is so that the user can do anything without failure,
;; like switch buffers and start another isearch, and return.
(condition-case nil
(isearch-done t t)
(exit nil)) ; was recursive editing
;; Save old point and isearch-other-end before reading from minibuffer
;; that can change their values.
(setq old-point (point) old-other-end isearch-other-end)
(unwind-protect
(progn ,@body)
(setq isearch-suspended nil)
;; Always resume isearching by restarting it.
(isearch-mode isearch-forward
isearch-regexp
isearch-op-fun
nil
isearch-regexp-function)
;; Copy new local values to isearch globals
(setq isearch-string isearch-new-string
isearch-message isearch-new-message
isearch-forward isearch-new-forward
isearch-nonincremental isearch-new-nonincremental
isearch-regexp-function isearch-new-regexp-function
isearch-case-fold-search isearch-new-case-fold
multi-isearch-current-buffer multi-isearch-current-buffer-new
multi-isearch-file-list multi-isearch-file-list-new
multi-isearch-buffer-list multi-isearch-buffer-list-new)
(isearch-update-from-string-properties isearch-string)
;; Restore the minibuffer message before moving point.
(funcall (or isearch-message-function #'isearch-message) nil t)
;; Set point at the start (end) of old match if forward (backward),
;; so after exiting minibuffer isearch resumes at the start (end)
;; of this match and can find it again.
(if (and old-other-end (eq old-point (point))
(eq isearch-forward isearch-new-forward))
(goto-char old-other-end)))
;; Empty isearch-string means use default.
(when (= 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 ""))
;; After taking the last element, adjust ring to previous one.
(isearch-ring-adjust1 nil)))
;; 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)
;; If no code has changed the search parameters, then pushing
;; a new state of Isearch should not be necessary.
(unless (and isearch-cmds
(equal (car isearch-cmds) (isearch--get-state)))
(isearch-push-state)) ; this pushes the correct state
(isearch-update)
(if isearch-nonincremental
(progn
;; (sit-for 1) ;; needed if isearch-done does: (message "")
(isearch-done)
;; The search done message is confusing when the string
;; is empty, so erase it.
(if (equal isearch-string "")
(message "")))))
(quit ; handle abort-recursive-edit
(setq isearch-suspended nil)
(isearch-abort) ;; outside of let to restore outside global values
)))