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)
This commit is contained in:
Juri Linkov 2019-07-12 00:35:21 +03:00
parent 0b0ed31df9
commit 53fb021acc

View file

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