1

I have an ancient function I've been using for decades which performs a regexp replacement in a region:

(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 (not case-replace) nil)))))

However, in recent emacs versions this function has started to fail with the message "Match data clobbered by buffer modification hooks".

I believe this can be fixed with judicious use of (save-match-data ...), but that doesn't seem to work for me.

How can this function be fixed?

4
  • emacs.stackexchange.com/tags/elisp/info
    – Drew
    Jun 18, 2021 at 3:46
  • There have been upstream "Match data clobbered by buffer modification hooks" bugs in the past. Your issue might have been an Emacs bug, and potentially now fixed. Which version of Emacs was this? Are you able to test with a newer one?
    – phils
    Nov 15, 2021 at 10:38
  • emacs version 27.1 Nov 16, 2021 at 22:17
  • Try to let-bin before-change-functions and after-change-functions to nil in your function. That way, the faulty hook isn't runed. (Of course, if could be a good idea to fid the culprit, which should be relative straight-forward once you found which hook variable it has attached itself to.) Mar 15 at 15:12

1 Answer 1

0

Why not just use the built–in replace-regexp function? It operates on the region, if one is active.

5
  • Consider explaining or showing how it specifically answers the question, to make the answer more useful.
    – Drew
    Jun 18, 2021 at 3:47
  • You mean mentioning that it’s completely bullet–proof? That it’s 550 lines long and calls save-match-data in two places and set-match-data in seven? Or that it would take a book to explain how it works so that he can update his own implementation?
    – db48x
    Jun 18, 2021 at 5:25
  • replace-regexp seems to lose the region after the replace, making multiple replacements upon the one region quite difficult. Jun 19, 2021 at 0:40
  • It deactivates the region, but it doesn’t “lose” it. The region is bounded on one end by the mark, and on the other by the point. You can use exchange-point-and-mark to reactivate the region (it is bound to C-x C-x by default). However, I suppose it is true that replace-regexp does not leave the point exactly where it was before you ran it; it places the point at the end of the last replacement. You may need to move the point back to the end of your region before using C-x C-x.
    – db48x
    Jun 19, 2021 at 1:57
  • I have to say that the code shown in the question does not look remotely problematic to me. Everything in that function is incredibly normal -- it's pretty much the canonical example of a search and replace in a region. The standard command ought to work of course, but I don't think the custom one ought to be failing.
    – phils
    Nov 15, 2021 at 10:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.