About text automation

7 minute read

This post includes an audio version. If you prefer that you can listen here or on the JAL Audioblog Podcast

I have been using text automation heavily for the last ten years. I’m a text person, so I write a lot. Keeping consistency and not retyping the same things over and over is essential. But what is “text automation”? I use this term to refer to shortcuts to generate text snippets.

For example, I say good morning to my team every day, but I do not need to write it. I just type :gm, and that becomes:

:wave: Good morning, everybody! 
/status :office: In the office

Here I’m saying good morning to my team and set my status on the chat applications. As you can imagine, I use the same approach for saying: coffee break, lunch, away from the keyboard, focus mode and out. Here I’m maximizing my communication while minimizing my typing.

You only implement some of those at a time. Adding new automation when you have mastered the ones you have already designed. With time, I ended up with many of them I use constantly. But those are the simple ones. I also have some complex automation that I’ll comment on later.

When I started with this years ago, I tried several applications, but I always returned to Typinator.

From Typinator 

Typinator is a commercial software by Ergonis Software. It is an efficient tool with a not-so-great interface that hasn’t evolved since I’ve used it. But it is relatively easy to use and could be an excellent tool for starting with text automation, especially if you are not a developer or tech-savvy.

I was happy with Typinator, paying for all the upgrades since they were relatively inexpensive. But it became difficult to work when you wanted to do more advanced stuff like creating your own scripts. You can create your scrips in Ruby, Python or Shell, but it feels obscure. Like the tool was not designed for that. I contacted their tech support, and they did answer the questions I asked them, but It became clear to me that I’ll be wasting my time fighting the tool. At that point, I decided to search for an alternative and found Espanso.

To Espanso

Espanso is an open-source project by Federico Terzi. As he explains it, it was his pet project to learn Rust. I read the documentation first and was surprised at how well it matched what I was looking for. It is a more technical tool since it doesn’t have a user interface. Instead, it is all configured with text files you can locate anywhere in your system.

I had no problems migrating all my basic expansions, and in two days’ work, I created a Python script that does more advanced expansions and integrates perfectly with the tool.

The documentation is excellent and easy to read. It is built incrementally, covering from the most straightforward cases to advances uses. Reading it, I was directly migrating most of my automation to the new format with ease.

One of the key points for me is being able to define all my expansions on text files with a simple format, “YAML”, in this case. I split them into different files and moved them to my bin folder under git. That keeps my setup simple, clean and easy to maintain.

The tools behave as expected. Even when you make mistakes on expansions format or integration with the shell, it provides excellent mechanisms to debug and find the problem. That was surprising for this kind of tool.

One note, I’m using macOS, and I haven’t used the tool on Windows or Linux, so I can not comment on that.

Basic expansions

I won’t explain how the tool works here because, as I said, the documentation does a great job explaining it. It will take no more than 30 minutes to read it, and you will be on your way to taking advantage of Espanso. Instead, I’ll explain some of the daily uses for me.

Dates and times

In my daily notes and diary, I use time and date stamps all over the place, so I have some of them defined there:

# These a re global variables that I'll use later
  - name: "short_date"
    type: date
      format: "%Y-%m-%d"
  - name: "compact_date"
    type: date
      format: "%y%m%d"
  - name: "time"
    type: date
      format: "%k:%M"

# And these are the expansions.
  - triggers: [":date", ":dt "]
    label: "Insert the date with the format 2022-10-12"
    replace: ""

  - triggers: [":t ", ":time"]
    label: "Insert time with with the format 9:30"
    replace: ""  

  - triggers: [":tf ", ":timeFenced"]
    label: "Insert time with with the format (9:30)"
    replace: "()"  


I do not want to type my telephone, address or e-mail, so I have shortcuts for those as well. And, of course, I use the same with the personal data of my family; their IDs or Social Security numbers are all expansions.


As I explained, I also use expansions to inform my team about my status and set the state in the chat room. I even use it to add emojis combinations to my messages. Here is an example in which I inform my team I’ll be out for a bit and change my state in the chat application.

  - triggers: [":afk ", ":chat_away_from_keyboard"]
    label: "Say afk on chat and update status" 
    replace: |
      :stopwatch: AFK :keyboard:
      /status :runner: Away From Keyboard


We use Google Meet as our meeting tool. I have shortcuts for some channels’ URLs, so I can paste them quickly on chat and go there without using the mouse: Cmd+L :meet . I also expand it in chat whenever I want to start an impromptu meeting so that the rest of the participants only have to click on it to enter.

Git and Github

I have some triggers for Git and Github that only function on the terminal. That way, it does not affect other applications. GitHub on CLI uses quite long commands. As an example, using :cpr (read as “create pull request”) becomes:

gh pr create --base develop --reviewer "Teamwork/ios-devs" --assignee josealobato --label 

With the cursor at the end, ready to type the label associated with the pull request.

Programming languages

I have a bunch of snippets for some constructions that I repeat all the time. For example, creating a test case in PyTest with Given/When/Then construction, or, also in PyTest, disabling a test. I go making those as I feel the need. Whenever I see that, I could gain brain power by avoiding typing repetitive text snippets.

espanso offering options
espanso offering options

Advanced options

I’m using all kinds of expansions in my setup, from the basics to random selections or small forms. But, to keep consistency in my Personal Knowledge Management System (PKM), I must create all kinds of entries. Every entry has different tags but the same title format, references and links to shared resources. All that I achieve with a Python Script that I launch with Espanso.

I use Espanso to gather information nicely with a Form and then trigger the command line python script to do the rest, which works perfectly. On Python, I use YAML for configuration and Jinja2 to manage templates.

That way, when I need to create a new entry on my PKM, I just type :kbe (meaning “Knowledge Base Entry”) and the form appears; I type the title, the source link, select the subject and some other things and the right template is expanded.

The same I use for blogging. My blog entries are massive in configuration, and I have many checkboxes to avoid forgetting steps. I use the same :kbe expansion for that.

espanso form
espanso form

You can see all that on the attached file at the end of this post. There you will find the expansions and the python scripts with some documentation.

All under control version

Another essential thing for me is having all my configuration in my ~/bin folder that I keep under version control (git). The textual configuration files make this very easy to manage and keep in sync with other computers.

In the documentation, you can find steps to move the configuration files to any folder while allowing Espanso to find them.

Wish list

I do not miss a user interface, but I miss a few things. One is the possibility of keeping the forms filled with the last values used. Sometimes I make mistakes filling out the form, and I need to fill it all again if I re-trigger it.

Also, I was looking for ways to better use the clipboard. Some fields on the forms could get automatically populated with the clipboard content.

Another minor thing is a more human date representation. Sometimes I would like to expand my dates to something like: “Tuesday, January 2nd, 2022”. Weird, I know, but I like that stuff.


I really like Espanso. If you are sold on the importance of text expansions, I encourage you to read the Espanso documentation, and you will see how easy it is to set it up and start expanding everywhere.

If you do, please donate something for the great job of Federico Terzi and the other collaborators. Thanks, you guys did make an impact here.

In this container, you will find most of my expansions. I did omit the ones that contained sensitive information.