Designing a 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.

Mac keyboard viewer us int 2017  41373
Mac keyboard viewer, with ⌥ option key down, US International layout, 2017. Those colored orange are prefix keys, allowing you to type accented characters such as {é ü ô}.

〔►see Mac Keyboard Viewer and Unicode

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 hundred of math symbols, and different people have different set of chars that's frequently used for them. (See: Math Symbols in UnicodeArrows in UnicodeMatching Brackets in Unicode)

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

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 How Mathematica does 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's 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 Keyboard: Alt Graph Key, Compose Key, Dead Key

In Mathematica, you press 【Esc abbrev Esc】 to insert a special char. 〔►see How Mathematica does 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

I also had Emacs Abbrev:

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

Now they are all gone. In replacement is a emacs minor mode Emacs: xah-math-input.el.