Creating An Emacs Command

Ranked #11,860 in Computers & Electronics, #247,089 overall

Emacs Command Creation - A Tutorial

Whenever you press a key in emacs, a command is run. E.g. if you press 'a' it calls a command called self-insert-command. Much of the power of emacs derives from the fact that anyone can define their own command in emacs lisp. This command will look the same as any built-in command and can be bound to any key or key combination.

For example, if you don't like the letter 'e' you could bind it to a command that would display a message "Please don't use the letter 'e'". How can you do this?

If you want a more useful example of extending emacs, have a look at my emacs hooks lens.

The basics of emacs commands

The (interactive) function

(defun no-e-please ()
  (message "Please don't use the letter e"))

(global-set-key (kbd "e") 'no-e-please)



However, when you try this, typing the letter 'e' results in the following error.

Wrong type argument: commandp, no-e-please



What happened here? It turns out that emacs differentiates between commands, that can be bound to a key, and normal functions which cannot. A command is simply a function that is marked interactive.

(defun no-e-please ()
  (interactive)
  (message "Please don't use the letter e"))

Self Insert Command

Inserting the character you pressed

However, we probably still want to insert the letter 'e', even though we've given a warning (otherwise, you will find it tricky, although not impossible, to enter a letter 'e' when you really want to).

(defun no-e-please ()
  (interactive)
  (self-insert-command 1)
  (message "Please don't use the letter e"))



That is better, but it still has a couple of problems. The first thing is if we want to assign this to a key other than 'e' then it will insert the wrong character. Not wanting to ruin my configuration, I tested it with C-c C-q and it emitted ^Q.

As the parameter in self-insert-command specifies how many times the character should be inserted how do we choose the character?

Prefix commands (C-u)

The other problem is that if you enter C-u e then it only enters a single e whereas most emacs users would expect eeee. If you use (interactive "p") then the prefix argument is passed in to the command.

(defun no-e-please (&optional n)
  (interactive "p")
  (let ((last-command-char ?e))
    (self-insert-command (or n 1)))
  (message "Please don't use the letter e"))

Important!

In Emacs you have complete control over everything

All bound keys execute emacs commands. You can define commands that behave in the same way as built-in commands, many of which are implemented in emacs-lisp.

My Other Emacs Lenses

...take a look at my other emacs lenses

Loading

Curious Programmer Emacs Blog

Tips and Tutorials

Loading Fetching RSS feed... please stand by

Leave Me Feedback

If there is anything else you want to know about defining your own emacs command let me know here.

submit
  • Reply
    Oz DiGennaro (4dtext) Sep 30, 2010 @ 1:34 pm | delete
    Very clear discussion. I finally, after twenty years of using Emacs, understand how to bind functions to keystrokes.
    Oz
  • Reply
    Son Hua Aug 12, 2010 @ 3:20 am | delete
    Thanks for the explanation. The (interactive) command is important as I'm trying to insert some texts into Emacs when a key combination is pressed. Without it, the function simply gives the strange error: Wrong type argument: commandp, insert-matrix-env.

    My working function is like this. Actually I'm binding C-c m to insert the phrase "mat{}" into the document.

    (add-hook 'LaTeX-mode-hook 'define-custom-key)

    (defun define-custom-key()
    (define-key LaTeX-mode-map "C-cm" 'insert-matrix-env)
    )

    (defun insert-matrix-env()
    (interactive)
    (insert "\mat{}")
    (backward-char 1)
    )

by

jareddavison2009

My Emacs Lenses:
Creating An Emacs Command
Emacs Hooks - An Introduction
All About Ediff
more »

Feeling creative? Create a Lens!