# Snippets (/features/snippets)



Type `vn`, get `Vietnam`. Each snippet decides for itself when it fires and
where it works, and a replacement can hold [dynamic variables](/features/variables)
so part of it is fresh every time.

Needs the [Accessibility permission](/get-started/permissions) — it watches what
you type and replaces it. The master switch is at the top of the **Snippets**
pane, and five tabs sit under it: the list, the [Playground](#playground), the
[History](#history), **Excluded apps** and **Settings**.

<Screenshot name="snippets-pane" alt="The Snippets pane: the master switch, five tabs, and a list of snippets showing their trigger, replacement and when each fires" />

## A snippet [#a-snippet]

<Screenshot name="snippet-sheet" alt="The Edit snippet sheet: Trigger, Case sensitive, Replacement with Insert variable, the Becomes preview, the Expand choices and Where it works" />

| Field              | Notes                                                                                                                                                                                                              |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Trigger**        | The text you type. No spaces — a trigger with a space in it can never be typed as one word, so it would never fire.                                                                                                |
| **Case sensitive** | Leave *Any casing fires it* on and `VN` fires `vn`; switch it off and only the spelling you wrote does.                                                                                                            |
| **Replacement**    | The text it becomes. **Insert variable** offers the [variables](/features/variables), and the **Becomes** line under the field shows what the snippet would produce right now — the ↻ beside it rolls a fresh one. |
| **Expand**         | When it fires. Four choices, below.                                                                                                                                                                                |
| **Where it works** | Per-snippet scope, below.                                                                                                                                                                                          |

### When it fires [#when-it-fires]

The **Expand** group in the sheet:

| Choice                           | Behaviour                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **After a space or punctuation** | Nothing fires until the word is finished, so an everyday word is safe to use as a trigger.                                                                                                                                                                                                                                                                                                                                                                                                          |
| **As soon as it is typed**       | Fires mid-word. Best with a trigger nobody types by accident, like `;email`.                                                                                                                                                                                                                                                                                                                                                                                                                        |
| **When you tap ⌥ Right Option**  | No stray space or full stop, and nothing fires until you ask. The row names whichever key is picked under **Snippets → Settings → Expand key**, and is disabled until one is.                                                                                                                                                                                                                                                                                                                       |
| **When you press ⇥ Tab**         | Same again — no stray character, nothing fires until you ask — and no key to pick, because every keyboard has a Tab. The catch is that Tab is a key applications use themselves: an editor accepts its own completion on it, a terminal completes a path, a form moves to the next field. While a trigger is waiting, Lumi takes it. So scope this one under **Where it works**, or keep those applications out under **Snippets → Settings**. A Tab that completes nothing goes through untouched. |

### Where it works [#where-it-works]

A snippet is **everywhere**, **everywhere except** a list of applications, or
**only in** a list. "Only in" with nothing chosen is a snippet that can never
fire, and Save says so.

On top of that, the **Excluded apps** tab holds a pane-wide list — applications
*no* snippet works in, whatever each one's own scope says. Editors and terminals
are the usual entries: a trigger that is also a command is worse than no
expansion at all.

## Vietnamese and other input methods [#vietnamese-and-other-input-methods]

A Vietnamese input method — EVKey, OpenKey, Gõ Nhanh — rewrites keystrokes
*after* Lumi's event tap has seen them, inside the target application: telex
turns the two keys `dd` into the one character `đ`. So what Lumi watched being
typed is not always what the document holds.

Lumi therefore &#x2A;*never deletes on trust.** Before replacing anything, it reads
the text actually in front of the caret and compares it to the trigger:

| The application                             | What happens                                           |
| ------------------------------------------- | ------------------------------------------------------ |
| exposes its text, and it matches            | replaced exactly, through Accessibility                |
| exposes its text, and it does **not** match | **nothing happens, silently** — the snippet is skipped |
| exposes no text at all                      | falls back to backspaces                               |

A missed expansion is a nuisance; eating the wrong characters is not, so the
middle row is deliberate.

## Playground [#playground]

**Snippets → Playground** is a box to try triggers in. Nothing is simulated:
the event tap watches every keystroke on the machine, this window included, so a
trigger typed there is replaced there by the same code that would replace it
anywhere else. Snippets have to be switched on, and a snippet pinned to other
applications sits it out.

Nothing typed there reaches History.

## History [#history]

A variable's output is gone the moment it leaves — the snippet only ever holds
the template. So Lumi keeps the last 200 expansions under **Snippets →
History**: the generated text, the trigger as it was typed, the application it
went into, and when. Clicking a row copies it; the tray's **Recent** submenu
carries the newest ten.

<Screenshot name="snippet-history" alt="The History tab: what each expansion produced, the trigger, the application and when" />

The list is append-only — renaming a trigger or deleting the snippet leaves the
old rows exactly as they were. It lives in `history.json` beside the config, in
plain text, which matters if you generate passwords with `{{$randomPassword}}`.
The switch at the foot of the tab stops the recording, the bin on a row forgets
one, and **Clear history** empties it.

Two things are **never** written to History, whatever the switch says:

* Anything typed in the Playground, or that expands elsewhere in Lumi's own
  window.
* Any expansion that used `{{$clipboardText}}` — the row is still there, saying
  which trigger fired where and when, but not what came out. Lumi cannot tell a
  copied paragraph from a copied one-time code.

## Importing a pack [#importing-a-pack]

**Export…** and &#x2A;*Import…** at the foot of the list move snippets between Macs,
or hand a set to somebody else.

A snippet pack is a list of triggers and replacements, and it gets **no import
review** — one of those replacements can hold `{{$clipboardText}}`. Read a pack
before you import it, the way you would any other text somebody sent you. (A
replacement cannot reach the *selection*: `{{$selectedText}}` does not stand in
a snippet, because a snippet fires mid-word when nothing is selected.)
