>_EXECUTIVE SUMMARY
zsh-gem-completion is a #compdef gem completion plugin that ships the entire OMZ gem-completion surface (30 subcommands — install, uninstall, update, list, build, cert, fetch, owner, push, yank, etc., all with man-page-quality descriptions) plus live remote package completion for gem install <TAB>. The remote dispatcher (__gem_search) shells out to gem search -q $PREFIX 2>/dev/null and parses two-column output (name version_string) into zsh's _describe format with descriptions rendered inline in the menu. Two layers of caching absorb network cost: an in-shell typeset array (__gems_${PREFIX}) for the rest of the shell session, and _retrieve_cache / _store_cache on disk for cross-session persistence. The plugin entrypoint also registers three publishing shortcuts (gemb build, gemp push, gemy yank-with-version) for the standard gem-author workflow. A single zstyle line (list-grouped false) tells zsh's menu to render each candidate on its own row instead of grouping by description — legibility win for the remote-search code path where descriptions are long and unique.
gem Subcommands Completedgemb/gemp/gemy)~ARCHITECTURE · FILE STRUCTURE
Two files. _gem is the #compdef consumer that zsh's completion system autoloads; the plugin entrypoint wires src/ into fpath and adds the publishing aliases.
| Path | Lines | Role |
|---|---|---|
| src/_gem | 115 | #compdef gem — 30-entry _1st_arguments subcommand table; __gem_installed queries gem list --local --no-versions; __gem_search + __gem_search_mem drive remote completion; per-subcommand case dispatch for install / list / uninstall / update / build |
| zsh-gem-completion.plugin.zsh | 12 | Three aliases (gemb=gem build *.gemspec, gemp=gem push *.gem, gemy=gem yank $1 -v $2 function); ZSH_ARGZERO self-locate; fpath=("${0:h}/src" $fpath) |
| Total source | 127 | Two files, one completion namespace |
@COMPLETION COVERAGE
Full gem command surface, with the killer feature being live remote completion against rubygems.org for the install code path.
30 subcommands with descriptions
_1st_arguments hand-curates every gem(1) subcommand and its one-line description so the menu shows what each one does:
- install/uninstall:
install,uninstall,update,pristine,cleanup - query:
list,search,query,specification,which,contents,dependency,outdated,stale - publish:
build,push,yank,fetch,owner,mirror,cert,sources - server:
server,generate_index,environment,rdoc - misc:
check,help,lock,unpack
Live gem install completion (remote)
gem install <TAB> → __gem_search → gem search -q $PREFIX → per-line parse (name version_string) → _describe -t remote-gem 'remote gems' tmp_ary. Names and versions are ${(q)...}-quoted so colons/spaces/special chars survive zsh's name:desc tuple format.
Installed-gem completion (local)
gem uninstall and gem update fall through to __gem_installed, which calls gem list --local --no-versions and feeds the result to _wanted installed_gems expl 'installed gems' compadd -a installed_gems. Cheap, no network, always current with the local install set.
gem build file completion
gem build <TAB> → _files -g "*.gemspec". Glob-restricted to .gemspec files only, so gem build never offers random tarballs or directories.
Top-level flags
Before the subcommand state, _arguments -s offers -v/--version and -h/--help with mutex declarations ((-v --version)) so the menu doesn't double-list them.
Publishing aliases (3)
Workflow shortcuts that pre-fill the common arguments:
gemb→gem build *.gemspec(auto-glob current dir)gemp→gem push *.gem(push freshly-built tarball)gemy <name> <version>→gem yank $1 -v $2(function, not alias, so args order is enforced)
#TEST COVERAGE
41 zunit @test cases across 7 files, plus 21 structural shell gates from the umbrella.
| Test file | @test count | What it pins |
|---|---|---|
| tests/t-plugin.zsh | 14 | Plugin-entrypoint surface — 3 aliases register, gemy defined as function (not alias) with positional args, fpath contains src/, _gem starts with #compdef gem |
| tests/t-contract.zsh | 3 | Entrypoint stem matches plugin-dir basename; src/_gem exists; #compdef gem first non-comment line |
| tests/t-contract2.zsh | 5 | ZSH_ARGZERO self-locate idiom intact; fpath manipulation uses "${0:h}/src" form |
| tests/t-contract3.zsh | 5 | Completion-function shape — __gem_search, __gem_search_mem, __gem_installed defined; cache-file name is gem_${PREFIX}_cache |
| tests/t-contract4.zsh | 5 | zstyle ':completion:*:*:gem:*:remote-gem' list-grouped false present (menu-rendering pin) |
| tests/t-aliases.zsh | 4 | Each of gemb / gemp resolves to documented expansion; gemy is a function with two positional args |
| tests/t-syntax.zsh | 5 | zsh -n on entrypoint + src/_gem + all helper scripts |
| Total | 41 | 7 zunit files |
// STRUCTURAL GATES (21 shell scripts)
Same 21-script umbrella gate-set as the rest of the family: 9 docs/*.html gates (h1, body/html closing, final newline, no deprecated tags, https-only, no inline handlers, no placeholder hrefs, target-blank-rel-noopener) + 4 README + 3 man-page + 2 tests/ + 2 workflows + 1 cargo (vacuous).
?KEY DESIGN DECISIONS
Five places this plugin diverges from upstream OMZ and why.
Live remote completion for install
Upstream OMZ gem completion offers installed gems for install too — useless, because the gem you want to install is by definition not installed yet. This plugin shells out to gem search -q $PREFIX and offers the rubygems.org index. Cost is one rubygems network round-trip per prefix; absorbed by both cache layers after first hit.
Two-layer cache (in-shell + on-disk)
__gem_search_mem checks an in-shell typeset array (__gems_${PREFIX}) first — nanosecond hit. Misses fall through to _retrieve_cache for disk-backed persistence across shell sessions. Hits eventually fall through to gem search on network. Three tiers, latency growing by ~3 orders of magnitude each.
${(q)...} quoting on parsed output
Gem names + version strings can contain colons, spaces, parentheses (rspec-rails:7.0.0 (rspec-rails)-style descriptions). _describe's tag:description tuple format would mis-split on raw colons. ${(q)tag}:${(q)desc} backslash-quotes both halves so zsh parses them as a single tuple.
list-grouped false for remote-gem
Default zsh menu groups candidates by description — useful when many gems share a description, useless when every remote search hit has a unique version+description pair (which is the common case). The zstyle scope :completion:*:*:gem:*:remote-gem is tight enough that it only affects the remote-search code path; local gem list completion uses default grouping.
gemy as function, not alias
gemy <name> <version> needs the two args in a specific order (gem yank $1 -v $2). An alias couldn't enforce that — alias gemy='gem yank' would let users type gemy 0.0.0 some-gem and produce nonsense. The function form makes the contract typeable.