On my GNU/Linux system, the Compose key is my
favourite method for typing any kind of “special” (or not-so-special)
characters, such as typographically correct punctuation marks (e.g., dashes,
quotes, thin spaces…), diacritics, or characters from foreign languages (e.g.
greek letters). It works independently of the application I am using (contrary
to, say, Vim’s digraphs)
and independently of the keyboard layout; also, compose key sequences are
generally quite “intuitive” (e.g., Compose + hypen + hypen + hypen
for an em dash, Compose + hyphen + hypen + full stop
for an en
dash) and can easily be customised as needed.
While there is no such thing as a Compose key mechanism on macOS, it is quite easy to emulate it using macOS’s built-in Key Bindings system.
All that is needed is a
~/Library/KeyBindings/DefaultKeyBinding.dict
file (to be created
if such a file does not already exist). This file allows to associate an
arbitrary action to a key or to a combination of key. For example, the
following configuration associates the hyphen
key to an action
that inserts an em dash (do not use that example: it would prevent
you from ever being able to type a normal hypen again! this is just to
illustrate the principle):
{ "-" = ("insertText:", "\U2014"); }
This other example illustrates how to associate actions to key combinations instead of single keys:
{ "-" = { "-" = ("insertText:", "\U2014"); "." = ("insertText:", "\U2013"); }; }
Here, typing the hypen
key twice will insert an em dash
(U2014), while typing successively the hyphen
key and the
full stop
key will insert an en dash (U2013).
From the above, it is easy to define key bindings that emulate the behaviour of a compose key. All that is needed is to choose a key that will act as the Compose key, and then to define a series of combinations that all start with that key.
On my professional Apple machine (which I use with a PC-type keyboard,
not an Apple keyboard), I have chosen the left-side “menu” key, which
has the key code \U0010
(found by trial-and-error). I then creted
the following DefaultKeyBinding.dict
file, defining the Compose
sequences that I use the most:
{ "\U0010" = { /* Compose-like key */ "-" = { "m" = ("insertText:", "\U2212"); /* MINUS SIGN */ "+" = ("insertText:", "\U2213"); /* MINUS-OR-PLUS SIGN */ "-" = { "." = ("insertText:", "\U2013"); /* EN DASH */ "-" = ("insertText:", "\U2014"); /* EM DASH */ }; "0" = ("insertText:", "\U2080"); /* SUBSCRIPT 0 */ "1" = ("insertText:", "\U2081"); /* SUBSCRIPT 1 */ "2" = ("insertText:", "\U2082"); /* SUBSCRIPT 2 */ "3" = ("insertText:", "\U2083"); /* SUBSCRIPT 3 */ "4" = ("insertText:", "\U2084"); /* SUBSCRIPT 4 */ "5" = ("insertText:", "\U2085"); /* SUBSCRIPT 5 */ "6" = ("insertText:", "\U2086"); /* SUBSCRIPT 6 */ "7" = ("insertText:", "\U2087"); /* SUBSCRIPT 7 */ "8" = ("insertText:", "\U2088"); /* SUBSCRIPT 8 */ "9" = ("insertText:", "\U2089"); /* SUBSCRIPT 9 */ }; "_" = { "0" = ("insertText:", "\U2070"); /* SUPERSCRIPT 0 */ "1" = ("insertText:", "\U2071"); /* SUPERSCRIPT 1 */ "2" = ("insertText:", "\U00B2"); /* SUPERSCRIPT 2 */ "3" = ("insertText:", "\U00B3"); /* SUPERSCRIPT 3 */ "4" = ("insertText:", "\U2074"); /* SUPERSCRIPT 4 */ "5" = ("insertText:", "\U2075"); /* SUPERSCRIPT 5 */ "6" = ("insertText:", "\U2076"); /* SUPERSCRIPT 6 */ "7" = ("insertText:", "\U2077"); /* SUPERSCRIPT 7 */ "8" = ("insertText:", "\U2078"); /* SUPERSCRIPT 8 */ "9" = ("insertText:", "\U2079"); /* SUPERSCRIPT 9 */ }; "g" = { /* Fly pushing stuff */ "m" = ("insertText:", "\U2642"); /* MALE */ "f" = ("insertText:", "\U2640"); /* FEMALE */ "F" = ("insertText:", "\U263F"); /* VIRGIN FEMALE */ "y" = ("insertText:", "\U21C1"); /* Y CHROMOSOME */ }; "G" = { /* Greek letters */ "A" = ("insertText:", "\U0391"); /* GREEK CAPITAL LETTER ALPHA */ "B" = ("insertText:", "\U0392"); /* GREEK CAPITAL LETTER BETA */ "G" = ("insertText:", "\U0393"); /* GREEK CAPITAL LETTER GAMMA */ "D" = ("insertText:", "\U0394"); /* GREEK CAPITAL LETTER DELTA */ "E" = ("insertText:", "\U0395"); /* GREEK CAPITAL LETTER EPSILON */ "Z" = ("insertText:", "\U0396"); /* GREEK CAPITAL LETTER ZETA */ "Y" = ("insertText:", "\U0397"); /* GREEK CAPITAL LETTER ETA */ "H" = ("insertText:", "\U0398"); /* GREEK CAPITAL LETTER THETA */ "I" = ("insertText:", "\U0399"); /* GREEK CAPITAL LETTER IOTA */ "K" = ("insertText:", "\U039A"); /* GREEK CAPITAL LETTER KAPPA */ "L" = ("insertText:", "\U039B"); /* GREEK CAPITAL LETTER LAMBDA */ "M" = ("insertText:", "\U039C"); /* GREEK CAPITAL LETTER MU */ "N" = ("insertText:", "\U039D"); /* GREEK CAPITAL LETTER NU */ "C" = ("insertText:", "\U039E"); /* GREEK CAPITAL LETTER XI */ "O" = ("insertText:", "\U039F"); /* GREEK CAPITAL LETTER OMICRON */ "P" = ("insertText:", "\U03A0"); /* GREEK CAPITAL LETTER PI */ "R" = ("insertText:", "\U03A1"); /* GREEK CAPITAL LETTER RHO */ "S" = ("insertText:", "\U03A3"); /* GREEK CAPITAL LETTER SIGMA */ "T" = ("insertText:", "\U03A4"); /* GREEK CAPITAL LETTER TAU */ "U" = ("insertText:", "\U03A5"); /* GREEK CAPITAL LETTER UPSILON */ "F" = ("insertText:", "\U03A6"); /* GREEK CAPITAL LETTER PHI */ "X" = ("insertText:", "\U03A7"); /* GREEK CAPITAL LETTER CHI */ "Q" = ("insertText:", "\U03A8"); /* GREEK CAPITAL LETTER PSI */ "W" = ("insertText:", "\U03A9"); /* GREEK CAPITAL LETTER OMEGA */ "a" = ("insertText:", "\U03B1"); /* GREEK SMALL LETTER ALPHA */ "b" = ("insertText:", "\U03B2"); /* GREEK SMALL LETTER BETA */ "g" = ("insertText:", "\U03B3"); /* GREEK SMALL LETTER GAMMA */ "d" = ("insertText:", "\U03B4"); /* GREEK SMALL LETTER DELTA */ "e" = ("insertText:", "\U03B5"); /* GREEK SMALL LETTER EPSILON */ "z" = ("insertText:", "\U03B6"); /* GREEK SMALL LETTER ZETA */ "y" = ("insertText:", "\U03B7"); /* GREEK SMALL LETTER ETA */ "h" = ("insertText:", "\U03B8"); /* GREEK SMALL LETTER THETA */ "i" = ("insertText:", "\U03B9"); /* GREEK SMALL LETTER IOTA */ "k" = ("insertText:", "\U03BA"); /* GREEK SMALL LETTER KAPPA */ "l" = ("insertText:", "\U03BB"); /* GREEK SMALL LETTER LAMBDA */ "m" = ("insertText:", "\U03BC"); /* GREEK SMALL LETTER MU */ "n" = ("insertText:", "\U03BD"); /* GREEK SMALL LETTER NU */ "c" = ("insertText:", "\U03BE"); /* GREEK SMALL LETTER XI */ "o" = ("insertText:", "\U03BF"); /* GREEK SMALL LETTER OMICRON */ "p" = ("insertText:", "\U03C0"); /* GREEK SMALL LETTER PI */ "r" = ("insertText:", "\U03C1"); /* GREEK SMALL LETTER RHO */ "v" = ("insertText:", "\U03C2"); /* GREEK SMALL LETTER FINAL SIGMA */ "s" = ("insertText:", "\U03C3"); /* GREEK SMALL LETTER SIGMA */ "t" = ("insertText:", "\U03C4"); /* GREEK SMALL LETTER TAU */ "u" = ("insertText:", "\U03C5"); /* GREEK SMALL LETTER UPSILON */ "f" = ("insertText:", "\U03C6"); /* GREEK SMALL LETTER PHI */ "x" = ("insertText:", "\U03C7"); /* GREEK SMALL LETTER CHI */ "q" = ("insertText:", "\U03C8"); /* GREEK SMALL LETTER PSI */ "w" = ("insertText:", "\U03C9"); /* GREEK SMALL LETTER OMEGA */ }; "?" = { "?" = ("insertText:", "\U2E2E"); /* IRONY MARK */ "-" = ("insertText:", "\U2243"); /* ASYMPTOTICALLY EQUAL TO */ "=" = ("insertText:", "\U2248"); /* ALMOST EQUAL TO */ }; "d" = { "d" = ("insertText:", "\U00B0"); /* DEGREE SIGN */ "C" = ("insertText:", "\U2103"); /* CELSIUS DEGREE */ "F" = ("insertText:", "\U2109"); /* FARENHEIT DEGREE */ }; "x" = { "x" = ("insertText:", "\U2A09"); /* N-ARY TIMES OPERATOR */ }; "\U0020" = { "\U0020" = ("insertText:", "\U00A0"); /* NO-BREAK SPACE */ "." = ("insertText:", "\U2008"); /* PUNCTUATION SPACE */ "," = ("insertText:", "\U202F"); /* NARROW NO-BREAK SPACE */ "!" = ("insertText:", "\U200B"); /* ZERO WIDTH SPACE */ }; "c" = { "o" = ("insertText:", "\U00A9"); /* COPYRIGHT SIGN */ }; }; }
Unrelated to the Compose emulation, the same
DefaultKeyBinding.dict
file can be used to fix the very
annoying default behaviour of the Home
and End
keys
on macOS. Those keys move the cursor to the beginning and end of the
viewport, instead of moving it to the beginning and end of the
current line. This is not what I expect from those keys, so I use the
following additions to the DefaultKeyBinding.dict
file:
{ /* Sane behavior for Home and End keys. */ "\UF729" = "moveToBeginningOfLine:"; "\UF72B" = "moveToEndOfLine:"; "$\UF729" = "moveToBeginningOfLineAndModifySelection:"; "$\UF72B" = "moveToEndOfLineAndModifySelection:"; "^\UF729" = "moveToBeginningOfDocument:"; "^\UF72B" = "moveToEndOfDocument:"; "^$\UF729" = "moveToBeginningOfDocumentAndModifySelection:"; "^$\UF72B" = "moveToEndOfDocumentAndModifySelection:"; }
Now, the Home
key will move the cursor to the beginning of the
line; only when it is combined with the Ctrl
key, will it move
the cursor to the beginning of the viewport; combined with the
Shift
key, it will move the cursor and select the text
on the way. Likewise for the End
key and the end of the line or
end of the viewport.
You can add a comment by replying to this message on the Fediverse.