zsh-workers
 help / color / mirror / code / Atom feed
* Re: PATCH: completion caching layer
@ 2000-08-02  9:36 Sven Wischnowsky
  2000-08-02 13:35 ` Adam Spiers
  0 siblings, 1 reply; 16+ messages in thread
From: Sven Wischnowsky @ 2000-08-02  9:36 UTC (permalink / raw)
  To: zsh-workers


Adam Spiers wrote:

> ...
> 
> OK, I've implemented this via the 'cache-policy' style, which should
> contain the name of a function which returns zero iff the cache needs
> rebuilding.  _cache_invalid is a helper function which makes it easy
> to perform this calculation.
> 
> Here's the patch (with documentation too, woohoo!)  It's quite big,
> mainly because of reindentation.  I'd be very grateful if one or two
> people could give it a quick thrashing to see whether I've
> missed/broken anything (it seems fine for me but ...)  I'll commit it
> if it works for someone else or if I get bored of waiting for people
> to try :-)

It's a bit unfortunate that _cache_invalid can be called twice (in
your examples), once directly and once from _retrieve_cache. I think.

And why do _cache_invalid and _retrieve_cache re-define themselves?
There's nothing else in the files (_retrieve_cache doesn't even call
its new definition). Or have I missed something?

And the styles or not in the style list in compsys.yo. Nor in _zstyle
(I always forget that, too ;-).

About the lookup: I /think/ it would be more convenient if the type of 
information cached would appear in the context, so that you could say
`zstyle ":completion:*:rpms" cache-policy ...'. Haven't really played
with it yet, though.

And another thing: with `zstyle -e' one could use a boolean style
`cache-invalid' or whatever and let the user do the rest. It's hard to 
give arguments to that, though. Other than by documenting
$_cache_path, that is.


Minor comment: `foo && return 0' is both smaller and faster than
`if foo; then return 0; fi'. But since I may have done that myself,
I'll better not say this too loudly ;-}

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread

* PATCH: completion caching layer
  2000-08-02  9:36 PATCH: completion caching layer Sven Wischnowsky
@ 2000-08-02 13:35 ` Adam Spiers
  0 siblings, 0 replies; 16+ messages in thread
From: Adam Spiers @ 2000-08-02 13:35 UTC (permalink / raw)
  To: zsh-workers

Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
> It's a bit unfortunate that _cache_invalid can be called twice (in
> your examples), once directly and once from _retrieve_cache. I think.

Yes, I didn't like that either, but couldn't think of a better
design.  The problem is that there are actually two caching layers -
the parameters, and the cache files on disk, but the _cache_invalid
check needs to be invoked if either is about to be used.  Suggestions
for how to avoid this welcome.

> And why do _cache_invalid and _retrieve_cache re-define themselves?
> There's nothing else in the files (_retrieve_cache doesn't even call
> its new definition). Or have I missed something?

No you didn't miss anything, that's just me forgetting to tidy up
after thinking that I was going to include other function definitions
on those files.

> And the styles or not in the style list in compsys.yo. Nor in _zstyle
> (I always forget that, too ;-).

Doh!  I've added them in.

> About the lookup: I /think/ it would be more convenient if the type of 
> information cached would appear in the context, so that you could say
> `zstyle ":completion:*:rpms" cache-policy ...'. Haven't really played
> with it yet, though.

I agree entirely.  That way also I could make _perl_modules set a
default style (if one is not already set) when the function is loaded,
rather than each time it's invoked.  But where would it appear in the
context?  My knowledge of this stuff is slightly weak, I'm afraid.

> And another thing: with `zstyle -e' one could use a boolean style
> `cache-invalid' or whatever and let the user do the rest. It's hard to 
> give arguments to that, though. Other than by documenting
> $_cache_path, that is.

I think I understand that, but how would it be better than the current
system?

> Minor comment: `foo && return 0' is both smaller and faster than
> `if foo; then return 0; fi'. But since I may have done that myself,
> I'll better not say this too loudly ;-}

:-)  I know; where it's the slow way it's usually because I previously
had some debugging in there, and thought I might need to put some back
in in the near future.

Thanks for the feedback guys, it's much appreciated.  I think I'll
commit this now that the main concerns have been addressed.  It
certainly should affect anyone who hasn't turned on their use-cache
style anyway.

P.S. Do non-RedHat systems store packages.rpm somewhere other than
/var/lib/rpm?

Index: Completion/Base/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/.distfiles,v
retrieving revision 1.4
diff -u -r1.4 .distfiles
--- Completion/Base/.distfiles	2000/05/30 09:30:08	1.4
+++ Completion/Base/.distfiles	2000/08/02 13:31:24
@@ -1,7 +1,7 @@
 DISTFILES_SRC='
     .distfiles 
-    _arg_compile _arguments _brace_parameter _combination
+    _arg_compile _arguments _brace_parameter _cache_invalid _combination
     _command_names _condition _default _describe _equal _first _in_vared
-    _jobs _math _parameter _precommand _redirect _regex_arguments _subscript
-    _tilde _value _values
+    _jobs _math _parameter _precommand _redirect _regex_arguments
+    _retrieve_cache _store_cache _subscript _tilde _value _values
 '
Index: Completion/Base/_cache_invalid
===================================================================
RCS file: _cache_invalid
diff -N _cache_invalid
--- /dev/null	Tue May  5 13:32:27 1998
+++ _cache_invalid	Wed Aug  2 06:31:24 2000
@@ -0,0 +1,21 @@
+#autoload
+#
+# Function to decide whether a completions cache needs rebuilding
+
+local _cache_ident _cache_dir _cache_path _cache_policy
+_cache_ident="$1"
+
+# If the cache is disabled, we never want to rebuild it, so pretend
+# it's valid.
+zstyle -t ":completion:${curcontext}:" use-cache || return 1
+
+zstyle -s ":completion:${curcontext}:" cache-path _cache_dir
+: ${_cache_dir:=${ZDOTDIR:-$HOME}/.zcompcache}
+_cache_path="$_cache_dir/$_cache_ident"
+
+# See whether the caching policy says that the cache needs rebuilding
+# (the policy will return 0 if it does).
+zstyle -s ":completion:${curcontext}:" cache-policy _cache_policy
+[[ -n "$_cache_policy" ]] && "$_cache_policy" "$_cache_path" && return 0
+
+return 1
Index: Completion/Base/_retrieve_cache
===================================================================
RCS file: _retrieve_cache
diff -N _retrieve_cache
--- /dev/null	Tue May  5 13:32:27 1998
+++ _retrieve_cache	Wed Aug  2 06:31:24 2000
@@ -0,0 +1,31 @@
+#autoload
+#
+# Retrieval component of completions caching layer
+
+local _cache_ident _cache_dir _cache_path _cache_policy
+_cache_ident="$1"
+
+if zstyle -t ":completion:${curcontext}:" use-cache; then
+  # Decide which directory to retrieve cache from, and ensure it exists
+  zstyle -s ":completion:${curcontext}:" cache-path _cache_dir
+  : ${_cache_dir:=${ZDOTDIR:-HOME}/.zcompcache}
+  if [[ ! -d "$_cache_dir" ]]; then
+    [[ -e "$_cache_dir" ]] &&
+      _message "cache-dir ($_cache_dir) isn't a directory\!"
+    return 1
+  fi
+
+  _cache_path="$_cache_dir/$_cache_ident"
+
+  if [[ -e "$_cache_path" ]]; then
+    _cache_invalid "$_cache_ident" && return 1
+
+    . "$_cache_path"
+    return 0
+  else
+    return 1
+  fi
+else
+  return 1
+fi
+
Index: Completion/Base/_store_cache
===================================================================
RCS file: _store_cache
diff -N _store_cache
--- /dev/null	Tue May  5 13:32:27 1998
+++ _store_cache	Wed Aug  2 06:31:24 2000
@@ -0,0 +1,36 @@
+#autoload
+#
+# Storage component of completions caching layer
+
+local _cache_ident
+_cache_ident="$1"
+
+if zstyle -t ":completion:${curcontext}:" use-cache; then
+  # Decide which directory to cache to, and ensure it exists
+  zstyle -s ":completion:${curcontext}:" cache-path _cache_dir
+  : ${_cache_dir:=${ZDOTDIR:-$HOME}/.zcompcache}
+  if [[ ! -d "$_cache_dir" ]]; then
+    if [[ -e "$_cache_dir" ]]; then
+      _message "cache-dir style points to a non-directory\!"
+    else
+      mkdir -p "$_cache_dir"
+      if [[ ! -d "$_cache_dir" ]]; then
+        _message "Couldn't create cache-dir $_cache_dir"
+        return 1
+      fi
+    fi
+  fi
+
+  shift
+  for var; do
+    case ${(Pt)var} in
+    (*readonly*) ;;
+    (*(association|array)*) print -r "$var=( ${(kv@Pqq)^^var} )";;
+    (*)                     print -r "$var=${(Pqq)^^var}";;
+    esac
+  done >! "$_cache_dir/$_cache_ident"
+else
+  return 1
+fi
+
+return 0
Index: Completion/Builtins/_zstyle
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Builtins/_zstyle,v
retrieving revision 1.16
diff -u -r1.16 _zstyle
--- Completion/Builtins/_zstyle	2000/06/22 08:42:36	1.16
+++ Completion/Builtins/_zstyle	2000/08/02 13:31:24
@@ -15,6 +15,7 @@
   assign-list            c:
   auto-description	 c:
   break-keys             c:
+  cache-path		 'c:_wanted directories expl directory _path_files -/'
   command                c:command
   completer		 c:completer
   completions		 c:bool
@@ -80,6 +81,7 @@
   suffix		 c:bool
   tag-order		 c:tag
   try-to-use-pminst	 c:bool
+  use-cache		 c:bool
   use-compctl		 c:urgh
   users			 c:_users
   users-hosts		 c:user-host
cvs server: Diffing Completion/Commands
cvs server: Diffing Completion/Core
Index: Completion/Linux/_rpm
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Linux/_rpm,v
retrieving revision 1.15
diff -u -r1.15 _rpm
--- Completion/Linux/_rpm	2000/07/12 09:01:41	1.15
+++ Completion/Linux/_rpm	2000/08/02 13:31:24
@@ -41,213 +41,238 @@
 
 # Used by `_arguments', made local here.
 
-local curcontext="$curcontext" state lstate line nm="$compstate[nmatches]"
-typeset -A opt_args
-
-state=''
-
-local ret=1
-local -a tmp expl commonopts packageopts
-commonopts=(
-  '*-v[verbose mode]'
-  '--rcfile:resource file:_files'
-  '--ftpproxy:FTP proxy server:_hosts'
-  '--ftpport:FTP port number:'
-  '--httpproxy:HTTP proxy server:_hosts'
-  '--httpport:HTTP port number:'
-)
-packageopts=(
-  '-a[query all packages]'
-  '-p+[query uninstalled package file]:*:RPM package file:->package_file'
-  '-f[specify file to query owner of]:file:_files'
-  '--triggeredby:RPM package:->package'
-  '--whatprovides:RPM capability:->capability'
-  '--whatrequires:RPM capability:->capability'
-)
-pathopts=(
-  '--root:RPM root directory:_files -/'
-  '--dbpath:RPM database path:_files -/'
-)
-
-# Do simple completions or get the first state.
-
-_arguments -C -s \
-  '--help[print help message]' \
-  '--version[print version number]' \
-  "${commonopts[@]}" \
-  '-q+[query mode]:*:query:->query' \
-  --{querytags,initdb,showrc} \
-  '--pipe:pipe command:_command_names -e' \
-  -{V,y}'[verify mode]:*:verify:->verify' \
-  '--verify[verify mode]:*:verify:->verify' \
-  '--setperms[set file permissions]:*:package:->setattrs' \
-  '--setugids[set file owner/group]:*:package:->setattrs' \
-  '(--install)-i+[install mode]:*:install:->install' \
-  '(-i)--install:*:install:->install' \
-  '(--upgrade)-U+[upgrade mode]:*:upgrade:->upgrade' \
-  '(-U)--upgrade:*:upgrade:->upgrade' \
-  '(--freshen)-F+[freshen mode]:*:upgrade:->upgrade' \
-  '(-F)--freshen:*:upgrade:->upgrade' \
-  '(--erase)-e+[uninstall mode]:*:uninstall:->uninstall' \
-  '(-e)--erase:*:uninstall:->uninstall' \
-  '-b+[build mode (spec file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
-  '(-b)-t+[build mode (tar file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
-  --{resign,addsign}':*:RPM package:->package_file' \
-  '--rmsource:*:spec file:->spec_file' \
-  --{rebuild,recompile}':*:Src RPM files:->package_src' \
-  '(--checksig)-K+[signature check mode]:*:sigcheck:->sigcheck' \
-  '(-K)--checksig:*:sigcheck:->sigcheck' \
-  '--rebuilddb:*:rebuild:->rebuild' && ret=0
-
-# As long as we have a state name...
-
-while [[ -n "$state" ]]; do
-
-  # First try to call a user-defined function.
-
-  _funcall ret _rpm_$state && return ret
-
-  # Copy the state and reset `state', to simplify the test above.
-
-  lstate="$state"
+_rpm () {
+  local curcontext="$curcontext" state lstate line nm="$compstate[nmatches]"
+  typeset -A opt_args
+  
   state=''
-  tmp=()
-
-  # Dispatch...
-
-  case "$lstate" in
-  query)
-    # --dump requires on of -{l,c,d}
-    # --triggers requires --script
-    _arguments -s \
-      -q "${commonopts[@]}" "${packageopts[@]}" "${pathopts[@]}" \
-      '--queryformat:RPM query format:->tags' \
-      '-i[display package information]' \
-      '--changelog[display change log]' \
-      '-l[display package file list]' \
-      '-s[show file states]' \
-      '-d[documentation files only]' \
-      '-c[configuration files only]' \
-      '--dump[show all information]' \
-      --provides \
-      -{R,-requires}'[list dependencies]' \
-      '--scripts[show (un)install scripts]' \
-      '--triggers[show trigger scripts]' \
-      '*:RPM package:->package_or_file' && ret=0
-    ;;
-  setattrs)
-    _arguments -s --set{perm,ugids} "${packageopts[@]}" && ret = 0
-    ;;
-  verify)
-    _arguments -s \
-      '(-y --verify)-V' '(-V --verify)-y' '(-y -V)--verify' \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      --no{deps,md5,files} \
-      '*:RPM package:->package' && ret=0
-    ;;
-  upgrade)
-    tmp=( '(--upgrade)-U' '(-U)--upgrade' '(--force)--oldpackage' )
-    ;&
-  install)
-    (( $#tmp )) || tmp=( '(--install)-i' '(-i)--install' )
-    _arguments -s "$tmp[@]" \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      '--excludepath:exclude files in following path:_files -/' \
-      '--relocate:relocate:->relocate' \
-      '--prefix:package prefix directory:_files -/' \
-      '(-h)--hash' '(--hash)-h' \
-      '(--replacepkgs --replacefiles --oldpackage)--force' \
-      '(--force)--'{replacefiles,replacepkgs} \
-      --{badreloc,excludedocs,allfiles,ignorearch,ignoreos,includedocs,justdb,nodeps,noorder,noscripts,notriggers,percent,test} \
-      '*:pkg file:->package_file' && ret=0
-    ;;
-  uninstall)
-    _arguments -s \
-      '(-e)--erase' '(--erase)-e' \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      --{allmatches,justdb,nodeps,noorder,noscripts,notriggers} \
-      '*:RPM package:->package' && ret=0
-    ;;
-  build_b)
-    tmp=( '*:spec file:_files -g \*.spec' )
-    ;&
-  build_t)
-    (( $#tmp )) || tmp=( '*:tar file:_files -g \*.\(\#i\)tar\(.\*\|\)' )
-
-    _arguments -s \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      --{short-circuit,clean,rmsource,sign,test} \
-      '--target:specify a build target:->target'\
-      '--buildroot:build root directory:_files -/' \
-      '--buildarch:architecture for which to build:->target' \
-      '--buildos:ositecture for which to build:' \
-      '--timecheck:time check (seconds):' "$tmp[1]" && ret=0
-    ;;
-  sigcheck)
-    _arguments -s \
-      '(-K)--checksig' '(--checksig)-K' \
-      "${commonopts[@]}" \
-      --no{pgp,md5} \
-      '*:RPM package file:->package_file' && ret=0
-    ;;
-  rebuild)
-    _arguments -s \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      '*:RPM source package file:->package_file' && ret=0
-    ;;
-  target)
-    _wanted target expl 'Target platforms' \
-        compadd $(_call target rpm --showrc 2> /dev/null |grep 'compatible archs'|sed 's/.*: //') && ret=0
-    ;;
-  package_or_file)
-    state=package_file
-    ;&
-  package)
-    _wanted packages expl 'RPM package' \
-        compadd -M 'r:|-=* r:|=*' - $(_call packages rpm -qa 2> /dev/null) && ret=0
-    ;;
-  spec_file)
-    _wanted specfiles expl 'spec file' \
-        _files -g \*.spec && ret=0
-    ;;
-  package_file)
-    _wanted files expl 'RPM package file' \
-        _files -g '*.(#i)rpm' && ret=0
-    if [[ -prefix 1 (f|ht)tp:// ]]; then
-      _wanted urls expl 'URL of RPM package file' \
-          _urls -f -g '*.(#i)rpm' "${expl[@]}" && ret=0
-    else
-      _wanted urls expl 'URL of RPM package file' \
-          compadd -S '' "${expl[@]}" ftp:// http:// && ret=0
-    fi
-    ;;
-  package_src)
-    _files -g \*.src\(\#i\).rpm
-   ;&
-  tags)
-    if compset -P '*%*\{'; then
-      _wanted tags expl 'RPM tag' \
-          compadd -M 'm:{a-z}={A-Z}' -S '\}' - \
-                  "${(@)${(@f)$(_call tags rpm --querytags 2> /dev/null)}#RPMTAG_}" && ret=0
-    else
-      _message 'RPM format'
-    fi
-    ;;
-  capability)
-    _message 'RPM capability'
-    ;;
-  relocate)
-    if compset -P '*='; then
-      _description directories expl 'new path'
-    else
-      _description directories expl 'old path'
-    fi
-
-    _files "$expl[@]" -/ && ret=0
-    ;;
-  esac
+  
+  local ret=1
+  local -a tmp expl commonopts packageopts
+  commonopts=(
+    '*-v[verbose mode]'
+    '--rcfile:resource file:_files'
+    '--ftpproxy:FTP proxy server:_hosts'
+    '--ftpport:FTP port number:'
+    '--httpproxy:HTTP proxy server:_hosts'
+    '--httpport:HTTP port number:'
+  )
+  packageopts=(
+    '-a[query all packages]'
+    '-p+[query uninstalled package file]:*:RPM package file:->package_file'
+    '-f[specify file to query owner of]:file:_files'
+    '--triggeredby:RPM package:->package'
+    '--whatprovides:RPM capability:->capability'
+    '--whatrequires:RPM capability:->capability'
+  )
+  pathopts=(
+    '--root:RPM root directory:_files -/'
+    '--dbpath:RPM database path:_files -/'
+  )
+  
+  # Do simple completions or get the first state.
+  
+  _arguments -C -s \
+    '--help[print help message]' \
+    '--version[print version number]' \
+    "${commonopts[@]}" \
+    '-q+[query mode]:*:query:->query' \
+    --{querytags,initdb,showrc} \
+    '--pipe:pipe command:_command_names -e' \
+    -{V,y}'[verify mode]:*:verify:->verify' \
+    '--verify[verify mode]:*:verify:->verify' \
+    '--setperms[set file permissions]:*:package:->setattrs' \
+    '--setugids[set file owner/group]:*:package:->setattrs' \
+    '(--install)-i+[install mode]:*:install:->install' \
+    '(-i)--install:*:install:->install' \
+    '(--upgrade)-U+[upgrade mode]:*:upgrade:->upgrade' \
+    '(-U)--upgrade:*:upgrade:->upgrade' \
+    '(--freshen)-F+[freshen mode]:*:upgrade:->upgrade' \
+    '(-F)--freshen:*:upgrade:->upgrade' \
+    '(--erase)-e+[uninstall mode]:*:uninstall:->uninstall' \
+    '(-e)--erase:*:uninstall:->uninstall' \
+    '-b+[build mode (spec file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
+    '(-b)-t+[build mode (tar file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
+    --{resign,addsign}':*:RPM package:->package_file' \
+    '--rmsource:*:spec file:->spec_file' \
+    --{rebuild,recompile}':*:Src RPM files:->package_src' \
+    '(--checksig)-K+[signature check mode]:*:sigcheck:->sigcheck' \
+    '(-K)--checksig:*:sigcheck:->sigcheck' \
+    '--rebuilddb:*:rebuild:->rebuild' && ret=0
+  
+  # As long as we have a state name...
+  
+  while [[ -n "$state" ]]; do
+  
+    # First try to call a user-defined function.
+  
+    _funcall ret _rpm_$state && return ret
+  
+    # Copy the state and reset `state', to simplify the test above.
+  
+    lstate="$state"
+    state=''
+    tmp=()
+  
+    # Dispatch...
+  
+    case "$lstate" in
+    query)
+      # --dump requires on of -{l,c,d}
+      # --triggers requires --script
+      _arguments -s \
+        -q "${commonopts[@]}" "${packageopts[@]}" "${pathopts[@]}" \
+        '--queryformat:RPM query format:->tags' \
+        '-i[display package information]' \
+        '--changelog[display change log]' \
+        '-l[display package file list]' \
+        '-s[show file states]' \
+        '-d[documentation files only]' \
+        '-c[configuration files only]' \
+        '--dump[show all information]' \
+        --provides \
+        -{R,-requires}'[list dependencies]' \
+        '--scripts[show (un)install scripts]' \
+        '--triggers[show trigger scripts]' \
+        '*:RPM package:->package_or_file' && ret=0
+      ;;
+    setattrs)
+      _arguments -s --set{perm,ugids} "${packageopts[@]}" && ret = 0
+      ;;
+    verify)
+      _arguments -s \
+        '(-y --verify)-V' '(-V --verify)-y' '(-y -V)--verify' \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        --no{deps,md5,files} \
+        '*:RPM package:->package' && ret=0
+      ;;
+    upgrade)
+      tmp=( '(--upgrade)-U' '(-U)--upgrade' '(--force)--oldpackage' )
+      ;&
+    install)
+      (( $#tmp )) || tmp=( '(--install)-i' '(-i)--install' )
+      _arguments -s "$tmp[@]" \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        '--excludepath:exclude files in following path:_files -/' \
+        '--relocate:relocate:->relocate' \
+        '--prefix:package prefix directory:_files -/' \
+        '(-h)--hash' '(--hash)-h' \
+        '(--replacepkgs --replacefiles --oldpackage)--force' \
+        '(--force)--'{replacefiles,replacepkgs} \
+        --{badreloc,excludedocs,allfiles,ignorearch,ignoreos,includedocs,justdb,nodeps,noorder,noscripts,notriggers,percent,test} \
+        '*:pkg file:->package_file' && ret=0
+      ;;
+    uninstall)
+      _arguments -s \
+        '(-e)--erase' '(--erase)-e' \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        --{allmatches,justdb,nodeps,noorder,noscripts,notriggers} \
+        '*:RPM package:->package' && ret=0
+      ;;
+    build_b)
+      tmp=( '*:spec file:_files -g \*.spec' )
+      ;&
+    build_t)
+      (( $#tmp )) || tmp=( '*:tar file:_files -g \*.\(\#i\)tar\(.\*\|\)' )
+  
+      _arguments -s \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        --{short-circuit,clean,rmsource,sign,test} \
+        '--target:specify a build target:->target'\
+        '--buildroot:build root directory:_files -/' \
+        '--buildarch:architecture for which to build:->target' \
+        '--buildos:ositecture for which to build:' \
+        '--timecheck:time check (seconds):' "$tmp[1]" && ret=0
+      ;;
+    sigcheck)
+      _arguments -s \
+        '(-K)--checksig' '(--checksig)-K' \
+        "${commonopts[@]}" \
+        --no{pgp,md5} \
+        '*:RPM package file:->package_file' && ret=0
+      ;;
+    rebuild)
+      _arguments -s \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        '*:RPM source package file:->package_file' && ret=0
+      ;;
+    target)
+      _wanted target expl 'Target platforms' \
+          compadd $(_call target rpm --showrc 2> /dev/null |grep 'compatible archs'|sed 's/.*: //') && ret=0
+      ;;
+    package_or_file)
+      state=package_file
+      ;&
+    package)
+      if ( [[ ${+_rpms} -eq 0 ]] || _cache_invalid RPMs ) &&
+         ! _retrieve_cache RPMs;
+      then
+        _rpms=( $(_call packages rpm -qa 2>/dev/null) )
+        _store_cache RPMs _rpms
+      fi
+      _wanted packages expl 'RPM package' \
+          compadd -M 'r:|-=* r:|=*' - "$_rpms[@]" && ret=0
+      ;;
+    spec_file)
+      _wanted specfiles expl 'spec file' \
+          _files -g \*.spec && ret=0
+      ;;
+    package_file)
+      _wanted files expl 'RPM package file' \
+          _files -g '*.(#i)rpm' && ret=0
+      if [[ -prefix 1 (f|ht)tp:// ]]; then
+        _wanted urls expl 'URL of RPM package file' \
+            _urls -f -g '*.(#i)rpm' "${expl[@]}" && ret=0
+      else
+        _wanted urls expl 'URL of RPM package file' \
+            compadd -S '' "${expl[@]}" ftp:// http:// && ret=0
+      fi
+      ;;
+    package_src)
+      _files -g \*.src\(\#i\).rpm
+     ;&
+    tags)
+      if compset -P '*%*\{'; then
+        _wanted tags expl 'RPM tag' \
+            compadd -M 'm:{a-z}={A-Z}' -S '\}' - \
+                    "${(@)${(@f)$(_call tags rpm --querytags 2> /dev/null)}#RPMTAG_}" && ret=0
+      else
+        _message 'RPM format'
+      fi
+      ;;
+    capability)
+      _message 'RPM capability'
+      ;;
+    relocate)
+      if compset -P '*='; then
+        _description directories expl 'new path'
+      else
+        _description directories expl 'old path'
+      fi
+  
+      _files "$expl[@]" -/ && ret=0
+      ;;
+    esac
+  
+    [[ ret -eq 0 || $nm -ne $compstate[nmatches] ]] && return 0
+  done
+  
+  return ret
+}
+
+# set a sensible default caching policy
+local update_policy
+zstyle -s ":completion:*:*:rpm:*" cache-policy update_policy
+if [[ -z "$update_policy" ]]; then
+  zstyle ":completion:*:*:rpm:*" cache-policy _rpms_caching_policy
+fi
+
+_rpms_caching_policy () {
+  # rebuild if cache is more than a week old
+  oldp=( "$1"(Nmw+1) )
+  (( $#oldp )) && return 0
 
-  [[ ret -eq 0 || $nm -ne $compstate[nmatches] ]] && return 0
-done
+  [[ /var/lib/rpm/packages.rpm -nt "$1" ]]
+}
 
-return ret
+_rpm "$@"
cvs server: Diffing Completion/User
Index: Completion/User/_perl_modules
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/User/_perl_modules,v
retrieving revision 1.6
diff -u -r1.6 _perl_modules
--- Completion/User/_perl_modules	2000/05/31 09:38:26	1.6
+++ Completion/User/_perl_modules	2000/08/02 13:31:24
@@ -17,49 +17,85 @@
 #   algorithm (the zsh code does almost the same, but only misses
 #   modules which don't begin with an uppercase letter).
 
-local opts
-zparseopts -D -a opts S: q
-
-if [[ ${+_perl_modules} -eq 0 ]]; then
-  if zstyle -t ":completion:${curcontext}:modules" try-to-use-pminst \
-     && (( ${+commands[pminst]} )); then
-    _perl_modules=( $(pminst) )
-  else
-    local inc libdir new_pms
-    if (( ${+commands[perl]} )); then
-      inc=( $( perl -e 'print "@INC"' ) )
+_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
+  
+  if ( [[ ${+_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
+      _perl_modules=( $(pminst) )
     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 ..."
-
-      setopt localoptions extendedglob
-      inc=( /usr/lib/perl5{,/{site_perl/,}<5->.([0-9]##)}(N) 
-            ${(s.:.)PERL5LIB} )
-    fi
-
-    typeset -agU _perl_modules  # _perl_modules is global, no duplicates
-    _perl_modules=( )
-
-    for libdir in $inc; do
-      # Ignore cwd - could be too expensive e.g. if we're near /
-      if [[ $libdir == '.' ]]; then break; fi
-
-      # Find all modules
-      if [[ -d $libdir && -x $libdir ]]; then
-      cd $libdir
-      new_pms=( {[A-Z]*/***/,}*.pm~*blib*(N) )
-      cd $OLDPWD
+      local inc libdir new_pms
+      if (( ${+commands[perl]} )); 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 ..."
+  
+        setopt localoptions extendedglob
+        inc=( /usr/lib/perl5{,/{site_perl/,}<5->.([0-9]##)}(N) 
+              ${(s.:.)PERL5LIB} )
       fi
-
-      # Convert to Perl nomenclature
-      new_pms=( ${new_pms:r:fs#/#::#} )
-
-      _perl_modules=( $new_pms $_perl_modules )
+  
+      typeset -agU _perl_modules  # _perl_modules is global, no duplicates
+      _perl_modules=( )
+  
+      for libdir in $inc; do
+        # Ignore cwd - could be too expensive e.g. if we're near /
+        if [[ $libdir == '.' ]]; then break; fi
+  
+        # Find all modules
+        if [[ -d $libdir && -x $libdir ]]; then
+        cd $libdir
+        new_pms=( {[A-Z]*/***/,}*.pm~*blib*(N) )
+        cd $OLDPWD
+        fi
+  
+        # Convert to Perl nomenclature
+        new_pms=( ${new_pms:r:fs#/#::#} )
+  
+        _perl_modules=( $new_pms $_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"(Nmw+1) )
+  (( $#oldp )) && return 0
+
+  _perllocals=( /usr/lib/perl5/**/perllocal.pod(N) )
+
+  if (( $#_perllocals )); then
+    for pod in $_perllocals; do
+      [[ "$pod" -nt "$1" ]] && return 0
     done
   fi
-fi
 
-local expl
+  return 1
+}
 
-_wanted modules expl 'Perl modules' compadd "$opts[@]" -a _perl_modules
+_perl_modules "$@"
cvs server: Diffing Completion/X
cvs server: Diffing Config
cvs server: Diffing Doc
cvs server: Diffing Doc/Zsh
Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.89
diff -u -r1.89 compsys.yo
--- Doc/Zsh/compsys.yo	2000/08/02 10:36:20	1.89
+++ Doc/Zsh/compsys.yo	2000/08/02 13:31:26
@@ -914,6 +914,13 @@
 widget to stop incremental completion without the key having any
 further effect.
 )
+kindex(cache-path, completion style)
+item(tt(cache-path))(
+This style defines the path where any cache files containing dumped
+completion data are stored.  Defaults to `tt($DOTDIR/.zcompcache)', or
+`tt($HOME/.zcompcache)' if tt($DOTDIR) is not defined.  The completion
+layer will not be used unless the tt(use-cache) style is set.
+)
 kindex(command, completion style)
 item(tt(command))(
 In many places, completion functions need to call external commands to
@@ -2083,6 +2090,13 @@
 arguments or arguments of options) to be completed before option names for
 most commands.
 )
+kindex(use-cache, completion style)
+item(tt(use-cache))(
+If this is set, the completion caching layer is activated for any completions
+which use it (via the tt(_store_cache), tt(_retrieve_cache), and
+tt(_cache_invalid) functions).  The directory containing the cache
+files can be changed with the tt(cache-path) style.
+)
 kindex(use-compctl, completion style)
 item(tt(use-compctl))(
 If this style is set to a string em(not) equal to tt(false), tt(0),
@@ -3189,6 +3203,22 @@
 be completed. The last description says that all other arguments are
 `var(page numbers)' but does not give possible completions.
 )
+findex(_cache_invalid)
+item(tt(_cache_invalid) var(cache_identifier))(
+This function returns 0 if the completions cache corresponding to the
+given cache identifier needs rebuilding.  It determines this by
+looking up the tt(cache-policy) style for the current context, and
+if it exists, runs the function of the same name, supplying the full
+path to the relevant cache file as the only argument.
+
+Example:
+
+example(_example_caching_policy () {
+    # rebuild if cache is more than a week old
+    oldp=( "$1"(Nmw+1) )
+    (( $#oldp ))
+})
+)
 findex(_call)
 item(tt(_call) var(tag) var(string) ...)(
 This function is used in places where a command is called, making it
@@ -3595,6 +3625,18 @@
   (( ret )) || break
 done)
 )
+findex(_retrieve_cache)
+item(tt(_retrieve_cache) var(cache_identifier))(
+This function retrieves completion information from the file given by
+var(cache_identifier), stored in a directory specified by the
+tt(cache-path) style (defaults to tt(~/.zsh/cache)).  The return value
+is zero if retrieval was successful.  It will only attempt retrieval
+if the tt(use-cache) style is set, so you can call this function
+without worrying about whether the user wanted to use the caching
+layer.
+
+See tt(_store_cache) below for more details.
+)
 findex(_sep_parts)
 item(tt(_sep_parts))(
 This function is passed alternating arrays and separators as arguments.
@@ -3717,6 +3759,36 @@
 separate set. With the tt(-m) option, the arguments are treated in the 
 same way as the the values for the tt(tag-order) style (except for the 
 `tt(!...)', `tt(-)' and `tt(foo())' forms).
+)
+findex(_store_cache)
+item(tt(_store_cache) var(cache_identifier) var(vars) ...)(
+This function, when combined with tt(_retrieve_cache) and
+tt(_cache_invalid), makes it easy to implement a caching layer for
+your completion functions.  If a completion function needs to perform
+a costly operation in order to generate data which is used to
+calculate completions, you can store that data in variables, and use
+this function to dump the values of those variables to a file.  Then,
+if they are needed in subsequent shell invocations, they can be
+retrieved quickly from that file via tt(_retrieve_cache), avoiding the
+needly for repeating the costly operation.
+
+The var(cache_identifier) specifies the file which the data should be
+dumped to, and is stored in a directory specified by the
+tt(cache-path) style (defaults to tt(~/.zsh/cache)).  The remaining
+var(vars) arguments are the variables to dump to the file.
+
+The return value is zero if storage was successful.  The function will
+only attempt storage if the tt(use-cache) style is set, so you can
+call this function without worrying about whether the user wanted to
+use the caching layer.
+
+If your completion function avoids calling _retrieve_cache when it
+already has the completion data in the environment, it should probably
+at least call tt(_cache_invalid) to check whether this data and the
+data cached on disk is still valid.
+
+See the _perl_modules completion function for a simple example of
+usage of this caching layer.
 )
 findex(_tags)
 item(tt(_tags) [ tt(-C) var(name) [ var(tags) ... ] ])(


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
@ 2000-08-04  6:59 Sven Wischnowsky
  0 siblings, 0 replies; 16+ messages in thread
From: Sven Wischnowsky @ 2000-08-04  6:59 UTC (permalink / raw)
  To: zsh-workers


Adam Spiers wrote:

> ...
> 
> Now, it's not hard to imagine a system which doesn't have any CPAN
> modules installed.  In that case, I was worried about the above test
> failing because _perl_CPAN_modules would be undefined.  However there
> appears to be an easy solution, which is just to ensure that all
> cache-related parameters are always defined after retrieval, even if
> they're defined to the empty array or string.  Does that sound OK?

Yes, I think (we do this thing of `empty is the same as undefined'
elsewhere anyway).

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
  2000-08-02 15:01 ` Adam Spiers
@ 2000-08-03 12:21   ` Adam Spiers
  0 siblings, 0 replies; 16+ messages in thread
From: Adam Spiers @ 2000-08-03 12:21 UTC (permalink / raw)
  To: zsh-workers

Adam Spiers (adam@spiers.net) wrote:
> Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
> > 
> > Adam Spiers wrote:
> > 
> > > Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
> > > > It's a bit unfortunate that _cache_invalid can be called twice (in
> > > > your examples), once directly and once from _retrieve_cache. I think.
> > > 
> > > Yes, I didn't like that either, but couldn't think of a better
> > > design.  The problem is that there are actually two caching layers -
> > > the parameters, and the cache files on disk, but the _cache_invalid
> > > check needs to be invoked if either is about to be used.  Suggestions
> > > for how to avoid this welcome.
> > 
> > Couldn't we stuff everything in _retrieve_cache? So that one only
> > needs to call:
> > 
> >   if ! _retrieve_cache RPMs _rpms; then
> >     _rpms=(...)
> >     _store_cache RPMs _rpms
> >   fi
> 
> I had thought of that, and then decided against it, probably for no
> good reason whatsoever, as I was exhausted at the time :-) 

I remembered the reason, and why I thought it might be good.  I was
thinking that the problem with moving the parameter test into
_retrieve_cache is that the completion function programmer loses
control over it, and while in the majority of the situations the test
will be of the nature 'check if the parameter is undefined, and if so
we need to retrieve from the cache file', there could be situations in
the future where the parameter would correctly end up undefined
/after/ retrieval from disk.  For example, suppose that _perl_modules
stored the results of its search for perl modules in several
parameters, instead of one:

  _perl_pragmatic_modules
  _perl_standard_modules
  _perl_extension_modules
  _perl_CPAN_modules

(See the perlmodlib man page for an explanation of these.)

Now, it's not hard to imagine a system which doesn't have any CPAN
modules installed.  In that case, I was worried about the above test
failing because _perl_CPAN_modules would be undefined.  However there
appears to be an easy solution, which is just to ensure that all
cache-related parameters are always defined after retrieval, even if
they're defined to the empty array or string.  Does that sound OK?


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
@ 2000-08-03  7:11 Sven Wischnowsky
  0 siblings, 0 replies; 16+ messages in thread
From: Sven Wischnowsky @ 2000-08-03  7:11 UTC (permalink / raw)
  To: zsh-workers


Adam Spiers wrote:

> ...
>
> > > I agree entirely.  That way also I could make _perl_modules set a
> > > default style (if one is not already set) when the function is loaded,
> > > rather than each time it's invoked.  But where would it appear in the
> > > context?  My knowledge of this stuff is slightly weak, I'm afraid.
> > 
> > After the last colon:
> > 
> >   zstyle -t ":completion:${curcontext}:" ...
> >                                        ^here
> > 
> > I.e., instead of the tag (if you would use tags).
> 
> OK.  Although that doesn't solve the problem of having to set a
> default for each of the commands _perl_modules completes.  Maybe
> 
>   zstyle ':completion:::::RPMs' cache-policy _rpms_caching_policy
> 
> would work?

For use by the completion function itself? We decided some time ago
that they shouldn't set styles themselves, only look them up.

So, instead of adding what you suggest (which most probably wouldn't
work because there are other things in the context, e.g. the command
name), one would use the return value of zstyle:

  zstyle -s ":completion:${curcontext}:RPMs" cache-policy foo ||
      foo=_rpms_caching_policy

I.e., the return value of zstyle is non-zero iff the style is not set
for that context.


> Incidentally I couldn't find anything in the documentation to explain
> the difference between e.g. ::: and :*:*: in contexts.  Did I miss it?

Err. Pattern matching. `:::' matches only itself, `:*:*:' matches
`::perl:' and `::perl:argument-rest' and `:complete:perl:argument-rest' 
and `predict:complete:perl:argument-rest'.

The patterns given when defining styles are really only matched agains 
the context-strings given when looking up styles. Normal shell pattern 
matching, nothing special there. Only the sorting of the patterns is
something not used elsewhere.

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
  2000-08-02 14:13 Sven Wischnowsky
@ 2000-08-02 15:01 ` Adam Spiers
  2000-08-03 12:21   ` Adam Spiers
  0 siblings, 1 reply; 16+ messages in thread
From: Adam Spiers @ 2000-08-02 15:01 UTC (permalink / raw)
  To: zsh-workers

Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
> 
> Adam Spiers wrote:
> 
> > Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
> > > It's a bit unfortunate that _cache_invalid can be called twice (in
> > > your examples), once directly and once from _retrieve_cache. I think.
> > 
> > Yes, I didn't like that either, but couldn't think of a better
> > design.  The problem is that there are actually two caching layers -
> > the parameters, and the cache files on disk, but the _cache_invalid
> > check needs to be invoked if either is about to be used.  Suggestions
> > for how to avoid this welcome.
> 
> Couldn't we stuff everything in _retrieve_cache? So that one only
> needs to call:
> 
>   if ! _retrieve_cache RPMs _rpms; then
>     _rpms=(...)
>     _store_cache RPMs _rpms
>   fi

I had thought of that, and then decided against it, probably for no
good reason whatsoever, as I was exhausted at the time :-) 

> > > About the lookup: I /think/ it would be more convenient if the type of 
> > > information cached would appear in the context, so that you could say
> > > `zstyle ":completion:*:rpms" cache-policy ...'. Haven't really played
> > > with it yet, though.
> > 
> > I agree entirely.  That way also I could make _perl_modules set a
> > default style (if one is not already set) when the function is loaded,
> > rather than each time it's invoked.  But where would it appear in the
> > context?  My knowledge of this stuff is slightly weak, I'm afraid.
> 
> After the last colon:
> 
>   zstyle -t ":completion:${curcontext}:" ...
>                                        ^here
> 
> I.e., instead of the tag (if you would use tags).

OK.  Although that doesn't solve the problem of having to set a
default for each of the commands _perl_modules completes.  Maybe

  zstyle ':completion:::::RPMs' cache-policy _rpms_caching_policy

would work?

Incidentally I couldn't find anything in the documentation to explain
the difference between e.g. ::: and :*:*: in contexts.  Did I miss it?

> One problem is your
> naming scheme (upper-case) which is different from what we've used so
> far.

That's easily fixed...

I just noticed I forgot hunks for cache-policy.  Coming up in the next
patch ...


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
@ 2000-08-02 14:13 Sven Wischnowsky
  2000-08-02 15:01 ` Adam Spiers
  0 siblings, 1 reply; 16+ messages in thread
From: Sven Wischnowsky @ 2000-08-02 14:13 UTC (permalink / raw)
  To: zsh-workers


Adam Spiers wrote:

> Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
> > It's a bit unfortunate that _cache_invalid can be called twice (in
> > your examples), once directly and once from _retrieve_cache. I think.
> 
> Yes, I didn't like that either, but couldn't think of a better
> design.  The problem is that there are actually two caching layers -
> the parameters, and the cache files on disk, but the _cache_invalid
> check needs to be invoked if either is about to be used.  Suggestions
> for how to avoid this welcome.

Couldn't we stuff everything in _retrieve_cache? So that one only
needs to call:

  if ! _retrieve_cache RPMs _rpms; then
    _rpms=(...)
    _store_cache RPMs _rpms
  fi

> ...
> 
> > About the lookup: I /think/ it would be more convenient if the type of 
> > information cached would appear in the context, so that you could say
> > `zstyle ":completion:*:rpms" cache-policy ...'. Haven't really played
> > with it yet, though.
> 
> I agree entirely.  That way also I could make _perl_modules set a
> default style (if one is not already set) when the function is loaded,
> rather than each time it's invoked.  But where would it appear in the
> context?  My knowledge of this stuff is slightly weak, I'm afraid.

After the last colon:

  zstyle -t ":completion:${curcontext}:" ...
                                       ^here

I.e., instead of the tag (if you would use tags). One problem is your
naming scheme (upper-case) which is different from what we've used so
far.

And then the tags should be documented, or similar tags which are
already used elsewhere could be used for caching.

> > And another thing: with `zstyle -e' one could use a boolean style
> > `cache-invalid' or whatever and let the user do the rest. It's hard to 
> > give arguments to that, though. Other than by documenting
> > $_cache_path, that is.
> 
> I think I understand that, but how would it be better than the current
> system?

Maybe hopefully consistency(?) I'm not too sure about this either,
since there are still other styles which allow to give names of
functions to be called (tag-order, for example).

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
  2000-08-01 23:37     ` Adam Spiers
@ 2000-08-02  3:53       ` Bart Schaefer
  0 siblings, 0 replies; 16+ messages in thread
From: Bart Schaefer @ 2000-08-02  3:53 UTC (permalink / raw)
  To: Adam Spiers, zsh-workers

On Aug 2, 12:37am, Adam Spiers wrote:
} > 
} >     while (($# > 1)); do
} >       shift
} >       ${(P)=1:+typeset $1}
} >     done > "$_cache_dir/$_cache_ident"
} > 
} > would be more accurate?
} 
} Is that better than what you suggested via private mail?

No, it's not.  This:

} >     typeset +g "$@[2,-1]" > "$_cache_dir/$_cache_ident"

Is probably the most efficient answer, but it doesn't skip the readonly
variables, which the longer suggestion the private message did.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
  2000-08-01 17:03   ` Bart Schaefer
  2000-08-01 17:09     ` Bart Schaefer
@ 2000-08-01 23:37     ` Adam Spiers
  2000-08-02  3:53       ` Bart Schaefer
  1 sibling, 1 reply; 16+ messages in thread
From: Adam Spiers @ 2000-08-01 23:37 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer (schaefer@candle.brasslantern.com) wrote:
> On Aug 1,  5:31pm, Adam Spiers wrote:
> } Subject: PATCH: completion caching layer
> }
> } +findex(_retrieve_cache)
> } +item(tt(_retrieve_cache) var(cache_identifier))(
> } +This function retrieves completion information from the file given by
> } +var(cache_identifier), stored in a directory specified by the
> } +tt(cache-path) style (defaults to tt(~/.zsh/cache)).
> 
> I'd prefer that the cache location be relative to $ZDOTDIR rather than
> relative to $HOME, and that it not be two levels removed, e.g. use
> $ZDODTIR/.zcompcache/ rather than ~/.zsh/cache/.  That'd be consistent
> with e.g. .zcompdump.

Sure, change applied, so will appear in the commit.  Makes no
difference to me; I already had

  zstyle ':completion::complete:*' cache-path ~/.zsh/cache/$HOST

in my .zshrc because my home directory is mounted via NFS so I need a
different cache path for each machine (for perldoc and rpm at least).

> } +  # grr, doesn't work, so we have to roll our own
> } +#  typeset "$@[2,-1]" > "$_cache_dir/$_cache_ident"
> 
> Isn't
> 
>     typeset +g "$@[2,-1]" > "$_cache_dir/$_cache_ident"

Ah, +g!  I was looking for that.

> what you want?  Or maybe
> 
>     while (($# > 1)); do
>       shift
>       ${(P)=1:+typeset $1}
>     done > "$_cache_dir/$_cache_ident"
> 
> would be more accurate?

Is that better than what you suggested via private mail?


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
  2000-08-01 17:03   ` Bart Schaefer
@ 2000-08-01 17:09     ` Bart Schaefer
  2000-08-01 23:37     ` Adam Spiers
  1 sibling, 0 replies; 16+ messages in thread
From: Bart Schaefer @ 2000-08-01 17:09 UTC (permalink / raw)
  To: Adam Spiers, zsh-workers

On Aug 1,  5:03pm, Bart Schaefer wrote:
} Subject: Re: PATCH: completion caching layer
}
}     while (($# > 1)); do
}       shift
}       ${(P)=1:+typeset $1}
}     done > "$_cache_dir/$_cache_ident"

There should be a +g in that typeset as well, sorry.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
  2000-08-01 16:31 ` Adam Spiers
@ 2000-08-01 17:03   ` Bart Schaefer
  2000-08-01 17:09     ` Bart Schaefer
  2000-08-01 23:37     ` Adam Spiers
  0 siblings, 2 replies; 16+ messages in thread
From: Bart Schaefer @ 2000-08-01 17:03 UTC (permalink / raw)
  To: Adam Spiers, zsh-workers

On Aug 1,  5:31pm, Adam Spiers wrote:
} Subject: PATCH: completion caching layer
}
} +findex(_retrieve_cache)
} +item(tt(_retrieve_cache) var(cache_identifier))(
} +This function retrieves completion information from the file given by
} +var(cache_identifier), stored in a directory specified by the
} +tt(cache-path) style (defaults to tt(~/.zsh/cache)).

I'd prefer that the cache location be relative to $ZDOTDIR rather than
relative to $HOME, and that it not be two levels removed, e.g. use
$ZDODTIR/.zcompcache/ rather than ~/.zsh/cache/.  That'd be consistent
with e.g. .zcompdump.

(Also, selfishly, I'm already using ~/.zsh/ for something else and I don't
want this stepping in it.)

} +  # grr, doesn't work, so we have to roll our own
} +#  typeset "$@[2,-1]" > "$_cache_dir/$_cache_ident"

Isn't

    typeset +g "$@[2,-1]" > "$_cache_dir/$_cache_ident"

what you want?  Or maybe

    while (($# > 1)); do
      shift
      ${(P)=1:+typeset $1}
    done > "$_cache_dir/$_cache_ident"

would be more accurate?

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 16+ messages in thread

* PATCH: completion caching layer
  2000-07-27  8:00 Sven Wischnowsky
@ 2000-08-01 16:31 ` Adam Spiers
  2000-08-01 17:03   ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: Adam Spiers @ 2000-08-01 16:31 UTC (permalink / raw)
  To: zsh-workers

Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
> Adam Spiers wrote:
> > This sounds very nice, but I'm not sure what sort of policies you have
> > in mind, and how they should be implement.  Could you give a few
> > examples?
> 
> Of course, that's the problem. One that may be useful quite often
> would compare the mtime of a file and re-build the cache when it has
> changed.
> 
> In some cases (when using data that gets updated after regular time
> intervals) wall-clock time comparison may be good (with that it would
> probably be possible to sensibly cache YP data if we would need that).
> 
> However, I don't think there can ever be a complete list. Maybe we
> should just give _retrieve_cache an optional argument which is
> evaluated or a function name or something that gets called to test if
> the cache should be re-build. We probably just need more experience...

OK, I've implemented this via the 'cache-policy' style, which should
contain the name of a function which returns zero iff the cache needs
rebuilding.  _cache_invalid is a helper function which makes it easy
to perform this calculation.

Here's the patch (with documentation too, woohoo!)  It's quite big,
mainly because of reindentation.  I'd be very grateful if one or two
people could give it a quick thrashing to see whether I've
missed/broken anything (it seems fine for me but ...)  I'll commit it
if it works for someone else or if I get bored of waiting for people
to try :-)

Index: Completion/Base/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/.distfiles,v
retrieving revision 1.4
diff -u -r1.4 .distfiles
--- Completion/Base/.distfiles	2000/05/30 09:30:08	1.4
+++ Completion/Base/.distfiles	2000/08/01 16:11:29
@@ -1,7 +1,7 @@
 DISTFILES_SRC='
     .distfiles 
-    _arg_compile _arguments _brace_parameter _combination
+    _arg_compile _arguments _brace_parameter _cache_invalid _combination
     _command_names _condition _default _describe _equal _first _in_vared
-    _jobs _math _parameter _precommand _redirect _regex_arguments _subscript
-    _tilde _value _values
+    _jobs _math _parameter _precommand _redirect _regex_arguments
+    _retrieve_cache _store_cache _subscript _tilde _value _values
 '
Index: Doc/Zsh/compsys.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/compsys.yo,v
retrieving revision 1.88
diff -u -r1.88 compsys.yo
--- Doc/Zsh/compsys.yo	2000/08/01 07:19:16	1.88
+++ Doc/Zsh/compsys.yo	2000/08/01 16:28:28
@@ -3186,6 +3186,22 @@
 be completed. The last description says that all other arguments are
 `var(page numbers)' but does not give possible completions.
 )
+findex(_cache_invalid)
+item(tt(_cache_invalid) var(cache_identifier))(
+This function returns 0 if the completions cache corresponding to the
+given cache identifier needs rebuilding.  It determines this by
+looking up the tt(cache-policy) style for the current context, and
+if it exists, runs the function of the same name, supplying the full
+path to the relevant cache file as the only argument.
+
+Example:
+
+example(_example_caching_policy () {
+    # rebuild if cache is more than a week old
+    oldp=( "$1"(Nmw+1) )
+    (( $#oldp ))
+})
+)
 findex(_call)
 item(tt(_call) var(tag) var(string) ...)(
 This function is used in places where a command is called, making it
@@ -3592,6 +3608,18 @@
   (( ret )) || break
 done)
 )
+findex(_retrieve_cache)
+item(tt(_retrieve_cache) var(cache_identifier))(
+This function retrieves completion information from the file given by
+var(cache_identifier), stored in a directory specified by the
+tt(cache-path) style (defaults to tt(~/.zsh/cache)).  The return value
+is zero if retrieval was successful.  It will only attempt retrieval
+if the tt(use-cache) style is set, so you can call this function
+without worrying about whether the user wanted to use the caching
+layer.
+
+See tt(_store_cache) below for more details.
+)
 findex(_sep_parts)
 item(tt(_sep_parts))(
 This function is passed alternating arrays and separators as arguments.
@@ -3714,6 +3742,37 @@
 separate set. With the tt(-m) option, the arguments are treated in the 
 same way as the the values for the tt(tag-order) style (except for the 
 `tt(!...)', `tt(-)' and `tt(foo())' forms).
+)
+findex(_store_cache)
+item(tt(_store_cache) var(cache_identifier) var(vars) ...)(
+This function, when combined with tt(_retrieve_cache) and
+tt(_cache_invalid), makes it easy to implement a caching layer for
+your completion functions.  If a completion function needs to perform
+a costly operation in order to generate data which is used to
+calculate completions, you can store that data in variables, and use
+this function to dump the values of those variables to a file.  Then,
+if they are needed in subsequent shell invocations, they can be
+retrieved quickly from that file via tt(_retrieve_cache), avoiding the
+needly for repeating the costly operation.
+
+The var(cache_identifier) specifies the file which the data should be
+dumped to, and is stored in a directory specified by the
+tt(cache-path) style (defaults to tt(~/.zsh/cache)).  The remaining
+var(vars) arguments are the variables to dump to the file.  Currently
+only arrays are supported.
+
+The return value is zero if storage was successful.  The function will
+only attempt storage if the tt(use-cache) style is set, so you can
+call this function without worrying about whether the user wanted to
+use the caching layer.
+
+If your completion function avoids calling _retrieve_cache when it
+already has the completion data in the environment, it should probably
+at least call tt(_cache_invalid) to check whether this data and the
+data cached on disk is still valid.
+
+See the _perl_modules completion function for a simple example of
+usage of this caching layer.
 )
 findex(_tags)
 item(tt(_tags) [ tt(-C) var(name) [ var(tags) ... ] ])(
Index: Completion/Base/_cache_invalid
===================================================================
RCS file: _cache_invalid
diff -N _cache_invalid
--- /dev/null	Tue May  5 13:32:27 1998
+++ _cache_invalid	Tue Aug  1 09:11:29 2000
@@ -0,0 +1,27 @@
+#autoload
+#
+# Function to decide whether a completions cache needs rebuilding
+
+_cache_invalid () {
+  local _cache_ident _cache_dir _cache_path _cache_policy
+  _cache_ident="$1"
+
+  # If the cache is disabled, we never want to rebuild it, so pretend
+  # it's valid.
+  zstyle -t ":completion:${curcontext}:" use-cache || return 1
+
+  zstyle -s ":completion:${curcontext}:" cache-path _cache_dir
+  : ${_cache_dir:=~/.zsh/cache}
+  _cache_path="$_cache_dir/$_cache_ident"
+
+  # See whether the caching policy says that the cache needs rebuilding
+  # (the policy will return 0 if it does).
+  zstyle -s ":completion:${curcontext}:" cache-policy _cache_policy
+  if [[ -n "$_cache_policy" ]] && "$_cache_policy" "$_cache_path"; then
+    return 0
+  fi
+
+  return 1
+}
+
+_cache_invalid "$@"
Index: Completion/Base/_retrieve_cache
===================================================================
RCS file: _retrieve_cache
diff -N _retrieve_cache
--- /dev/null	Tue May  5 13:32:27 1998
+++ _retrieve_cache	Tue Aug  1 09:11:29 2000
@@ -0,0 +1,38 @@
+#autoload
+#
+# Retrieval component of completions caching layer
+
+_retrieve_cache () {
+  local _cache_ident _cache_dir _cache_path _cache_policy
+  _cache_ident="$1"
+  
+  if zstyle -t ":completion:${curcontext}:" use-cache; then
+    # Decide which directory to retrieve cache from, and ensure it exists
+    zstyle -s ":completion:${curcontext}:" cache-path _cache_dir
+    : ${_cache_dir:=~/.zsh/cache}
+    if [[ ! -d "$_cache_dir" ]]; then
+      if [[ -e "$_cache_dir" ]]; then
+        _message "cache-dir ($_cache_dir) isn't a directory\!"
+        return 1
+      else
+        return 1
+      fi
+    fi
+  
+    _cache_path="$_cache_dir/$_cache_ident"
+  
+    if [[ -e "$_cache_path" ]]; then
+      if _cache_invalid "$_cache_ident"; then
+        return 1
+      fi
+
+      . "$_cache_path"
+      return 0
+    else
+      return 1
+    fi
+  else
+    return 1
+  fi
+}
+
Index: Completion/Linux/_rpm
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Linux/_rpm,v
retrieving revision 1.15
diff -u -r1.15 _rpm
--- Completion/Linux/_rpm	2000/07/12 09:01:41	1.15
+++ Completion/Linux/_rpm	2000/08/01 16:11:29
@@ -41,213 +41,238 @@
 
 # Used by `_arguments', made local here.
 
-local curcontext="$curcontext" state lstate line nm="$compstate[nmatches]"
-typeset -A opt_args
-
-state=''
-
-local ret=1
-local -a tmp expl commonopts packageopts
-commonopts=(
-  '*-v[verbose mode]'
-  '--rcfile:resource file:_files'
-  '--ftpproxy:FTP proxy server:_hosts'
-  '--ftpport:FTP port number:'
-  '--httpproxy:HTTP proxy server:_hosts'
-  '--httpport:HTTP port number:'
-)
-packageopts=(
-  '-a[query all packages]'
-  '-p+[query uninstalled package file]:*:RPM package file:->package_file'
-  '-f[specify file to query owner of]:file:_files'
-  '--triggeredby:RPM package:->package'
-  '--whatprovides:RPM capability:->capability'
-  '--whatrequires:RPM capability:->capability'
-)
-pathopts=(
-  '--root:RPM root directory:_files -/'
-  '--dbpath:RPM database path:_files -/'
-)
-
-# Do simple completions or get the first state.
-
-_arguments -C -s \
-  '--help[print help message]' \
-  '--version[print version number]' \
-  "${commonopts[@]}" \
-  '-q+[query mode]:*:query:->query' \
-  --{querytags,initdb,showrc} \
-  '--pipe:pipe command:_command_names -e' \
-  -{V,y}'[verify mode]:*:verify:->verify' \
-  '--verify[verify mode]:*:verify:->verify' \
-  '--setperms[set file permissions]:*:package:->setattrs' \
-  '--setugids[set file owner/group]:*:package:->setattrs' \
-  '(--install)-i+[install mode]:*:install:->install' \
-  '(-i)--install:*:install:->install' \
-  '(--upgrade)-U+[upgrade mode]:*:upgrade:->upgrade' \
-  '(-U)--upgrade:*:upgrade:->upgrade' \
-  '(--freshen)-F+[freshen mode]:*:upgrade:->upgrade' \
-  '(-F)--freshen:*:upgrade:->upgrade' \
-  '(--erase)-e+[uninstall mode]:*:uninstall:->uninstall' \
-  '(-e)--erase:*:uninstall:->uninstall' \
-  '-b+[build mode (spec file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
-  '(-b)-t+[build mode (tar file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
-  --{resign,addsign}':*:RPM package:->package_file' \
-  '--rmsource:*:spec file:->spec_file' \
-  --{rebuild,recompile}':*:Src RPM files:->package_src' \
-  '(--checksig)-K+[signature check mode]:*:sigcheck:->sigcheck' \
-  '(-K)--checksig:*:sigcheck:->sigcheck' \
-  '--rebuilddb:*:rebuild:->rebuild' && ret=0
-
-# As long as we have a state name...
-
-while [[ -n "$state" ]]; do
-
-  # First try to call a user-defined function.
-
-  _funcall ret _rpm_$state && return ret
-
-  # Copy the state and reset `state', to simplify the test above.
-
-  lstate="$state"
+_rpm () {
+  local curcontext="$curcontext" state lstate line nm="$compstate[nmatches]"
+  typeset -A opt_args
+  
   state=''
-  tmp=()
-
-  # Dispatch...
-
-  case "$lstate" in
-  query)
-    # --dump requires on of -{l,c,d}
-    # --triggers requires --script
-    _arguments -s \
-      -q "${commonopts[@]}" "${packageopts[@]}" "${pathopts[@]}" \
-      '--queryformat:RPM query format:->tags' \
-      '-i[display package information]' \
-      '--changelog[display change log]' \
-      '-l[display package file list]' \
-      '-s[show file states]' \
-      '-d[documentation files only]' \
-      '-c[configuration files only]' \
-      '--dump[show all information]' \
-      --provides \
-      -{R,-requires}'[list dependencies]' \
-      '--scripts[show (un)install scripts]' \
-      '--triggers[show trigger scripts]' \
-      '*:RPM package:->package_or_file' && ret=0
-    ;;
-  setattrs)
-    _arguments -s --set{perm,ugids} "${packageopts[@]}" && ret = 0
-    ;;
-  verify)
-    _arguments -s \
-      '(-y --verify)-V' '(-V --verify)-y' '(-y -V)--verify' \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      --no{deps,md5,files} \
-      '*:RPM package:->package' && ret=0
-    ;;
-  upgrade)
-    tmp=( '(--upgrade)-U' '(-U)--upgrade' '(--force)--oldpackage' )
-    ;&
-  install)
-    (( $#tmp )) || tmp=( '(--install)-i' '(-i)--install' )
-    _arguments -s "$tmp[@]" \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      '--excludepath:exclude files in following path:_files -/' \
-      '--relocate:relocate:->relocate' \
-      '--prefix:package prefix directory:_files -/' \
-      '(-h)--hash' '(--hash)-h' \
-      '(--replacepkgs --replacefiles --oldpackage)--force' \
-      '(--force)--'{replacefiles,replacepkgs} \
-      --{badreloc,excludedocs,allfiles,ignorearch,ignoreos,includedocs,justdb,nodeps,noorder,noscripts,notriggers,percent,test} \
-      '*:pkg file:->package_file' && ret=0
-    ;;
-  uninstall)
-    _arguments -s \
-      '(-e)--erase' '(--erase)-e' \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      --{allmatches,justdb,nodeps,noorder,noscripts,notriggers} \
-      '*:RPM package:->package' && ret=0
-    ;;
-  build_b)
-    tmp=( '*:spec file:_files -g \*.spec' )
-    ;&
-  build_t)
-    (( $#tmp )) || tmp=( '*:tar file:_files -g \*.\(\#i\)tar\(.\*\|\)' )
-
-    _arguments -s \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      --{short-circuit,clean,rmsource,sign,test} \
-      '--target:specify a build target:->target'\
-      '--buildroot:build root directory:_files -/' \
-      '--buildarch:architecture for which to build:->target' \
-      '--buildos:ositecture for which to build:' \
-      '--timecheck:time check (seconds):' "$tmp[1]" && ret=0
-    ;;
-  sigcheck)
-    _arguments -s \
-      '(-K)--checksig' '(--checksig)-K' \
-      "${commonopts[@]}" \
-      --no{pgp,md5} \
-      '*:RPM package file:->package_file' && ret=0
-    ;;
-  rebuild)
-    _arguments -s \
-      "${commonopts[@]}" "${pathopts[@]}" \
-      '*:RPM source package file:->package_file' && ret=0
-    ;;
-  target)
-    _wanted target expl 'Target platforms' \
-        compadd $(_call target rpm --showrc 2> /dev/null |grep 'compatible archs'|sed 's/.*: //') && ret=0
-    ;;
-  package_or_file)
-    state=package_file
-    ;&
-  package)
-    _wanted packages expl 'RPM package' \
-        compadd -M 'r:|-=* r:|=*' - $(_call packages rpm -qa 2> /dev/null) && ret=0
-    ;;
-  spec_file)
-    _wanted specfiles expl 'spec file' \
-        _files -g \*.spec && ret=0
-    ;;
-  package_file)
-    _wanted files expl 'RPM package file' \
-        _files -g '*.(#i)rpm' && ret=0
-    if [[ -prefix 1 (f|ht)tp:// ]]; then
-      _wanted urls expl 'URL of RPM package file' \
-          _urls -f -g '*.(#i)rpm' "${expl[@]}" && ret=0
-    else
-      _wanted urls expl 'URL of RPM package file' \
-          compadd -S '' "${expl[@]}" ftp:// http:// && ret=0
-    fi
-    ;;
-  package_src)
-    _files -g \*.src\(\#i\).rpm
-   ;&
-  tags)
-    if compset -P '*%*\{'; then
-      _wanted tags expl 'RPM tag' \
-          compadd -M 'm:{a-z}={A-Z}' -S '\}' - \
-                  "${(@)${(@f)$(_call tags rpm --querytags 2> /dev/null)}#RPMTAG_}" && ret=0
-    else
-      _message 'RPM format'
-    fi
-    ;;
-  capability)
-    _message 'RPM capability'
-    ;;
-  relocate)
-    if compset -P '*='; then
-      _description directories expl 'new path'
-    else
-      _description directories expl 'old path'
-    fi
-
-    _files "$expl[@]" -/ && ret=0
-    ;;
-  esac
+  
+  local ret=1
+  local -a tmp expl commonopts packageopts
+  commonopts=(
+    '*-v[verbose mode]'
+    '--rcfile:resource file:_files'
+    '--ftpproxy:FTP proxy server:_hosts'
+    '--ftpport:FTP port number:'
+    '--httpproxy:HTTP proxy server:_hosts'
+    '--httpport:HTTP port number:'
+  )
+  packageopts=(
+    '-a[query all packages]'
+    '-p+[query uninstalled package file]:*:RPM package file:->package_file'
+    '-f[specify file to query owner of]:file:_files'
+    '--triggeredby:RPM package:->package'
+    '--whatprovides:RPM capability:->capability'
+    '--whatrequires:RPM capability:->capability'
+  )
+  pathopts=(
+    '--root:RPM root directory:_files -/'
+    '--dbpath:RPM database path:_files -/'
+  )
+  
+  # Do simple completions or get the first state.
+  
+  _arguments -C -s \
+    '--help[print help message]' \
+    '--version[print version number]' \
+    "${commonopts[@]}" \
+    '-q+[query mode]:*:query:->query' \
+    --{querytags,initdb,showrc} \
+    '--pipe:pipe command:_command_names -e' \
+    -{V,y}'[verify mode]:*:verify:->verify' \
+    '--verify[verify mode]:*:verify:->verify' \
+    '--setperms[set file permissions]:*:package:->setattrs' \
+    '--setugids[set file owner/group]:*:package:->setattrs' \
+    '(--install)-i+[install mode]:*:install:->install' \
+    '(-i)--install:*:install:->install' \
+    '(--upgrade)-U+[upgrade mode]:*:upgrade:->upgrade' \
+    '(-U)--upgrade:*:upgrade:->upgrade' \
+    '(--freshen)-F+[freshen mode]:*:upgrade:->upgrade' \
+    '(-F)--freshen:*:upgrade:->upgrade' \
+    '(--erase)-e+[uninstall mode]:*:uninstall:->uninstall' \
+    '(-e)--erase:*:uninstall:->uninstall' \
+    '-b+[build mode (spec file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_b' \
+    '(-b)-t+[build mode (tar file)]:build stage:((p\:execute\ \%prep\ stage l\:do\ a\ list\ check c\:execute\ build\ stage i\:execute\ install\ stage b\:build\ a\ binary\ package a\:build\ binary\ and\ source\ packages)):*:build:->build_t' \
+    --{resign,addsign}':*:RPM package:->package_file' \
+    '--rmsource:*:spec file:->spec_file' \
+    --{rebuild,recompile}':*:Src RPM files:->package_src' \
+    '(--checksig)-K+[signature check mode]:*:sigcheck:->sigcheck' \
+    '(-K)--checksig:*:sigcheck:->sigcheck' \
+    '--rebuilddb:*:rebuild:->rebuild' && ret=0
+  
+  # As long as we have a state name...
+  
+  while [[ -n "$state" ]]; do
+  
+    # First try to call a user-defined function.
+  
+    _funcall ret _rpm_$state && return ret
+  
+    # Copy the state and reset `state', to simplify the test above.
+  
+    lstate="$state"
+    state=''
+    tmp=()
+  
+    # Dispatch...
+  
+    case "$lstate" in
+    query)
+      # --dump requires on of -{l,c,d}
+      # --triggers requires --script
+      _arguments -s \
+        -q "${commonopts[@]}" "${packageopts[@]}" "${pathopts[@]}" \
+        '--queryformat:RPM query format:->tags' \
+        '-i[display package information]' \
+        '--changelog[display change log]' \
+        '-l[display package file list]' \
+        '-s[show file states]' \
+        '-d[documentation files only]' \
+        '-c[configuration files only]' \
+        '--dump[show all information]' \
+        --provides \
+        -{R,-requires}'[list dependencies]' \
+        '--scripts[show (un)install scripts]' \
+        '--triggers[show trigger scripts]' \
+        '*:RPM package:->package_or_file' && ret=0
+      ;;
+    setattrs)
+      _arguments -s --set{perm,ugids} "${packageopts[@]}" && ret = 0
+      ;;
+    verify)
+      _arguments -s \
+        '(-y --verify)-V' '(-V --verify)-y' '(-y -V)--verify' \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        --no{deps,md5,files} \
+        '*:RPM package:->package' && ret=0
+      ;;
+    upgrade)
+      tmp=( '(--upgrade)-U' '(-U)--upgrade' '(--force)--oldpackage' )
+      ;&
+    install)
+      (( $#tmp )) || tmp=( '(--install)-i' '(-i)--install' )
+      _arguments -s "$tmp[@]" \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        '--excludepath:exclude files in following path:_files -/' \
+        '--relocate:relocate:->relocate' \
+        '--prefix:package prefix directory:_files -/' \
+        '(-h)--hash' '(--hash)-h' \
+        '(--replacepkgs --replacefiles --oldpackage)--force' \
+        '(--force)--'{replacefiles,replacepkgs} \
+        --{badreloc,excludedocs,allfiles,ignorearch,ignoreos,includedocs,justdb,nodeps,noorder,noscripts,notriggers,percent,test} \
+        '*:pkg file:->package_file' && ret=0
+      ;;
+    uninstall)
+      _arguments -s \
+        '(-e)--erase' '(--erase)-e' \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        --{allmatches,justdb,nodeps,noorder,noscripts,notriggers} \
+        '*:RPM package:->package' && ret=0
+      ;;
+    build_b)
+      tmp=( '*:spec file:_files -g \*.spec' )
+      ;&
+    build_t)
+      (( $#tmp )) || tmp=( '*:tar file:_files -g \*.\(\#i\)tar\(.\*\|\)' )
+  
+      _arguments -s \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        --{short-circuit,clean,rmsource,sign,test} \
+        '--target:specify a build target:->target'\
+        '--buildroot:build root directory:_files -/' \
+        '--buildarch:architecture for which to build:->target' \
+        '--buildos:ositecture for which to build:' \
+        '--timecheck:time check (seconds):' "$tmp[1]" && ret=0
+      ;;
+    sigcheck)
+      _arguments -s \
+        '(-K)--checksig' '(--checksig)-K' \
+        "${commonopts[@]}" \
+        --no{pgp,md5} \
+        '*:RPM package file:->package_file' && ret=0
+      ;;
+    rebuild)
+      _arguments -s \
+        "${commonopts[@]}" "${pathopts[@]}" \
+        '*:RPM source package file:->package_file' && ret=0
+      ;;
+    target)
+      _wanted target expl 'Target platforms' \
+          compadd $(_call target rpm --showrc 2> /dev/null |grep 'compatible archs'|sed 's/.*: //') && ret=0
+      ;;
+    package_or_file)
+      state=package_file
+      ;&
+    package)
+      if ( [[ ${+_rpms} -eq 0 ]] || _cache_invalid RPMs ) &&
+         ! _retrieve_cache RPMs;
+      then
+        _rpms=( $(_call packages rpm -qa 2>/dev/null) )
+        _store_cache RPMs _rpms
+      fi
+      _wanted packages expl 'RPM package' \
+          compadd -M 'r:|-=* r:|=*' - "$_rpms[@]" && ret=0
+      ;;
+    spec_file)
+      _wanted specfiles expl 'spec file' \
+          _files -g \*.spec && ret=0
+      ;;
+    package_file)
+      _wanted files expl 'RPM package file' \
+          _files -g '*.(#i)rpm' && ret=0
+      if [[ -prefix 1 (f|ht)tp:// ]]; then
+        _wanted urls expl 'URL of RPM package file' \
+            _urls -f -g '*.(#i)rpm' "${expl[@]}" && ret=0
+      else
+        _wanted urls expl 'URL of RPM package file' \
+            compadd -S '' "${expl[@]}" ftp:// http:// && ret=0
+      fi
+      ;;
+    package_src)
+      _files -g \*.src\(\#i\).rpm
+     ;&
+    tags)
+      if compset -P '*%*\{'; then
+        _wanted tags expl 'RPM tag' \
+            compadd -M 'm:{a-z}={A-Z}' -S '\}' - \
+                    "${(@)${(@f)$(_call tags rpm --querytags 2> /dev/null)}#RPMTAG_}" && ret=0
+      else
+        _message 'RPM format'
+      fi
+      ;;
+    capability)
+      _message 'RPM capability'
+      ;;
+    relocate)
+      if compset -P '*='; then
+        _description directories expl 'new path'
+      else
+        _description directories expl 'old path'
+      fi
+  
+      _files "$expl[@]" -/ && ret=0
+      ;;
+    esac
+  
+    [[ ret -eq 0 || $nm -ne $compstate[nmatches] ]] && return 0
+  done
+  
+  return ret
+}
+
+# set a sensible default caching policy
+local update_policy
+zstyle -s ":completion:*:*:rpm:*" cache-policy update_policy
+if [[ -z "$update_policy" ]]; then
+  zstyle ":completion:*:*:rpm:*" cache-policy _rpms_caching_policy
+fi
+
+_rpms_caching_policy () {
+  # rebuild if cache is more than a week old
+  oldp=( "$1"(Nmw+1) )
+  (( $#oldp )) && return 0
 
-  [[ ret -eq 0 || $nm -ne $compstate[nmatches] ]] && return 0
-done
+  [[ /var/lib/rpm/packages.rpm -nt "$1" ]]
+}
 
-return ret
+_rpm "$@"
cvs server: Diffing Completion/User
Index: Completion/User/_perl_modules
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/User/_perl_modules,v
retrieving revision 1.6
diff -u -r1.6 _perl_modules
--- Completion/User/_perl_modules	2000/05/31 09:38:26	1.6
+++ Completion/User/_perl_modules	2000/08/01 16:11:29
@@ -17,49 +17,85 @@
 #   algorithm (the zsh code does almost the same, but only misses
 #   modules which don't begin with an uppercase letter).
 
-local opts
-zparseopts -D -a opts S: q
-
-if [[ ${+_perl_modules} -eq 0 ]]; then
-  if zstyle -t ":completion:${curcontext}:modules" try-to-use-pminst \
-     && (( ${+commands[pminst]} )); then
-    _perl_modules=( $(pminst) )
-  else
-    local inc libdir new_pms
-    if (( ${+commands[perl]} )); then
-      inc=( $( perl -e 'print "@INC"' ) )
+_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
+  
+  if ( [[ ${+_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
+      _perl_modules=( $(pminst) )
     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 ..."
-
-      setopt localoptions extendedglob
-      inc=( /usr/lib/perl5{,/{site_perl/,}<5->.([0-9]##)}(N) 
-            ${(s.:.)PERL5LIB} )
-    fi
-
-    typeset -agU _perl_modules  # _perl_modules is global, no duplicates
-    _perl_modules=( )
-
-    for libdir in $inc; do
-      # Ignore cwd - could be too expensive e.g. if we're near /
-      if [[ $libdir == '.' ]]; then break; fi
-
-      # Find all modules
-      if [[ -d $libdir && -x $libdir ]]; then
-      cd $libdir
-      new_pms=( {[A-Z]*/***/,}*.pm~*blib*(N) )
-      cd $OLDPWD
+      local inc libdir new_pms
+      if (( ${+commands[perl]} )); 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 ..."
+  
+        setopt localoptions extendedglob
+        inc=( /usr/lib/perl5{,/{site_perl/,}<5->.([0-9]##)}(N) 
+              ${(s.:.)PERL5LIB} )
       fi
-
-      # Convert to Perl nomenclature
-      new_pms=( ${new_pms:r:fs#/#::#} )
-
-      _perl_modules=( $new_pms $_perl_modules )
+  
+      typeset -agU _perl_modules  # _perl_modules is global, no duplicates
+      _perl_modules=( )
+  
+      for libdir in $inc; do
+        # Ignore cwd - could be too expensive e.g. if we're near /
+        if [[ $libdir == '.' ]]; then break; fi
+  
+        # Find all modules
+        if [[ -d $libdir && -x $libdir ]]; then
+        cd $libdir
+        new_pms=( {[A-Z]*/***/,}*.pm~*blib*(N) )
+        cd $OLDPWD
+        fi
+  
+        # Convert to Perl nomenclature
+        new_pms=( ${new_pms:r:fs#/#::#} )
+  
+        _perl_modules=( $new_pms $_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"(Nmw+1) )
+  (( $#oldp )) && return 0
+
+  _perllocals=( /usr/lib/perl5/**/perllocal.pod(N) )
+
+  if (( $#_perllocals )); then
+    for pod in $_perllocals; do
+      [[ "$pod" -nt "$1" ]] && return 0
     done
   fi
-fi
 
-local expl
+  return 1
+}
 
-_wanted modules expl 'Perl modules' compadd "$opts[@]" -a _perl_modules
+_perl_modules "$@"
Index: Completion/Base/_store_cache
===================================================================
RCS file: _store_cache
diff -N _store_cache
--- /dev/null	Tue May  5 13:32:27 1998
+++ _store_cache	Tue Aug  1 09:13:53 2000
@@ -0,0 +1,37 @@
+#autoload
+#
+# Storage component of completions caching layer
+
+local _cache_ident
+_cache_ident="$1"
+
+if zstyle -t ":completion:${curcontext}:" use-cache; then
+  # Decide which directory to cache to, and ensure it exists
+  zstyle -s ":completion:${curcontext}:" cache-path _cache_dir
+  : ${_cache_dir:=~/.zsh/cache}
+  if [[ ! -d "$_cache_dir" ]]; then
+    if [[ -e "$_cache_dir" ]]; then
+      _message "cache-dir style points to a non-directory\!"
+    else
+      mkdir -p "$_cache_dir"
+      if [[ ! -d "$_cache_dir" ]]; then
+        _message "Couldn't create cache-dir $_cache_dir"
+        return 1
+      fi
+    fi
+  fi
+
+  # grr, doesn't work, so we have to roll our own
+#  typeset "$@[2,-1]" > "$_cache_dir/$_cache_ident"
+
+  # only deals with arrays so far
+  for var in "$@[2,-1]"; do
+    print -n "$var=("
+    print -nr - "${(o@P)${var}}"
+    print ")\n"
+  done >! "$_cache_dir/$_cache_ident"
+else
+  return 1
+fi
+
+return 0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
@ 2000-07-27  8:00 Sven Wischnowsky
  2000-08-01 16:31 ` Adam Spiers
  0 siblings, 1 reply; 16+ messages in thread
From: Sven Wischnowsky @ 2000-07-27  8:00 UTC (permalink / raw)
  To: zsh-workers


Adam Spiers wrote:

> ...
> 
> > Shouldn't there be some way to flush the caches (in _retrieve_cache)?
> > I.e. some style that says when the caches should be rebuilt.
> > 
> > This could be done either by a style with values that describe update
> > policies sensible in enough possible contexts or by using a boolean
> > style and let users use `zstyle -e' to implement their own policy (and 
> > of course users could do that in the first case, too, but there may be 
> > ways to make this more convenient for common cases).
> 
> This sounds very nice, but I'm not sure what sort of policies you have
> in mind, and how they should be implement.  Could you give a few
> examples?

Of course, that's the problem. One that may be useful quite often
would compare the mtime of a file and re-build the cache when it has
changed.

In some cases (when using data that gets updated after regular time
intervals) wall-clock time comparison may be good (with that it would
probably be possible to sensibly cache YP data if we would need that).

However, I don't think there can ever be a complete list. Maybe we
should just give _retrieve_cache an optional argument which is
evaluated or a function name or something that gets called to test if
the cache should be re-build. We probably just need more experience...

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
  2000-07-19 14:48 Sven Wischnowsky
@ 2000-07-26 19:53 ` Adam Spiers
  0 siblings, 0 replies; 16+ messages in thread
From: Adam Spiers @ 2000-07-26 19:53 UTC (permalink / raw)
  To: zsh-workers

Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
> Adam Spiers wrote:
> > OK, I've written the first draft of the completion caching layer I
> > mentioned I was thinking about ages ago.

[snip]

> Shouldn't there be some way to flush the caches (in _retrieve_cache)?
> I.e. some style that says when the caches should be rebuilt.
> 
> This could be done either by a style with values that describe update
> policies sensible in enough possible contexts or by using a boolean
> style and let users use `zstyle -e' to implement their own policy (and 
> of course users could do that in the first case, too, but there may be 
> ways to make this more convenient for common cases).

This sounds very nice, but I'm not sure what sort of policies you have
in mind, and how they should be implement.  Could you give a few
examples?


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: completion caching layer
@ 2000-07-19 14:48 Sven Wischnowsky
  2000-07-26 19:53 ` Adam Spiers
  0 siblings, 1 reply; 16+ messages in thread
From: Sven Wischnowsky @ 2000-07-19 14:48 UTC (permalink / raw)
  To: zsh-workers


Adam Spiers wrote:

> OK, I've written the first draft of the completion caching layer I
> mentioned I was thinking about ages ago.
> 
> It uses two styles: use-cache (yes/no/1/0) and cache-path (the
> directory for the cache, defaults to ~/.zsh/cache).  I also included
> patches for _rpm and _perl_modules to show example uses.  I think
> you'll agree the interface is very simple.  Everything else should (!)
> be crystal clear; if not, please ask.
> 
> The patch follows.  I won't commit until someone else has gone through
> it and thinks it looks OK.  I'll also write some documentation at some
> point ...

Shouldn't there be some way to flush the caches (in _retrieve_cache)?
I.e. some style that says when the caches should be rebuilt.

This could be done either by a style with values that describe update
policies sensible in enough possible contexts or by using a boolean
style and let users use `zstyle -e' to implement their own policy (and 
of course users could do that in the first case, too, but there may be 
ways to make this more convenient for common cases).

Bye
 Sven


--
Sven Wischnowsky                         wischnow@informatik.hu-berlin.de


^ permalink raw reply	[flat|nested] 16+ messages in thread

* PATCH: completion caching layer
@ 2000-07-17 14:38 Adam Spiers
  0 siblings, 0 replies; 16+ messages in thread
From: Adam Spiers @ 2000-07-17 14:38 UTC (permalink / raw)
  To: zsh workers mailing list

OK, I've written the first draft of the completion caching layer I
mentioned I was thinking about ages ago.

It uses two styles: use-cache (yes/no/1/0) and cache-path (the
directory for the cache, defaults to ~/.zsh/cache).  I also included
patches for _rpm and _perl_modules to show example uses.  I think
you'll agree the interface is very simple.  Everything else should (!)
be crystal clear; if not, please ask.

The patch follows.  I won't commit until someone else has gone through
it and thinks it looks OK.  I'll also write some documentation at some
point ...

Adam

P.S. I know we decided against caching for _rpm, as any use of the rpm
command is likely to change the rpm database anyway.  However, it
really is important that we provide the user the choice on this issue
(as the patch does via styles); for instance running rpm -qa on my
laptop is excrutiatingly slow, and there's little point providing
correct completions when you could type the whole rpm name manually
faster.


Index: Completion/Base/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Base/.distfiles,v
retrieving revision 1.4
diff -u -r1.4 .distfiles
--- Completion/Base/.distfiles	2000/05/30 09:30:08	1.4
+++ Completion/Base/.distfiles	2000/07/17 14:31:30
@@ -2,6 +2,6 @@
     .distfiles 
     _arg_compile _arguments _brace_parameter _combination
     _command_names _condition _default _describe _equal _first _in_vared
-    _jobs _math _parameter _precommand _redirect _regex_arguments _subscript
-    _tilde _value _values
+    _jobs _math _parameter _precommand _redirect _regex_arguments _retrieve_cache
+    _store_cache _subscript _tilde _value _values
 '
Index: Completion/Base/_retrieve_cache
===================================================================
RCS file: _retrieve_cache
diff -N _retrieve_cache
--- /dev/null	Tue May  5 13:32:27 1998
+++ _retrieve_cache	Mon Jul 17 07:31:30 2000
@@ -0,0 +1,29 @@
+#autoload
+#
+# Retrieval component of completions caching layer
+
+local _cache_filename
+_cache_filename="$1"
+
+if zstyle -t ":completion:${curcontext}:" use-cache; then
+  # Decide which directory to retrieve cache from, and ensure it exists
+  zstyle -s ":completion:${curcontext}:" cache-path _cache_dir
+  : ${_cache_dir:=~/.zsh/cache}
+  if [[ ! -d "$_cache_dir" ]]; then
+    if [[ -e "$_cache_dir" ]]; then
+      _message "cache-dir ($_cache_dir) isn't a directory\!"
+      return 1
+    else
+      return 1
+    fi
+  fi
+
+  if [[ -e "$_cache_dir/$_cache_filename" ]]; then
+    . "$_cache_dir/$_cache_filename"
+    return 0
+  else
+    return 1
+  fi
+else
+  return 1
+fi
Index: Completion/Base/_store_cache
===================================================================
RCS file: _store_cache
diff -N _store_cache
--- /dev/null	Tue May  5 13:32:27 1998
+++ _store_cache	Mon Jul 17 07:31:30 2000
@@ -0,0 +1,35 @@
+#autoload
+#
+# Storage component of completions caching layer
+
+local _cache_filename
+_cache_filename="$1"
+
+if zstyle -t ":completion:${curcontext}:" use-cache; then
+  # Decide which directory to cache to, and ensure it exists
+  zstyle -s ":completion:${curcontext}:" cache-path _cache_dir
+  : ${_cache_dir:=~/.zsh/cache}
+  if [[ ! -d "$_cache_dir" ]]; then
+    if [[ -e "$_cache_dir" ]]; then
+      _message "cache-dir style points to a non-directory\!"
+    else
+      mkdir -p "$_cache_dir"
+      if [[ ! -d "$_cache_dir" ]]; then
+        _message "Couldn't create cache-dir $_cache_dir"
+        return 1
+      fi
+    fi
+  fi
+
+  # grr, doesn't work, so we have to roll our own
+#  typeset "$@[2,-1]" > "$_cache_dir/$_cache_filename"
+
+  # only deals with arrays so far
+  for var in "$@[2,-1]"; do
+    print -n "$var=("
+    print -nr - "${(o@P)${var}}"
+    print ")\n"
+  done > "$_cache_dir/$_cache_filename"
+else
+  return 1
+fi
Index: Completion/Linux/_rpm
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Linux/_rpm,v
retrieving revision 1.15
diff -u -r1.15 _rpm
--- Completion/Linux/_rpm	2000/07/12 09:01:41	1.15
+++ Completion/Linux/_rpm	2000/07/17 14:31:30
@@ -203,8 +203,12 @@
     state=package_file
     ;&
   package)
+    if ! _retrieve_cache RPMs; then
+      _rpms=( $(_call packages rpm -qa 2>/dev/null) )
+      _store_cache RPMs _rpms
+    fi
     _wanted packages expl 'RPM package' \
-        compadd -M 'r:|-=* r:|=*' - $(_call packages rpm -qa 2> /dev/null) && ret=0
+        compadd -M 'r:|-=* r:|=*' - "$_rpms[@]" && ret=0
     ;;
   spec_file)
     _wanted specfiles expl 'spec file' \
cvs server: Diffing Completion/User
Index: Completion/User/_perl_modules
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/User/_perl_modules,v
retrieving revision 1.6
diff -u -r1.6 _perl_modules
--- Completion/User/_perl_modules	2000/05/31 09:38:26	1.6
+++ Completion/User/_perl_modules	2000/07/17 14:31:30
@@ -21,42 +21,46 @@
 zparseopts -D -a opts S: q
 
 if [[ ${+_perl_modules} -eq 0 ]]; then
-  if zstyle -t ":completion:${curcontext}:modules" try-to-use-pminst \
-     && (( ${+commands[pminst]} )); then
-    _perl_modules=( $(pminst) )
-  else
-    local inc libdir new_pms
-    if (( ${+commands[perl]} )); then
-      inc=( $( perl -e 'print "@INC"' ) )
+  if ! _retrieve_cache perl_modules; then
+    if zstyle -t ":completion:${curcontext}:modules" try-to-use-pminst \
+       && (( ${+commands[pminst]} )); then
+      _perl_modules=( $(pminst) )
     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 ..."
-
-      setopt localoptions extendedglob
-      inc=( /usr/lib/perl5{,/{site_perl/,}<5->.([0-9]##)}(N) 
-            ${(s.:.)PERL5LIB} )
-    fi
-
-    typeset -agU _perl_modules  # _perl_modules is global, no duplicates
-    _perl_modules=( )
-
-    for libdir in $inc; do
-      # Ignore cwd - could be too expensive e.g. if we're near /
-      if [[ $libdir == '.' ]]; then break; fi
-
-      # Find all modules
-      if [[ -d $libdir && -x $libdir ]]; then
-      cd $libdir
-      new_pms=( {[A-Z]*/***/,}*.pm~*blib*(N) )
-      cd $OLDPWD
+      local inc libdir new_pms
+      if (( ${+commands[perl]} )); 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 ..."
+  
+        setopt localoptions extendedglob
+        inc=( /usr/lib/perl5{,/{site_perl/,}<5->.([0-9]##)}(N) 
+              ${(s.:.)PERL5LIB} )
       fi
-
-      # Convert to Perl nomenclature
-      new_pms=( ${new_pms:r:fs#/#::#} )
+  
+      typeset -agU _perl_modules  # _perl_modules is global, no duplicates
+      _perl_modules=( )
+  
+      for libdir in $inc; do
+        # Ignore cwd - could be too expensive e.g. if we're near /
+        if [[ $libdir == '.' ]]; then break; fi
+  
+        # Find all modules
+        if [[ -d $libdir && -x $libdir ]]; then
+        cd $libdir
+        new_pms=( {[A-Z]*/***/,}*.pm~*blib*(N) )
+        cd $OLDPWD
+        fi
+  
+        # Convert to Perl nomenclature
+        new_pms=( ${new_pms:r:fs#/#::#} )
+  
+        _perl_modules=( $new_pms $_perl_modules )
+      done
+    fi
 
-      _perl_modules=( $new_pms $_perl_modules )
-    done
+    _store_cache perl_modules _perl_modules
   fi
 fi
 


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2000-08-04  7:00 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-08-02  9:36 PATCH: completion caching layer Sven Wischnowsky
2000-08-02 13:35 ` Adam Spiers
  -- strict thread matches above, loose matches on Subject: below --
2000-08-04  6:59 Sven Wischnowsky
2000-08-03  7:11 Sven Wischnowsky
2000-08-02 14:13 Sven Wischnowsky
2000-08-02 15:01 ` Adam Spiers
2000-08-03 12:21   ` Adam Spiers
2000-07-27  8:00 Sven Wischnowsky
2000-08-01 16:31 ` Adam Spiers
2000-08-01 17:03   ` Bart Schaefer
2000-08-01 17:09     ` Bart Schaefer
2000-08-01 23:37     ` Adam Spiers
2000-08-02  3:53       ` Bart Schaefer
2000-07-19 14:48 Sven Wischnowsky
2000-07-26 19:53 ` Adam Spiers
2000-07-17 14:38 Adam Spiers

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).