// ZSH-CPAN-COMPLETION — LIVE CPAN MODULE COMPLETION FOR cpan / cpanm

zsh plugin · live perl -MCPAN -e 'CPAN::Shell->m(...)' module completion · intelligent cache · tarball completion

GitHub Issues
// Color scheme

>_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_PREFIXdefault 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:

  1. 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)(-.)".
  2. If the prefix is long enough, it calls __cpan_modules $PREFIX, which spawns perl -MCPAN -e 'CPAN::Shell->m("/$PREFIX/")' — the CPAN.pm shell's m (module) command with a regex anchored on your prefix.
  3. The Perl output is split into lines and matched against two shapes: single-module verbose output (a Module id = NAME line paired with a CPAN_FILE TARBALL line, 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 _describe doesn't treat them as value/description separators.
  4. Each entry is built as name:tarball and passed to _describe -t cpan-module 'CPAN modules', which renders the completion menu with the tarball shown as the description.
  5. 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_cache with 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.

-acreate a CPAN.pm autobundle with CPAN::Shell->autobundle
-A -C -Dtake [ module ... ] arguments
-crun make clean in the specified modules' directories
-fforce the specified action when it would normally have failed
-Fturn off CPAN.pm's attempts to lock anything
-g -Gtake [ module ... ] arguments
-hprint a help message and exit
-iinstall the specified [ module ... ]
-Iload local::lib
-jload a config file (.pm)
-Jdump the configuration in CPAN.pm's own format
-llist all installed modules with their versions
-Ltake [ author ... ] arguments
-mmake the specified modules
-Mset the mirror list (mirror1,mirror2,...)
-ndry run — don't actually install (unimplemented)
-Oshow the out-of-date modules
-pping the configured mirrors and print a report
-Pfind the best mirrors and use them
-rrecompile dynamically loaded modules via CPAN::Shell->recompile
-sdrop into the CPAN.pm shell
-t -xtake [ module ... ] arguments
-Tdo not test modules; simply install them
-uupgrade all installed modules
-vprint the script version and CPAN.pm version, then exit
-Vprint detailed information about the cpan client
-wunimplemented
-Xdump 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 / -iinstall the modules
--self-upgradeupgrade cpanm itself
--infodisplay distribution info on CPAN
--installdepsonly install dependencies
--lookdownload/unpack the distribution and open the directory in your shell
--help / -hdisplay help information
--version / -Vdisplay software version
--force / -fforce install
--notest / -ndo not run unit tests
--sudo / -Suse sudo to run install commands
--verbose / -vturn on chatty output (mutex with --quiet)
--quiet / -qturn off all output (mutex with --verbose)
--local-lib / -lspecify the install base for modules
--local-lib-contained / -Lspecify the install base for all non-core modules
--mirrorbase URL for the mirror — completes URLs via _urls
--mirror-onlyuse the mirror's index file instead of the CPAN Meta DB
--promptprompt when configure/build/test fails
--reinstallreinstall even if the latest version is already installed
--interactiveturn on interactive configure
--scandepsscan dependencies and output the tree as text
--formatscandeps output format — completes literal set tree / json / yaml / dists
--save-distsdirectory path to copy downloaded tarballs into
--uninst-shadowsuninstall shadow files of the distribution being installed
--auto-cleanupdays until cpanm's work directories expire (default 7)
--man-pages / --no-man-pagesgenerate (or skip) man1/man3 man pages (mutex pair)
--lwp / --wget / --curlchoose 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 appearConfirm 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+ charsExpected. 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 fastThe 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 allEnsure 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: