From b236a2529dd90c9f506243b594e2a0d33afb0946 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 17 Feb 2025 16:46:48 +0800 Subject: [PATCH] Adapt query-replace and lazy highlighting to text conversion * lisp/isearch.el (isearch-lazy-highlight-new-loop): Rather call redisplay to guarantee a valid window-start than sit-for, to account for cases where this function is called from an after-change-function bound to a special input event quickly followed by another event that does not modify the buffer. * lisp/progmodes/prog-mode.el (treesit-node-at): Declare function before references. * lisp/replace.el (perform-replace): When querying, suppress text conversion around the input loop. --- lisp/isearch.el | 5 ++++- lisp/progmodes/prog-mode.el | 2 ++ lisp/replace.el | 19 +++++++++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/lisp/isearch.el b/lisp/isearch.el index 1e65a645a1d..c2e41927f08 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -4098,7 +4098,10 @@ 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) ;make sure (window-start) is credible + ;; This used to read `(sit-for 0)', but that has proved + ;; unreliable when called from within + ;; after-change-functions bound to certain special events. + (redisplay) ;make sure (window-start) is credible (or (not (equal isearch-string isearch-lazy-highlight-last-string)) (not (memq (selected-window) diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el index cdd7765bd7c..77724e04f11 100644 --- a/lisp/progmodes/prog-mode.el +++ b/lisp/progmodes/prog-mode.el @@ -144,6 +144,8 @@ instead." (end (progn (forward-sexp 1) (point)))) (indent-region start end nil)))) +(declare-function treesit-node-at "treesit.c") + (defun prog-fill-reindent-defun (&optional argument) "Refill or reindent the paragraph or defun that contains point. diff --git a/lisp/replace.el b/lisp/replace.el index 3bd803ce347..b1b417b226f 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -2815,6 +2815,8 @@ and END." (<= end (cdr bounds)))) region-bounds))))) +(defvar overriding-text-conversion-style) + (defun perform-replace (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end backward region-noncontiguous-p) @@ -2877,10 +2879,13 @@ characters." (limit nil) (region-filter nil) + ;; Disable text conversion during the replacement operation. + (old-text-conversion-style overriding-text-conversion-style) + overriding-text-conversion-style + ;; Data for the next match. If a cons, it has the same format as ;; (match-data); otherwise it is t if a match is possible at point. (match-again t) - (message (if query-flag (apply #'propertize @@ -2935,6 +2940,10 @@ characters." (push-mark) (undo-boundary) + (when query-flag + (setq overriding-text-conversion-style nil) + (when (fboundp 'set-text-conversion-style) + (set-text-conversion-style text-conversion-style))) (unwind-protect ;; Loop finding occurrences that perhaps should be replaced. (while (and keep-going @@ -3352,7 +3361,13 @@ characters." last-was-act-and-show nil)))))) (replace-dehighlight) (when region-filter - (remove-function isearch-filter-predicate region-filter))) + (remove-function isearch-filter-predicate region-filter)) + (when query-flag + ;; Resume text conversion. + (setq overriding-text-conversion-style + old-text-conversion-style) + (when (fboundp 'set-text-conversion-style) + (set-text-conversion-style text-conversion-style)))) (or unread-command-events (message (ngettext "Replaced %d occurrence%s" "Replaced %d occurrences%s"