"re-replace-region: Match data clobbered by buffer modification hooks"
"re-replace-region: Match data clobbered by buffer modification hooks"
升级到 Aquamacs 版本 3.3 (emacs 25.1.1) 后,我在 运行 re-replace-region
(定义如下)时收到标题中提到的错误,试图更改字符串一个区域中的 9(例如“99”或“999”)到 0。我以前的 Aquamacs 版本(或一般的 emacs)从来没有遇到过这个问题,而且我也没有想到,无论是在 emacs 环境还是一般的机器环境(Mac OS 10.9. 5),这可能与问题有关。
事实上,我在同一台机器上有一个 emacs 可执行文件(版本 22.1.1),在同一环境(例如,相同的 ~/.emacs 等)中调用它后,re-replace-region
的工作方式如下应该。
我能提供的唯一其他线索是,当 运行 re-replace-region 在其中包含三个 9 (999) 的区域上时,尝试将 9 更改为 0,前 9 被更改在引发错误条件之前。
这是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)))))
我可以告诉你这个错误消息是在 2016 年 7 月引入的,这解释了为什么旧版本的 Emacs 没有引发它:
commit 3a9d6296b35e5317c497674d5725eb52699bd3b8
Author: Eli Zaretskii
Date: Mon Jul 4 18:34:40 2016 +0300
Avoid crashes when buffer modification hooks clobber match data
* src/search.c (Freplace_match): Error out if buffer modification
hooks triggered by buffer changes in replace_range, upcase-region,
and upcase-initials-region clobber the match data needed to be
adjusted for the replacement. (Bug#23869)
所以我会先假设错误中的信息正确,然后尝试确认。检查 before-change-functions
和 after-change-functions
变量的值(在有问题的缓冲区中),并确定列出的函数之一是否负责。
大概其中一个确实破坏了匹配数据,然后应该将其作为相关功能的错误来解决。如果是自定义的,您很可能只需要围绕相关代码包装对 save-match-data
的调用。
问题似乎是因为变量 before-change-functions
在受影响的缓冲区中是 (aquamacs-undo--rec-region-when-buffer-changes)
。
一个简单的解决方法是使用 replace-regexp
而不是 re-replace-region
。事实上,它比单纯的解决方法要好,因为当按预期使用时(即,当交互使用时),replace-regexp
被调用如下:
(replace-regexp REGEX TOSTRING nil
(if (use-region-p) (region-beginning))
(if (use-region-p) (region-end)) nil)
也就是说,如果定义了一个区域,replace-regexp
只会影响该区域——当然这首先是 re-replace-region
的基本原理。
我仍然有兴趣了解更多关于 (aquamacs-undo--rec-region-when-buffer-changes)
的信息。同时,特别感谢@phils。
升级到 Aquamacs 版本 3.3 (emacs 25.1.1) 后,我在 运行 re-replace-region
(定义如下)时收到标题中提到的错误,试图更改字符串一个区域中的 9(例如“99”或“999”)到 0。我以前的 Aquamacs 版本(或一般的 emacs)从来没有遇到过这个问题,而且我也没有想到,无论是在 emacs 环境还是一般的机器环境(Mac OS 10.9. 5),这可能与问题有关。
事实上,我在同一台机器上有一个 emacs 可执行文件(版本 22.1.1),在同一环境(例如,相同的 ~/.emacs 等)中调用它后,re-replace-region
的工作方式如下应该。
我能提供的唯一其他线索是,当 运行 re-replace-region 在其中包含三个 9 (999) 的区域上时,尝试将 9 更改为 0,前 9 被更改在引发错误条件之前。
这是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)))))
我可以告诉你这个错误消息是在 2016 年 7 月引入的,这解释了为什么旧版本的 Emacs 没有引发它:
commit 3a9d6296b35e5317c497674d5725eb52699bd3b8
Author: Eli Zaretskii
Date: Mon Jul 4 18:34:40 2016 +0300
Avoid crashes when buffer modification hooks clobber match data
* src/search.c (Freplace_match): Error out if buffer modification
hooks triggered by buffer changes in replace_range, upcase-region,
and upcase-initials-region clobber the match data needed to be
adjusted for the replacement. (Bug#23869)
所以我会先假设错误中的信息正确,然后尝试确认。检查 before-change-functions
和 after-change-functions
变量的值(在有问题的缓冲区中),并确定列出的函数之一是否负责。
大概其中一个确实破坏了匹配数据,然后应该将其作为相关功能的错误来解决。如果是自定义的,您很可能只需要围绕相关代码包装对 save-match-data
的调用。
问题似乎是因为变量 before-change-functions
在受影响的缓冲区中是 (aquamacs-undo--rec-region-when-buffer-changes)
。
一个简单的解决方法是使用 replace-regexp
而不是 re-replace-region
。事实上,它比单纯的解决方法要好,因为当按预期使用时(即,当交互使用时),replace-regexp
被调用如下:
(replace-regexp REGEX TOSTRING nil
(if (use-region-p) (region-beginning))
(if (use-region-p) (region-end)) nil)
也就是说,如果定义了一个区域,replace-regexp
只会影响该区域——当然这首先是 re-replace-region
的基本原理。
我仍然有兴趣了解更多关于 (aquamacs-undo--rec-region-when-buffer-changes)
的信息。同时,特别感谢@phils。