Keyboard Macros: Build custom commands with the Emacs Command Language


Have you ever been in a situation where you repeat the same sequence of commands over and over again.   Then  Keyboard Macros are for you.

Using Keyboard Macros you can build complex commands that fit your specific needs and you can do this without any iota of proficiency with the Emacs Lisp programming language.

A simple and stupid Usecase: Insert a Horizontal Line

For the sake of this article, let us pretend that you are in the habit of collecting  memorable quotes and you separate the quotes in your file with a horizontal line.  Here is a sample of your fortune file, say fortune.txt:

You are dishonest, but never to the point of hurting a friend.
--------------------------------------------------------------------------------
Be careful! UGLY strikes 9 out of 10!
--------------------------------------------------------------------------------
They have been at a great feast of languages, and stolen the scraps.
 -- William Shakespeare, "Love's Labour's Lost"
--------------------------------------------------------------------------------
Living your life is a task so difficult, it has never been attempted before.
--------------------------------------------------------------------------------
Q: How many Bell Labs Vice Presidents does it take to change a light bulb?
A: That's proprietary information. Answer available from AT&T on payment
 of license fee (binary only).
--------------------------------------------------------------------------------
"You have been in Afghanistan, I perceive."
 -- Sir Arthur Conan Doyle, "A Study in Scarlet"
--------------------------------------------------------------------------------

You love collecting the quotes, but you hate typing out all those 80 hyphen characters.   You now have a repetitive task and  you want to automate this task by programming your Emacs.   You can accomplish this using  Keyboard Macros.

Preparatory Step: Add Macro commands to Menu

The stock Emacs doesn’t come with a menu for recording and re-playing keyboard macros.  As a preparatory step, we will create this menu.

Copy the snippet below to your .emacs, and restart your Emacs.

(easy-menu-define kmacro-menu nil
 "Keyboard Macro Menu."
 '("Keyboard Macro"
 ["Universal Argument" universal-argument :help "Begin a numeric argument for the following command."]
 "--"
 ["Start Macro" kmacro-start-macro :help "Record subsequent keyboard input, defining a keyboard macro."]
 ["End Macro" kmacro-end-macro :help "Finish defining a keyboard macro."]
 ["End And Call Macro" kmacro-end-and-call-macro :help "Call last keyboard macro, ending it first if currently being defined."]
 "--"
 ["Kmacro Bind To Key" kmacro-bind-to-key :help "When not defining or executing a macro, offer to bind last macro to a key."]
 ["Name Last Macro" kmacro-name-last-macro :help "Assign a name to the last keyboard macro defined."]
 ["Insert Macro" insert-kbd-macro :help "Insert in buffer the definition of kbd macro MACRONAME, as Lisp code."]
 ))

(easy-menu-add-item menu-bar-tools-menu nil kmacro-menu "grep")

Once you restart your Emacs, you should see the menu items for Keyboard Macros.

Screenshot from 2018-05-26 21-28-56

Start Recording the Macro

 

Screenshot from 2018-05-26 21-37-39

Compose your Macro

Play the following keystrokes C-u 8 0 - This inserts 80 numbers of hyphen characters in the current buffer.

Screenshot from 2018-05-26 21-38-07

 

Screenshot from 2018-05-26 21-39-57

Stop Recording the Macro

 

Screenshot from 2018-05-26 21-40-26

Run the above recorded Macro

At this point, you have created a macro for inserting a horizontal line.  Now whenever you want to create an horizontal line, just run this recorded macro.  Note that you are re-playing the recently recorded macro, whatever that may be.  Consequently, if you were to record a new macro, the same re-play command will behave differently.  This is because it is now running the newly recorded macro and not the old one.  So long as you don’t need a new macro, or need a macro for future sessions, replaying the last recorded macro is all you need.   However there are occasions where you want more than one macro and you want them across sessions.  This is where naming your macro, binding it to it’s own key and saving it in your .emacs  becomes a necessity.

 

Screenshot from 2018-05-26 21-53-28

 

Screenshot from 2018-05-26 21-55-55

Give your Macro a Name

You can give the macro a name, say  insert-horizontal-line .

 

Screenshot from 2018-05-26 22-00-28

 

Screenshot from 2018-05-26 22-01-01.png

Congrats!!! You have created your own custom edit command

Once you have given your macro a name, you can invoke it with M-x ... , just like any other regular command. In the present case, you have created a custom command insert-horizontal-line which you can invoke with M-x insert-horizontal-line.

 

Screenshot from 2018-05-26 22-06-55.png

Save it for future use

Now that you have created a command, you can save it for future use by storing it in your .emacs.

 

Screenshot from 2018-05-26 22-01-39.png

 

Screenshot from 2018-05-26 22-03-28.png

 

Here is the Emacs Lisp snippet created by your  Emacs.

(fset 'insert-horizontal-line
 (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([(menu-bar) tools Keyboard\ Macro Universal\ Argument (menu-bar) tools Keyboard\ Macro Universal\ Argument 56 48 45] 0 "%d")) arg)))

Bind your macro to a custom key sequence

You can bind the macro to a key sequence.  Emacs recommends that keyboard macros be bound to key sequences starting with C-x C-k, and ending with one of the digits 0 through 9 or one of the uppercase letters A through Z.  You can bind your macro to say H.  Whenever you need to create a horizontal line, all you need to do is type C-x C-k H.

 

Screenshot from 2018-05-26 22-27-53

 

Screenshot from 2018-05-26 22-29-53

 

Screenshot from 2018-05-26 22-28-37

 

Concluding Words

There are many more commands for working with Keyboard Macros. However, for most situations, a working knowledge of the steps introduced here is all you would need.

2 thoughts on “Keyboard Macros: Build custom commands with the Emacs Command Language

  1. Compro Prasad May 27, 2018 — 3:23 pm

    Does the macro definition gets stored somewhere? Where is it stored? If it is not stored somewhere permanent then how to store it?

    Like

  2. Does the macro definition gets stored somewhere?

    No . If you quit your Emacs, the macro definition will disappear.

    If it is not stored somewhere permanent then how to store it?

    You need to store the macro in your .emacs. Here are the steps:

    1. Name the macro with C-x C-k n. See screenshot.
    2. Save the named macro in your .emacs with M-x insert-kbd-macro. See screenshot.

    Now, when you restart Emacs, the macro will be available via the name you gave it. However any key binding you may have created with C-x C-k b is not carried forward.

    To create a permanent key binding, say C-x C-k H, for the macro discussed in this post, do the following.

    1. M-x global-set-key RET C-x C-k H insert-horizontal-line
    2. M-x list-command-history
    3. From the command history, copy over the line (global-set-key [24 11 72] (quote insert-horizontal-line)) to your .emacs

    So, at the end of all the above steps, your .emacs will contain what you see in the screenshot below.

    screeshot

    If you created your macro not with the menu, but with the default Emacs key-bindings, then your .emacs will contain what you see in the screenshot below.

    screenshot

    Like

Leave a comment