undo,save-excursion,delete-region之间的交互

时间:2013-11-12 16:31:21

标签: emacs elisp undo

这是两个删除句子的命令(不保存到kill ring)。第一个基于EmacsWiki Elisp Cookbook的示例,后者与前者类似,只是对save-excursion的调用位于不同的位置。

;; good with undo
(defun my-test-1 ()
  (interactive)
  (delete-region (point)
                 (save-excursion
                   (forward-sentence 1)
                   (point))))

;; bad with undo
(defun my-test-2 ()
  (interactive)
  (save-excursion
    (delete-region (point)
                   (progn
                     (forward-sentence 1)
                     (point)))))

当我运行第一个命令然后撤消它时,点会在正确的位置结束,而第二个命令则不是这样。为什么会出现这种差异?

2 个答案:

答案 0 :(得分:2)

save-excursion仅保存(并尝试恢复)点,标记和当前缓冲区。围绕delete-region这样做是没有意义的。以C编码,delete-region无法跟踪任何事情,AFAIK。不知道undo如何处理它的影响。

一般的经验法则是尽可能在本地使用save-excursion来做你需要做的事情。在这种情况下,您只需要save-excursion隐藏forward-sentence的效果,而不是delete-region的效果。

这可能只是部分解释。要了解更多信息,您可以执行M-x debug-on-entry my-test-N并使用d(和c)逐步调试调试器。这将有助于您了解正在发生的事情。

答案 1 :(得分:1)

命令delete-region记录buffer-undo-list中删除文本时的点位置(请参阅buffer-undo-list的帮助)。

my-test-1中,构造(save-excursion (forward-sentence 1) (point))只返回句子结尾位置,但不会在delete-region命令的范围内移动点。

my-test-2中,当删除发生时,该点移动到句子的末尾。因此,句子结尾位置保存在buffer-undo-list中。只有在那之后旧点位置才会恢复。