>_EXECUTIVE SUMMARY
zsh-expand rewrites the spacebar into a live alias expander. Every press of Space runs a ZLE widget that walks the current command line, resolves the command position through arbitrarily deep prefix chains (sudo, env, nice, nsenter, strace, ltrace, nohup, rlwrap, numactl, chrt, ionice, flock, unshare, setpriv, setarch, ...), and dispatches to one of:
regular alias expand, global alias expand, suffix alias expand (alias -s), misspelling correction, glob / parameter / history expansion via zle expand-word, or fall-through. Total surface: 2,753 zsh lines across 4 source files, pinned by 11,688 @test blocks across 79 zunit files. Zero external commands in the hot path — the entire expansion is pure parameter expansion, associative lookup, and shell-builtin parsing. Hot-path latency: ~36 µs per regular alias expand.
~ARCHITECTURE
Four-file load order. The plugin entry point sources the parser first (pure functions, no side effects), then the API (state container helpers), then the lib (widget bodies + dictionary). Final block defines ZLE widgets, binds Space + Ctrl-Space + Esc-Ctrl-E, and adds completions/ to fpath.
| File | Lines | Role |
|---|---|---|
zsh-expand.plugin.zsh |
443 | Plugin entry point. Sources the three siblings, defines the 292 built-in correction entries, declares ZLE widgets (zpwrExpandSupernaturalSpace, zpwrExpandTerminateSpace, zpwrExpandGlobalAliases, zpwrExpandDebugWidget), binds keys, registers the _zpwrExpandStats completion via compdef. |
zpwrExpandParser.zsh |
929 | Prefix-chain parser. Walks the current buffer left-to-right, consumes nocorrect / builtin / command / exec / eval / noglob / coproc shell keywords first, then iterates external prefix commands (sudo, doas, env, nice, nohup, rlwrap, timeout, strace, ltrace, ionice, caffeinate, setsid, chrt, taskset, watch, flock, chroot, runuser, unshare, cpulimit, su, stdbuf, ...) with their full flag tables. Variable assignments (X=1) are skipped at any position. |
zpwrExpandLib.zsh |
1,179 | Widget bodies. Implements the expansion state machine: alias resolve → global resolve → correction lookup → native expand. Holds the O(1) reverse-lookup dictionary build (ZPWR_EXPAND_CORRECT_REVERSE). Suffix alias handling, self-referential \backslash escape, blacklist enforcement, autopair detection / delegation, history injection, preview ghost text, stats append. |
zpwrExpandApi.zsh |
202 | State-container helpers and config init. Exports ZPWR_VARS association keys consumed by the parser/lib, sets default values for the ZPWR_EXPAND_* / ZPWR_CORRECT_* family, declares the public-callable shape (caller / enter detection, multiword tail extraction). |
| Total source | 2,753 | 4 files · pure zsh · zero forks in hot path |
#TEST COVERAGE
79 zunit test files (tests/t-*.zsh) totalling 11,688 @test blocks. Coverage is partitioned by area — each file pins one class of behavior with exhaustive edge cases.
| Area | Representative Files | Pins |
|---|---|---|
| Alias expansion | t-alias-position.zsh, t-alias-escape-edge.zsh, t-expand-alias-edge.zsh, t-expand-combo.zsh, t-expand-more.zsh, t-expand-unit.zsh, t-expand-utility-edge.zsh, t-expand-parse-edge.zsh |
First-position vs subcommand-position expand; self-referential alias \backslash escape; combined prefix + alias chains; deep-stack regression. |
| Spelling correction | t-correct-context.zsh, t-correct-dict-full.zsh, t-correct-exhaustive.zsh, t-correct-guards.zsh, t-correct-multi-ctx.zsh, t-correct-user-extend.zsh, t-correct-word-edge.zsh |
All 292 built-in entries round-trip; user-extension hook; correct-then-expand chain; per-context guards (don't correct real commands). |
| Prefix-chain blacklist | t-blacklist-firstpos-alias.zsh, t-blacklist-subcommand-suffix.zsh |
ZPWR_EXPAND_BLACKLIST wins in command position AND after every supported prefix; suffix-alias exclusion respected. |
| Config flag matrix | t-config-flags.zsh, t-api-caller-and-enter.zsh, t-api-multiword-tail.zsh |
Every ZPWR_EXPAND_* toggle pinned on + off; caller-context API behaves the same on Enter as on Space; multi-word tail extraction. |
| Debug widget & UI | t-box-backspace-and-color.zsh, t-box-double-dash.zsh, t-box-fuzz.zsh |
Esc-Ctrl-E debug-overlay rendering: ANSI escapes don't poison ${#string} math; backspace doesn't corrupt the line; fuzz-input doesn't crash the widget. |
| Prefix-chain parser | t-parse-massive.zsh, t-correct-multi-ctx.zsh, t-parser-*.zsh (per-wrapper: sudo, su, strace, nsenter, unshare, setpriv, firejail, bwrap, proot, valgrind, …) |
Each wrapper's combo-flag and flag-with-arg table is pinned independently; VAR=val vs flag-arg disambiguation; mandatory positional slots (su→USER, chroot→PATH) not mistaken for the command. |
| Suffix / global / regex | t-suffix-alias.zsh, t-suffix-alias-ext.zsh, t-suffix-prefix-chain.zsh, t-global-alias-exhaustive.zsh, t-regex-exhaustive.zsh, t-regex-edge.zsh |
Suffix-alias expand at command position and through prefix chains; global-alias expansion anywhere on the line; regex-match command-position resolution and edge cases. |
| Preview / stats / integration | t-preview-resolve-and-stats.zsh, t-regex-cache-api.zsh, t-integration-flow.zsh, t-is-command.zsh |
Ghost-text preview resolution; stats record/render; cache-API metadata; real-command detection (don't correct valid commands); end-to-end space-to-buffer flow. |
Runner: zunit. CI matrix (.github/workflows/ci.yml) runs the full 11,688 on every push.
/INTEGRATION
Zinit (recommended)
zinit ice lucid nocompilezinit load MenkeTechnologies/zsh-expand
The plugin's 0= header follows the Zsh Plugin Standard; nocompile keeps the source path stable for the ${0:A:h} resolution of sibling files.
Oh My Zsh
git clone into $ZSH_CUSTOM/plugins/zsh-expand, then plugins+=(zsh-expand) in .zshrc. No init hook required — the file is sourced top-to-bottom and the ZLE widgets register before the prompt fires.
ZLE widgets installed
Four widgets registered via zle -N: zpwrExpandSupernaturalSpace (bound to Space), zpwrExpandTerminateSpace (bound to Enter when ZPWR_EXPAND_PRE_EXEC_NATIVE=true), zpwrExpandGlobalAliases (callable from user widgets), zpwrExpandDebugWidget (bound to Esc-Ctrl-E).
Completion registration
fpath+=(${0:A:h}/completions) adds the one shipped completion file (completions/_zpwrExpandStats) for the zpwrExpandStats command, then compdef _zpwrExpandStats zpwrExpandStats registers it when compsys is active.
Autopair coexistence
If zsh-autopair is detected, the supernatural-space widget delegates the trailing space insertion to autopair's own autopair-insert rather than emitting a raw space — bracket/quote auto-pairing keeps working after expansion.
Preview hook
When ZPWR_EXPAND_PREVIEW=true, the plugin installs a chained zle-line-pre-redraw hook (preserves any pre-existing user hook), rendering ghost-text of what the next Space would expand to. No polling — fires on the existing ZLE redraw cadence.
!DESIGN DECISIONS
O(1) reverse lookup, not Levenshtein
The 292 entries declare correct → list of misspellings. On load, zpwrExpandRebuildCorrectReverse inverts to misspelling → correct, so correction is one associative-array probe per word, not an edit-distance scan against the dictionary. Userland additions plug into the same rebuild path.
Parse the prefix chain, don't peel one prefix
Naive plugins handle sudo gco by stripping sudo and re-running the test. zsh-expand instead walks an open-ended chain (sudo -kE -u root env -0iv -C /tmp nice -n 10 nohup gco) honoring every flag table from the README. The cost: a 929-line parser. The gain: arbitrarily deep prefix combos work without per-case tuning.
Flag tables hand-curated per command
Each of the 62 supported prefixes lists its combo flags (consume next char) AND its flag-with-arg flags (consume next word). Mixing these is what lets strace -cf -s 256 gco and su -l root gco both work. The flag tables live in zpwrExpandParser.zsh and are pinned by t-expand-combo.zsh regression tests.
Self-referential alias = backslash escape
alias git=hub would loop forever under naive recursion. zsh-expand detects when the head of the expansion equals the original command and prepends \\ to suppress the second-round lookup — the same trick zsh's own _expand_alias uses internally. Pinned by t-alias-escape-edge.zsh.
Blacklist over whitelist
ZPWR_EXPAND_BLACKLIST=(g gco) ships empty by default. Every alias expands unless explicitly excluded — the inverse of opt-in expansion plugins. Lowers config burden: users add the 1–2 aliases they want quiet, not the 100s they want loud.
Zero forks in the hot path
The widget body uses only parameter expansion (${var//pattern/repl}), associative-array indexing ($aliases[word], $galiases[word]), and built-in ZLE state. No sed, no awk, no grep, no $(...) in the expansion path — each fork on macOS is ~1 ms, more than the entire ~36 µs budget.
%PARSER PHASES
The command-position parser (zpwrExpandParserFindCommandPosition) walks the word array left-to-right in two phases. Shared helpers _zpwr_bare (strip quotes/backslash) and _zpwr_is_assignment (NAME=value detection) are defined once at file scope, not per parse. A first-word precheck short-circuits the common case (plain command, no prefix) by replicating the two O(1) hash lookups inline and skipping the array copy and loop machinery — ~35% lower parser latency on non-prefixed lines.
| Phase | Consumes | Tokens |
|---|---|---|
| Phase 1 — shell keywords | case-sensitive shell builtins/keywords, consumed before any external wrapper | nocorrect · time (-p -l -v) · - · builtin · command (-p) · exec (-c -l -a NAME) · eval · noglob · coproc |
| Phase 2 — external prefixes | 62 privilege-escalation / wrapper commands, each with its own combo-flag and flag-with-arg table; VAR=val assignments stripped at any position |
sudo · doas · su · env · nice · nohup · rlwrap · timeout · strace · ltrace · ionice · caffeinate · setsid · chrt · taskset · watch · runuser · flock · chroot · unshare · cpulimit · stdbuf · sg · choom · nsenter · numactl · prlimit · setpriv · setarch · linux32 · linux64 · runcon · xvfb-run · chpst · cgexec · trickle · faketime · proot · bwrap · capsh · valgrind · fakeroot · unbuffer · chronic · torsocks · proxychains4 · daemonize · firejail · sem · systemd-run · nocache · fakechroot · ccache · distcc · pkexec · torify · dbus-run-session · dbus-launch · eatmydata · tsocks · catchsegv |
| Result | ZPWR_VARS[cachedRegexMatch] = command + args · ZPWR_VARS[cachedParserPrefix] = consumed prefix |
everything remaining is the command word + its arguments |
=CONFIGURATION REFERENCE
User-facing knobs. All are plain environment variables / arrays read at load and on each keypress.
| Variable | Default | Effect |
|---|---|---|
ZPWR_EXPAND | true | Master switch. false makes the widget return immediately (no parse cost). |
ZPWR_EXPAND_SECOND_POSITION | true | Alias expansion after sudo/env/… prefixes. |
ZPWR_EXPAND_NATIVE | true | Expand globs, $params, !history via zle expand-word. |
ZPWR_CORRECT | true | Spelling correction. |
ZPWR_CORRECT_EXPAND | true | Chain alias expansion after a correction (correct-then-expand). |
ZPWR_EXPAND_QUOTE_DOUBLE | — | Expand aliases inside "double"-quoted argument strings. |
ZPWR_EXPAND_QUOTE_SINGLE | — | Expand aliases inside 'single'-quoted argument strings. |
ZPWR_EXPAND_TO_HISTORY | false | Write the expanded form into history on accept-line. |
ZPWR_EXPAND_PRE_EXEC_NATIVE | — | Also expand globs/params/history on accept-line. |
ZPWR_EXPAND_SUFFIX | true | Expand suffix aliases (alias -s) at command position. |
ZPWR_EXPAND_PREVIEW | false | Ghost-text preview of the pending expansion via zle-line-pre-redraw. |
ZPWR_EXPAND_BLACKLIST | () | Array of aliases to never expand (wins in every position). |
ZPWR_EXPAND_CORRECT_WORDS | 292 | The correction dictionary (correct → misspellings). User-extensible. |
ZPWR_EXPAND_STATS_FILE | ~/.cache/… | Stats file path (falls back through $ZPWR_LOCAL / $XDG_CACHE_HOME / ~/.cache). |
ZPWR_EXPAND_STATS_TOP | 20 | Default top-N alias count in the zpwrExpandStats dashboard. |
*STATS DASHBOARD
zpwrExpandStats reads the append-only stats log and renders a cyberpunk dashboard: per-trigger (spacebar S: vs history H:) and per-type tallies, total keystrokes saved, and the top aliases as proportional bar charts. The completion file completions/_zpwrExpandStats wires up compsys for these flags.
-h, --help
Print the dashboard help banner and exit.
-t, --top <N>
Show the top N aliases. Default 20, or $ZPWR_EXPAND_STATS_TOP.
-w, --width <N>
Box width for the rendered dashboard. Default 70.
-c, --color
Force ANSI colors (e.g. when piping to a pager that supports them).
-r, --reset
Delete the stats file and clear all tallies.
-f, --file <PATH>
Read/operate on an alternate stats file path for this invocation.
$POSITION
Quantitative position against the established alias-expansion plugin set. Numbers for siblings come from each project's published README/source as of writing; zsh-expand's figures are derived in-tree by wc -l / grep -c.
| Plugin | Tests | Prefix cmds parsed | Correction dict | Suffix-alias expand | Preview ghost |
|---|---|---|---|---|---|
| zsh-expand | 11,688 | 62 | 292 entries + user-extend | yes | yes |
| globalias (OMZ) | 0 | 0 | none | no | no |
| zsh-abbr | ~100s | 0 | none | no | partial (cursor-time) |
| zsh-abbrev-alias | ~0 | 0 | none | no | no |
| zsh-you-should-use | ~dozens | 0 (post-exec only) | none | n/a | n/a |
Sibling plugins handle the alias-in-command-position case only. zsh-expand is the only one that parses arbitrarily-deep prefix chains AND ships a misspelling-correction dictionary AND ships a suffix-alias hook AND ships preview ghost text — in a single ZLE widget with sub-millisecond latency.
@FOOTPRINT
No daemons. No timers. No state outside zsh.
- Disk:
~/.oh-my-zsh/custom/plugins/zsh-expand(or zinit cache) — one repo clone, no install hook. - Memory: 2 associative arrays (
ZPWR_EXPAND_CORRECT_WORDS,ZPWR_EXPAND_CORRECT_REVERSE) · one global association (ZPWR_VARS) · 4 widget closures. - Startup cost: source + dictionary build + reverse-table build, one-shot, no compile step.
- Runtime cost: 1 widget per Space keystroke · zero external processes · ~36 µs typical.
- Stats file: optional, opt-in via
ZPWR_EXPAND_STATS_FILE— the only on-disk side effect.