10

Classic use-case:

  1. You start recording a macro: C-x (
  2. You do some stuff, let's say hello.
  3. You run a command that throws an error, let's say C-g (e.g. you mistakenly run C-s and you have to cancel that with C-g, now your work is lost).

Now your recording so far is lost.

I would like to resume where I left off before I ran a command which interrupted my recording. I looked at C-h f start-kbd-macro, but it's written in C, so I can't tweak it. I also hunted around for a variable like current-kbd-macro, but found none so far.

Can it be recovered?

Update:

I couldn't figure out why C-u C-x ( wasn't working for me, but I've discovered it's because I was testing with C-g.

It turns out that C-g is special -- if you trigger a different kind of error e.g.

C-x ( M-: (signal 'quit nil) 

Then this will stop the recording, but last-kbd-macro will contain "M-: M-( signal 'quit nil", but with

C-x ( C-g

This stops recording and discards anything recorded. As a C-g-happy user (as are at least two of my friends), this is a rather unfortunate distinction. I tried editing keyboard-quit, but there's nothing I can do in there.

It looks like the only way to recover this is via recent-keys and automatically figuring out where a start-kbd-macro (or similar) was called, as in kmacro-edit-lossage.

4 Answers4

8

I started an implementation here which lets you rebind your C-x ( to resmacro-start-macro.

Now, suppose you get half way through a macro and make a mistake and hit C-g, e.g. you run C-s by mistake and so you hit C-g to cancel it, or w/e.

C-x ( hello C-s C-g 

Now run C-u C-x ( which will prompt in the minibuffer with:

Resume macro with (RET: continue, DEL: remove last): h e l l o C-s

So you hit backspace (DEL) to delete the C-s and then RET to proceed. Now it says:

Appending to kbd macro...

And you can continue.

In total:

C-x (      -- start macro
hello
C-s        -- mistake
C-g        -- cancel mistake (and macro)
C-u C-x (  -- recover lost macro
DEL        -- remove mistake
RET        -- continue recording
world!

Convenient, no context switch, minimum keybindings to achieve task, automatically figures out where your macro started (at C-x () from (recent-keys).

NickD
  • 27,023
  • 3
  • 23
  • 42
  • 1
    Hey, that sounds really nice. Care to submit it as a patch to Emacs? – Stefan Nov 07 '14 at 14:17
  • You're welcome to do so/relicense as you like! I'm going to trial it for a while locally before announcing it anywhere, so that I can know it's reliable. The Emacs maintainers might think it's too hacky, though. ;-) – Christopher Done Nov 07 '14 at 18:12
  • To include it in Emacs we need the author to sign copyright paperwork (the same paperwork would also cover god-mode, of course). – Stefan Nov 07 '14 at 21:12
  • The link is broken now :( – DirtY iCE May 13 '18 at 15:14
2

Execute kmacro-start-macro-or-insert-counter with prefix (C-u) to append to the previous macro.

artagnon
  • 2,237
  • 1
  • 15
  • 17
  • 2
    The docstring doesn't say so, but a double prefix arg (`C-u C-u`) sets *both* the `APPEND` and `NO-EXEC` arguments to `start-kbd-macro`, which lets you append *without* the initial replay of the macro-so-far. This behaviour *is* documented in the manual, however: `(emacs) Basic Keyboard Macro` – phils Nov 07 '14 at 02:42
  • Try this with the example in my question, does not work. – Christopher Done Nov 07 '14 at 13:20
2

Combining the good answers from stsquad and artagnon gives (to my mind) a total solution to the problem which is entirely reasonable:

  • C-xC-keC-hl to edit a macro generated from the lossage
  • edit the macro, to reduce it to the original recording
  • C-cC-c to store the edited macro
  • Either C-u<f3> to firstly replay that macro, and then continue recording subsequent keystrokes which will be appended to the macro definition
  • ...or C-uC-u<f3> to continue recording without the initial replay of the macro-thus-far.

Maybe the need to edit the lossage-as-macro isn't ideal, but (a) you were bound to need to edit the macro regardless, if you aborted the recording, and (b) this shouldn't be happening very often, if you just remember how to stop the macro normally (e.g. with <f4> rather than C-g).

None of which is to say that it wouldn't be useful if the aborted macro was stored somewhere; it's just that I don't think this actually happens. It would probably be worth M-x report-emacs-bug to suggest this feature.

phils
  • 48,657
  • 3
  • 76
  • 115
  • This does not address the problem. With your solution half of the time it would be easier to just start the macro over again. I've posted an answer elsewhere which does solve the problem nicely. – Christopher Done Nov 07 '14 at 13:22
  • 1
    Sure, for simple cases starting over would be easier. It's still useful for the remainder, though, which means some people will find it helpful; especially as it's available by default. As I indicated, I think the idea of a more automated approach is a good one, so I'm happy to see you working on a solution, and have certainly up-voted your answer. – phils Nov 07 '14 at 13:34
0

The canonical solution is C-x C-k C-e (kmacro-edit-macro) which will allow you to step through each key-press and insert/delete whatever you want. The command syntax for the editor is a little terse but ? will bring up a guide. There is a more natural editor bound to C-x C-k e (edit-kbd-macro) which gives a plain text macro editor with commentary.

Another option is M-x insert-kbd-macro which will allow you to edit the macro as Lisp but it's not the most readable thing in the world.

As far as variables are concerned you are looking for last-kbd-macro and kmacro-ring.

As you mention you haven't completed your macro, you can just create it from your lossage. C-x C-k e C-h l and delete up to 300 preceding characters.

itsjeyd
  • 14,586
  • 3
  • 58
  • 87
stsquad
  • 4,626
  • 28
  • 45
  • This is a bad answer I'd downvote if I could. You either didn't read the question or are ignoring it. Neither `last-kbd-macro` nor `kmacro-ring` contain the keys pressed before `C-g` or an error happened. I specifically put INCOMPLETE in all-caps in my title anticipating such bad answers. Thanks for trying to help, though. – Christopher Done Nov 06 '14 at 23:09
  • 1
    @ChristopherDone: sure you can - I've added a note at the bottom to mention the lossage. You can create a macro from up to 300 of your previously typed characters. – stsquad Nov 06 '14 at 23:22
  • Yeah, someone mentioned lossage on #emacs. I just want to resume where I left off. I don't want to have to open the editor and start deleting things from that when I'm in the middle of doing something. – Christopher Done Nov 06 '14 at 23:34
  • 2
    The combination of this and artagnon's answers give a fine solution: `C-x C-k e C-h l`, edit, `C-c C-c`, then `C-u f3` to carry on recording (noting that that last `f3` will firstly *play* the macro-thus-far before awaiting further input). Maybe the need to edit the lossage-as-macro isn't *ideal*, but (a) you were bound to need to edit the macro regardless, if you aborted the recording, and (b) this shouldn't be happening very often, if you just remember how to stop the macro normally. – phils Nov 07 '14 at 02:32
  • 1
    @phils +1 Maybe you should turn that into a separate answer. – itsjeyd Nov 07 '14 at 08:43