regexemacsregionaquamacs

"re-replace-region: Match data clobbered by buffer modification hooks"


After upgrading to Aquamacs Version 3.3 (emacs 25.1.1), I'm getting the error mentioned in the title when running re-replace-region (as defined below), trying to change a string of 9s in a region (e.g. "99" or "999") to 0s. I've never had this problem with prior versions of Aquamacs (or emacs generally), and there is nothing I can think of, either in the emacs environment or the machine environment generally (Mac OS 10.9.5), that might be associated with the problem.

In fact, I have an emacs executable (version 22.1.1) on the same machine, and after invoking it in the same environment (e.g., same ~/.emacs etc), re-replace-region works as it should.

The only other clue I can offer is that when running re-replace-region on a region with say three 9s (999) in it, trying to change 9 to 0, the first 9 is altered before the error condition is raised.

Here is the defun:

;;; RE-REPLACE-REGION replaces OLD (a regular expression) with NEW
;;; throughout the region indicated by BEGIN and END.
;;; For example, to insert a prefix ">" at the beginning of each line
;;; in the region:
;;;   M-x re-replace-regionRET^RET>RET
;;; I don't know who wrote this function!
(defun re-replace-region (begin end old new)
"Replace occurrences of REGEXP with TO-STRING in region."
  (interactive "*r\nsReplace string: \nswith: ")
  (save-excursion
    (save-restriction
      (narrow-to-region begin end)
      (goto-char (point-min))
      (while (re-search-forward old (point-max) t)
        (replace-match new nil nil)))))

Solution

  • The problem seems to arise because the variable before-change-functions is (aquamacs-undo--rec-region-when-buffer-changes) in the affected buffers.

    A simple workaround is to use replace-regexp instead of re-replace-region. Indeed, it's better than a mere workaround, because when used as intended (i.e., when used interactively), replace-regexp is called as follows:

     (replace-regexp REGEX TOSTRING nil
       (if (use-region-p) (region-beginning)) 
       (if (use-region-p) (region-end)) nil)
    

    That is, if a region is defined, replace-regexp only affects the region -- which is of course the rationale for re-replace-region in the first place.

    I'd still be interested to know more about (aquamacs-undo--rec-region-when-buffer-changes). Meanwhile, thanks especially to @phils.