Extensions
Extensions are the heart of Espanso's dynamic matches and can be used to accomplish complex tasks.
Date Extension
The Date Extension can be used to include date and time information in a match.
For example, the following match will be expanded into It's 09:30
if triggered at 9:30 am:
- trigger: ":now"
replace: "It's {{mytime}}"
vars:
- name: mytime
type: date
params:
format: "%H:%M"
The most important aspect to consider is the format
parameter,
which specifies how the date will be rendered.
To see a list of all the possible formatting options, click here.
Date specifiers
Option | Example | Description |
---|---|---|
%Y | 2001 | The full proleptic Gregorian year, zero-padded to 4 digits. |
%C | 20 | The proleptic Gregorian year divided by 100, zero-padded to 2 digits. |
%y | 01 | The proleptic Gregorian year modulo 100, zero-padded to 2 digits. |
%m | 07 | Month number (01--12), zero-padded to 2 digits. |
%b | Jul | Abbreviated month name. Always 3 letters. |
%B | July | Full month name. Also accepts corresponding abbreviation in parsing. |
%h | Jul | Same as %b . |
%d | 08 | Day number (01--31), zero-padded to 2 digits. |
%e | _ 8_ | Same as %d but space-padded. Same as %_d . |
%a | Sun | Abbreviated weekday name. Always 3 letters. |
%A | Sunday | Full weekday name. Also accepts corresponding abbreviation in parsing. |
%w | 0 | Sunday = 0, Monday = 1, ..., Saturday = 6. |
%u | 7 | Monday = 1, Tuesday = 2, ..., Sunday = 7. (ISO 8601) |
%U | 28 | Week number starting with Sunday (00--53), zero-padded to 2 digits. |
%W | 27 | Same as %U , but week 1 starts with the first Monday in that year instead. |
%G | 2001 | Same as %Y but uses the year number in ISO 8601 week date. |
%g | 01 | Same as %y but uses the year number in ISO 8601 week date. |
%V | 27 | Same as %U but uses the week number in ISO 8601 week date (01--53). |
%j | 189 | Day of the year (001--366), zero-padded to 3 digits. |
%D | 07/08/01 | Month-day-year format. Same as %m/%d/%y . |
%x | 07/08/01 | Locale's date representation (e.g., 12/31/99). |
%F | 2001-07-08 | Year-month-day format (ISO 8601). Same as %Y-%m-%d . |
%v | _ 8-Jul-2001_ | Day-month-year format. Same as %e-%b-%Y . |
Time specifiers
Option | Example | Description |
---|---|---|
%H | 00 | Hour number (00--23), zero-padded to 2 digits. |
%k | _ 0_ | Same as %H but space-padded. Same as %_H . |
%I | 12 | Hour number in 12-hour clocks (01--12), zero-padded to 2 digits. |
%l | 12 | Same as %I but space-padded. Same as %_I . |
%P | am | am or pm in 12-hour clocks. |
%p | AM | AM or PM in 12-hour clocks. |
%M | 34 | Minute number (00--59), zero-padded to 2 digits. |
%S | 60 | Second number (00--60), zero-padded to 2 digits. |
%f | 026490000 | The fractional seconds (in nanoseconds) since last whole second. |
%.f | .026490 | Similar to .%f but left-aligned. These all consume the leading dot. |
%.3f | .026 | Similar to .%f but left-aligned but fixed to a length of 3. |
%.6f | .026490 | Similar to .%f but left-aligned but fixed to a length of 6. |
%.9f | .026490000 | Similar to .%f but left-aligned but fixed to a length of 9. |
%3f | 026 | Similar to %.3f but without the leading dot. |
%6f | 026490 | Similar to %.6f but without the leading dot. |
%9f | 026490000 | Similar to %.9f but without the leading dot. |
%R | 00:34 | Hour-minute format. Same as %H:%M . |
%T | 00:34:60 | Hour-minute-second format. Same as %H:%M:%S . |
%X | 00:34:60 | Locale's time representation (e.g., 23:13:48). |
%r | 12:34:60 AM | Hour-minute-second format in 12-hour clocks. Same as %I:%M:%S %p . |
Time zone specifiers
Option | Example | Description |
---|---|---|
%Z | ACST | Local time zone name. Skips all non-whitespace characters during parsing. |
%z | +0930 | Offset from the local time to UTC (with UTC being +0000 ). |
%:z | +09:30 | Same as %z but with a colon. |
%#z | +09 | Parsing only: Same as %z but allows minutes to be missing or present. |
Date & Time specifiers
Option | Example | Description |
---|---|---|
%c | Sun Jul 8 00:34:60 2001 | Locale's date and time (e.g., Thu Mar 3 23:05:25 2005). |
%+ | 2001-07-08T00:34:60.026490+09:30 | ISO 8601 / RFC 3339 date & time format. |
%s | 994518299 | UNIX timestamp, the number of seconds since 1970-01-01 00:00 UTC. |
Special specifiers
Option | Example | Description |
---|---|---|
%t | Literal tab (\t ). | |
%n | Literal newline (\n ). | |
%% | Literal percent sign. |
It is possible to override the default padding behavior of numeric specifiers %?
.
This is not allowed for other specifiers and will result in the BAD_FORMAT
error.
Modifier | Description |
---|---|
%-? | Suppresses any padding including spaces and zeroes. (e.g. %j = 012 , %-j = 12 ) |
%_? | Uses spaces as a padding. (e.g. %j = 012 , %_j = 12 ) |
%0? | Uses zeroes as a padding. (e.g. %e = 9 , %0e = 09 ) |
The list was taken from the official chrono documentation, please follow the link for more information.
Future and past dates
In the previous section, we discussed how to add the current date to your matches, but you might also want to add future and past dates.
Luckily, Espanso supports the concept of offset, that is, the number of seconds to be added to the current time when expanding a match. An example will surely make it easier to understand:
Let's say we need tomorrow's date as part of a snippet. We could do that with:
- trigger: ":tomorrow"
replace: "{{mytime}}"
vars:
- name: mytime
type: date
params:
format: "%x"
offset: 86400
If you now type :tomorrow
, you should see tomorrow's date appear (something like 03/20/2022
)!
What made this possible was the offset
parameter set to 86400
, which equals to 24 hours in the future,
expressed in seconds (60 seconds x 60 minutes x 24 hours = 86400 seconds).
If you need past dates, you can specify a negative offset as well. Such as:
- trigger: ":yesterday"
replace: "{{mytime}}"
vars:
- name: mytime
type: date
params:
format: "%x"
offset: -86400
Advanced: Localized dates
Localized dates have been introduced in version v2.1.4-beta, so make sure to have an up-to-date release.
Espanso automatically localizes dates based on your system's country and language, but advanced users might want to force a particular locale.
For this reason, the Date extension supports the locale
option to override your system preferences.
For example, the following snippet always expand to the current date in US format:
matches:
- trigger: ":today"
replace: "{{mytime}}"
vars:
- name: mytime
type: date
params:
format: "%x"
locale: "en-US"
The locale
parameter must be specified in the BCP47 format.
You can find a list of the available locales here.
Choice Extension
The Choice extension was introduced in version 2.1.2.
The Choice extension can be used to open a selection dialog, letting you choose the right value from a list. For example, lets consider the following snippet:
- trigger: ":quote"
replace: "{{output}}"
vars:
- name: output
type: choice
params:
values:
- "Every moment is a fresh beginning."
- "Everything you can imagine is real."
- "Whatever you do, do it well."
In this case, typing :quote
will open the Search bar, letting you choose the right
value:
If your goal is to choose between different replacements starting from a single trigger, you should prefer the built-in Match Disambiguation feature.
In a nutshell, Espanso automatically shows a selection dialog after typing a trigger that's shared between multiple matches. For example, the previous example is functionally equivalent to adding these 3 matches:
- trigger: ":quote"
replace: "Every moment is a fresh beginning."
- trigger: ":quote"
replace: "Everything you can imagine is real."
- trigger: ":quote"
replace: "Whatever you do, do it well."
Because all three matches share the same trigger, Espanso will let you choose the right
one after typing :quote
.
At this point, you might be wondering why the Choice extension was needed in the first place. The answer is that for some advanced use-cases (including scripts and other transformations), having an extension that lets you choose a value comes handy.
Advanced use with IDs
Using the Choice extension as shown in the previous section is enough for most use-cases, but it has one significant limitation: the label shown in the list and the final value are the same.
For example, if you select "Every moment is a fresh beginning." from the search bar, the value
of output
will be "Every moment is a fresh beginning."
For advanced use-cases, you might want to differentiate between the label (the text shown in the selection dialog), with the actual value of the item:
matches:
- trigger: ":quote"
replace: "{{output}}"
vars:
- name: output
type: choice
params:
values:
- label: "Every moment is a fresh beginning."
id: "bar"
- label: "Everything you can imagine is real."
id: "foo"
- label: "Whatever you do, do it well."
id: "foobar"
In this case, typing :quote
and selecting "Every moment is a fresh beginning" will insert bar
instead.
Random Extension
The Random Extension can be used to write non-deterministic replacement texts. In other words, you can specify a set of possible expansions for a match and Espanso will choose a random one, useful to avoid repetitions.
You can use this feature by declaring a variable of type random
and then passing a number of choices
as a parameter:
- trigger: ":quote"
replace: "{{output}}"
vars:
- name: output
type: random
params:
choices:
- "Every moment is a fresh beginning."
- "Everything you can imagine is real."
- "Whatever you do, do it well."
In this case, typing :quote
will expand randomly to one of the tree quotes.
Clipboard Extension
The Clipboard Extension enables to include the current clipboard content in a match.
For example, let's imagine you want to create the ultimate HTML link shortcut:
- trigger: ":a"
replace: "<a href='{{clipb}}' />$|$</a>"
vars:
- name: "clipb"
type: "clipboard"
If you now copy a link in the clipboard (for example by selecting it and then CTRL+C) and then type :a
, you'll
see the following replacement appear:
<a href='YOUR_COPIED_LINK'></a>
Echo Extension
The Echo extension makes it easy to create variables containing a fixed value. For example:
- trigger: ":greet"
replace: "Hello {{myname}}"
vars:
- name: myname
type: echo
params:
echo: "John"
In this case, typing :greet
gets expanded to Hello John
.
This extension is particularly useful to define common global variables, such as:
global_vars:
- name: myname
type: echo
params:
echo: "John"
matches:
- trigger: ":greet"
replace: "Hello {{myname}}"
- trigger: ":sig"
replace: "Best regards, {{myname}}"
Script Extension
There will be tasks for which espanso was not designed for. For those cases, espanso offers the Script Extension, that enables you to call an external script, written in any language, and use its output in a match.
To better understand this feature, let's dive into an example:
We want to use the output of a Python script as an expansion. Let's create the script.py
file,
place it anywhere you want and paste the following code:
print("Hello from python")
Now take note of the path of the script, and add the following match to the espanso configuration:
- trigger: ":pyscript"
replace: "{{output}}"
vars:
- name: output
type: script
params:
args:
- python
- /path/to/your/script.py
If you now try to type :pyscript
anywhere, you should see Hello from python
appear.
You can do the same thing with any programming language, just change the args
array accordingly.
The current best-practice when creating Script matches is to create a scripts
directory in the espanso
directory
(at the same level of the match
and config
directory) and store the scripts there.
That way, you can use the %CONFIG%
wildcard to automatically replace the config directory with the correct path, such as:
- trigger: ":pyscript"
replace: "{{output}}"
vars:
- name: output
type: script
params:
args:
- python
- "%CONFIG%/scripts/script.py"
This makes it easier to create matches that work across many machines.
Because of the execution time, you should limit yourself to fast-running scripts to avoid any lag.
Useful Environment Variables
When triggering the shell command, Espanso also injects a few useful Environment Variables that you can use:
-
CONFIG
: Points to the path of the espanso config directory -
All the values of the previously evaluated match variables. For more information, check out the Variables section.
UTF-8 characters
By default, some scripts don't return UTF-8 characters, which can interfere with shell expansions generating foreign-language letters. A solution for Python scripts is to include the following in the script:
import sys
sys.stdout.reconfigure(encoding='utf-8')
Shell Extension
The Shell Extension is similar to the Script Extension, but instead of executing
a script, it executes shell commands. This offers a lot of flexibility on Unix systems thanks to the
bash
shell (and thanks to PowerShell/WSL support also on Windows).
Let's say you regularly send your IP address to your coworkers. You can setup a match to fetch your public IP from ipify.
Note: this example uses the
curl
command, usually preinstalled on most Unix systems.
- trigger: ":ip"
replace: "{{output}}"
vars:
- name: output
type: shell
params:
cmd: "curl 'https://api.ipify.org'"
Now every time you type :ip
, it gets expanded to your public
IP address!
Choosing the Shell
The shell extension supports many different shells out of the box. By default it uses:
Powershell
on Windowsbash
on Linuxsh
on macOS
You can also specify different shells by using the shell
param. For example, let's say we want to use bash on Windows through the Windows Subsystem for Linux
. We would use:
- trigger: ":ip"
replace: "{{output}}"
vars:
- name: output
type: shell
params:
cmd: "curl 'https://api.ipify.org'"
shell: wsl
Other possible values for the shell
parameter are:
- On Windows:
cmd
,powershell
,wsl
- On macOS:
sh
,bash
- On Linux:
sh
,bash
Bash pipes
This extension also supports bash pipes as your shell does, such as:
- trigger: ":localip"
replace: "{{output}}"
vars:
- name: output
type: shell
params:
cmd: "ip a | grep 'inet 192' | awk '{ print $2 }'"
Trimming the output
It's very common for commands to have outputs that also spawn a newline at the end. By default a trim option is enabled to remove any excess spaces/newlines. You can optionally disable the trim
option:
- trigger: ":localip"
replace: "{{output}}"
vars:
- name: output
type: shell
params:
cmd: "ip a | grep 'inet 192' | awk '{ print $2 }'"
trim: false
Useful Environment Variables
When triggering the shell command, espanso also injects a few useful Environment Variables that you can use:
CONFIG
: Points to the path of the espanso config directory- All the values of the previously evaluated match variables. For more information, check out the Variables section.
UTF-8 characters in PowerShell
As with some scripts, Windows PowerShell doesn't return UTF-8 characters by default, interfering with shell expansions generating foreign-language letters. The command needs to be specifically configured to work with UTF-8 as in the following example:
- trigger: ":pl"
replace: "{{output}}"
vars:
- name: output
type: shell
params:
cmd: "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; echo 'ąśα'"
Using Linux commands on Windows
As you might have understood from previous sections, Espanso supports the Windows Subsystem for Linux through the shell: wsl
parameter.
This allows Windows users to execute Linux commands from their machine.
Debugging
Sometimes it's useful to understand what get's executed exactly, what are the return codes and error messages returned by the command. In order to do that, you can use the debug: true
option:
- trigger: ":localip"
replace: "{{output}}"
vars:
- name: output
type: shell
params:
cmd: "ip a | grep 'inet 192' | awk '{ print $2 }'"
debug: true
At this point, after triggering a match, the logs will be populated with useful information. Too see them, use the espanso log
command.
Form Extension
Espanso's forms are implemented as extensions under the hood, and therefore you can use them as you would do with any other extension.
Besides regular expansions, you can also pass the values inserted inside the form to other extensions, such as scripts, opening up a world of possibilities.
For more information, please visit the Forms section.