Design of Math Symbols Input System

By Xah Lee. Date: . Last updated: .

This article discuss some of my thoughts about the problem of a input system for entering math symbols and special characters.

In the past few years, i need to type math symbols a lot in Emacs. In some hodgepodge way, i created several custom ways to enter special chars i need in emacs, such as: “” 【】〈 〉 「」 © • ◇ ◆ ★ × α θ λ ← → ⇒ ≠ ∞ etc. The system is nowhere consistent or comprehensive. In the back of my mind, i thought that someday i'll think about it and find a way that's efficient and comprehensive for inputting hundreds of math chars. When you need to type a lot special chars, there's a interface design issue, because there are so many ways to do it.

AltGraph Key System vs Abbrev System

AltGraph Key System

For example, first is a simple method of using a modifier key (usually called AltGr) to insert special chars.

macOS 10.15.5 keyboard viewer 2020-07
MacOS Keyboard Viewer. macOS 10.15.5, 2020-07-25. Hold ⌥ option down to type Unicode symbols. Those colored orange are prefix keys, allowing you to type accented characters such as é ü ô. You can make it insert emoji. 〔see Mac: Create Custom Keyboard Layout

In this method, you press a key combination to insert a char. This is great solution if you just need a few chars that's frequently used. If you need more than say 50 chars, you need to add more modifier key combinations, it quickly become a problem of remembering which chars are what key. So, this method isn't good if you need to input a lot math for example, because there are few hundreds of math symbols, and different people have different set of chars that's frequently used for them.

(For how to do this on Mac, see: Creating Keyboard Layout in Mac OS X.)

See also

Abbrev System

Other solution is to use abbreviation. For example, you type “a”, then press a hotkey, and it becomes α, and “inf” becomes , “ne” becomes , etc. While studying WolframLang: Source Code Encoding and Unicode, i realized that this is the most practical, efficient, method, to input large number of chars. Math symbols, and also common chars such as ‹ › « » ¢ € £ ¥ © ® ™ § ¶ † ‡ ※ ● ■ ◆ ↑ ↓ → ← ◀ ▶ ▲ ▼ etc. This way, you don't have to remember hundreds of key combination for each char. You just type the name of the symbol, using full name or short abbrevs (1 to 5 letters).

The advantage of this method are:

The disadvantage is that it is slower. If you need let's say only 10 to 30 chars that you need to type every few minutes, for example, say the acute e é in some language, then the 2-keys by AltGraph+e is faster.

However, the 2 methods can both be used. That is, have a AltGraph layout, but also have the abbrev system.

When is Hotkey Pressed

The hotkey can be pressed before you type the abbrev, or, it can be pressed after. Or, it can be completely eliminated by a automatic change.

For example, in emacs, you press Ctrl+x 8, then type ' e then you get é. This is a example of hotkey first. 〔see Emacs and Unicode Tips

The emacs Ctrl+x 8 act as compose key.

〔see Alt Graph Key, Compose Key, Dead Key

In Mathematica, you press Escape abbrev Escape to insert a special char. 〔see WolframLang: Source Code Encoding and Unicode

For automatic abbrev expansion, both emacs and Microsoft Word and many editors support that. For example, in Word, typing (c) automatically becomes “©”. The automatic change method is great, but the problem is that if you have hundreds of abbrevs, often some of them are common words too, which you do not want to automatically become a special char. For example, you don't want “not” to always automatically become the logic symbol ¬, or this “>=” becoming in programing source code.

Changes to my Emacs Elisp Code

So, yesterday, i started to organize my several elisp code related to inputting special math symbols to a unified minor mode. For example, i had the following code that sets up a emacs hyper key to insert chars:

(global-set-key (kbd "H-y <up>") (lambda () (interactive) (insert "↑"))) ; up arrow
(global-set-key (kbd "H-y <down>") (lambda () (interactive) (insert "↓"))) ; down arrow
(global-set-key (kbd "H-y <left>") (lambda () (interactive) (insert "←"))) ; left arrow
(global-set-key (kbd "H-y <right>") (lambda () (interactive) (insert "→"))) ; right arrow
(global-set-key (kbd "H-y <kp-6>") (lambda () (interactive) (insert "⇒"))) ; RIGHTWARDS DOUBLE ARROW
(global-set-key (kbd "H-y <kp-add>") (lambda () (interactive) (insert "⊕"))) ; CIRCLED PLUS
(global-set-key (kbd "H-y *") (lambda () (interactive) (insert "⊗"))) ; CIRCLED TIMES
(global-set-key (kbd "H-y <kp-multiply>") (lambda () (interactive) (insert "×"))) ; MULTIPLICATION SIGN
(global-set-key (kbd "H-y <") (lambda () (interactive) (insert "≤"))) ; greater htan
(global-set-key (kbd "H-y >") (lambda () (interactive) (insert "≥"))) ; less than
(global-set-key (kbd "H-y Z") (lambda () (interactive) (insert "ℤ"))) ; integer
(global-set-key (kbd "H-y Q") (lambda () (interactive) (insert "ℚ"))) ; rational
(global-set-key (kbd "H-y R") (lambda () (interactive) (insert "ℝ"))) ; real
(global-set-key (kbd "H-y C") (lambda () (interactive) (insert "ℂ"))) ; complex
(global-set-key (kbd "H-y a") (lambda () (interactive) (insert "α"))) ; alpha
(global-set-key (kbd "H-y b") (lambda () (interactive) (insert "β"))) ; beta
(global-set-key (kbd "H-y g") (lambda () (interactive) (insert "γ"))) ; gamma
(global-set-key (kbd "H-y t") (lambda () (interactive) (insert "θ"))) ; theta
(global-set-key (kbd "H-y l") (lambda () (interactive) (insert "λ"))) ; lambda
(global-set-key (kbd "H-y p") (lambda () (interactive) (insert "π"))) ; pi
(global-set-key (kbd "H-y A") (lambda () (interactive) (insert "∀"))) ; FOR ALL
(global-set-key (kbd "H-y E") (lambda () (interactive) (insert "∃"))) ; THERE EXISTS
(global-set-key (kbd "H-y ^") (lambda () (interactive) (insert "∧"))) ; and
(global-set-key (kbd "H-y 6") (lambda () (interactive) (insert "∨"))) ; or
(global-set-key (kbd "H-y !") (lambda () (interactive) (insert "¬"))) ; not
(global-set-key (kbd "H-y =") (lambda () (interactive) (insert "≡"))) ; equivalent
(global-set-key (kbd "H-y +") (lambda () (interactive) (insert "≠"))) ; not equal
(global-set-key (kbd "H-*") (lambda () (interactive) (insert "°"))) ; degree

〔see Emacs: Bind Super Hyper Keys

I also had Emacs Abbrev:

〔see Emacs: Abbrev Mode

(define-abbrev-table 'global-abbrev-table '(
    ;; math/unicode symbols
    ("tin" "∈")
    ("nin" "∉")
    ("inf" "∞")
    ("luv" "♥")
    ("smly" "☺")
    ;;))

Note, now i replacement them all in a emacs package Emacs: xah-math-input.el

Keybinding and Input-System