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
     )))