【问题标题】:How to undo call-last-kbd-macro in emacs如何撤消 emacs 中的 call-last-kbd-macro
【发布时间】:2011-05-01 10:18:21
【问题描述】:

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

【问题讨论】:

    标签: emacs undo


    【解决方案1】:

    恐怕您不能仅使用内置的'undo 机制来做到这一点。 Emacs 中的宏系统实际上会像用户实际键入击键(或鼠标事件)一样回放事物,因此undo history (buffer-undo-list) 会正常更新。

    这里有一个关于如何扩展当前undo 机制来做你想做的事情的建议。

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

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

    3. undo 代码将两个标记之间的所有撤消事件视为一个单元并将它们全部撤消(并在撤消历史记录的末尾添加适当的标记,因此当您redo 事物时,它们'仍然被视为单个块)

    注意事项:

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

    不用说,这是一项复杂的工作。祝你好运。

    【讨论】:

    • 谢谢特雷。确实是一个复杂的答案。本着同样的精神,一个更简单但更骇人听闻的解决方案是让 call-last-kbd-macro (或包装器)在撤消列表中插入某种无操作标记。然后创建一个新函数 clear-to-macro-marker 将撤消所有更改,直到标记被击中。
    【解决方案2】:

    这可以很容易地通过覆盖 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)))
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-24
      • 1970-01-01
      • 1970-01-01
      • 2012-09-25
      • 2012-05-15
      • 1970-01-01
      • 2011-09-29
      相关资源
      最近更新 更多