aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/replace.el
diff options
context:
space:
mode:
authorPaul Eggert1997-06-24 10:48:10 +0000
committerPaul Eggert1997-06-24 10:48:10 +0000
commit5632eb272c7efcd57cb42120fac9ad077c78e42e (patch)
treee8f600b50e77d61da7c4acd5fb80b6bf21e4f01e /lisp/replace.el
parent6f0e09d4d05ac66aa11e5fccb8f24eb2999ca598 (diff)
downloademacs-5632eb272c7efcd57cb42120fac9ad077c78e42e.tar.gz
emacs-5632eb272c7efcd57cb42120fac9ad077c78e42e.zip
(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.el69
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."
576 (stack nil) 576 (stack nil)
577 (next-rotate-count 0) 577 (next-rotate-count 0)
578 (replace-count 0) 578 (replace-count 0)
579 (lastrepl nil) ;Position after last match considered. 579 (nonempty-match nil)
580
581 ;; Data for the next match. If a cons, it has the same format as
582 ;; (match-data); otherwise it is t if a match is possible at point.
580 (match-again t) 583 (match-again t)
584
581 (message 585 (message
582 (if query-flag 586 (if query-flag
583 (substitute-command-keys 587 (substitute-command-keys
@@ -597,30 +601,37 @@ which will run faster and probably do exactly what you want."
597 ;; Loop finding occurrences that perhaps should be replaced. 601 ;; Loop finding occurrences that perhaps should be replaced.
598 (while (and keep-going 602 (while (and keep-going
599 (not (eobp)) 603 (not (eobp))
600 (funcall search-function search-string nil t) 604 ;; Use the next match if it is already known;
601 ;; If the search string matches immediately after 605 ;; otherwise, search for a match after moving forward
602 ;; the previous match, but it did not match there 606 ;; one char if progress is required.
603 ;; before the replacement was done, ignore the match. 607 (setq real-match-data
604 (if (or (eq lastrepl (point)) 608 (if (consp match-again)
605 (and regexp-flag 609 (progn (goto-char (nth 1 match-again))
606 (eq lastrepl (match-beginning 0)) 610 match-again)
607 (not match-again))) 611 (and (or match-again
608 (if (eobp) 612 (progn
609 nil 613 (forward-char 1)
610 ;; Don't replace the null string 614 (not (eobp))))
611 ;; right after end of previous replacement. 615 (funcall search-function search-string nil t)
612 (forward-char 1) 616 ;; For speed, use only integers and
613 (funcall search-function search-string nil t)) 617 ;; reuse the list used last time.
614 t)) 618 (match-data t real-match-data)))))
615 619
616 ;; Save the data associated with the real match. 620 ;; Record whether the match is nonempty, to avoid an infinite loop
617 ;; For speed, use only integers and reuse the list used last time. 621 ;; repeatedly matching the same empty string.
618 (setq real-match-data (match-data t real-match-data)) 622 (setq nonempty-match
619 623 (/= (nth 0 real-match-data) (nth 1 real-match-data)))
620 ;; Before we make the replacement, decide whether the search string 624
621 ;; can match again just after this match. 625 ;; If the match is empty, record that the next one can't be adjacent.
622 (if regexp-flag 626 ;; Otherwise, if matching a regular expression, do the next
623 (setq match-again (looking-at search-string))) 627 ;; match now, since the replacement for this match may
628 ;; affect whether the next match is adjacent to this one.
629 (setq match-again
630 (and nonempty-match
631 (or (not regexp-flag)
632 (and (looking-at search-string)
633 (match-data t)))))
634
624 ;; If time for a change, advance to next replacement string. 635 ;; If time for a change, advance to next replacement string.
625 (if (and (listp replacements) 636 (if (and (listp replacements)
626 (= next-rotate-count replace-count)) 637 (= next-rotate-count replace-count))
@@ -714,8 +725,9 @@ which will run faster and probably do exactly what you want."
714 ;; Before we make the replacement, 725 ;; Before we make the replacement,
715 ;; decide whether the search string 726 ;; decide whether the search string
716 ;; can match again just after this match. 727 ;; can match again just after this match.
717 (if regexp-flag 728 (if (and regexp-flag nonempty-match)
718 (setq match-again (looking-at search-string)))) 729 (setq match-again (and (looking-at search-string)
730 (match-data t)))))
719 ((eq def 'delete-and-edit) 731 ((eq def 'delete-and-edit)
720 (delete-region (match-beginning 0) (match-end 0)) 732 (delete-region (match-beginning 0) (match-end 0))
721 (store-match-data 733 (store-match-data
@@ -738,8 +750,7 @@ which will run faster and probably do exactly what you want."
738 (setq stack 750 (setq stack
739 (cons (cons (point) 751 (cons (cons (point)
740 (or replaced (match-data t))) 752 (or replaced (match-data t)))
741 stack)))) 753 stack)))))
742 (setq lastrepl (point)))
743 (replace-dehighlight)) 754 (replace-dehighlight))
744 (or unread-command-events 755 (or unread-command-events
745 (message "Replaced %d occurrence%s" 756 (message "Replaced %d occurrence%s"