Snapshot the snippet name inline Tab would expand into a panel field in refresh_stats, so it rides the typing-pause throttle rather than repainting per keystroke. Draw it as `» name` on the row above the mode line (Latin-9 has no tab glyph), sharing the slot with the NO KBD flag, which can't co-occur since the hint means you're typing.
6.2 KiB
v0.6 — Markdown affordances
Part of the Typoena macro plan. Requirements and targets: qfd.md. Load-bearing decisions: adr.md.
Status: render affordances done early; the snippet engine is the remaining
work (snippets are net-new scope, added 2026-07-08; reshaped 2026-07-12 from a
hard-coded table into a git-synced, Zed-compatible library with a $ palette
launcher — see typoena-snippets.md for the file format).
- Heading lines bolded in render (faux-bold double-strike)
- List continuation on Enter inside
-/1.(with empty-item exit) - Soft-wrap at word boundaries
Snippets
Trigger-driven text expansion for Markdown authoring (Zed-inspired, but no
completion popup: e-ink's ~630 ms refresh rules out a live filtering menu, and
it fights the distraction-free premise). The library is a git-synced,
Zed-compatible JSON file — full file-format reference in
typoena-snippets.md. This section is the editor
behaviour.
- The tab-stop engine — the shared core both surfaces drive. A body is
literal text plus numbered stops
$1 … $nand a final$0; on insertion the caret lands on$1(or the end), in Insert. Tab advances to the next stop, forward only (no Shift-Tab); pending stops sit after the caret and shift with edits there. The session auto-aborts on Esc, a mode change, or a motion that leaves the stops.${n:label}parses to a bare$n(the label is stripped — no selection model to fill); no dynamic values (no RTC, so nodate). - Inline Tab-expansion (Insert mode). If the word immediately before the
caret matches a snippet prefix, Tab expands it and starts the tab-stop
session; otherwise Tab inserts spaces as today. A check in the Insert
handler alongside the existing
list_markertransform (expand_snippet(word) -> Option<Snippet>). Tab already arrives asKey::Char('\t'), so no new key event. - Hint-on-pause. On the typing pause (same throttle as the word-count /
cursor refresh — never a per-keystroke repaint), if the word before the
caret is a prefix, the right side panel shows a quiet hint (
» name, on the row above the mode line, sharing the slot with theNO KBDflag — the two never co-occur since the hint means you're typing). The panel is ~15 cols, so the hint is the snippet name, not the whole body — the full preview is the$palette's job. Snapshotted inrefresh_statsso it rides the pause, and the firmware's Insert-pause repaint already carries it (no firmware change). Latin-9 has no↹glyph, hence the»marker. $palette (browse + insert).Cmd-Pthen$switches the palette to the snippet list (the same sigil mechanism as>). Fuzzy-matches name / prefix / description; Enter inserts the body at the caret and starts the tab-stop session. Lists all snippets — the fuzzy filter handles clutter, so there's no hidden "inline-only vs palette-only" split. Rows readName [prefix], so browsing also teaches the inline trigger.- Boot wiring. The host reads
/sd/repo/.typoena.snippets.jsonat boot and callsEditor::set_snippets(mirroringset_prefs); a missing or malformed file is non-fatal (no snippets, editor runs). Parse lives in the host-testableeditorcrate viaserde_json— the one new dependency.
The palette, generalised (Cmd-P · > · $)
v0.5 shipped Cmd-P = files and > = a five-entry settings list (save_on_idle,
format_on_save, line_numbers toggles + theme/auto_sync rotations). v0.6
makes the sigils a clean split by verb, and the empty-palette placeholder legends:
Go to file · > settings · $ snippets.
- bare
Cmd-P→ navigate: go to file (unchanged). >→ act on the editor — the command palette. The pref toggles are just its stateful entries, not a special section. Dispatch differs per entry: a toggle flips and the list stays open (as today); a one-shot (e.g.format,publish) runs and closes; a parameterised command morphs the palette into a second input step (selectNew file→ the box becomes a filename prompt → Enter creates it, scope read from arepo//local/prefix as:enewdoes today). This retires:e(bareCmd-Pcovers file-opening; dotfiles get a dedicated> edit …command if/when wanted).$→ insert content — the snippet launcher above.
format / publish as > entries are a small opportunistic add (they prove >
is a real action registry, not a settings box); the headline is snippets.
First-time setup — snippet catalog (just init)
just init gains a step that
seeds the two git-tracked config files into repo/ (so they commit + sync on the
device's first :sync): a starter .typoena.toml (the four
keys at their defaults, or confirmed at a prompt) and a
.typoena.snippets.json chosen from a curated catalog
checked into the repo. The catalog is grouped and opt-in — you pick the groups
you want rather than getting all of one writer's personal templates. Not every
Zed snippet is worth proposing: the Slidev/blog-pipeline ones (@[youtube],
<v-clicks>, frontmatter, mermaid) and render-dependent or hyper-specific ones
are left out of the menu, since a distraction-free prose appliance can't render
them and you'd never miss them. Proposed groups (pending sign-off):
- Symbols (inline, keyboard can't type them):
fleche→→,different→≠,fois→×,median→·,degre→°,euro→€,edanso→œ(dead keys in v0.2.5 cover accents, not these). - Structure:
todo→- [ ],link→[$1]($2)$0,img→$0(net-new — obvious for Markdown),table,code(fenced block). - Prose / PKM templates (
${n:label}stripped to$n):fiche(book notes),reference/refangl(reference block),biais,capture,standard,5w1h.