I love using macros in Emacs, they help me speed up several tasks in a regular basis. Writing a macro is a relative easy thing to do and a topic for another article.
What I want to talk about today is how and why you could name a macro.
If you don't know what a macro is, the concept is simple, it's a sequence of actions that can be recorded and reused later.
We start recording a macro by hitting C-x (
and then hit C-x )
when finished. Then we can reproduce it by pressing C-x e
(and just e
for consecutive repetitions).
But what if we have two or more distinctive repetitive tasks that we need to perform one after the other? Recording a macro wouldn't be effective here, since we'd be overwriting it over and over and the "record once, use multiple times" effect would be lost… unless…
Naming a macro
Emacs allows us to give a name to a macro by invoking the kmacro-name-last-macro
command. Then we'll be able to access it just as we access any command in Emacs (i.e. M-x
).
Now we can record an action, give it a name, then record another and give it a different name and we'll have it available until the end of our Emacs session.
But… why?
Why would I record a macro and give it a name instead of writing a proper elisp command? Why would I want to lose what I recorded at the end of the session?
Well, a macro is a tool meant for impromptu tasks, tasks that are repeated, but that we won't need later (allegedly).
For example, we'd write a macro if we wanted to convert a list of groceries from a simple text format to an HTML ordered list. This requires going into each line and adding the start and end tags from the ol
. This gets repetitive, but it's something you are not gonna be using in a regular basis.
My use case
But I like to go one step further. A while ago I was presented with an HTML file that contained a very nested list of attributes in an API. I wanted to convert this into a JSON object.
So I created a macro to convert a row into a key-value pair in a different buffer.
This worked for a couple of lines, but early enough I noted a second pattern: some of those rows contained a string for the key, but a separate object for the value, which made me retrace my steps and modify what needed, so I named my first macro and wrote a second one.
And soon enough I found myself writing a third one for the cases where an array was needed as a value.
I had to do this for several files on subsequent days and I found myself hitting M-x kmacro-name-last-macro
repeatedly.
On steroids
So I decided to up my game and wrote a command that, after I define a macro, I can hit M-9
and it'll name the macro for me and ask me to input a character. Say I choose a
, then the next time I hit H-a
, my macro will be run.
Here's the command
(defun fdx/kmacro-name-and-assign (char)
"Name last macro and assign a key combination"
(interactive "c")
(let (
(char-s (char-to-string char))
(macro-name (concat "fdx/last-macro-" (char-to-string char)))
(key (concat "H-" (char-to-string char)))
)
(kmacro-name-last-macro (intern macro-name))
(global-set-key (kbd key) (intern macro-name))
(message key)))
You'd probably be asking yourself "but why marry with the Hyper
key instead of asking for a keybinding" and my answer is that, if you read my article about why I use Hyper
, you'll know that I'm trying to force myself to use it as sort of a wildcard in order not to override default keybindings. This is a completely personal choice, feel free to modify the code above if it's not your preferred approach.
Try it out and save yourselves a great amount of work!
Saluti.