summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Completion/Unix/Type/_perl_modules111
1 files changed, 111 insertions, 0 deletions
diff --git a/Completion/Unix/Type/_perl_modules b/Completion/Unix/Type/_perl_modules
new file mode 100644
index 000000000..9bfc0463d
--- /dev/null
+++ b/Completion/Unix/Type/_perl_modules
@@ -0,0 +1,111 @@
+#compdef pmpath pmvers pmdesc pmload pmexp pmeth pmls pmcat pman pmfunc podgrep podtoc podpath
+#
+# _perl_modules - zsh completion function
+#
+# Adam Spiers <adam@spiers.net>
+#
+# Calculate all installed Perl modules.  The result is cached
+# for future use.
+#
+# Available styles:
+#
+# * try-to-use-pminst
+#
+#   Set this if you have pminst and want to use it.  The zsh code
+#   actually produces better results because pminst misses modules of
+#   the form Foo/bar/Baz.pm through its clumsy -d && /^[A-Z]/ && prune
+#   algorithm (the zsh code does almost the same, but only misses
+#   modules which don't begin with an uppercase letter).
+
+_perl_modules () {
+  local opts
+  zparseopts -D -a opts S: q
+
+  # Set a sensible default caching policy.  This has to be done inside
+  # this function otherwise we wouldn't know the context for the style.
+  local update_policy
+  zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+  if [[ -z "$update_policy" ]]; then
+    zstyle ":completion:${curcontext}:" cache-policy \
+      _perl_modules_caching_policy
+  fi
+
+  local perl=${words[0]%doc} perl_modules
+  if whence $perl >/dev/null; then
+    perl_modules=_${${perl//[^[:alnum:]]/_}#_}_modules
+  elif (( ${+commands[perl]} )); then
+    perl=perl
+    perl_modules=_perl_modules
+  else
+    perl=
+    perl_modules=_unknown_perl_modules
+  fi
+
+  if ( [[ ${(P)+perl_modules} -eq 0 ]] || _cache_invalid $perl_modules ) &&
+     ! _retrieve_cache ${perl_modules#_};
+  then
+    if zstyle -t ":completion:${curcontext}:modules" try-to-use-pminst &&
+       (( ${+commands[pminst]} ));
+    then
+      set -A $perl_modules $(pminst)
+    else
+      local inc libdir new_pms
+
+      if [[ ${+perl} -eq 1 ]]; then
+        inc=( $( $perl -e 'print "@INC"' ) )
+      else
+        # If perl isn't there, one wonders why the user's trying to
+        # complete Perl modules.  Maybe her $path is wrong?
+        _message "Didn't find perl on \$PATH; guessing @INC ..."
+
+        inc=( /usr/lib/perl5{,/{site_perl/,}<5->.([0-9]##)}(N) 
+              ${(s.:.)PERL5LIB} )
+      fi
+
+      typeset -agU $perl_modules  # $perl_modules is global, no duplicates
+      set -A $perl_modules
+
+      for libdir in $inc; do
+        # Ignore cwd - could be too expensive e.g. if we're near /
+        if [[ $libdir == '.' ]]; then continue; fi
+
+        # Find all modules
+        if [[ -d $libdir && -x $libdir ]]; then
+          new_pms=( $libdir/{[A-Z]*/***/,}*.pm~*blib* )
+          new_pms=( "${(@)new_pms##$libdir/##}" )
+        fi
+
+        # Convert to Perl nomenclature
+        new_pms=( ${new_pms:r:fs#/#::#} )
+
+        set -A $perl_modules $new_pms ${(P)perl_modules}
+      done
+    fi
+
+    _store_cache ${perl_modules#_} $perl_modules
+  fi
+
+  local expl
+
+  _wanted modules expl 'Perl modules' compadd "$opts[@]" -a $perl_modules
+}
+
+_perl_modules_caching_policy () {
+  local _perllocals
+
+  # rebuild if cache is more than a week old
+  oldp=( "$1"(mw+1) )
+  (( $#oldp )) && return 0
+
+  _perllocals=( /usr/lib/perl5/**/perllocal.pod )
+
+  if (( $#_perllocals )); then
+    for pod in $_perllocals; do
+      [[ "$pod" -nt "$1" ]] && return 0
+    done
+  fi
+
+  return 1
+}
+
+_perl_modules "$@"