The Compose Key

% Remco Bloemen % 2014-02-27, last updated 2014-03-04

Unless you are shouting on online fora, the tab key is pretty much useless. I've remapped it to a compose key. With XCompose you can enter all sorts of unicode characters using the compose key followed by key sequences. But, the format to configure this is a bit verbose:

<Multi_key> <A> <A> : "∀"
<Multi_key> <C> <c> : "∁"
<Multi_key> <p> <d> : "∂"
<Multi_key> <E> <E> : "∃"
<Multi_key> <slash> <E> <E> : "∄"
<Multi_key> <q> <e> <d> : "∎"
<Multi_key> <slash> <o> : "∅"
<Multi_key> <plus> <minus> : "±"
<Multi_key> <minus> <plus> : "∓"
<Multi_key> <v> <slash> : "√"
<Multi_key> <slash> <asciitilde> <minus> : "≄"
<Multi_key> <asciitilde> <equal> : "≅"
<Multi_key> <slash> <asciitilde> <equal> : "≇"
<Multi_key> <asciitilde> <asciitilde> <space> : "≈"

To fix this I developed my own specification format that compiles to the above format. It looks like:

∀     AA
∁     Cc
∂     pd
∃     EE
∄     /EE
∎     qed
∅     /o
±   +-
∓     -+
√     v/
≄     /~-
≅     ~=
≇     /~=
≈     ~~
#!/usr/bin/python
# coding=utf-8
import sys

XComposeNames = {
	"~": "asciitilde",  "=": "equal",       "-": "minus",
	"_": "underscore",  "+": "plus",        ">": "greater",
	"<": "less",        "|": "bar",         "/": "slash",
	"\": "backslash",  ".": "period",      "!": "exclam",
	":": "colon",       "^": "asciicircum", "?": "question",
	"(": "parenleft",   ")": "parenright",  "[": "bracketleft",
	"]": "bracketright","`": "grave",       "'": "apostrophe",
	""": "quotedbl",   " ": "space",       ",": "comma",
	"@": "at",          "#": "numbersign",  "$": "dollar",
	"%": "percent",     "*": "asterisk",   u"←": "Left",
	u"↑": "Up",        u"→": "Right",      u"↓": "Down",
}

def XComposeSequence(s, target):
	seq = "<Multi_key> "
	for c in s:
		if c in XComposeNames:
			seq += "<" + XComposeNames[c] + "> "
		else:
			seq += "<" + c + "> "
	seq += ": "" + target + """
	return seq

sequences = {}
while True:
	try: line = raw_input().decode("utf-8");
	except EOFError: break
	if line == "" or line[0] == "#":
		print line.encode("utf-8")
		continue
	target, sequence = line.split("t", 2)
	for s in sequences.iterkeys():
		if s.startswith(sequence) or sequence.startswith(s):
				sys.stderr.write(("WARNING: sequence "" + sequence +
					"" for "" + target + "" clashes with " +
					"previous sequence "" + s + "" for "" +
					sequences[s] + ""n").encode("utf-8"))
	sequences[sequence] = target
	print XComposeSequence(sequence, target).encode("utf-8")
$ ./XCompile < UnicodeMath > ~/.XCompose && setxkbmap

xmodmap -pke

Full source is available on https://github.com/Recmo/XCompile.

Remco Bloemen
Math & Engineering
https://2π.com