Function: replace-preview-setup

replace-preview-setup is a byte-compiled function defined in replace.el.gz.

Signature

(replace-preview-setup FROM REGEXP-FLAG DELIMITED-FLAG)

Documentation

Return a closure that previews the replacement of FROM.

Add it to minibuffer-setup-hook while reading the replacement text: on every change it shows, in the original window, how the visible matches of FROM would look after the replacement. REGEXP-FLAG and DELIMITED-FLAG say how to search for FROM, as in replace-search.

Source Code

;; Defined in /usr/src/emacs/lisp/replace.el.gz
(defun replace-preview-setup (from regexp-flag delimited-flag)
  "Return a closure that previews the replacement of FROM.
Add it to `minibuffer-setup-hook' while reading the replacement text:
on every change it shows, in the original window, how the visible
matches of FROM would look after the replacement.
REGEXP-FLAG and DELIMITED-FLAG say how to search for FROM, as in
`replace-search'."
  (if (or (not query-replace-show-preview) (minibufferp))
      #'ignore
    (let ((unwind (make-symbol "replace-preview--unwind"))
	  (after-change (make-symbol "replace-preview--after-change"))
	  (buffer (current-buffer))
	  (case-fold (if (and case-fold-search search-upper-case)
			 (isearch-no-upper-case-p from regexp-flag)
		       case-fold-search))
	  (region-filter (when (use-region-p)
			   (replace--region-filter
			    (funcall region-extract-function 'bounds)))))
      (fset unwind
	    (lambda ()
	      (remove-hook 'after-change-functions after-change t)
	      (remove-hook 'minibuffer-exit-hook unwind t)
	      (when (buffer-live-p buffer)
		(with-current-buffer buffer
		  (when region-filter
		    (remove-function (local 'isearch-filter-predicate)
				     region-filter))
		  (replace-preview-cleanup)))))
      (fset after-change
	    (lambda (_beg _end _len)
	      (let ((to (minibuffer-contents-no-properties)))
		(with-minibuffer-selected-window
		  ;; The replacement text is typed one character at a
		  ;; time, so it's expected to be invalid meanwhile,
		  ;; e.g. when it ends with a backslash or refers to a
		  ;; group that the regexp doesn't have.
		  (condition-case nil
		      (if (and regexp-flag
			       (string-match
				query-replace-eval-replacement-regexp to))
			  ;; Neither \, nor \# can be previewed, for
			  ;; different reasons.  \, is a Lisp expression
			  ;; that the user is still typing: evaluating it
			  ;; on each keystroke would run the side effects
			  ;; of a half-typed form as soon as it happens
			  ;; to be readable.  \# expands to the number of
			  ;; replacements made so far, and none has been
			  ;; made yet, so the preview would show 0 for
			  ;; every match where the replacement itself
			  ;; will show 0, 1, 2...
			  (replace-preview-cleanup)
			(replace-preview-update from to regexp-flag
						delimited-flag case-fold))
		    (error (replace-preview-cleanup)))))))
      (lambda ()
	(add-hook 'minibuffer-exit-hook unwind nil t)
	(add-hook 'after-change-functions after-change nil t)
	(when region-filter
	  (with-current-buffer buffer
	    (add-function :after-while (local 'isearch-filter-predicate)
			  region-filter)))
	(funcall after-change nil nil nil)))))