How to cancel call-last-kbd-macro in emacs

In emacs, I sometimes call call-last-kbd-macro by mistake. When canceling, I would expect cancellation to cancel the whole effect of the keyboard macro atomically, but this does not happen. Instead, I have to discard every macro step at a time. How can I make emacs return to the buffer state before executing the macro?

+7
undo emacs
source share
2 answers

I'm afraid you cannot do this only with the built-in 'undo mechanism. The macro system in Emacs actually reproduces things as if the user was typing keys (or mouse events), and therefore cancel history ( buffer-undo-list ) is updated as usual.

Here is a suggestion on how to extend the current undo mechanism to do what you want.

  • expand 'undo to understand the new cancel list entry, macro-begin marker and macro-end element

  • report / change macro playback to insert markers at the beginning / end of macro playback

  • undo code treats all undo events between two tokens as one and undoes all of them (and adds the appropriate tokens to the end of undo history, so when you redo things, re still treated as one block)

Cautions:

  • This will only work for macros that work in one buffer, if your macros switched buffers (or had side effects in other buffers), these changes will not be considered as a block.
  • If your macro ended in a different buffer than it ran, you will have to handle this cleanly - you do not want to mark the "unbalanced" macro-begin and macro-end markers in the undo list.

Needless to say, this is a difficult task. I wish you good luck.

+3
source share

This can be done quite easily by overriding the undo-boundary noflet for example with the noflet package.

A macro definition (generated by insert-kbd-macro ) is given as follows:

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

or:

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

Edit it like this:

 (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))) 

If you do not want to edit all macro definitions, you can alternatively add a shell that calls the macro specified as an argument, creating / suppressing undo borders, as described above.

0
source share

All Articles