Skip to content

Compose

reminiscience edited this page Aug 13, 2026 · 1 revision

Compose

Compose sequences produce characters that no keyboard could hold. Press a modifier, then the parts of what you want, and the sequence resolves into a single character.

AnaNeo inherits a large body of X11-style compose sequences – about 6400 of them – and adds its own on top, arranged by a stated grammar. This page covers how to use them; Compose modules covers which files load, and Compose tool covers how to find out what exists.

Starting a sequence

Mod3+Tab starts a classic compose sequence – the Multi_key of X11 tradition.

Mod3+Tab  a  e     →  æ
Mod3+Tab  t  m     →  ™
Mod3+Tab  (  1  )  →  ①

Mod3+Tab is a trigger, not a key on a layer, which means it works in every lock state. Multi_key also sits on layer 3 of the Tab key, but layer 3 is out of reach while a block is locked – so the trigger is what makes the familiar grip keep working everywhere.

The other six starting characters are the modifiers on layer 21, reached by holding Mod3+Mod4.

The division of labour

The layer carries the grip, the tree carries the derivation.

A character may exist on a layer and in the compose tree. Superscript ² is on maths layer 7; it is also ˣ 2. That is two routes, not a contradiction: the layer is the fast grip for the handful you need constantly, the tree is the complete, derivable system behind it.

The rule draws its line elsewhere. A compose sequence that is part of a system stays even if the character is also on a key. A compose sequence that stands alone – a single entry mirroring a single key, part of no series – is a duplicate and gets cut.

There is deliberately no test for this. What counts as "alone" depends on a threshold with no natural break, and a test would force a number where the point is a judgement. ananeo-tool compose spiegel reports the cases and classifies them; a human decides.

The modifier alphabet

Six modifiers, all on layer 21:

Character Category Reaches
ˣ superscript 70 characters
subscript 37 characters
enclosure 264 characters
𝔵 font variant 1021 characters
rotation inherited sequences
˞ retroflex hook inherited sequences

The modifier character is the letter x with the transformation already applied. ˣ is a raised x, ⓧ a circled one, 𝔵 an x in another font. The two inherited ones do not follow the rule and are kept as named exceptions.

The grammar

A modifier leads a category. If the category has variants, they come as further characters before the base.

Order is always modifier, form, attribute, base. The tree stays unambiguous because each category satisfies one of two conditions: either it has no default variant, so the position after the modifier is always a variant and never a base – or its variant characters come from a stock that is never a base, namely brackets and punctuation.

Superscript and subscript

ˣ 2     →  ²
ˣ n     →  ⁿ
ₓ 5     →  ₅

Complete for what Unicode has: 70 raised characters, 37 lowered.

Font variants

After 𝔵 comes a family letter, then the base. Capitalising the family letter means bold. A / before the base means italic.

Six families: a antiqua, s script, r fraktur, d double-struck, l sans-serif (serifenlos), m monospace.

𝔵 d K      →  𝕂     double-struck
𝔵 A B      →  𝐁     antiqua bold
𝔵 a / B    →  𝐵     antiqua italic
𝔵 A / B    →  𝑩     antiqua bold italic
𝔵 s B      →  ℬ     script
𝔵 R B      →  𝕭     fraktur bold

𝔵 a B does not exist – that is an ordinary B.

The whole table is computed, not typed by hand: the Mathematical Alphanumeric Symbols block is a grid of six families by four styles, and the 24 holes in it are all filled from Letterlike Symbols. 1021 entries.

Enclosures

Default form is the circle; the variant characters (, [, . and ! are never bases.

ⓧ a        →  ⓐ     circled
ⓧ ( a      →  ⒜     parenthesised
ⓧ [ A      →  🄰     squared
ⓧ . 5      →  ⒌     with a full stop (digits only)
ⓧ ! A      →  🅐     negative circled
ⓧ [ ! A    →  🅰     negative squared

Not every combination exists – Unicode has squares and negatives for capitals only, dotted forms for digits only. Where there is no character, there is no sequence.

Sticky modifiers

Some modifiers keep the sequence open after producing a character instead of ending it. The next keypress continues at the modifier rather than starting over. ˣ, ₓ, ⓧ and 𝔵 all work this way:

ˣ 1 2 3    →  ¹²³

Three ways out:

  • A key with no compose entry – it types normally again and the mode ends.
  • Escape – discards the whole sequence, types nothing.
  • The modifier itself – a silent exit that types nothing.

The pitfall: x ˣ 2 y gives x²ʸ, not x²y. The y is still inside superscript mode. The way out is one more press of the modifier: x ˣ 2 ˣ yx²y.

With compose.oskAutoShow on, the on-screen keyboard shows which keys continue, which finish, and which exit – which makes sticky modes much easier to live with.

The generated modules

Two of the compose files in compose/ are computed from code, not maintained by hand:

  • ananeo-schrift.module – the 1021 font variants, from the six-by-four grid described above
  • ananeo-kreis.module – the 264 enclosed characters

Do not edit them. Regenerate instead:

ananeo-tool compose gen-schrift
ananeo-tool compose gen-kreis

A test holds each file against the calculation and fails if they diverge, naming the command to run. Generating them is not a convenience: a hand-typed table of 1021 entries would contain errors that nobody would ever find.

The third of AnaNeo's own modules, ananeo-hochtief.module, is the opposite – it is hand-maintained, because it cannot be computed. Unicode's decomposition data offers more than one candidate for some bases (ª alongside ᵃ for a raised a), and choosing between them is an editorial decision. A test checks every line of it against Unicode's decomposition field instead: correct base, no ordinal indicators, and the exact counts of 70 and 37.

Special modes

Two built-in routines, both started from a compose sequence and both ended by a space:

Unicode inputuu followed by a code point in hexadecimal:

Mod3+Tab  u u 1 f 5 7 4  ␣    →  🕴

Roman numeralsrn for lower case, RN for upper, then a number from 1 to 3999:

Mod3+Tab  r n 1 9 7 0  ␣      →  ⅿⅽⅿⅼⅹⅹ
Mod3+Tab  R N 1 9 7 0  ␣      →  ⅯⅭⅯⅬⅩⅩ

Both work while a block is locked. If the key you need carries something else on the locked layer – a hexadecimal f while Greek is locked, say – AnaNeo falls back to what that key would produce unlocked, so the digit still arrives.

What is not reachable

The inherited body contains sequences that cannot be typed on this keyboard: about 1400 of its 7800 endpoints start with, or pass through, a keysym no layer produces. Roughly 160 of those have no alternative route at all.

This is not an oversight but a consequence of inheriting a body designed for X11 keyboards with different dead keys. The rule that is enforced is narrower and more useful: every root of the tree must exist on a layer, so no branch is unreachable from the start. A test fails if one is not.

Clone this wiki locally