>_ZSH-CPAN-COMPLETION
Perl modules, completed from CPAN. Live remote CPAN package completion via perl -MCPAN -e 'CPAN::Shell->m("...")'. Full cpan / cpanm flag completion, intelligent cache, tarball completion (.tar.gz, .tgz, .tar.bz2, .zip), prefix-length guard to keep the shell responsive.
Install
# Zinit
zinit ice lucid nocompile
zinit load MenkeTechnologies/zsh-cpan-completion
# Oh My Zsh
git clone https://github.com/MenkeTechnologies/zsh-cpan-completion \
"$HOME/.oh-my-zsh/custom/plugins/zsh-cpan-completion"
# then: plugins+=(zsh-cpan-completion)
# Manual
git clone https://github.com/MenkeTechnologies/zsh-cpan-completion
source zsh-cpan-completion/zsh-cpan-completion.plugin.zsh
What it does
Two zsh #compdef completion files — src/_cpan (for the cpan CPAN.pm client) and src/_cpanm (for cpanm / App::cpanminus) — plus a plugin entrypoint that defines the shared module-search helpers and prepends src/ to fpath. Both completion files declare their full flag table via _arguments -s, then fall through to a single shared dispatcher, __cpan_modules, that runs perl -MCPAN -e 'CPAN::Shell->m("/$PREFIX/")' at completion time to resolve module names from the live CPAN index. Results render through zsh's _describe and are cached per-prefix via _retrieve_cache / _store_cache, so the Perl spawn happens at most once per prefix per shell session.
Configuration
One environment variable. It is exported with a default of 2 by the plugin entrypoint (export ZPWR_CPAN_MIN_PREFIX=2); set it in ~/.zshrc before the plugin loads to override.
ZPWR_CPAN_MIN_PREFIX | default 2 — minimum number of characters typed before a live remote CPAN query fires. Below this length, only local tarball file-completion runs (no network call). It exists to keep a stray TAB on a one-character or empty prefix from asking CPAN for the entire module index. Lower = more eager remote lookups, higher latency / overload risk; raise it on slow networks. |
# ~/.zshrc — require 3 chars before hitting the network export ZPWR_CPAN_MIN_PREFIX=3 zinit load MenkeTechnologies/zsh-cpan-completion
How completion fires
For both cpan and cpanm, when you TAB in a positional (module-name) argument:
- The completion file checks
$#PREFIX >= $ZPWR_CPAN_MIN_PREFIX. If the typed prefix is too short, it skips the network and offers only tarball files (.tar.gz,.tgz,.tar.bz2,.zip) plus directories via_files -/ -g "*.(tar.gz|tgz|tar.bz2|zip)(-.)". - If the prefix is long enough, it calls
__cpan_modules $PREFIX, which spawnsperl -MCPAN -e 'CPAN::Shell->m("/$PREFIX/")'— the CPAN.pm shell'sm(module) command with a regex anchored on your prefix. - The Perl output is split into lines and matched against two shapes: single-module verbose output (a
Module id = NAMEline paired with aCPAN_FILE TARBALLline, handled by__cpan_single_module) and the multi-module short listing (Module < NAME TARBALL, handled by__cpan_multiple_modules). Colons in module names are backslash-escaped so_describedoesn't treat them as value/description separators. - Each entry is built as
name:tarballand passed to_describe -t cpan-module 'CPAN modules', which renders the completion menu with the tarball shown as the description. - For the multi-module path, the parsed list is stored with
_store_cache cpan_${PREFIX}_cache; subsequent TABs on the same prefix are served from_retrieve_cachewith no Perl spawn.
cpan flag reference
Every short flag the cpan(1) client accepts, taken from src/_cpan. Flags whose description is a bracketed [ module ... ] / [ author ... ] placeholder take list arguments and fall through to module-name completion.
-a | create a CPAN.pm autobundle with CPAN::Shell->autobundle |
-A -C -D | take [ module ... ] arguments |
-c | run make clean in the specified modules' directories |
-f | force the specified action when it would normally have failed |
-F | turn off CPAN.pm's attempts to lock anything |
-g -G | take [ module ... ] arguments |
-h | print a help message and exit |
-i | install the specified [ module ... ] |
-I | load local::lib |
-j | load a config file (.pm) |
-J | dump the configuration in CPAN.pm's own format |
-l | list all installed modules with their versions |
-L | take [ author ... ] arguments |
-m | make the specified modules |
-M | set the mirror list (mirror1,mirror2,...) |
-n | dry run — don't actually install (unimplemented) |
-O | show the out-of-date modules |
-p | ping the configured mirrors and print a report |
-P | find the best mirrors and use them |
-r | recompile dynamically loaded modules via CPAN::Shell->recompile |
-s | drop into the CPAN.pm shell |
-t -x | take [ module ... ] arguments |
-T | do not test modules; simply install them |
-u | upgrade all installed modules |
-v | print the script version and CPAN.pm version, then exit |
-V | print detailed information about the cpan client |
-w | unimplemented |
-X | dump all namespaces to standard output |
cpanm flag reference
Long+short flag pairs from src/_cpanm (cpanminus completion, supported version 1.4000). Pairs are declared with zsh brace expansion ({--long,-s}); several carry mutex groups so conflicting flags drop out of the menu.
--install / -i | install the modules |
--self-upgrade | upgrade cpanm itself |
--info | display distribution info on CPAN |
--installdeps | only install dependencies |
--look | download/unpack the distribution and open the directory in your shell |
--help / -h | display help information |
--version / -V | display software version |
--force / -f | force install |
--notest / -n | do not run unit tests |
--sudo / -S | use sudo to run install commands |
--verbose / -v | turn on chatty output (mutex with --quiet) |
--quiet / -q | turn off all output (mutex with --verbose) |
--local-lib / -l | specify the install base for modules |
--local-lib-contained / -L | specify the install base for all non-core modules |
--mirror | base URL for the mirror — completes URLs via _urls |
--mirror-only | use the mirror's index file instead of the CPAN Meta DB |
--prompt | prompt when configure/build/test fails |
--reinstall | reinstall even if the latest version is already installed |
--interactive | turn on interactive configure |
--scandeps | scan dependencies and output the tree as text |
--format | scandeps output format — completes literal set tree / json / yaml / dists |
--save-dists | directory path to copy downloaded tarballs into |
--uninst-shadows | uninstall shadow files of the distribution being installed |
--auto-cleanup | days until cpanm's work directories expire (default 7) |
--man-pages / --no-man-pages | generate (or skip) man1/man3 man pages (mutex pair) |
--lwp / --wget / --curl | choose the downloader backend |
Examples
cpan install Mo<TAB> # live remote completion of modules matching /Mo/ cpanm install DBI<TAB> # same shared dispatcher via cpanm cpan -<TAB> # short-flag menu: -a -i -l -u -p ... cpanm --<TAB> # long-flag menu: --install --force --scandeps ... cpanm --format <TAB> # literal set: tree json yaml dists cpanm --mirror <TAB> # _urls completion for the mirror base URL cpan install ./Some-1.0.tar.gz # tarball file completion (.tar.gz/.tgz/.tar.bz2/.zip)
Troubleshooting
| No module names appear | Confirm perl with the CPAN core module is on PATH (perl -MCPAN -e 1 must succeed) and that CPAN.pm has been configured at least once. The query is silenced with 2>/dev/null, so a missing/unconfigured CPAN.pm yields an empty menu rather than an error. |
| Nothing happens until 2+ chars | Expected. The remote query is gated by ZPWR_CPAN_MIN_PREFIX (default 2). Type more characters or lower the variable. |
| First TAB is slow, later ones fast | The first lookup spawns Perl and hits the network; results are cached per prefix via _store_cache, so repeats on the same prefix are served from _retrieve_cache. |
| Completion not found at all | Ensure the plugin was sourced so its fpath=("${0:h}/src" $fpath) line ran before compinit. With Zinit, use nocompile as shown in Install. |
Sibling plugins
Part of the MenkeTechnologies zsh plugin family — the MenkeTechnologiesMeta umbrella:
- zsh-better-npm-completion — cache-aware
npm installcompletion - zsh-cargo-completion — live
cargo add/cargo installcompletion - zsh-dotnet-completion — dotnet CLI completion
- zsh-expand — spacebar expansion (11,683 tests)
- zsh-gem-completion — ruby
gem installremote completion - zsh-git-acp — 159 git aliases + add/commit/push keybindings
- zsh-git-repo-cache — index every git repo on disk
- zsh-learn — MySQL-backed learning collection / quiz
- zsh-more-completions — 33,175-file mega completion corpus
- zsh-nginx — nginx commands + service-wrapper aliases
- zsh-pip-description-completion — pip remote completion with descriptions
- zsh-sed-sub — in-place sed substitution on the command line
- zsh-sudo — ESC ESC to prepend sudo
- zsh-xcode-completions — xcodebuild / xcrun / swift completion