如何在emacs中撤消call-last-kbd-macro

时间:2010-10-27 16:26:59

标签: emacs undo

在emacs中,我有时会错误地调用call-last-kbd-macro。在撤消时我会预期撤销以原子方式撤消键盘宏的整个效果,但这不会发生。相反,我发现自己必须一次撤消宏的每一步。如何在执行宏之前让emacs返回缓冲区状态?

2 个答案:

答案 0 :(得分:3)

我担心你只能使用内置的'undo机制来做到这一点。 Emacs中的宏系统实际上回放的东西就像用户实际键入击键(或鼠标事件)一样,因此undo historybuffer-undo-list)正常更新。

以下是如何扩展当前undo机制以执行您想要的操作的建议。

  1. 延长'undo以了解撤消列表中的新条目,macro-begin标记和macro-end元素

  2. 建议/更改宏播放以在宏播放的开头/结尾插入标记

  3. undo代码将两个标记之间的所有撤消事件视为一个整体并将其全部撤消(并在撤消历史记录末尾添加相应的标记,以便redo事情,他们仍然被视为一个单独的块)

  4. 警告:

    • 这仅适用于在单个缓冲区中运行的宏,如果您的宏切换缓冲区(或在其他缓冲区中有副作用),则这些更改不会被视为块。
    • 如果您的宏结束的缓冲区不同于它开始的缓冲区,那么您必须干净利落地处理它 - 您不希望撤消列表中出现“不平衡”macro-beginmacro-end标记。

    毋庸置疑,这是一项复杂的工作。祝你好运。

答案 1 :(得分:1)

例如,可以通过覆盖undo-boundary来轻松完成此操作。 noflet包。

给出如下的宏定义(由insert-kbd-macro生成):

(fset 'my-macro
   [... keys ...])

或:

(fset 'my-macro
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([...keys...] 0 "%d")) arg)))

这样编辑它:

(require 'noflet)

(fset 'my-macro
      (lambda (&optional arg) "Keyboard macro." (interactive "p")
        (undo-boundary)
        (noflet ((undo-boundary ()))
          (kmacro-exec-ring-item (quote ([...keys...] 0 "%d")) arg))
        (undo-boundary)))

如果您不想编辑所有的宏定义,则可以选择添加一个包装器,该包装器调用作为参数指定的宏,同时如上所述创建/抑制撤消边界。