Skip to content

Mastering Key Bindings in Emacs

by mickey on February 8th, 2011

Altering the key bindings in Emacs should not, on the face of it, be a difficult task. But there’s a reason why the Emacs manual has dedicated 30-odd pages to describing, in great detail, all the subtleties and nuances of how to bind keys.

To save you the time of reading all of that, I’ve written a guide that covers what you need to know to bind keys to even complex commands, and a set of templates you can use in your own code.


This guide will assume that you have little or no knowledge of elisp

What makes up a key bind?

Emacs is “self-hosting” and, depending on who you ask, close to achieving sentience. Almost all of Emacs is written in Emacs-Lisp (weighing in at roughly 1.2 million lines of code!), and most of the complex elisp functions you use are in turn built with simpler building blocks and so on, right down to the core C source code layer.

Emacs’s key engine is very similar, because Emacs lets you control almost every facet of self-insertion and other key binds. For instance, when you press “f” it runs self-insert-command, a special command that repeats the last typed key N times. So if you type C-u 10 f you will see ffffffffff printed on your screen. As you can see, every keypress — even elemental ones like typing a character on the screen — has an associated key binding that you can modify or even remove.

Keymaps

A keymap is an internal data structure used by Emacs to store keys and their associated actions. Keymaps are rarely modified directly, but through a set of commands that manipulate the data structure for you. Most Emacs users will never interact with keymaps aside from indirectly assigning keys to them.

Every buffer and most major and minor modes have a keymap, and that keymap defines what the keys do when key sequences are sent to that buffer. Keys can be divided into three categories: undefined, prefix key, or complete key. Undefined is self-explanatory: it does no operation when it is invoked. Prefix keys are keys like C-x and C-c; they are parts of a complete key, and each constituent part of a prefix key is made up of its own keymap. A complete key is a command that, when input, executes its associated command.

It is possible for Emacs to enumerate all the active minor and major mode key bindings in a buffer by typing C-h m. This command is very useful if you want to learn more about what a major or minor mode can do. Likewise, you can type out parts of a complete key (say M-s) and then type C-h to get a list of all keys that belong to that prefix.

Key Bind Commands

There are several ways you can define (or undefine) keys, as the table below shows, but in reality there are dozens of ways you can hack the keymaps.

(define-key KEYMAP KEY DEF)
Defines a key against a keyboard map. Use this if you want to change a keymap that isn’t the current buffer map.
(local-set-key KEY COMMAND)
Binds a key to the local keymap used by the active buffer, unlike define-key which takes an explicit keymap to bind a key against.
(global-set-key KEY COMMAND)
Binds a key to the global keymap, making it available in all buffers (with a caveat — see below.)
(global-unset-key KEY)
Removes KEY from the global keymap
(local-unset-key KEY)
Removes KEY from the active, local keymap.

Representing Keys in Code

In order to actually bind a key you must first tell Emacs what key you intend to use. Unfortunately there’s more than one way of representing keys in Emacs: as a string, or as a vector. We won’t concern ourselves with either, as we will use a handy macro built in to Emacs called kbd.

The kbd macro translates a human-readable key into a format Emacs can understand.

One important point to note is that you must surround function and navigation keys with < and >. Those keys include F-keys, arrow keys and home row keys, like so: <home>, <f8> and <down>. But if you want represent the key C-c p then write (kbd "C-c p").

Remapping Commands

You can tell Emacs that you want to replace all keys pointing to a certain command with one of your own choosing by using the remap event; this should be done instead of passing a key to the key bind function you are using. This is arguably the best way of replacing existing commands with your own as Emacs will automagically handle the key reassignment in the background.

Example:

Here I globally remap all key binds that point to kill-line to my-homemade-kill-line.

For some more hands-on examples read my article Fixing the mark commands in transient mark mode.

Reserved Keys

You can pick any keyboard combination you desire — even if that key bind is already taken, so be careful — but Emacs has set aside certain keys for use by users. Generally, all keys prefixed with C-c ? (where ? is a single character) are reserved for you, and you alone. In practice most third-party packages don’t give a hoot and will gladly stuff their own key binds in there.

The other set of reserved keys are the F-keys from F5 and onwards. The other two prefix keys reserved to you are hyper and super. They are remnants from ancient keyboards used in the 80s, but live on today in Emacs. Most PC-compatible keyboards won’t have a super or hyper key so some people rebind the Windows key and the Application Context key to be hyper and super instead.

Anyway, if you want to use hyper then use the prefix key H- (e.g., H-q) and if you want super use the prefix key s-. Take note of the lower case ‘s’!

In Windows you can add this to to your .emacs to enable hyper and super:

In X you’ll have to play around with xmodmap or your own tool of choice.

Keymap Lookup Order

Emacs will look for keys in a certain order, and that order I have described below. Keep in mind that only active keymaps are used, and that the order is top-to-bottom; the first “match” is used, subject to criteria that we don’t care about.

  1. overriding-terminal-local-map for terminal-specific key binds.
  2. overriding-local-map for keys that should override all other local keymaps. Be VERY careful if you use this!
  3. Keymap char property at point for keymaps that are local to the character point is at. This is used for stuff like fields in yasnippet and the customize dialog.
  4. emulation-mode-map-alists for advanced multi-mode keymap management
  5. minor-mode-overriding-map-alist for overriding the keymaps used by minor modes in major modes.
  6. minor-mode-map-alist is exactly like the overriding version above, but the preferred means of specifying the keymaps for minor modes.
  7. Keymap text property at point is like the one above for char properties but is for text properties only.
  8. current-local-map for keymaps defined in the buffers’ current local map
  9. current-global-map is the last place Emacs will look for key binds and it is for the global ones.

All you care about is that minor mode keys come before local keys, and they in turn are checked before global keys.

Global vs Local

A global key is functionally identical to that of a local one, except it is declared in a “global” keymap, governed by the current-global-map function (but usually it points to the default, the global-map variable.) Therefore, it is possible for you to define a global key simply by passing the current-global-map function to define-key. The other — often better — alternative is to use the designated function, global-set-key.

In a similar vein, to bind a local key you can use the “designated” function local-set-key or the more general define-key. Like the global map, there exists an equivalent function current-local-map that returns the keymap local to the buffer. It’s important that you know that although the major mode in a buffer will define the bulk of the key binds used in a buffer, the minor modes often add, remove or change the key binds as they take precedence over the local keymap.

Defining your Command

If you thought the mechanics of keymaps and keys were difficult, think again! Deciding on what you want to bind to those keys is even harder — especially so if you want the command to do very specific things, like switching to a specific buffer name. But I’ve got a few tricks up my sleeve to help you cut out most of the elisp writing by letting Emacs do all the heavy lifting.

Invoking a command

Before I talk about the how and why of Emacs commands it is important that I mention how Emacs handles interactive functions — commonly known as commands. An Emacs command is one that has the (interactive ...) statement at the top of a function body; this magic statement tells Emacs the command is interactive and that it is intended for consumption by users. That is also what determines if you can invoke a command through the M-x prompt.

When you bind a function to a key it is important that you keep the above in mind, as you cannot invoke a non-interactive function through a key binding — it must be a command. Also, for a key definition to function it must invoke a command with no parameters. If it is your intent — as it so often is — to call a function with parameters you must wrap it in a little helper function, like a lambda expression or even a standard defun. I have prepared templates (see below) that show you how to do this.

Describing the command

There are two ways of describing a command in elisp: the manual way, and the smart way. Let’s start out with the manual way.

The manual way is to use C-h k KEY to describe what KEY is bound to; the other way is to describe a function, FUNCTION, with C-h f FUNCTION. Because Emacs is a self-documenting editor all functions, variables, keys, etc. loaded in Emacs can be accessed by way of the describe-xxx commands (type C-h C-h to see them all!) and that is what most Emacs hackers use.

But there’s another way… the smarter way. It has one teensy-weensy little downside: it’ll only work for interactive functions (the ones we call commands, remember?), and then only complex commands — that is, a command that needs user input from the minibuffer.

The smarter way has a name, repeat-complex-command, and it is conveniently bound to the key C-x ESC ESC. When you type it, Emacs will ask you to redo the last typed command, but it will do so showing you the elisp expression to execute; so you can not only change it then-and-there and re-run it, but you can copy it and use it in your own code!.

Here’s a practical example: C-M-% foo RET bar RET — which does a query-replace-regexp replacing foo with bar. Now, if you type C-x ESC ESC you should see something similar to this (reformatted for clarity):

Observe how Emacs has kindly filled in all the function arguments to query-replace-regexp, including the optional parameters. If you were to run that command again (by say pasting it into the prompt in M-:) you will be asked to interactively search and replace with the search term foo and its replacement bar already filled in!

Here’s another one, this time I type C-x b *scratch* to switch to the *scratch* buffer:

And there you have it. Obviously the commands seen here are the interactive commands. Stuff like replacing strings in a buffer is normally done with specialist elisp functions that don’t require user input, but that may not be a big deal if you are writing your own quick-and-dirty key binds.

Putting it all together

Yay. You’ve made it this far. I just need to explain a few more important concepts that confuse a lot of newbies: mode hooks and mode-specific keymaps, and then it’s on to the templates.

Most major and minor modes will usually set their keys once, when the module is first loaded; that’s good news for us, as we can use define-key to add key definitions straight into their mode map, the map that holds keys relevant to that mode. Some modes are very advanced, and have several maps — isearch is a good example — and for those you will have to mess around with the source code (or possibly the info manual) to find out how to add keys.

It’s the modes that force you to use a mode hook that’s the problem: for that you must set your keys when the mode is launched (using its mode hook), and that takes a little bit more work.

It is a convention in Emacs that all major mode functions (the ones that activate the mode) end in -mode (e.g., python-mode), and it is also required that its mode map is named xxxx-mode-map, and its major mode hook xxxx-mode-hook.

Keymaps

Modifying a keymap is dirt simple, you use define-key as I’ve mentioned before. What’s not so easy is determining what keymap to modify in the first place.

Listing all the Mode Maps

If you type this Emacs will give you an apropos buffer with all the known mode maps that follow the major mode naming scheme:

C-u M-x apropos-variable RET -mode-map$ RET

Amusingly, you can use the repeat-complex-command trick to get the expression for use in a key bind or custom function…

Quick Keymap Example

This assumes you are using the built-in python mode that comes with GNU Emacs
Let’s say I want to extend python-mode by adding a key, I’ll use F12, that switches to the python process buffer. Currently, that’s bound to C-c C-z.

I had to use the manual way (C-h k C-c C-z) to determine the name of the command because the smart way wouldn’t work: the command is not complex, as it does not require user input from the minibuffer.

Hooks

A mode hook has zero-or-more functions that are called when its mode is activated, like say when you open a file that uses that mode or when you change the major mode in a buffer.

You can add a mode hook using the special function add-hook that takes the name of a hook (say python-mode-hook) and the name of a function to call.

Listing all the Mode Hooks

If you are unsure of the exact name of the mode hook, you can use this handy trick to list the ones Emacs can see:

C-u M-x apropos-variable RET -mode-hook$ RET.

That will show all mode hooks known to Emacs, including their docstring description. If you don’t see your mode it may be because Emacs hasn’t loaded it outright or it lacks the autoload keyword.

Quick Hook Example

Let’s add a key (C-c q to run M-x shell) local to python-mode using a hook. For that to work we will need our special hook function, I’ve named it mp-add-python-keys, and in it we need local-set-key, the function that adds a key to the active buffer’s local map. Observe that the command will be called within the context of the buffer that invoked the major mode.

Next is the command that tells Emacs that we want to add a mode hook to Python.

Templates

Here’s a bunch of templates for various use-cases that you can cut’n'paste and use in your own code. I recommend naming things sensibly, and giving them a docstring (in-code documentation that explains what the code does) as well. The best way to avoid accidentally overriding another function with the same name, I would suggest you use a moniker or prefix (I use mp-.)

I suggest you read my article, Evaluating Elisp in Emacs, to learn how to evaluate and test the code you write!

Function Template

Purpose

Required if you want to invoke non-interactive functions or functions/commands with parameters. Use this functions’ name in the command definition argument.

Definition

Example

Displays the message “Hello, World” in the echo area when invoked.

Basic Global Key Bind

Purpose

Creates a global key bind available to all buffers.

Definition

Example

Binds F1 to M-x shell

Add key definition to a keymap

Purpose

Adds a key and its associated command to a local keymap. Useful for extending major modes with your own custom key binds.

Definition

Example

Binds C-c p to python-switch-to-python

Complex Command Key Bind

Purpose

Creates a global key bind that invokes multiple commands in a row. Use this to create compound keys or invoke commands that take parameters. Uses code from the Function Template.

Definition

Example

Switches to the *scratch* buffer and inserts “Hello, World” where point is, and switches back to where it came from.

Binding keys with a mode hook

Purpose

Use this mode hook template to bind keys that won’t work with a standard define-key template or that require local binding for other reasons. The advantage of a mode hook is that it also gives you the opportunity to set mode-specific settings like indentation, etc.

Definition

Example

Make the return key automatically indent on a newline in emacs-lisp-mode, and enable eldoc mode as well.

Remapping a function

Purpose

This template will remap all keys that point to a specific function; say you want to rebind kill-line which is bound to C-k but you want your code to only override the key binds that kill-line is actually bound to. Use this template to replace existing commands with those of your own, without worrying about explicitly rebinding each key.

Definition

Note: to replace a global key, you must use global-map or call current-global-map.

Example

Example here is taken from my article on fixing the mark commands in transient mark mode. I remap the keys that point to exchange-point-and-mark to my own function exchange-point-and-mark-no-activate.

Custom Prefixes

Purpose

Creating a prefix is easy nowadays as you don’t have to explicitly create your own prefix keymaps, provided you use local-set-key or global-set-key. Use custom prefixes to group or categorize your commands.

Definition

Example

Global keys that will insert either the time of the day, or the current date. Type C-c i d to insert the date; and C-c i t to insert the time. Type C-c i C-h to list all bound keys under the C-c i prefix.

Conclusion

I have covered almost every facet of key binding that most Emacs users would care to know about. I know there’s a lot of tutorials out there that essentially capture only what I have in the templates section, but for your edification I decided I wanted to cover everything (or near as well anyway) that make up a key definition.

That I can dedicate so much to a topic that on the outset appears straightforward highlights the flexibility — and complexity — of Emacs. I hope the guide has taught you how to do one of the most frequently-asked things in Emacs.

31 Comments
  1. I miss how to bind a macro to a specific key binding

    Start capturing a macro: C-x (
    Stop and save the macro: C-x )

    Give a name to the last saved macro : M-x name-last-kbd-macro macroname

    Write the macro in a kdb format: M-x insert-kbd-macro macroname

    And now you can bind that macro in anyway you like.

    • mickey permalink

      Good tip, Pedro. By the way, the macro recorder is bound to F3 and F4 now. F3 is bound to kmacro-start-macro-or-insert-counter (unlike C-x () meaning repeated presses will insert the number in the counter and increment it by 1.

  2. This is getting to be a really good series. I hope you keep at it.

  3. roy_hu permalink

    On my Linux system, the Windows key is bound to Super, and the Application Context key to Menu.

  4. ECL permalink

    Also note that you can bind a string to a key:

    Pressing

    will now insert “some text” in your current buffer.

  5. Aurélien Bottazzini permalink

    Thank you for this nice article

  6. Alexis permalink

    This is fantastic post. I feel like you’ve literally cleared away years worth of lingering confusion.

    Please keep up the blog!

  7. Dan permalink

    Hi Mikey, Very good information. Thank you.

    I have a quick question, hoping to find some help here.

    I checked current key binding (CTRL h b) CTRL e is still bound to move-end-of-line, but somehow CTRL e (end-of-line) stopped working on my machine, I tried “M-x end-of-line” and that works fine!

    Where should I check/look at to fix this? Also, how to reset all key bindings to default install (not that I want to revert it all at this stage but just for my knowledge).

    (my emacs 23.3.1 runs on win7 with bunch of stuff in .emacs like cedet, enhanced ruby-mode, yasnipett, zen coding, mod compile).

    • mickey permalink

      Clearing debris from your .emacs will by its nature reset things to their defaults. Run emacs with emacs -q and if it works there it’s one of your .emacs changes or modules that’s screwing up your keybinds.

  8. Greg permalink

    Very useful, as always! One related tip that I recently discovered: you can define a minor mode map as a way to ensure your global key bindings don’t get overridden by some other mode.

    Details here on StackOverflow: http://bit.ly/sqlMus

    • mickey permalink

      Yeah, that’s right; the keymap lookup order does hint at that, though perhaps I should add a template to demonstrate it.

      Thanks!

  9. Bryan Henderson permalink

    I’ve found that the most vexing part of assigning Emacs commands to keystrokes is the several layers of mapping that happens below what’s described here. E.g. when I press the piece of plastic that says “Page Down”, what “key” have I pressed, as the term is used in the article. In some cases, I have pressed a key Emacs calls . In others, I have pressed four in a row: Escape, [, 6, and tilde.

    If you want to assign the physical Page Down key to some command, you have to master those lower level mappings as well.

    Those layers exist in keyboards, drivers, terminal emulators, and other places. At least one of them is inside Emacs: on one of my newer systems, when Emacs gets the three ASCII characters Escape, O, W, I have pressed the Emacs “7″ key (this is not arbitrary – some terminals in some modes generate that sequence when you press numeric keypad 7).

    • mickey permalink

      I know what you mean, but Emacs is at the very least flexible and very accommodating of just about every window manager and terminal emulator you may end up using. That’s why there’s so many layers but for all practical purposes you shouldn’t care.

      I advise everybody to never, ever, ever use Emacs in a terminal unless you’re confident in your ability to diagnose strange behavior, or because you have no other choice.

  10. Bryan Henderson permalink

    My comment above got mangled. “I have pressed a key Emacs calls …” is supposed to be followed by the word “next” in angle brackets, in the Emacs key naming style.

  11. Saheel permalink

    Hi Mickey, a very informative post indeed.
    I have a task at hand:
    I am using Evil and in “insert” and “normal” state, C-e is bound to ‘evil-copy-from-below and ‘evil-scroll-line-down command resp. I want to remap it to ‘end-of-line. I tried this:

    (define-key (current-global-map) [remap evil-copy-from-below] ‘end-of-line)
    (define-key (current-global-map) [remap evil-scroll-line-down] ‘end-of-line)

    and it worked. But I want C-e to execute ‘end-of-line in other states also (such as “visual” state, etc.). And I don’t want to find out what C-e does in each state and then remap it to ‘end-of-line. I tried this:

    (define-key (current-global-map) (kbd “C-e”) ‘end-of-line)

    but it didn’t work. It didn’t even do what ‘remap’ did earlier.

    Can you help me?

  12. Pavan Ghatty permalink

    Hello Mickey,
    I was trying to getting an alpha and a beta symbol in emacs which I did by adding the two lines below to .emacs file.

    (global-set-key (kbd ” a”) “α”)
    (global-set-key (kbd ” b”) “β”)

    When I tried to get an umlaut using the same procedure it didn’t work.
    (global-set-key (kbd ” u”) “ü”)
    I learned that C-x, 8, “, a/e//i/o/u gives the corresponding alphabet. But I find this rather tedious. So I tried to set up a shortcut which didn’t work either.
    (global-set-key (kbd ” u”) C-x 8 ” u)

    Could you please suggest a solution?
    Thank you!
    P

    • mickey permalink

      OK, so, I’m not really answering your question here — and you may well have changed your code for brewity’s sake — but why are you overriding your global keymap like so? If you want to use a different input method (Greek, iso-8859-1, etc.) you should look into using that instead as Emacs has a flexible input method system that does what you need. I’ve written about it on the blog.

      Check out “Olé! Diacritics in Emacs”

  13. Hugo permalink

    Hi Mickey! I really liked yout article. This is the best Emacs blog I know. There’s alot of Emacs stuff on the web that’s very cryptic but your blog has very clear articles. Thanks for your posts :)

  14. Federico C. permalink

    Thank you for this guide. Best I’ve read until now.
    I’m trying to learn to use emacs with its key bindings, but since I usually work on a mac pro I’m asking if is it possible bind ctrl+option for meta key instead of command and pass command to system or bind command in CUA style for movement, copying and pasting. It is not very important to do it, because I’m trying to use emacs original keys and I find they very simple to remind. Just asking if is it possible. As I’ve seen the combination ctrl+option is used for symbols, but I’ve already custom system bindings for symbols based on option key or shift+option key combination. Since I’m using emacs just for write C and Python programs I don’t need a vast set of symbols.

  15. Joost permalink

    Nice article. :-) One small correction, though: you say that key sequences of C-c ? with ? being anything are reserved for the user, but that is not entirely true. Only key sequences of C-c are reserved for the user. Sequences of C-c followed by some non-letter (and non-number) character are reserved for minor modes.

  16. Drew permalink

    Good presentation!

    * You might want to also mention the minibuffer keymaps. They are local maps (so major-mode maps), but they are a bit peculiar.

    * The structure of a keymap is an advanced topic (not for this overview), and that is what you see if you try to use, say, C-h v' on a keymap variable. C-h b’ and C-h m' can sometimes help by providing a user-readable list of bindings, but they don't help with keymaps that are hard to get at except via their variables (e.g., minibuffer keymaps).

    * For that, C-h M-k’ (command describe-keymap') in library help-fns+.el’ can help. (http://www.emacswiki.org/help-fns%2b.el)

    • Drew permalink

      (All quote chars following backquote chars in my post should have been backquotes. I don’t see a way to edit the post, but perhaps you could do that, for clarity. Sorry.)

    • mickey permalink

      Minibuffer mode maps! I can’t believe I missed those. Nice catch, Drew. Thanks for all your hard work over the years!

  17. Doug permalink

    Hey, Mickey. I just started using emacs, on Windows and lubuntu. I’m working my way through the tutorial, but when I get to the part about “C-<" it throws the error "C-< is undefined." Per the tutorial it is supposed to go all the way back to the beginning of the text. I have found the "global-set-key" command, but I don't know how to tell it to go to the beginning of the text.

    Thanks for your help, and this blog.

    • mickey permalink

      Not sure I follow. Where did you read about C-< and C->?

      • Doug permalink

        Mickey,
        I apologize. It’s “M-”. I don’t know what I seeing. Once I use the correct command it works.

        Thanks for the quick reply,

Trackbacks & Pingbacks

  1. After some time, updates! | Crazy thinking – Just my Weblog
  2. My current .emacs file » ./klaus hofeditz :: weblog
  3. Zen Coding | 따라쟁이
  4. Read Lisp Tweak Emacs (Beginner 3/4): How can I make things more convenient? - sacha chua :: living an awesome life

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS