I’ve been an Emacs user for a while now and, since the beginning, I’ve been pondering whether to override the keybindings that come with the editor by default.

I’ve seen good arguments for both cases and I’d love to say that I agreed with one side more than the other (that would make the decision much more easy).

On one hand, people advocate that keeping the default keybindings intact will make you “more portable”. This would be a good practice if you engaged in pair programming on regular basis. Knowing the defaults will help you move to other environment and have, potentially, the same fluidness as in your own (assuming that this new env has the same approach).

But on the other hand, Emacs comes with a very (VERY) extensive collection of default keybindings. And you also need to consider the new ones that every installed package brings to the table. This leaves little room for custom keys, which is a good argument for overriding them: your environment should be comfortable to you, because you’ll be the one spending the majority of the time there. This approach can make you extremely proficient, because you won’t need to assign weird and/or uncomfortable fatalities to the list. You’ll be able to perform your most common tasks in a single keystroke.

As I said, I’ve been in the middle of this choice from the beginning and I couldn’t decide which approach I liked the most. Until I discovered the Hyper key.

In this article I’ll explain why I use the Hyper key on my configuration and how to set it up on GNU/Linux for you to use it too.

What’s the Hyper key

In simple terms, it’s a modifier key, the same way Control and Meta are. But it’s unused by default and in most systems not even present. It’s usually mapped to the Menu key (the one that normally appears between the control and alt keys).

A case for the Hyper key

After a lot of thinking over the time, I remembered a concept from my Vim days. Vim uses the comma as the “leader key”, which basically means that it’s a key that’s left for the user to, well, use. It’s sort of a modifier key, so you can have multiple bindings assigned to it.

For Emacs, the Hyper key is a perfect candidate to use the way Vim uses the comma. There are no bindings assigned by default, so you can use the entire range of options.

For example, I have H-c (Hyper plus the letter "c"), =H-h, H-t, H-n mapped as my cursor keys (Up, Left, Down, Right), so I don’t have the need to reach for the arrow keys.

And, even though I still have a lot of custom mappings that use the Control and Meta keys, I’m slowly moving towards changing them to Hyper.

By doing this, I have the best of both worlds

  • I have the original keybindings available, which I try to use more or less on a regular basis in order to have them committed to memory
  • And I have an enormous amount of flexibility when I need to add a new binding

The case that pushed me to embrace Hyper

Long time ago, in a pairing session far far away I was working with a friend. We both used Emacs at the time and had, of course, very different configurations.

I was using Linux while he was a Mac user. We were working on my setup at the moment and he was driving the keyboard from his end. After a while, I noticed a pattern on his workflow… every few seconds the current line got duplicated. He was typing, made an error and suddenly the line appeared in the next line. The problem was that the default keybinding for delete-char is C-d, but I had this remapped to a custom command that was used to, you guessed it, duplicate the current line.

Having this happen every couple of seconds was very annoying and kept us context switching all the time.

After remapping my duplicate-line command to H-d we never had this problem again.

How to set it up in GNU/Linux

In order to make the Hyper key available on your keyboard, we first need to decide to what modifier to assign it.

So we check the modifier’s table by running

$ xmodmap -pm
xmodmap:  up to 4 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Alt_L (0x40),  Meta_L (0xcd)
mod2        Num_Lock (0x4d)
mod3
mod4        Super_L (0x85),  Super_R (0x86),  Super_L (0xce),  Hyper_L (0xcf)
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)

In my config, mod3 is available so we can use this one. For you it might be different, but whatever slot is unused (either by the OS or by you), you can use.

Now that we know this, we can create a file for configuring Xmodmap (the program we’ll use to remap keys at the OS level).

I called it ~/.Xmodmap. There, we start by making sure our slot is clear

clear mod3

Then we need to get the code that corresponds to the key we want to use (Menu in my case). To do this, we run the xev command from the terminal. This command has two parts|

  • The GUI, where we can press and release keys and mouse buttons
  • and the terminal, were the codes of the key and mouse events will show up.

Here’s the part of the output that corresponds to me pressing and releasing the Menu key:

$ xev
# ...

KeyPress event, serial 32, synthetic NO, window 0x2000001,
    root 0x2a5, subw 0x0, time 547514766, (39,347), root:(1323,371),
    state 0x0, keycode 135 (keysym 0xffee, Hyper_R), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyRelease event, serial 32, synthetic NO, window 0x2000001,
    root 0x2a5, subw 0x0, time 547514852, (39,347), root:(1323,371),
    state 0x20, keycode 135 (keysym 0xffee, Hyper_R), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False

# ...

This is the line that interest us:

state 0x0, keycode 135 (keysym 0xffee, Hyper_R), same_screen YES,

It says that the code for the Menu key is 135. The next step is to update the Xmodmap config to assign the code to the Hyper key.

clear mod3
keycode 135 = Hyper_R

And finally assign the Hyper key to mod3

clear mod3
keycode 135 = Hyper_R
add mod3 = Hyper_R

And our config is done. After invoking the new configuration file

$ xmodmap ~/.Xmodmap

we can see that the Hyper key is ready to be used

$ xmodmap -pm
xmodmap:  up to 4 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Alt_L (0x40),  Meta_L (0xcd)
mod2        Num_Lock (0x4d)
mod3        Hyper_R (0x87)
mod4        Super_L (0x85),  Super_R (0x86),  Super_L (0xce),  Hyper_L (0xcf)
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)

Using it on Emacs

Having this key in our arsenal, we can now use it to create awesome keybindings by using global-set-key or local-set-key at any point in our Emacs configuration

Here are some of the ones I’m using myself

;; Moving cursor
(global-set-key (kbd "H-h") 'backward-char)
(global-set-key (kbd "H-n") 'forward-char)
(global-set-key (kbd "H-c") 'previous-line)
(global-set-key (kbd "H-t") 'next-line)

;; Text
(global-set-key (kbd "H--") 'kill-whole-line)
(global-set-key (kbd "H-d") 'fdx/duplicate-line)
(global-set-key (kbd "<H-S-down>") 'fdx/move-line-down)
(global-set-key (kbd "<H-S-up>") 'fdx/move-line-up)

;; Compilation
(global-set-key (kbd "H-m") 'recompile)
(global-set-key (kbd "H-b") 'compile)


(global-set-key (kbd "H-e") 'er/expand-region)

Final words

I love this technique, it’s provided a lot of flexibility for me and my Emacs workflow. Did you like it? Would you be willing to try it out? I’d love to know your take on this topic.

I hope this post triggers a Hyper revolution! Thanks for reading and see you on the next one.

Saluti.