diff options
author | Paul Eggert <eggert@twinsun.com> | 1997-06-24 10:48:10 +0000 |
---|---|---|
committer | Paul Eggert <eggert@twinsun.com> | 1997-06-24 10:48:10 +0000 |
commit | 5632eb272c7efcd57cb42120fac9ad077c78e42e (patch) | |
tree | e8f600b50e77d61da7c4acd5fb80b6bf21e4f01e /lisp/replace.el | |
parent | 6f0e09d4d05ac66aa11e5fccb8f24eb2999ca598 (diff) | |
download | emacs-5632eb272c7efcd57cb42120fac9ad077c78e42e.tar.gz |
(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".
Diffstat (limited to 'lisp/replace.el')
-rw-r--r-- | lisp/replace.el | 69 |
1 files changed, 40 insertions, 29 deletions
diff --git a/lisp/replace.el b/lisp/replace.el index 99e8921a26c..2f3fb9a6fe6 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -576,8 +576,12 @@ which will run faster and probably do exactly what you want." (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 @@ which will run faster and probably do exactly what you want." ;; 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)) - - ;; 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)) - - ;; 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))) + ;; 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))))) + + ;; 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))) + + ;; 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 @@ which will run faster and probably do exactly what you want." ;; 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 @@ which will run faster and probably do exactly what you want." (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" |