Werden wir Helden für einen Tag

Home | About | Archive

Advent of emacs #7: How I type special characters in emacs

Posted on Dec 7, 2022 by Chung-hong Chan

Yesterday, I talked about displaying programming ligatures. A programming ligature, although in one single glyph as being displayed, is actually a sequence of characters. For example, |> are two characters | (the pipe) and > (greater than), although it looks like a single triangle in a font supporting programming ligatures.

I program extensively in R. I write a lot like this 1.

iris %>%
    group_by(Species) %>%
    summarize_if(is.numeric, mean) %>%
    ungroup() %>%
    gather(measure, value, -Species) %>%
    arrange(value) -> res
res |> print()

I need to type special characters such as %>%, ->, and |> quite frequently. To be sure, actually to type the %>% (the magrittr pipe), one actually needs to type the surrounding spaces also. Therefore, to type the magrittr pipe, the complete sequence on my QWERTY keyboard is “press space bar, hold the shift key, press 5, press ., press 5, release the shift key, space” 2. There are 7 actions, just to type one operator which should occupy one bit of your mental capacity. In the above code, there are 5 of these operators. 35 actions. In emacs, I can save a file with three actions (C-x C-s by default, which basically holding Ctrl and hit x and s). Seven actions for typing just one operators are certainly too many.

We probably accept that sometimes we need to type special characters with two actions. A colon “:”, used very extensively in python for example, requires two actions to type (Shift + semicolon). For a complicated but frequently used special characters such as %>%, I think it should only occupy three actions at most. Or else, it becomes tedious.

The problem is not exclusive to R. This type of code is also common in javascript.

fetch('//api.users.com/' + uid)
    .then((response) => {
		return response.json()

The arrow function => character needs five actions. Of course, the mother of ‘em all, is Lisp’s lambda (anonymous function), that’s 6 actions: l, a, m, b, d, a , space.

((lambda (arg) (/ arg 50)) 100)

Source: Symbolics Space Cadet keyboard review (Honeywell Hall effect 4B3E)

A historical note: On a Lisp Machine using the Space-cadet Keyboard, one could enter a lambda by pressing the modifier key “Greek” (Yes, there was a modifier key called “Greek”) and “l”. There was a lambda symbol on the keyboard. But on a modern keyboard, one has to spell it out.

Type efficiently, not quickly

Before I move on, I also need to stress that I am not a fast typist. I type at around 50 wpm (just tested, which is just slightly faster than the average speed of the population). I don’t know touch typing and most of my typing is done with my index fingers, middle fingers and thumbs. I only use my left pinky to hold the left shift key and left Ctrl key usually, but not always. Luckily, I still don’t have the so-called emacs pinky. I use my left thumb to press the Alt Meta key. I don’t need to look at my keyboard all the time, but sometimes I need to move my eyeballs a bit.

I also don’t like to type very quickly, because of the empathetic mirroring behavior. I am not a fast thinker anyway, so there is no need to be a fast typist. I always want to give myself some time to think about what I’ve typed.

Therefore, I am not talking about typing those special characters quickly, but more efficiently. Type more by typing less.

Today and the next two days, I will talk about how I type more by typing more. In between, i.e. tomorrow, I will continue the background bit at the end of this blog. Übermorgen I will continue the topic of typing more by typing less.

Key Chord

The first tool that I use to type more efficiently is key-chord by David Andersson et al 3.

The idea is to type very quickly, or a key chord, to enter a character sequence. For example, I can type two “greater than” very quickly (i.e. “hold shift” and type two periods on a QWERTY) to enter the sequence “ “, “>”, “%”, “>”, “ “. In my configuration file, I have this:

(use-package key-chord
  (key-chord-mode 1)
  (key-chord-define ess-r-mode-map ">>" " %>% ")
  (key-chord-define inferior-ess-r-mode-map ">>" " %>% ")

The above code snippet three things: 1) install key-chord mode, 2) make key-chord mode activate in all sessions, 3) create some key chords. Punkt.

The result is like this:

If I really need to type two “greater than”, I need to type slowly. But most of the time, I type quickly to enter “ %>% “. One side effect is that when I type these key chords, I hit my keyboard more violently and create noise. My coworkers / wife might complain.

Background: keymaps

It’s also a good time to talk more about keymaps, which I mentioned on day 2. A keymap is a data structure to store key combinations and their corresponding commands. A mode usually has its own keymap to store all key combinations specific to that mode.

On day 5, I did something like this:

(use-package vterm
		("C-y" . vterm-yank))

vterm-mode-map is the keymap of the vterm mode. We can also say vterm-mode-map is the mode-map of vterm. I add an entry to vterm-mode-map, which C-y maps to the command vterm-yank. And this is only specific to vterm, not all modes. For example, when I edit a markdown document in the markdown-mode, pressing C-y will not trigger vterm-yank (if it did, that would be a disaster). Instead, it still triggers the generic yank.

But one may want to have some key combinations that work across all modes. In those cases, one can use global-set-key.

(global-set-key (kbd "M-s M-s") 'save-buffer)

key-chord mode also creates an entry in a modemap, but those entries are not “a key combination maps to a command”, but “a key combination maps to a sequence”.

As an exercise, we can also more key chord. Let’s say you want to add a keyboard to type lambda quickly in the emacs-lisp-mode.

(key-chord-define emacs-lisp-mode-map "ll" "lambda ")

A recommendation: when creating key chords, consider using shift plus two repeated keys, e.g. “»”, “++”, even “QQ”. You are far less likely to type two characters like this and they require the shift key for a reason. Actually, the above example is not a good one because in emacs lisp, one also needs to type “ll” sometimes, e.g. many command names contain “ll”, e.g. “fill”, “shell” etc.

Also, it is a good idea to make these key chords enable in a per mode basis. In R, it is not likely to really need “»”. In Java, one might need to use “»” for bitwise operations. So, put key chords in mode-maps.

But the question is: How should one find out all these information for customization, e.g. which mode-map corresponding to which mode. I will talk about it tomorrow.

  1. I don’t need you advice on my R code. But I can give my advice: Don’t write like me. The R community might frown at the reverse assignment operator. But I think it fits perfectly with the pipe. But as you can see, the syntax highlighter can’t even highlight my code. 

  2. OK, that’s how I usually type it and I may have exaggerated a bit. It is actually okay to hold the shift through out the whole process. Because shift space is still a space on most settings. It is actually slightly more complicated on a German qwertz keyboard because of the dedicated “>” key on the keyboard: “space, hold shift, 5, release shift, > hold shift, 5, release shift, space”. Nine actions. 

  3. Maybe it’s also a good time to detour a bit and talking about the Emacs Orphanage. key-chord has been abandoned by its original author. And the Emacs Orphanage is a place to collect those abandoned projects. 

Powered by Jekyll and profdr theme