Associate Teaching Professor of Linguistics at UC San Diego
Director of UCSD's Computational Social Science Program
Using Espanso to type in the International Phonetic Alphabet
February 16th, 2023
Although I’ve long tried to educate the world about using IPA keyboards on MacOS, in practice, in 2023, I almost never use a dedicated IPA layout, and have switched almost entirely to a different method of IPA text entry, that is, using ‘snippet expander’ tools like Espanso.
The Problems with IPA Keyboards
IPA keyboards are great if you’re doing a lot of IPA. For long, continuous strings of IPA text with a large number of non-ASCII characters, you’re hard-pressed to find a more efficient way to input than using a full IPA keyboard. However, that’s not my life, at least for the last few years.
Instead, as a college professor and phonetician working largely with English and bits and pieces of a few other languages, in practice, I end up writing bits and pieces of IPA, and mostly the same few dozen symbols, over and over. So, IPA keyboards are a bit of a pain, because they’re…
- Modal, requiring me to switch keyboards to write chunks of IPA
- Not Cross-Platform, which is frustrating as a person who uses both MacOS and Linux regularly
- Often unintuitive, requiring long sequences of deadkeys for things I regularly type (e.g. Ṽ)
Instead, I’d rather be able to write, and then, wɛn aj wɑnə swɪt͡ʃɾə aj pi ej from time to time, just keep typing and create IPA characters without bɹejkɪŋ maj train of thought.
Enter Espanso
I’ve used lots of ‘snippet expansion’ programs. At the simplest
level, these allow you to exchange short strings for longer ones
(e.g. automatically changing :spcv
when typed followed by a
space into https://savethevowels.org/
, or any other
substitution you configure), and are even then, wildly useful. They’re
also handy for fixing common errors (e.g. ‘liek’ gets exchanged for
‘like’ automagically), swapping in emoji in apps that don’t support them
(e.g. :rofl
turning into 🤣 for us millenials), and for
writing the same thing over and over again (e.g. dumping my email
signature when I type :wsig
). You can even use dynamic
expansion, such that :isotime
, typed right now, writes
2023-02-16T15:55:07.353421199-08:00
, but typed again,
writes 2023-02-16T15:55:23.949788229-08:00
. I have a mix of
these kinds of macros which I use on a regular basis.
I’ve used many programs which do this, first TextExpander, then the (much more powerful) Alfred for MacOS. But as I moved to Linux, and as I tried to move to more free software, a student pointed out Espanso, which is a free, cross-platform tool for this task, which handily configures using a specific yml file format which I can sync across platforms.
The best part of these tools is that you can set a large dictionary of substitutions, including short sequences which turn into a single character.
IPA with Espanso
So, rather than switching keyboards, then using a complex sequence of
deadkeys to produce an /ɾ̃/, I just type the ;ntap
and it is
replaced with ɾ̃
. This works because I’ve added an entry to
my espanso/match/base.yml
file with:
- trigger: ";ntap"
replace: "ɾ̃"
Which makes the magic happen. I’ve simply added new macros for regularly used IPA, and for my life, this is about as efficient, and much better than or going online and using an online IPA keyboard. I’ve also added a number of symbols, greek letters, math symbols, and other characters which I regularly use, along with common snippets of text. I’ve chosen semicolon as the prefix for IPA, because simply put, I don’t use them, so it’s basically an extra key which is easy to type without modifiers. Given the flexibility of the format, it’s pretty easy to add anything you’d like to this file.
How well does it work?
Honestly, for me, quite well. Typing three ASCII keys for one IPA character may feel inefficient, but compared to switching keyboards, then entering a deadkey sequence, it’s not markedly less efficient. And after a while, it becomes pretty second nature.
This does have the downside that you need to create entries for each new IPA symbol you want to use. But I’ve found there’s cognitive benefit to seeing what I think the abbreviation should be, only to find it not working, and then adding it to your config file. And in cases where there’s an oddball IPA character I need, but which I don’t need enough to macro, I can just use an online IPA keyboard to compose and grab the symbol I need.
One other downside is that it is currently set to expand without
spaces, so you can’t have two macros that share the same initial string
(e.g. ;sch
cannot co-exist with ;schr
, as
it’ll automatically expand before you ‘finish’). But this can be fixed
by adding spaces, or cleverly naming your expansion triggers.
It’s also the case, still, that not every program supports unicode
and IPA at all, and some apps may not cleanly accept unicode pastes on
Linux (e.g. the kitty
terminal).
But on the whole, this makes me IPA capable on Mac and Linux, with the same abbreviations and workflow, and without using additional keyboard layouts, and without breaking my stride while writing. It’s probably not ideal for people writing large chunks of IPA over and over, but the core insight could be used for many kinds of ‘grab bag’ symbol use.
My espanso config
Here’s the portion of my espanso/match/base.yml
configuration for IPA, other symbols, and some accent marks and
diacritics. This is current as of 2023-02-16T16:41:37.192468579-08:00
(thanks Espanso!). Note the Unicode code points for some items, which
shows that you can use Unicode codepoints here, too!
#### IPA ####
- trigger: ";ng"
replace: "ŋ"
- trigger: ";beta"
replace: "β"
- trigger: ";gamma"
replace: "ɣ"
- trigger: ";ae"
replace: "æ"
- trigger: ";zh"
replace: "ʒ"
- trigger: ";r"
replace: "ɹ"
- trigger: ";gs"
replace: "ʔ"
- trigger: ";ntap"
replace: "ɾ̃"
- trigger: ";opo"
replace: "ɔ"
- trigger: ";tap"
replace: "ɾ"
- trigger: ";th"
replace: "θ"
- trigger: ";oo"
replace: "ʊ"
- trigger: ";asp"
replace: "ʰ"
- trigger: ";uh"
replace: "ʌ"
- trigger: ";zero"
replace: "Ø"
- trigger: ";ba"
replace: "ɑ"
- trigger: ";ch"
replace: "t͡ʃ"
- trigger: ";dz"
replace: "d͡ʒ"
- trigger: ";eh"
replace: "ɛ"
- trigger: ";sh"
replace: "ʃ"
- trigger: ";eth"
replace: "ð"
- trigger: ";ih"
replace: "ɪ"
- trigger: ";nn"
replace: "ñ"
- trigger: ";sch"
replace: "ə"
- trigger: ";nasv"
replace: "Ṽ"
#### Composes ####
- trigger: ";;oo"
replace: "\u00b0"
# Ess set
- trigger: ";;ss"
replace: "\u00df"
# Spanish Punctuation
- trigger: ";;!"
replace: "\u00a1"
- trigger: ";;?"
replace: "\u00bf"
# Math
- trigger: ";;=/"
replace: "\u2260"
- trigger: ";;=~"
replace: "\u2248"
- trigger: ";;<>"
replace: "\u2260"
- trigger: ";;=>"
replace: "\u2265"
- trigger: ";;=<"
replace: "\u2264"
- trigger: ";;+-"
replace: "\u00b1"
# Partial Derivative
- trigger: ";;dd"
replace: "\u2202"
# ∆
- trigger: ";;delta"
replace: "\u2206"
# λ
- trigger: ";;lambda"
replace: "\u03bb"
# π
- trigger: ";;pi"
replace: "\u03c0"
# Norsk ø
- trigger: ";;o/"
replace: "\u00f8"
- trigger: ";;O/"
replace: "\u00d8"
# Accents
- trigger: ";;`"
replace: "\u0300"
- trigger: ";;'"
replace: "\u0301"
- trigger: ";;^"
replace: "\u0302"
- trigger: ";;~"
replace: "\u0303"
- trigger: ";;.."
replace: "\u0308"
- trigger: ";;-"
replace: "\u0305"
- trigger: ";;v"
replace: "\u030c"
# µ
- trigger: ";;mu"
replace: "\u00b5"