Mercurial > emacs
changeset 18433:1de7cef26431
(perform-replace): When matching regexps, if the next match is
adjacent to this one, record the next match before replacing this one.
This fixes a bug where (replace-regexp "\\ba " "c") replaced "a a a "
with "ca c" instead of "ccc".
author | Paul Eggert <eggert@twinsun.com> |
---|---|
date | Tue, 24 Jun 1997 10:48:10 +0000 |
parents | b2bc7438b6b0 |
children | fa88b9cfa8bf |
files | lisp/replace.el |
diffstat | 1 files changed, 38 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/replace.el Tue Jun 24 05:25:09 1997 +0000 +++ b/lisp/replace.el Tue Jun 24 10:48:10 1997 +0000 @@ -576,8 +576,12 @@ (stack nil) (next-rotate-count 0) (replace-count 0) - (lastrepl nil) ;Position after last match considered. + (nonempty-match nil) + + ;; 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 (substitute-command-keys @@ -597,30 +601,37 @@ ;; Loop finding occurrences that perhaps should be replaced. (while (and keep-going (not (eobp)) - (funcall search-function search-string nil t) - ;; If the search string matches immediately after - ;; the previous match, but it did not match there - ;; before the replacement was done, ignore the match. - (if (or (eq lastrepl (point)) - (and regexp-flag - (eq lastrepl (match-beginning 0)) - (not match-again))) - (if (eobp) - nil - ;; Don't replace the null string - ;; right after end of previous replacement. - (forward-char 1) - (funcall search-function search-string nil t)) - t)) + ;; Use the next match if it is already known; + ;; otherwise, search for a match after moving forward + ;; one char if progress is required. + (setq real-match-data + (if (consp match-again) + (progn (goto-char (nth 1 match-again)) + match-again) + (and (or match-again + (progn + (forward-char 1) + (not (eobp)))) + (funcall search-function search-string nil t) + ;; For speed, use only integers and + ;; reuse the list used last time. + (match-data t real-match-data))))) - ;; Save the data associated with the real match. - ;; For speed, use only integers and reuse the list used last time. - (setq real-match-data (match-data t real-match-data)) + ;; Record whether the match is nonempty, to avoid an infinite loop + ;; repeatedly matching the same empty string. + (setq nonempty-match + (/= (nth 0 real-match-data) (nth 1 real-match-data))) - ;; Before we make the replacement, decide whether the search string - ;; can match again just after this match. - (if regexp-flag - (setq match-again (looking-at search-string))) + ;; If the match is empty, record that the next one can't be adjacent. + ;; Otherwise, if matching a regular expression, do the next + ;; match now, since the replacement for this match may + ;; affect whether the next match is adjacent to this one. + (setq match-again + (and nonempty-match + (or (not regexp-flag) + (and (looking-at search-string) + (match-data t))))) + ;; If time for a change, advance to next replacement string. (if (and (listp replacements) (= next-rotate-count replace-count)) @@ -714,8 +725,9 @@ ;; Before we make the replacement, ;; decide whether the search string ;; can match again just after this match. - (if regexp-flag - (setq match-again (looking-at search-string)))) + (if (and regexp-flag nonempty-match) + (setq match-again (and (looking-at search-string) + (match-data t))))) ((eq def 'delete-and-edit) (delete-region (match-beginning 0) (match-end 0)) (store-match-data @@ -738,8 +750,7 @@ (setq stack (cons (cons (point) (or replaced (match-data t))) - stack)))) - (setq lastrepl (point))) + stack))))) (replace-dehighlight)) (or unread-command-events (message "Replaced %d occurrence%s"