From 53fb021acc9cae6dcfc3cbe2004a070036e5c4e7 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Fri, 12 Jul 2019 00:35:21 +0300 Subject: Better match-data handling in perform-replace * lisp/replace.el (perform-replace): Don't wrap replace-highlight in save-match-data. Use `(nth 0 real-match-data)' instead of `(match-beginning 0)' after replace-highlight. (Bug#36328) --- lisp/replace.el | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/lisp/replace.el b/lisp/replace.el index ab1ff327f6c..7839bed7fb5 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -285,7 +285,7 @@ the original string if not." (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]" to))) (setq to (nreverse (delete "" (cons to list)))) (replace-match-string-symbols to) - (cons 'replace-eval-replacement + (cons #'replace-eval-replacement (if (cdr to) (cons 'concat to) (car to)))) @@ -543,7 +543,7 @@ for Lisp calls." "22.1")) (if (use-region-p) (region-beginning)) (if (use-region-p) (region-end)) (if (use-region-p) (region-noncontiguous-p)))))) - (perform-replace regexp (cons 'replace-eval-replacement to-expr) + (perform-replace regexp (cons #'replace-eval-replacement to-expr) t 'literal delimited nil nil start end nil region-noncontiguous-p)) (defun map-query-replace-regexp (regexp to-strings &optional n start end region-noncontiguous-p) @@ -2471,7 +2471,8 @@ characters." replacements nil)) ((stringp (car replacements)) ; If it isn't a string, it must be a cons (or repeat-count (setq repeat-count 1)) - (setq replacements (cons 'replace-loop-through-replacements + ;; This is a hand-made `iterator'. + (setq replacements (cons #'replace-loop-through-replacements (vector repeat-count repeat-count replacements replacements))))) @@ -2578,14 +2579,10 @@ characters." (if (not query-flag) (progn (unless (or literal noedit) - (save-match-data - ;; replace-highlight calls isearch-lazy-highlight-new-loop - ;; and `sit-for' whose redisplay might clobber match data. - ;; (Bug#36328) - (replace-highlight - (nth 0 real-match-data) (nth 1 real-match-data) - start end search-string - regexp-flag delimited-flag case-fold-search backward))) + (replace-highlight + (nth 0 real-match-data) (nth 1 real-match-data) + start end search-string + regexp-flag delimited-flag case-fold-search backward)) (setq noedit (replace-match-maybe-edit next-replacement nocasify literal @@ -2600,27 +2597,31 @@ characters." ;; Commands not setting `done' need to adjust ;; `real-match-data'. (while (not done) + ;; This sets match-data only for the next hook and + ;; replace-highlight that calls `sit-for' from + ;; isearch-lazy-highlight-new-loop whose redisplay + ;; might clobber match-data. So subsequent code should + ;; use only real-match-data, not match-data (bug#36328). (set-match-data real-match-data) (run-hooks 'replace-update-post-hook) ; Before `replace-highlight'. - (save-match-data - (replace-highlight - (match-beginning 0) (match-end 0) - start end search-string - regexp-flag delimited-flag case-fold-search backward)) + (replace-highlight + (match-beginning 0) (match-end 0) + start end search-string + regexp-flag delimited-flag case-fold-search backward) ;; Obtain the matched groups: needed only when ;; regexp-flag non nil. (when (and last-was-undo regexp-flag) (setq last-was-undo nil real-match-data (save-excursion - (goto-char (match-beginning 0)) + (goto-char (nth 0 real-match-data)) (looking-at search-string) (match-data t real-match-data)))) ;; Matched string and next-replacement-replaced ;; stored in stack. (setq search-string-replaced (buffer-substring-no-properties - (match-beginning 0) - (match-end 0)) + (nth 0 real-match-data) + (nth 1 real-match-data)) next-replacement-replaced (query-replace-descr (save-match-data -- cgit v1.2.1