Home / Alt manpages / xcompose(5)

  • xcompose(5)
  • File format
  • linux

Add Reliable Custom XCompose Sequences Without Losing Defaults

You will add a personal XCompose rule, keep the system's existing compose mappings, and test the resulting file without changing system files. The example creates a sequence that inserts the text -> when you press Compose, then -, then >. Replace that rule with a useful sequence of your own once the test works.

Allow about fifteen minutes. You need an X11 client that uses Xlib compose input, a working Compose key, and a text editor. The installed reference here is libX11 1.8.7, supplied by Debian package libx11-data 2:1.8.7-1build1. Wayland applications, toolkit input methods and applications that do not use Xlib may not read this file.

This guide changes only your user configuration. It does not edit the system Compose database or require sudo.

1. Check the locale and the active Compose file

First, inspect the locale that X clients inherit. This is an ordinary, read-only command:

$ locale | sed -n '1,8p'
LANG=C.UTF-8
LANGUAGE=
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"

Your values will differ. The locale affects the system Compose file selected when there is no user override, and it can also affect the result of a rule that names a keysym without specifying a string.

libX11 searches for the Compose file in this order: $XCOMPOSEFILE, then $HOME/.XCompose, then the locale-mapped system file. Check whether the first two choices already exist:

$ if [ -n "${XCOMPOSEFILE:-}" ]; then
>     printf 'XCOMPOSEFILE=%s\n' "$XCOMPOSEFILE"
>     ls -l -- "$XCOMPOSEFILE"
> else
>     printf 'XCOMPOSEFILE is not set\n'
> fi
$ if [ -f "$HOME/.XCompose" ]; then
>     ls -l -- "$HOME/.XCompose"
> else
>     printf '%s\n' '$HOME/.XCompose does not exist'
> fi

Checkpoint

If XCOMPOSEFILE points to another file, creating ~/.XCompose will not affect clients that keep that environment variable. Decide whether to unset it for the session you are testing or edit the file it names.

2. Create a user file that includes the defaults

A user file replaces the normal selection, so a file containing only your new rule can make familiar sequences disappear. Include the locale-specific system file first, then add your rule. The %L substitution means the Compose file selected for the current locale:

$ cp --preserve=all "$HOME/.XCompose" "$HOME/.XCompose.backup" 2>/dev/null || true
$ editor "$HOME/.XCompose"

Put these lines in the file:

include "%L"

<Multi_key> <minus> <greater> : "->"

Multi_key is the keysym normally assigned to the Compose key. The three events are the keysyms for minus and greater-than, followed by a result string. The result is deliberately a string, so the X client receives two characters rather than a locale-dependent named keysym.

The first command above makes a backup only when an old file already exists. If the file did not exist, the shell's failed cp is intentionally ignored. The editor command is a placeholder: replace editor with nano, vim or another editor installed on your machine.

Warning

Do not overwrite an existing file blindly. If you have personal rules already, add the include line near the top and keep those rules below it. The later rule can replace an earlier matching rule.

3. Check the file before restarting anything

Read back the relevant lines and check that the file is readable. This does not load or modify an X server:

$ test -r "$HOME/.XCompose" && echo 'Compose file is readable'
Compose file is readable
$ sed -n '1,12p' "$HOME/.XCompose"
include "%L"

<Multi_key> <minus> <greater> : "->"

Compose syntax has one rule per line. A comment begins with #. The colon separates the input events from the result. Keysyms are written without the XK_ prefix, so use <greater>, not <XK_greater>.

Keep literal angle brackets escaped when copying the rule into HTML documentation, but write ordinary angle brackets in the actual file. In the real .XCompose, the rule must be exactly <Multi_key> <minus> <greater> : "->" as shown by sed.

4. Start a fresh X client and test the sequence

Compose mappings are read by the client input stack. Close and reopen the application you want to test after saving the file. A running terminal may keep its old mapping until it is restarted.

In a text field, press the Compose key, release it, press -, release it, then press >. The expected result is:

->

Test in a simple X11 application first. If the sequence appears as separate characters or nothing appears, do not keep changing the rule at random. Check the failure in order:

  1. Confirm that the application is an X11 client and that it was restarted.
  2. Confirm that the Compose key is actually producing Multi_key in your keyboard layout.
  3. Confirm that XCOMPOSEFILE is empty or names the file you edited.
  4. Confirm that the test client inherited the same HOME and locale as your shell.

A missing result is not proof that the syntax is wrong. The file may be correct while the application uses another input method or has not reloaded it.

5. Make rules exact when modifiers matter

By default, a rule can match the listed keysyms with modifier states that are not explicitly constrained. Use an exact modifier list when accidental Shift, Ctrl, Alt or Meta state would be dangerous. For example, this rule requires Shift and rejects Alt:

!<Shift>~Alt <Multi_key> <c> : "copyright"

The exclamation mark makes the modifier requirements exact. A tilde before a modifier means that modifier must not be present. The special event None means that no modifier may be present. Start with the simple rule unless you have a clear reason to constrain modifiers; over-specific rules are a common reason a sequence appears to stop working.

For a single character, you can return a keysym instead of a string, for example:

<Multi_key> <o> <c> : copyright

A named keysym is resolved for the current locale. Use a quoted string or an escaped octal or hexadecimal code when the exact text matters. The manual's forms are "\123" for octal and "\x3a" for hexadecimal.

6. Undo the change or isolate a broken rule

To return to the previous user configuration, remove the new rule and keep the original include, or restore the backup you made before editing:

$ cp --preserve=all "$HOME/.XCompose.backup" "$HOME/.XCompose"
$ printf '%s\n' 'Restored the previous user Compose file'

Restart affected X clients and test again. If there was no backup because the file was new, move the file aside rather than deleting it:

$ mv -- "$HOME/.XCompose" "$HOME/.XCompose.disabled"
$ printf '%s\n' 'Disabled the user Compose override; restart affected clients'

This is reversible: move .XCompose.disabled back to .XCompose when you want to retry. Do not clear system caches or edit /usr/share/X11/locale to solve a user-rule problem. libX11 may cache compiled Compose data, but its documented cache locations are separate from the source file and system-wide changes require elevated privileges.

Done means

  • The installed libX11 version and active locale are known.
  • Your user file includes %L when existing system mappings need to remain available.
  • Your custom rule uses valid keysyms, a colon and an explicit result.
  • A newly started X11 client produces the intended result.
  • You know how to distinguish a stale client, wrong Compose key and wrong file path.
  • You have a backup or a reversible disabled copy before further edits.