Will Styler's Homepage
Will Styler

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…

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"