zsh-workers
 help / color / mirror / code / Atom feed
* PATCH Completion for _yum (contains FIXMEs)
@ 2016-10-26 17:37 Paul Seyfert
  2016-10-27  1:30 ` Daniel Shahaf
  0 siblings, 1 reply; 19+ messages in thread
From: Paul Seyfert @ 2016-10-26 17:37 UTC (permalink / raw)
  To: zsh workers

[-- Attachment #1: Type: text/plain, Size: 1640 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi,

as posted [here][1] I'm attaching my patch for the completion of yum.

In two versions: once just the changes I did, and then the outcome of
autoindenting (the original file was anyhow mixed in tabs and spaces so
i didn't bother to reproduce the indentation style)

There are two fixmes for which I'd need suggestions. Some of the yum
history commands take IDs of past transactions. Single IDs or ID ranges,
e.g.

   yum history list 3..16

where IDs range from 1 to
`yum history stats | grep Transactions | sed "s/.*: //"`

At the moment, there are just '1' '2' '3' '1..2' '1..3' '2..3' hard
coded as place holders. I don't know what's a sensible way to provide
a completion for these.

Thanks for consideration,
Paul

[1] : https://github.com/zsh-users/zsh/pull/10
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAEBCAAGBQJYEOnRAAoJEPOmP9OjPXmr7XcQAJw18rPLyIXa1Td4yxmEn4Gs
8ZBARDJlETSaLsmgv24CX6Q7BkTacBWD1UGLkC3r5H4x60z07fhMjrkD5h92DtO8
sueg5rvLlGBGzj7VMaP4jpAFl//qxFhTZPO2+RWEiRFadkkb2H7V+9cJdO8t85nN
wSrOCduB7MyBRdicA97q5p9/FSaDa7RocMKAlpvYV6Y2fYm3NVg3i8dectswItap
ys00668PfaCdaLurn0+mqJDDAj43IyoOaGjo29dZ8lv/h5Gn/EG74+fRsdtCtroW
qLBKT5Xx4t90PuUia8D7CWLSBwdM3oFzeRLd+Y2BMpWtzuNiwBqG3UkfM8CRrZz5
/UhEGEX6YbxMBhRo1a82f2KA85lylahRVo411SXaXWDnTaQLUy+iS+Y+vmgkds/2
wfVQue7PtfK+DTdGuALP/0YgEkUJjniOkhuBGMZ0Ebg3dE0xMBAYr/mHEy3E37NT
SY5WKqQszkNDVV3h4zYU8G+3vHm3JcXCHhirMBhADxsIBztM+M9c3TTPAV0YYf+e
wxZbaZBu8hdQ4ugtZIwT4fuZmLv1VuVd/T4gxXhbW9jSk0e4n7qYcKLtqsMRb5HS
kuYYXIvTBd5VdlM0KBGPNUGfQBwXljkAU6BZYBmWDylhho9U9VNLXcea8UNNR9pc
MtidaBwmZ5Z811gJ/Yuy
=eLut
-----END PGP SIGNATURE-----

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: extend-yum-completion.patch --]
[-- Type: text/x-patch; name="extend-yum-completion.patch", Size: 21847 bytes --]

From d6d425f5469299d7ae7ae6c33769868eb0b0e87e Mon Sep 17 00:00:00 2001
From: Paul Seyfert <paul.seyfert@mib.infn.it>
Date: Sun, 23 Oct 2016 01:42:46 +0200
Subject: [PATCH] extend yum completion

Follwing the man page of yum 3.2.29

 * update-to (just what update expands)
 * upgrade-to (just what update expands)
 * history (the actual tricky one)
 * help (printing the available commands)
 * load-transaction (_files)
 * load-ts (_files)
 * check (just what the man page suggested)
 * reinstall (just what erase does - suggest installed packages)
 * downgrade (just what erase does - suggest installed packages)
 * repolist (just what the man page suggested)
 * distribution-synchronization (just what erase does - suggest installed packages)
 * distro-sync (just what erase does - suggest installed packages)

auto indented entire file
---
 Completion/Redhat/Command/_yum | 508 ++++++++++++++++++++++++++---------------
 1 file changed, 320 insertions(+), 188 deletions(-)

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index f453806..537b0da 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -3,293 +3,425 @@
 # Main dispatcher
 _yum() 
 {
-	local curcontext="$curcontext" state lstate line
-
-	_arguments -s \
-	   '(- *)'{-h,--help}'[show the help message]' \
-	   '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
-	   '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
-	   '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
-	   '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
-	   '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
-	   '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
-	   '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
-	   '--installroot=[set install root]:install root:_files -/' \
-	   '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
-	   '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
-	   {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
-	   '--version[show yum version]' \
-	   '--obsoletes[enable obsoletes processing during updates]' \
-	   '--nogpgcheck[disable gpg signature checking]' \
-	   '--noplugins[disable yum plugins]' \
-	   '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
-	   '*::yum command:_yum_command'
+  local curcontext="$curcontext" state lstate line
+
+  _arguments -s \
+    '(- *)'{-h,--help}'[show the help message]' \
+    '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
+    '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
+    '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
+    '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
+    '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
+    '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
+    '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
+    '--installroot=[set install root]:install root:_files -/' \
+    '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
+    '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
+    {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
+    '--version[show yum version]' \
+    '--obsoletes[enable obsoletes processing during updates]' \
+    '--nogpgcheck[disable gpg signature checking]' \
+    '--noplugins[disable yum plugins]' \
+    '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
+    '*::yum command:_yum_command'
 }
 
 (( $+functions[_yum_command] )) || _yum_command() 
 {
-  	local -a _yum_cmds
-  	_yum_cmds=(
-		"install:install the latest version of a package or group of packages"
-		"erase:remove an installed package (with its dependencies)"
-		"remove:remove an installed package (with its dependencies)"
-		"clean:clean local yum cache"
-		"deplist:gives a list of all dependencies for a package"
-		"check-update:check if any updates are available"
-		"info:get description of available packages"
-		"list:is used to list various information about packages"
-		"groupinfo:get info on package groups"
-		"groupinstall:install a package group or groups"
-		"groupremove:remove a package group or groups"
-		"grouplist:list package groups"
-		"groupupdate:update a package group or groups"
-		"localinstall:install packages with local rpm files"
-		"localupdate:update packages with local rpm files"
-		"makecache:makes a local yum cache"
-		"provides:find out which package provides some feature or file"
-		"whatprovides:find out which package provides some feature or file"
-		"resolvedep:list packages providing the specified dependencies"
-		"search:find any packages matching pattern"
-		"shell:enter the 'yum shell'"
-		"update:update one or more packages"
-		"upgrade:upgrade one or more packages"
-  	)
-
-  	if (( CURRENT == 1 )); then
-		_describe -t commands 'yum command' _yum_cmds || compadd "$@"
-  	else
-    	local curcontext="$curcontext"
-
-	    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
-		# Deal with any aliases
-		case $cmd in
-			remove) cmd="erase";;
-			whatprovides) cmd="provides";;
-			upgrade) cmd="update";;
-		esac
-		
-    	if (( $#cmd )); then
-    		curcontext="${curcontext%:*:*}:yum-${cmd}:"
-	
-	      	local update_policy
-		  	zstyle -s ":completion:${curcontext}:" cache-policy update_policy
-		  	if [[ -z "$update_policy" ]]; then
-				zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
-	  		fi
-
-      		_call_function ret _yum_$cmd || _message 'no more arguments'
-    	else
-      		_message "unknown yum command: $words[1]"
-    	fi
-    	return ret
-  	fi
+  local -a _yum_cmds
+  _yum_cmds=(
+    "install:install the latest version of a package or group of packages"
+    "erase:remove an installed package (with its dependencies)"
+    "remove:remove an installed package (with its dependencies)"
+    "clean:clean local yum cache"
+    "deplist:gives a list of all dependencies for a package"
+    "check-update:check if any updates are available"
+    "info:get description of available packages"
+    "list:is used to list various information about packages"
+    "groupinfo:get info on package groups"
+    "groupinstall:install a package group or groups"
+    "groupremove:remove a package group or groups"
+    "grouplist:list package groups"
+    "groupupdate:update a package group or groups"
+    "localinstall:install packages with local rpm files"
+    "localupdate:update packages with local rpm files"
+    "makecache:makes a local yum cache"
+    "provides:find out which package provides some feature or file"
+    "whatprovides:find out which package provides some feature or file"
+    "resolvedep:list packages providing the specified dependencies"
+    "search:find any packages matching pattern"
+    "shell:enter the 'yum shell'"
+    "update:update one or more packages"
+    "upgrade:upgrade one or more packages"
+    "update-to:update one or more packages taking obsoletes into account"
+    "upgrade-to:upgrade one or more packages taking obsoletes into account"
+    "history:view past transactions"
+    "help:produce help for all or given command"
+    "load-transaction:load a saved transaction from a textfile"
+    "load-ts:load a saved transaction from a textfile"
+    "check:Check for problems in the rpmdb"
+    "reinstall:reinstall a package"
+    "downgrade:downgrade a package"
+    "repolist:Display the configured software repositories"
+    "distribution-synchronization:Synchronize installed packages to the latest available versions"
+    "distro-sync:Synchronize installed packages to the latest available versions"
+  )
+
+  if (( CURRENT == 1 )); then
+    _describe -t commands 'yum command' _yum_cmds || compadd "$@"
+  else
+    local curcontext="$curcontext"
+
+    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
+    # Deal with any aliases
+    case $cmd in
+      remove) cmd="erase";;
+      whatprovides) cmd="provides";;
+      upgrade) cmd="update";;
+      upgrade-to) cmd="update";;
+      update-to) cmd="update";;
+      load-ts) cmd="load-transaction";;
+      distro-sync) cmd="distribution-synchronization";;
+    esac
+
+    if (( $#cmd )); then
+      curcontext="${curcontext%:*:*}:yum-${cmd}:"
+
+      local update_policy
+      zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+      if [[ -z "$update_policy" ]]; then
+        zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
+      fi
+
+      if [ "$cmd" = "help" ]; then
+        if (( CURRENT == 2 )); then
+          local -a _yum_cmd_names
+          _yum_cmd_names=(${_yum_cmds%%:*})
+          _describe -t commands 'commands' _yum_cmd_names
+        else
+          _message 'no more arguments'
+        fi
+      else
+        _call_function ret _yum_$cmd || _message 'no more arguments'
+      fi
+    else
+      _message "unknown yum command: $words[1]"
+    fi
+    return ret
+  fi
+}
+
+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    local -a chkargs
+    #chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    #chkargs=("dependencies" "duplicates" "all") # according to help
+    chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    _describe -t arguments 'check arguments' chkargs
+  fi
+  return 0
 }
 
+# Expand next argument after 'yum repolist'
+_yum_repolist() {
+  if (( CURRENT == 2 )); then
+    local -a suggests
+    suggests=("all" "enabled" "disabled")
+    _describe -t arguments 'repolist arguments' suggests
+  fi
+  return 0
+}
+
+# Expand next argument after 'yum history'
+_yum_history() {
+  if (( CURRENT == 2 )); then
+    local -a historycommands
+    historycommands=('info' 'list' 'packages-list' 'packages-info' 'summary' 'addon-info' 'redo' 'undo' 'roll-back' 'new' 'sync' 'stats')
+    _describe -t commands 'yum history command' historycommands
+  fi
+  if (( CURRENT == 3 )); then
+    local -a ID_commands
+    local -a ID_range_commands
+    local -a package_commands
+    local -a suggests
+    local description
+    description=""
+    suggests=()
+    ID_commands=('summary' 'info' 'list' 'stats' 'addon-info')
+    ID_range_commands=('summary' 'info' 'list' 'stats')
+    package_commands=('summary' 'info' 'list' 'stats' 'packages-list' 'packages-info')
+    # packages-list, packages-info   : needs package name
+    # summary, info, list, stats     : ID, ID range, package name
+    # addon-info                     : ID
+    # redo, undo, roll-back, sync    : unknown
+    if [[ -n "${ID_commands[(r)$words[2]]}" ]]; then
+      description+="IDs"
+      # FIXME: hard coded IDs just a draft
+      suggests+=('last' 'all' 1 2 3)
+    fi
+    if [[ -n "${ID_range_commands[(r)$words[2]]}" ]]; then
+      if [[ -n $description ]] ; then description+=", "; fi
+      description+="ID ranges"
+      # FIXME: hard coded IDs just a draft
+      suggests+=('1..2' '2..3' '1..3')
+    fi
+    if [[ -n "${package_commands[(r)$words[2]]}" ]]; then
+      if [[ -n $description ]] ; then description+=", "; fi
+      description+="packages"
+      _yum_installed_pkgs
+      suggests+=($_installed_pkgs)
+    fi
+    if [[ ! -n $description ]] ; then
+      _message "unknown expansion for: yum history $words[2]"
+    else
+      _describe $description suggests
+    fi
+  fi
+  if (( CURRENT == 4 )); then
+    if [ "$words[2]" = "addon-info" ]; then
+      local -a historyargs
+      historyargs=(saved_tx)
+      _describe 'additional option' historyargs
+    fi
+  fi
+}
+
+
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
-	if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
-		! _retrieve_cache ALL;
-	then
-		_all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache ALL _all_pkgs
-	fi
+  if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
+    ! _retrieve_cache ALL;
+then
+  _all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache ALL _all_pkgs
+fi
 }
 
 # Fills the installed pkg cache
 _yum_installed_pkgs()
 {
-	if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
-		! _retrieve_cache INSTALLED;
-	then
-		_installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache INSTALLED _installed_pkgs
-	fi
+  if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
+    ! _retrieve_cache INSTALLED;
+then
+  _installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache INSTALLED _installed_pkgs
+fi
 }
 
 # Fills the available pkg cache
 _yum_available_pkgs()
 {
-	if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
-		! _retrieve_cache AVAILABLE;
-	then
-		_available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache AVAILABLE _available_pkgs
-	fi
+  if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
+    ! _retrieve_cache AVAILABLE;
+then
+  _available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache AVAILABLE _available_pkgs
+fi
 }
 
 # Fills the upgrade pkg cache
 _yum_upgrade_pkgs()
 {
-	if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
-		! _retrieve_cache UPGRADE;
-	then
-		_upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache UPGRADE _upgrade_pkgs
-	fi
+  if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
+    ! _retrieve_cache UPGRADE;
+then
+  _upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache UPGRADE _upgrade_pkgs
+fi
 }
 
 # Gets the list of defined repos
 yum_repos() {
-    local trepo
-    local -a tarray
-    tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
-    local -i eindex=0
-    local -i dindex=0
-    for line in $tarray; do
-        if [[ "$line" = "enabled=1" ]]; then
-            enabled_yum_repos=($enabled_yum_repos $trepo)
-        elif [[ "$line" = "enabled=0" ]]; then
-            disabled_yum_repos=($disabled_yum_repos $trepo)
-        elif [[ "$line" != "main" ]]; then
-            trepo=$line
-        fi
-    done
+  local trepo
+  local -a tarray
+  tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
+  local -i eindex=0
+  local -i dindex=0
+  for line in $tarray; do
+    if [[ "$line" = "enabled=1" ]]; then
+      enabled_yum_repos=($enabled_yum_repos $trepo)
+    elif [[ "$line" = "enabled=0" ]]; then
+      disabled_yum_repos=($disabled_yum_repos $trepo)
+    elif [[ "$line" != "main" ]]; then
+      trepo=$line
+    fi
+  done
 }
 
 (( $+functions[_yum_disabled_repos_list] )) || _yum_disabled_repos_list()
 {
-	compset -P '*,'
-	compset -S ',*'
-	yum_repos			
-	compadd "$@" -a -- disabled_yum_repos
+  compset -P '*,'
+  compset -S ',*'
+  yum_repos			
+  compadd "$@" -a -- disabled_yum_repos
 }
 
 (( $+functions[_yum_enabled_repos_list] )) || _yum_enabled_repos_list()
 {
-	compset -P '*,'
-	compset -S ',*'
-	yum_repos			
-	compadd "$@" -a -- enabled_yum_repos
+  compset -P '*,'
+  compset -S ',*'
+  yum_repos			
+  compadd "$@" -a -- enabled_yum_repos
+}
+
+# Suggest installed packages
+_yum_act_on_installed_pkgs() {
+  _yum_installed_pkgs
+  compadd "$@" -a -- _installed_pkgs
+}
+
+# Completion function for distribution-synchronization|distro-sync
+(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+{
+  _yum_act_on_installed_pkgs
 }
 
 # Completion function for erase|remove
 (( $+functions[_yum_erase] )) || _yum_erase()
 {
-	_yum_installed_pkgs
-	compadd "$@" -a -- _installed_pkgs
+  _yum_act_on_installed_pkgs
+}
+
+# Completion function for downgrade
+(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+{
+  _yum_act_on_installed_pkgs
+}
+
+# Completion function for reinstall
+(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+{
+  _yum_act_on_installed_pkgs
 }
 
 # Completion function for install
 (( $+functions[_yum_install] )) || _yum_install()
 {
-        if ! [[ $PREFIX == */* ]]; then
-          _yum_available_pkgs
-        fi
+  if ! [[ $PREFIX == */* ]]; then
+    _yum_available_pkgs
+  fi
+
+  local ret=1
+  _tags files packages
+  while _tags; do
+    if _requested files; then
+      compadd "$@" -a -- _available_pkgs
+    fi
+    if _requested packages; then
+      _call_function - _yum_localinstall
+    fi
+    (( ret )) || break
+  done
+  return ret
+}
 
-        local ret=1
-        _tags files packages
-        while _tags; do
-          if _requested files; then
-            compadd "$@" -a -- _available_pkgs
-          fi
-          if _requested packages; then
-            _call_function - _yum_localinstall
-          fi
-          (( ret )) || break
-        done
-        return ret
+# Completion function for load-transaction
+(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+{
+  _files
 }
 
 # Completion function for localinstall
 (( $+functions[_yum_localinstall] )) || _yum_localinstall()
 {
-	_files -/ -g '(#i)*.rpm(-.)'
+  _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for localupdate
 (( $+functions[_yum_localupdate] )) || _yum_localupdate()
 {
-	_files -/ -g '(#i)*.rpm(-.)'
+  _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for update/upgrade
 (( $+functions[_yum_update] )) || _yum_update()
 {
-	_yum_upgrade_pkgs
-	compadd "$@" -a -- _upgrade_pkgs
+  _yum_upgrade_pkgs
+  compadd "$@" -a -- _upgrade_pkgs
 }
 
 # Completion function for deplist
 (( $+functions[_yum_deplist] )) || _yum_deplist()
 {
-	_yum_available_pkgs
-	compadd "$@" -a -- _available_pkgs
+  _yum_available_pkgs
+  compadd "$@" -a -- _available_pkgs
 }
 
 _yum_all()
 {
-	_yum_all_pkgs
-	compadd "$@" -a -- _all_pkgs
+  _yum_all_pkgs
+  compadd "$@" -a -- _all_pkgs
 }
 _yum_list_or_info()
 {
-	local -a listlist
-	listlist=(
-		"all:all packages in repositories"
-		"available:packages available in repositories"
-		"updates:packages with updates available"
-		"installed:installed packages"
-		"extras:packages installed that are not available in any yum repository"
-		"obsoletes:packages installed that are obsoleted"
-		"recent:packages recently added to repositories"
-	)
-	
-  	if (( CURRENT == 2 )); then
-		_describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
-	else
-	    local subcmd
-		subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
-		# offer packages selected by the subcommand
-		case $subcmd in
-			all) _yum_all;;
-			installed) _yum_erase;;
-			available) _yum_install;;
-			updates) _yum_update;;
-		esac
-	fi
+  local -a listlist
+  listlist=(
+    "all:all packages in repositories"
+    "available:packages available in repositories"
+    "updates:packages with updates available"
+    "installed:installed packages"
+    "extras:packages installed that are not available in any yum repository"
+    "obsoletes:packages installed that are obsoleted"
+    "recent:packages recently added to repositories"
+  )
+
+  if (( CURRENT == 2 )); then
+    _describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
+  else
+    local subcmd
+    subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
+    # offer packages selected by the subcommand
+    case $subcmd in
+      all) _yum_all;;
+      installed) _yum_erase;;
+      available) _yum_install;;
+      updates) _yum_update;;
+    esac
+  fi
 }
 
 # Completion function for list
 (( $+functions[_yum_list] )) || _yum_list()
 {
-	_yum_list_or_info
+  _yum_list_or_info
 }
 
 # Completion function for info
 (( $+functions[_yum_info] )) || _yum_info()
 {
-	_yum_list_or_info
+  _yum_list_or_info
 }
 
 # Completion function for provides|whatprovides
 (( $+functions[_yum_provides] )) || _yum_provides()
 {
-	_files	
+  _files	
 }
 
 # Completion function for resolvedep
 (( $+functions[_yum_resolvedep] )) || _yum_resolvedep()
 {
-	_files	
+  _files	
 }
 
 # Completion function for clean
 (( $+functions[_yum_clean] )) || _yum_clean()
 {
-	local -a cleanlist
-	cleanlist=(
-		"all:all cache"
-		"cache:all cache"
-		"dbcache:DB cache"
-		"headers:cache headers"
-		"packages:cache packages"
-		"metadata:cache meta-data"
-	)
-	
-  	if (( CURRENT == 2 )); then
-		_describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist 
-	fi
+  local -a cleanlist
+  cleanlist=(
+    "all:all cache"
+    "cache:all cache"
+    "dbcache:DB cache"
+    "headers:cache headers"
+    "packages:cache packages"
+    "metadata:cache meta-data"
+  )
+
+  if (( CURRENT == 2 )); then
+    _describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist 
+  fi
 }
 
 _yum_caching_policy() 
-- 
2.1.4


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: just_changes.patch --]
[-- Type: text/x-patch; name="just_changes.patch", Size: 10058 bytes --]

From 72f9dd44c4856caf9b1c60e7df732d19ebe0c3b0 Mon Sep 17 00:00:00 2001
From: Paul Seyfert <paul.seyfert@mib.infn.it>
Date: Sun, 23 Oct 2016 01:42:46 +0200
Subject: [PATCH] extend yum completion

---
 Completion/Redhat/Command/_yum | 246 +++++++++++++++++++++++++++++++----------
 1 file changed, 189 insertions(+), 57 deletions(-)

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index f453806..139bcbd 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -28,63 +28,166 @@ _yum()
 
 (( $+functions[_yum_command] )) || _yum_command() 
 {
-  	local -a _yum_cmds
-  	_yum_cmds=(
-		"install:install the latest version of a package or group of packages"
-		"erase:remove an installed package (with its dependencies)"
-		"remove:remove an installed package (with its dependencies)"
-		"clean:clean local yum cache"
-		"deplist:gives a list of all dependencies for a package"
-		"check-update:check if any updates are available"
-		"info:get description of available packages"
-		"list:is used to list various information about packages"
-		"groupinfo:get info on package groups"
-		"groupinstall:install a package group or groups"
-		"groupremove:remove a package group or groups"
-		"grouplist:list package groups"
-		"groupupdate:update a package group or groups"
-		"localinstall:install packages with local rpm files"
-		"localupdate:update packages with local rpm files"
-		"makecache:makes a local yum cache"
-		"provides:find out which package provides some feature or file"
-		"whatprovides:find out which package provides some feature or file"
-		"resolvedep:list packages providing the specified dependencies"
-		"search:find any packages matching pattern"
-		"shell:enter the 'yum shell'"
-		"update:update one or more packages"
-		"upgrade:upgrade one or more packages"
-  	)
-
-  	if (( CURRENT == 1 )); then
-		_describe -t commands 'yum command' _yum_cmds || compadd "$@"
-  	else
-    	local curcontext="$curcontext"
-
-	    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
-		# Deal with any aliases
-		case $cmd in
-			remove) cmd="erase";;
-			whatprovides) cmd="provides";;
-			upgrade) cmd="update";;
-		esac
-		
-    	if (( $#cmd )); then
-    		curcontext="${curcontext%:*:*}:yum-${cmd}:"
-	
-	      	local update_policy
-		  	zstyle -s ":completion:${curcontext}:" cache-policy update_policy
-		  	if [[ -z "$update_policy" ]]; then
-				zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
-	  		fi
-
-      		_call_function ret _yum_$cmd || _message 'no more arguments'
-    	else
-      		_message "unknown yum command: $words[1]"
-    	fi
-    	return ret
-  	fi
+  local -a _yum_cmds
+  _yum_cmds=(
+  "install:install the latest version of a package or group of packages"
+  "erase:remove an installed package (with its dependencies)"
+  "remove:remove an installed package (with its dependencies)"
+  "clean:clean local yum cache"
+  "deplist:gives a list of all dependencies for a package"
+  "check-update:check if any updates are available"
+  "info:get description of available packages"
+  "list:is used to list various information about packages"
+  "groupinfo:get info on package groups"
+  "groupinstall:install a package group or groups"
+  "groupremove:remove a package group or groups"
+  "grouplist:list package groups"
+  "groupupdate:update a package group or groups"
+  "localinstall:install packages with local rpm files"
+  "localupdate:update packages with local rpm files"
+  "makecache:makes a local yum cache"
+  "provides:find out which package provides some feature or file"
+  "whatprovides:find out which package provides some feature or file"
+  "resolvedep:list packages providing the specified dependencies"
+  "search:find any packages matching pattern"
+  "shell:enter the 'yum shell'"
+  "update:update one or more packages"
+  "upgrade:upgrade one or more packages"
+  "update-to:update one or more packages taking obsoletes into account"
+  "upgrade-to:upgrade one or more packages taking obsoletes into account"
+  "history:view past transactions"
+  "help:produce help for all or given command"
+  "load-transaction:load a saved transaction from a textfile"
+  "load-ts:load a saved transaction from a textfile"
+  "check:Check for problems in the rpmdb"
+  "reinstall:reinstall a package"
+  "downgrade:downgrade a package"
+  "repolist:Display the configured software repositories"
+  "distribution-synchronization:Synchronize installed packages to the latest available versions"
+  "distro-sync:Synchronize installed packages to the latest available versions"
+  )
+
+  if (( CURRENT == 1 )); then
+    _describe -t commands 'yum command' _yum_cmds || compadd "$@"
+  else
+    local curcontext="$curcontext"
+
+    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
+    # Deal with any aliases
+    case $cmd in
+      remove) cmd="erase";;
+      whatprovides) cmd="provides";;
+      upgrade) cmd="update";;
+      upgrade-to) cmd="update";;
+      update-to) cmd="update";;
+      load-ts) cmd="load-transaction";;
+      distro-sync) cmd="distribution-synchronization";;
+    esac
+
+    if (( $#cmd )); then
+      curcontext="${curcontext%:*:*}:yum-${cmd}:"
+
+      local update_policy
+      zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+      if [[ -z "$update_policy" ]]; then
+        zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
+      fi
+
+      if [ "$cmd" = "help" ]; then
+        if (( CURRENT == 2 )); then
+          local -a _yum_cmd_names
+          _yum_cmd_names=(${_yum_cmds%%:*})
+          _describe -t commands 'commands' _yum_cmd_names
+        else
+          _message 'no more arguments'
+        fi
+      else
+        _call_function ret _yum_$cmd || _message 'no more arguments'
+      fi
+    else
+      _message "unknown yum command: $words[1]"
+    fi
+    return ret
+  fi
 }
 
+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    local -a chkargs
+    #chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    #chkargs=("dependencies" "duplicates" "all") # according to help
+    chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    _describe -t arguments 'check arguments' chkargs
+  fi
+  return 0
+}
+
+# Expand next argument after 'yum repolist'
+_yum_repolist() {
+  if (( CURRENT == 2 )); then
+    local -a suggests
+    suggests=("all" "enabled" "disabled")
+    _describe -t arguments 'repolist arguments' suggests
+  fi
+  return 0
+}
+
+# Expand next argument after 'yum history'
+_yum_history() {
+  if (( CURRENT == 2 )); then
+    local -a historycommands
+    historycommands=('info' 'list' 'packages-list' 'packages-info' 'summary' 'addon-info' 'redo' 'undo' 'roll-back' 'new' 'sync' 'stats')
+    _describe -t commands 'yum history command' historycommands
+  fi
+  if (( CURRENT == 3 )); then
+    local -a ID_commands
+    local -a ID_range_commands
+    local -a package_commands
+    local -a suggests
+    local description
+    description=""
+    suggests=()
+    ID_commands=('summary' 'info' 'list' 'stats' 'addon-info')
+    ID_range_commands=('summary' 'info' 'list' 'stats')
+    package_commands=('summary' 'info' 'list' 'stats' 'packages-list' 'packages-info')
+    # packages-list, packages-info   : needs package name
+    # summary, info, list, stats     : ID, ID range, package name
+    # addon-info                     : ID
+    # redo, undo, roll-back, sync    : unknown
+    if [[ -n "${ID_commands[(r)$words[2]]}" ]]; then
+      description+="IDs"
+      # FIXME: hard coded IDs just a draft
+      suggests+=('last' 'all' 1 2 3)
+    fi
+    if [[ -n "${ID_range_commands[(r)$words[2]]}" ]]; then
+      if [[ -n $description ]] ; then description+=", "; fi
+      description+="ID ranges"
+      # FIXME: hard coded IDs just a draft
+      suggests+=('1..2' '2..3' '1..3')
+    fi
+    if [[ -n "${package_commands[(r)$words[2]]}" ]]; then
+      if [[ -n $description ]] ; then description+=", "; fi
+      description+="packages"
+      _yum_installed_pkgs
+      suggests+=($_installed_pkgs)
+    fi
+    if [[ ! -n $description ]] ; then
+      _message "unknown expansion for: yum history $words[2]"
+    else
+      _describe $description suggests
+    fi
+  fi
+  if (( CURRENT == 4 )); then
+    if [ "$words[2]" = "addon-info" ]; then
+      local -a historyargs
+      historyargs=(saved_tx)
+      _describe 'additional option' historyargs
+    fi
+  fi
+}
+
+
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
@@ -163,11 +266,34 @@ yum_repos() {
 	compadd "$@" -a -- enabled_yum_repos
 }
 
+# Suggest installed packages
+_yum_act_on_installed_pkgs() {
+	_yum_installed_pkgs
+	compadd "$@" -a -- _installed_pkgs
+}
+
+# Completion function for distribution-synchronization|distro-sync
+(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+{
+  _yum_act_on_installed_pkgs
+}
+
 # Completion function for erase|remove
 (( $+functions[_yum_erase] )) || _yum_erase()
 {
-	_yum_installed_pkgs
-	compadd "$@" -a -- _installed_pkgs
+  _yum_act_on_installed_pkgs
+}
+
+# Completion function for downgrade
+(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+{
+  _yum_act_on_installed_pkgs
+}
+
+# Completion function for reinstall
+(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+{
+  _yum_act_on_installed_pkgs
 }
 
 # Completion function for install
@@ -191,6 +317,12 @@ yum_repos() {
         return ret
 }
 
+# Completion function for load-transaction
+(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+{
+	_files
+}
+
 # Completion function for localinstall
 (( $+functions[_yum_localinstall] )) || _yum_localinstall()
 {
-- 
2.1.4


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

* Re: PATCH Completion for _yum (contains FIXMEs)
  2016-10-26 17:37 PATCH Completion for _yum (contains FIXMEs) Paul Seyfert
@ 2016-10-27  1:30 ` Daniel Shahaf
  2016-10-31 12:09   ` Paul Seyfert
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel Shahaf @ 2016-10-27  1:30 UTC (permalink / raw)
  To: Paul Seyfert; +Cc: zsh workers

I've taken a look at the FIXMEs — answers below — but haven't done
a full review.

Paul Seyfert wrote on Wed, Oct 26, 2016 at 19:37:21 +0200:
> There are two fixmes for which I'd need suggestions. Some of the yum
> history commands take IDs of past transactions. Single IDs or ID ranges,
> e.g.
> 
>    yum history list 3..16
> 
> where IDs range from 1 to
> `yum history stats | grep Transactions | sed "s/.*: //"`
> 
> At the moment, there are just '1' '2' '3' '1..2' '1..3' '2..3' hard
> coded as place holders. I don't know what's a sensible way to provide
> a completion for these.

Something like this:
.
    _id_ranges() { if compset -P '*..'; then _ids; else _ids -S ..; fi } 
.
where _ids() is a function that adds "1" "2" "3" as completions.

There should be examples of this in the revision ranges handling in
_git/_hg/_subversion.

> +    if [[ -n "${ID_commands[(r)$words[2]]}" ]]; then
> +      description+="IDs"
> +      # FIXME: hard coded IDs just a draft
> +      suggests+=('last' 'all' 1 2 3)
> +    fi
> +    if [[ -n "${ID_range_commands[(r)$words[2]]}" ]]; then
> +      if [[ -n $description ]] ; then description+=", "; fi
> +      description+="ID ranges"
> +      # FIXME: hard coded IDs just a draft
> +      suggests+=('1..2' '2..3' '1..3')
> +    fi
> +    if [[ -n "${package_commands[(r)$words[2]]}" ]]; then
> +      if [[ -n $description ]] ; then description+=", "; fi
> +      description+="packages"
> +      _yum_installed_pkgs
> +      suggests+=($_installed_pkgs)
> +    fi
> +    if [[ ! -n $description ]] ; then
> +      _message "unknown expansion for: yum history $words[2]"
> +    else
> +      _describe $description suggests
> +    fi
> +  fi

This looks like it would be better written with _alternative:

    alts=()
    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=( 'id-ranges:id ranges:_id-ranges' )
    [[ -n "${package_commands[(r)$words[2]]}" ]] && alts+=( 'packages:packages:...' )
    ⋮
    (( ${+alts[1]} )) && _alternative "$alts[@]"

To see the difference, set the «group-name» style to «''» (and
optionally the «format» style to something with «%d» in it).  You can
see this in «ssh <TAB>» too (compare with/without those two styles).

Let's see what the other devs have to say about the rest of the patch.

Cheers,

Daniel


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

* Re: PATCH Completion for _yum (contains FIXMEs)
  2016-10-27  1:30 ` Daniel Shahaf
@ 2016-10-31 12:09   ` Paul Seyfert
  2016-11-10 10:18     ` Paul Seyfert
  0 siblings, 1 reply; 19+ messages in thread
From: Paul Seyfert @ 2016-10-31 12:09 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1082 bytes --]

Hi,

thanks for the suggestions.

On 27.10.2016 03:30, Daniel Shahaf wrote:
> Something like this:
> .
>     _id_ranges() { if compset -P '*..'; then _ids; else _ids -S ..; fi } 
> .
> where _ids() is a function that adds "1" "2" "3" as completions.
> 
> There should be examples of this in the revision ranges handling in
> _git/_hg/_subversion.
>

added the id ranges similar to your suggestion and checking _git.

>> [snap]
>
> This looks like it would be better written with _alternative:
> 
>     alts=()
>     [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=( 'id-ranges:id ranges:_id-ranges' )
>     [[ -n "${package_commands[(r)$words[2]]}" ]] && alts+=( 'packages:packages:...' )
>     ⋮
>     (( ${+alts[1]} )) && _alternative "$alts[@]"
> 
> To see the difference, set the «group-name» style to «''» (and
> optionally the «format» style to something with «%d» in it).  You can
> see this in «ssh <TAB>» too (compare with/without those two styles).

also i'm using _alternative by now, but i'll bring it closer to your
suggestion soonish.

Cheers,
Paul

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: just_changes2.patch --]
[-- Type: text/x-patch; name="just_changes2.patch", Size: 6494 bytes --]

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index f453806..f9219f0 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -53,6 +53,18 @@ _yum()
 		"shell:enter the 'yum shell'"
 		"update:update one or more packages"
 		"upgrade:upgrade one or more packages"
+		"update-to:update one or more packages taking obsoletes into account"
+		"upgrade-to:upgrade one or more packages taking obsoletes into account"
+		"history:view past transactions"
+		"help:produce help for all or given command"
+		"load-transaction:load a saved transaction from a textfile"
+		"load-ts:load a saved transaction from a textfile"
+		"check:Check for problems in the rpmdb"
+		"reinstall:reinstall a package"
+		"downgrade:downgrade a package"
+		"repolist:Display the configured software repositories"
+		"distribution-synchronization:Synchronize installed packages to the latest available versions"
+		"distro-sync:Synchronize installed packages to the latest available versions"
   	)
 
   	if (( CURRENT == 1 )); then
@@ -66,6 +78,10 @@ _yum()
 			remove) cmd="erase";;
 			whatprovides) cmd="provides";;
 			upgrade) cmd="update";;
+			upgrade-to) cmd="update";;
+			update-to) cmd="update";;
+			load-ts) cmd="load-transaction";;
+			distro-sync) cmd="distribution-synchronization";;
 		esac
 		
     	if (( $#cmd )); then
@@ -77,7 +93,17 @@ _yum()
 				zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
 	  		fi
 
+		    if [ "$cmd" = "help" ]; then
+		      if (( CURRENT == 2 )); then
+		        local -a _yum_cmd_names
+		        _yum_cmd_names=(${_yum_cmds%%:*})
+		        _describe -t commands 'commands' _yum_cmd_names
+		      else
+		        _message 'no more arguments'
+		      fi
+		    else
       		_call_function ret _yum_$cmd || _message 'no more arguments'
+		    fi
     	else
       		_message "unknown yum command: $words[1]"
     	fi
@@ -85,6 +111,101 @@ _yum()
   	fi
 }
 
+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    local -a chkargs
+    #chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    #chkargs=("dependencies" "duplicates" "all") # according to help
+    chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    _describe -t arguments 'check arguments' chkargs
+  fi
+  return 0
+}
+
+# Expand next argument after 'yum repolist'
+_yum_repolist() {
+  if (( CURRENT == 2 )); then
+    local -a suggests
+    suggests=("all" "enabled" "disabled")
+    _describe -t arguments 'repolist arguments' suggests
+  fi
+  return 0
+}
+
+_ids() {
+  # the last argument will be the first valid transaction ID to be suggested
+  # all other arguments are forwarded to compadd
+  #
+  # maxid is the last transaction ID known to yum
+  # minusone is the number of arguments provided to _ids minus one
+  local maxid
+  local minusone
+
+  maxid=$(yum history stats | grep Transactions | sed "s/.*: //")
+  ((minusone=$#-1))
+  compadd "${(@)@[1,$minusone]}" $(echo {$@[$#]..$maxid})
+}
+
+_ranges() {
+  if compset -P '*..'; then
+    _ids ${(S)IPREFIX#..}
+  else
+    _ids -S '..' 1
+  fi
+}
+
+# Expand next argument after 'yum history'
+_yum_history() {
+  if (( CURRENT == 2 )); then
+    local -a historycommands
+    historycommands=('info' 'list' 'packages-list' 'packages-info' 'summary' 'addon-info' 'redo' 'undo' 'roll-back' 'new' 'sync' 'stats')
+    _describe -t commands 'yum history command' historycommands
+  fi
+  if (( CURRENT == 3 )); then
+    local -a ID_commands
+    local -a ID_range_commands
+    local -a package_commands
+    local -a suggests
+    suggests=()
+    #ID_commands=('summary' 'info' 'list' 'stats' 'addon-info')
+    ID_commands=('addon-info')
+    ID_range_commands=('summary' 'info' 'list' 'stats')
+    package_commands=('summary' 'info' 'list' 'stats' 'packages-list' 'packages-info')
+    #package_commands=('packages-list' 'packages-info')
+    # packages-list, packages-info   : needs package name
+    # summary, info, list, stats     : ID, ID range, package name
+    # addon-info                     : ID
+    # redo, undo, roll-back, sync    : unknown
+    if [[ -n "${ID_commands[(r)$words[2]]}" ]]; then
+      suggests+=(':special IDs:(last)')
+      suggests+=(':IDs:_ids 1')
+    fi
+    if [[ -n "${ID_range_commands[(r)$words[2]]}" ]]; then
+      suggests+=(':transaction ranges:_ranges')
+      suggests+=(':all transactions:(all)')
+    fi
+    if [[ -n "${package_commands[(r)$words[2]]}" ]]; then
+      _yum_installed_pkgs
+      #suggests+=(":packages:($_installed_pkgs)")
+      suggests+=(":packages:_yum_act_on_installed_pkgs")
+    fi
+    if [[ 0 -eq ${#suggests} ]] ; then
+      _message "unknown expansion for: yum history $words[2]"
+    else
+      _alternative $suggests
+    fi
+  fi
+  if (( CURRENT == 4 )); then
+    if [ "$words[2]" = "addon-info" ]; then
+      local -a historyargs
+      historyargs=(saved_tx)
+      _describe 'additional option' historyargs
+    fi
+  fi
+}
+
+
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
@@ -163,11 +284,34 @@ yum_repos() {
 	compadd "$@" -a -- enabled_yum_repos
 }
 
+# Suggest installed packages
+_yum_act_on_installed_pkgs() {
+	_yum_installed_pkgs
+	compadd "$@" -a -- _installed_pkgs
+}
+
+# Completion function for distribution-synchronization|distro-sync
+(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+{
+  _yum_act_on_installed_pkgs
+}
+
 # Completion function for erase|remove
 (( $+functions[_yum_erase] )) || _yum_erase()
 {
-	_yum_installed_pkgs
-	compadd "$@" -a -- _installed_pkgs
+	_yum_act_on_installed_pkgs
+}
+
+# Completion function for downgrade
+(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+{
+  _yum_act_on_installed_pkgs
+}
+
+# Completion function for reinstall
+(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+{
+  _yum_act_on_installed_pkgs
 }
 
 # Completion function for install
@@ -191,6 +335,12 @@ yum_repos() {
         return ret
 }
 
+# Completion function for load-transaction
+(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+{
+	_files
+}
+
 # Completion function for localinstall
 (( $+functions[_yum_localinstall] )) || _yum_localinstall()
 {

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: extend-yum-completion2.patch --]
[-- Type: text/x-patch; name="extend-yum-completion2.patch", Size: 21226 bytes --]

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index f453806..4cc00cf 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -3,293 +3,443 @@
 # Main dispatcher
 _yum() 
 {
-	local curcontext="$curcontext" state lstate line
-
-	_arguments -s \
-	   '(- *)'{-h,--help}'[show the help message]' \
-	   '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
-	   '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
-	   '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
-	   '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
-	   '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
-	   '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
-	   '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
-	   '--installroot=[set install root]:install root:_files -/' \
-	   '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
-	   '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
-	   {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
-	   '--version[show yum version]' \
-	   '--obsoletes[enable obsoletes processing during updates]' \
-	   '--nogpgcheck[disable gpg signature checking]' \
-	   '--noplugins[disable yum plugins]' \
-	   '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
-	   '*::yum command:_yum_command'
+  local curcontext="$curcontext" state lstate line
+
+  _arguments -s \
+    '(- *)'{-h,--help}'[show the help message]' \
+    '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
+    '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
+    '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
+    '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
+    '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
+    '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
+    '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
+    '--installroot=[set install root]:install root:_files -/' \
+    '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
+    '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
+    {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
+      '--version[show yum version]' \
+      '--obsoletes[enable obsoletes processing during updates]' \
+      '--nogpgcheck[disable gpg signature checking]' \
+      '--noplugins[disable yum plugins]' \
+      '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
+      '*::yum command:_yum_command'
 }
 
 (( $+functions[_yum_command] )) || _yum_command() 
 {
-  	local -a _yum_cmds
-  	_yum_cmds=(
-		"install:install the latest version of a package or group of packages"
-		"erase:remove an installed package (with its dependencies)"
-		"remove:remove an installed package (with its dependencies)"
-		"clean:clean local yum cache"
-		"deplist:gives a list of all dependencies for a package"
-		"check-update:check if any updates are available"
-		"info:get description of available packages"
-		"list:is used to list various information about packages"
-		"groupinfo:get info on package groups"
-		"groupinstall:install a package group or groups"
-		"groupremove:remove a package group or groups"
-		"grouplist:list package groups"
-		"groupupdate:update a package group or groups"
-		"localinstall:install packages with local rpm files"
-		"localupdate:update packages with local rpm files"
-		"makecache:makes a local yum cache"
-		"provides:find out which package provides some feature or file"
-		"whatprovides:find out which package provides some feature or file"
-		"resolvedep:list packages providing the specified dependencies"
-		"search:find any packages matching pattern"
-		"shell:enter the 'yum shell'"
-		"update:update one or more packages"
-		"upgrade:upgrade one or more packages"
-  	)
-
-  	if (( CURRENT == 1 )); then
-		_describe -t commands 'yum command' _yum_cmds || compadd "$@"
-  	else
-    	local curcontext="$curcontext"
-
-	    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
-		# Deal with any aliases
-		case $cmd in
-			remove) cmd="erase";;
-			whatprovides) cmd="provides";;
-			upgrade) cmd="update";;
-		esac
-		
-    	if (( $#cmd )); then
-    		curcontext="${curcontext%:*:*}:yum-${cmd}:"
-	
-	      	local update_policy
-		  	zstyle -s ":completion:${curcontext}:" cache-policy update_policy
-		  	if [[ -z "$update_policy" ]]; then
-				zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
-	  		fi
-
-      		_call_function ret _yum_$cmd || _message 'no more arguments'
-    	else
-      		_message "unknown yum command: $words[1]"
-    	fi
-    	return ret
-  	fi
+  local -a _yum_cmds
+  _yum_cmds=(
+  "install:install the latest version of a package or group of packages"
+  "erase:remove an installed package (with its dependencies)"
+  "remove:remove an installed package (with its dependencies)"
+  "clean:clean local yum cache"
+  "deplist:gives a list of all dependencies for a package"
+  "check-update:check if any updates are available"
+  "info:get description of available packages"
+  "list:is used to list various information about packages"
+  "groupinfo:get info on package groups"
+  "groupinstall:install a package group or groups"
+  "groupremove:remove a package group or groups"
+  "grouplist:list package groups"
+  "groupupdate:update a package group or groups"
+  "localinstall:install packages with local rpm files"
+  "localupdate:update packages with local rpm files"
+  "makecache:makes a local yum cache"
+  "provides:find out which package provides some feature or file"
+  "whatprovides:find out which package provides some feature or file"
+  "resolvedep:list packages providing the specified dependencies"
+  "search:find any packages matching pattern"
+  "shell:enter the 'yum shell'"
+  "update:update one or more packages"
+  "upgrade:upgrade one or more packages"
+  "update-to:update one or more packages taking obsoletes into account"
+  "upgrade-to:upgrade one or more packages taking obsoletes into account"
+  "history:view past transactions"
+  "help:produce help for all or given command"
+  "load-transaction:load a saved transaction from a textfile"
+  "load-ts:load a saved transaction from a textfile"
+  "check:Check for problems in the rpmdb"
+  "reinstall:reinstall a package"
+  "downgrade:downgrade a package"
+  "repolist:Display the configured software repositories"
+  "distribution-synchronization:Synchronize installed packages to the latest available versions"
+  "distro-sync:Synchronize installed packages to the latest available versions"
+  )
+
+  if (( CURRENT == 1 )); then
+    _describe -t commands 'yum command' _yum_cmds || compadd "$@"
+  else
+    local curcontext="$curcontext"
+
+    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
+    # Deal with any aliases
+    case $cmd in
+      remove) cmd="erase";;
+      whatprovides) cmd="provides";;
+      upgrade) cmd="update";;
+      upgrade-to) cmd="update";;
+      update-to) cmd="update";;
+      load-ts) cmd="load-transaction";;
+      distro-sync) cmd="distribution-synchronization";;
+    esac
+
+    if (( $#cmd )); then
+      curcontext="${curcontext%:*:*}:yum-${cmd}:"
+
+      local update_policy
+      zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+      if [[ -z "$update_policy" ]]; then
+        zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
+      fi
+
+      if [ "$cmd" = "help" ]; then
+        if (( CURRENT == 2 )); then
+          local -a _yum_cmd_names
+          _yum_cmd_names=(${_yum_cmds%%:*})
+          _describe -t commands 'commands' _yum_cmd_names
+        else
+          _message 'no more arguments'
+        fi
+      else
+        _call_function ret _yum_$cmd || _message 'no more arguments'
+      fi
+    else
+      _message "unknown yum command: $words[1]"
+    fi
+    return ret
+  fi
+}
+
+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    local -a chkargs
+    #chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    #chkargs=("dependencies" "duplicates" "all") # according to help
+    chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    _describe -t arguments 'check arguments' chkargs
+  fi
+  return 0
+}
+
+# Expand next argument after 'yum repolist'
+_yum_repolist() {
+  if (( CURRENT == 2 )); then
+    local -a suggests
+    suggests=("all" "enabled" "disabled")
+    _describe -t arguments 'repolist arguments' suggests
+  fi
+  return 0
+}
+
+_ids() {
+  # the last argument will be the first valid transaction ID to be suggested
+  # all other arguments are forwarded to compadd
+  #
+  # maxid is the last transaction ID known to yum
+  # minusone is the number of arguments provided to _ids minus one
+  local maxid
+  local minusone
+
+  maxid=$(yum history stats | grep Transactions | sed "s/.*: //")
+  ((minusone=$#-1))
+  compadd "${(@)@[1,$minusone]}" $(echo {$@[$#]..$maxid})
 }
 
+_ranges() {
+  if compset -P '*..'; then
+    _ids ${(S)IPREFIX#..}
+  else
+    _ids -S '..' 1
+  fi
+}
+
+# Expand next argument after 'yum history'
+_yum_history() {
+  if (( CURRENT == 2 )); then
+    local -a historycommands
+    historycommands=('info' 'list' 'packages-list' 'packages-info' 'summary' 'addon-info' 'redo' 'undo' 'roll-back' 'new' 'sync' 'stats')
+    _describe -t commands 'yum history command' historycommands
+  fi
+  if (( CURRENT == 3 )); then
+    local -a ID_commands
+    local -a ID_range_commands
+    local -a package_commands
+    local -a suggests
+    suggests=()
+    #ID_commands=('summary' 'info' 'list' 'stats' 'addon-info')
+    ID_commands=('addon-info')
+    ID_range_commands=('summary' 'info' 'list' 'stats')
+    package_commands=('summary' 'info' 'list' 'stats' 'packages-list' 'packages-info')
+    #package_commands=('packages-list' 'packages-info')
+    # packages-list, packages-info   : needs package name
+    # summary, info, list, stats     : ID, ID range, package name
+    # addon-info                     : ID
+    # redo, undo, roll-back, sync    : unknown
+    if [[ -n "${ID_commands[(r)$words[2]]}" ]]; then
+      suggests+=(':special IDs:(last)')
+      suggests+=(':IDs:_ids 1')
+    fi
+    if [[ -n "${ID_range_commands[(r)$words[2]]}" ]]; then
+      suggests+=(':transaction ranges:_ranges')
+      suggests+=(':all transactions:(all)')
+    fi
+    if [[ -n "${package_commands[(r)$words[2]]}" ]]; then
+      _yum_installed_pkgs
+      #suggests+=(":packages:($_installed_pkgs)")
+      suggests+=(":packages:_yum_act_on_installed_pkgs")
+    fi
+    if [[ 0 -eq ${#suggests} ]] ; then
+      _message "unknown expansion for: yum history $words[2]"
+    else
+      _alternative $suggests
+    fi
+  fi
+  if (( CURRENT == 4 )); then
+    if [ "$words[2]" = "addon-info" ]; then
+      local -a historyargs
+      historyargs=(saved_tx)
+      _describe 'additional option' historyargs
+    fi
+  fi
+}
+
+
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
-	if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
-		! _retrieve_cache ALL;
-	then
-		_all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache ALL _all_pkgs
-	fi
+  if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
+    ! _retrieve_cache ALL;
+then
+  _all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache ALL _all_pkgs
+fi
 }
 
 # Fills the installed pkg cache
 _yum_installed_pkgs()
 {
-	if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
-		! _retrieve_cache INSTALLED;
-	then
-		_installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache INSTALLED _installed_pkgs
-	fi
+  if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
+    ! _retrieve_cache INSTALLED;
+then
+  _installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache INSTALLED _installed_pkgs
+fi
 }
 
 # Fills the available pkg cache
 _yum_available_pkgs()
 {
-	if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
-		! _retrieve_cache AVAILABLE;
-	then
-		_available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache AVAILABLE _available_pkgs
-	fi
+  if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
+    ! _retrieve_cache AVAILABLE;
+then
+  _available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache AVAILABLE _available_pkgs
+fi
 }
 
 # Fills the upgrade pkg cache
 _yum_upgrade_pkgs()
 {
-	if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
-		! _retrieve_cache UPGRADE;
-	then
-		_upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache UPGRADE _upgrade_pkgs
-	fi
+  if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
+    ! _retrieve_cache UPGRADE;
+then
+  _upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache UPGRADE _upgrade_pkgs
+fi
 }
 
 # Gets the list of defined repos
 yum_repos() {
-    local trepo
-    local -a tarray
-    tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
-    local -i eindex=0
-    local -i dindex=0
-    for line in $tarray; do
-        if [[ "$line" = "enabled=1" ]]; then
-            enabled_yum_repos=($enabled_yum_repos $trepo)
-        elif [[ "$line" = "enabled=0" ]]; then
-            disabled_yum_repos=($disabled_yum_repos $trepo)
-        elif [[ "$line" != "main" ]]; then
-            trepo=$line
-        fi
-    done
+  local trepo
+  local -a tarray
+  tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
+  local -i eindex=0
+  local -i dindex=0
+  for line in $tarray; do
+    if [[ "$line" = "enabled=1" ]]; then
+      enabled_yum_repos=($enabled_yum_repos $trepo)
+    elif [[ "$line" = "enabled=0" ]]; then
+      disabled_yum_repos=($disabled_yum_repos $trepo)
+    elif [[ "$line" != "main" ]]; then
+      trepo=$line
+    fi
+  done
 }
 
 (( $+functions[_yum_disabled_repos_list] )) || _yum_disabled_repos_list()
 {
-	compset -P '*,'
-	compset -S ',*'
-	yum_repos			
-	compadd "$@" -a -- disabled_yum_repos
+  compset -P '*,'
+  compset -S ',*'
+  yum_repos			
+  compadd "$@" -a -- disabled_yum_repos
 }
 
 (( $+functions[_yum_enabled_repos_list] )) || _yum_enabled_repos_list()
 {
-	compset -P '*,'
-	compset -S ',*'
-	yum_repos			
-	compadd "$@" -a -- enabled_yum_repos
+  compset -P '*,'
+  compset -S ',*'
+  yum_repos			
+  compadd "$@" -a -- enabled_yum_repos
+}
+
+# Suggest installed packages
+_yum_act_on_installed_pkgs() {
+  _yum_installed_pkgs
+  compadd "$@" -a -- _installed_pkgs
+}
+
+# Completion function for distribution-synchronization|distro-sync
+(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+{
+  _yum_act_on_installed_pkgs
 }
 
 # Completion function for erase|remove
 (( $+functions[_yum_erase] )) || _yum_erase()
 {
-	_yum_installed_pkgs
-	compadd "$@" -a -- _installed_pkgs
+  _yum_act_on_installed_pkgs
+}
+
+# Completion function for downgrade
+(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+{
+  _yum_act_on_installed_pkgs
+}
+
+# Completion function for reinstall
+(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+{
+  _yum_act_on_installed_pkgs
 }
 
 # Completion function for install
 (( $+functions[_yum_install] )) || _yum_install()
 {
-        if ! [[ $PREFIX == */* ]]; then
-          _yum_available_pkgs
-        fi
+  if ! [[ $PREFIX == */* ]]; then
+    _yum_available_pkgs
+  fi
 
-        local ret=1
-        _tags files packages
-        while _tags; do
-          if _requested files; then
-            compadd "$@" -a -- _available_pkgs
-          fi
-          if _requested packages; then
-            _call_function - _yum_localinstall
-          fi
-          (( ret )) || break
-        done
-        return ret
+  local ret=1
+  _tags files packages
+  while _tags; do
+    if _requested files; then
+      compadd "$@" -a -- _available_pkgs
+    fi
+    if _requested packages; then
+      _call_function - _yum_localinstall
+    fi
+    (( ret )) || break
+  done
+  return ret
+}
+
+# Completion function for load-transaction
+(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+{
+  _files
 }
 
 # Completion function for localinstall
 (( $+functions[_yum_localinstall] )) || _yum_localinstall()
 {
-	_files -/ -g '(#i)*.rpm(-.)'
+  _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for localupdate
 (( $+functions[_yum_localupdate] )) || _yum_localupdate()
 {
-	_files -/ -g '(#i)*.rpm(-.)'
+  _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for update/upgrade
 (( $+functions[_yum_update] )) || _yum_update()
 {
-	_yum_upgrade_pkgs
-	compadd "$@" -a -- _upgrade_pkgs
+  _yum_upgrade_pkgs
+  compadd "$@" -a -- _upgrade_pkgs
 }
 
 # Completion function for deplist
 (( $+functions[_yum_deplist] )) || _yum_deplist()
 {
-	_yum_available_pkgs
-	compadd "$@" -a -- _available_pkgs
+  _yum_available_pkgs
+  compadd "$@" -a -- _available_pkgs
 }
 
 _yum_all()
 {
-	_yum_all_pkgs
-	compadd "$@" -a -- _all_pkgs
+  _yum_all_pkgs
+  compadd "$@" -a -- _all_pkgs
 }
 _yum_list_or_info()
 {
-	local -a listlist
-	listlist=(
-		"all:all packages in repositories"
-		"available:packages available in repositories"
-		"updates:packages with updates available"
-		"installed:installed packages"
-		"extras:packages installed that are not available in any yum repository"
-		"obsoletes:packages installed that are obsoleted"
-		"recent:packages recently added to repositories"
-	)
-	
-  	if (( CURRENT == 2 )); then
-		_describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
-	else
-	    local subcmd
-		subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
-		# offer packages selected by the subcommand
-		case $subcmd in
-			all) _yum_all;;
-			installed) _yum_erase;;
-			available) _yum_install;;
-			updates) _yum_update;;
-		esac
-	fi
+  local -a listlist
+  listlist=(
+  "all:all packages in repositories"
+  "available:packages available in repositories"
+  "updates:packages with updates available"
+  "installed:installed packages"
+  "extras:packages installed that are not available in any yum repository"
+  "obsoletes:packages installed that are obsoleted"
+  "recent:packages recently added to repositories"
+  )
+
+  if (( CURRENT == 2 )); then
+    _describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
+  else
+    local subcmd
+    subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
+    # offer packages selected by the subcommand
+    case $subcmd in
+      all) _yum_all;;
+      installed) _yum_erase;;
+      available) _yum_install;;
+      updates) _yum_update;;
+    esac
+  fi
 }
 
 # Completion function for list
 (( $+functions[_yum_list] )) || _yum_list()
 {
-	_yum_list_or_info
+  _yum_list_or_info
 }
 
 # Completion function for info
 (( $+functions[_yum_info] )) || _yum_info()
 {
-	_yum_list_or_info
+  _yum_list_or_info
 }
 
 # Completion function for provides|whatprovides
 (( $+functions[_yum_provides] )) || _yum_provides()
 {
-	_files	
+  _files	
 }
 
 # Completion function for resolvedep
 (( $+functions[_yum_resolvedep] )) || _yum_resolvedep()
 {
-	_files	
+  _files	
 }
 
 # Completion function for clean
 (( $+functions[_yum_clean] )) || _yum_clean()
 {
-	local -a cleanlist
-	cleanlist=(
-		"all:all cache"
-		"cache:all cache"
-		"dbcache:DB cache"
-		"headers:cache headers"
-		"packages:cache packages"
-		"metadata:cache meta-data"
-	)
-	
-  	if (( CURRENT == 2 )); then
-		_describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist 
-	fi
+  local -a cleanlist
+  cleanlist=(
+  "all:all cache"
+  "cache:all cache"
+  "dbcache:DB cache"
+  "headers:cache headers"
+  "packages:cache packages"
+  "metadata:cache meta-data"
+  )
+
+  if (( CURRENT == 2 )); then
+    _describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist 
+  fi
 }
 
 _yum_caching_policy() 

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

* Re: PATCH Completion for _yum (contains FIXMEs)
  2016-10-31 12:09   ` Paul Seyfert
@ 2016-11-10 10:18     ` Paul Seyfert
  2016-11-10 15:49       ` Oliver Kiddle
  0 siblings, 1 reply; 19+ messages in thread
From: Paul Seyfert @ 2016-11-10 10:18 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1613 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi again,

>>> [snap]
>>
>> This looks like it would be better written with _alternative:
>>
>>     alts=()
>>     [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=( 'id-ranges:id ranges:_id-ranges' )
>>     [[ -n "${package_commands[(r)$words[2]]}" ]] && alts+=( 'packages:packages:...' )
>>     ⋮
>>     (( ${+alts[1]} )) && _alternative "$alts[@]"
>>
>> To see the difference, set the «group-name» style to «''» (and
>> optionally the «format» style to something with «%d» in it).  You can
>> see this in «ssh <TAB>» too (compare with/without those two styles).
> 

Now done as you suggest. Nice indeed (and I learned what the first
packages in 'packages:packages:...' is good for).

Updated patches attached.

Cheers,
Paul
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAEBCAAGBQJYJEloAAoJEPOmP9OjPXmrzfAQAIiH8kEQtqh+70seIC52xehs
/xi10Pb18HqWJbWb7iBrk6/0+UE3ZX6M/q7PSSFaAfRCPsRcUUiS2bHgEHCzkhrk
i0c8WUiDC1CFSDHdlRxxnRt6jpyoVwlPWKLLaCjR/MwrBspAUWrOucDKtWMFbclM
fFb8M0XO4MgCDhoAE66Gf0PH9ezoa5gBqyClIv9M37bJpvNSCXXs0xCjtskJuTWa
49LEjKk4TzTNDnLGUZPKyIaki2tPaKG5NzYKeQZZvPn2Hrd4nm0YWP2/RKhwozuU
JipcLPMolJabHOrbxA9dATpUPtrUdJB+NU7w9NiAIOy8nON0xpib/Rlk2/CiRgxG
g2DUj7THibx261LZE/zqk5EgrIq/WQCHStq30Jyl0J9APFbFeEhSNl1DYMRYHqG6
56HB1yUrNVgaMFxm9qRTecv0lIyznBuR0yhHBwRTeRIQMK/+fiT3f92kGdwOZMSU
EBXADAub7Mp162WlU3Lb1/owdRYL6PgbSDXkbur5oK8an6kxUs7Jr+kTpiQrlzBR
Uk2sW7ECdGa/jUQFZK8fOHSK0KmRfVnK0Vfvcnp/WO9sG+eDVukK8S3wdsUFTYRU
39ChymUXI26d9R3CCcMv16R9DM26KQu4iAoMO+HLjac+vjLfWsAXDICU5LVwCNku
f7p+JVWq5pia0OiEi0oa
=TbJP
-----END PGP SIGNATURE-----

[-- Attachment #2: extend-yum-completion3.patch --]
[-- Type: text/x-patch, Size: 20536 bytes --]

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index f453806..f354261 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -3,293 +3,434 @@
 # Main dispatcher
 _yum() 
 {
-	local curcontext="$curcontext" state lstate line
-
-	_arguments -s \
-	   '(- *)'{-h,--help}'[show the help message]' \
-	   '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
-	   '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
-	   '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
-	   '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
-	   '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
-	   '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
-	   '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
-	   '--installroot=[set install root]:install root:_files -/' \
-	   '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
-	   '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
-	   {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
-	   '--version[show yum version]' \
-	   '--obsoletes[enable obsoletes processing during updates]' \
-	   '--nogpgcheck[disable gpg signature checking]' \
-	   '--noplugins[disable yum plugins]' \
-	   '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
-	   '*::yum command:_yum_command'
+  local curcontext="$curcontext" state lstate line
+
+  _arguments -s \
+    '(- *)'{-h,--help}'[show the help message]' \
+    '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
+    '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
+    '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
+    '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
+    '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
+    '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
+    '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
+    '--installroot=[set install root]:install root:_files -/' \
+    '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
+    '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
+    {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
+      '--version[show yum version]' \
+      '--obsoletes[enable obsoletes processing during updates]' \
+      '--nogpgcheck[disable gpg signature checking]' \
+      '--noplugins[disable yum plugins]' \
+      '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
+      '*::yum command:_yum_command'
 }
 
 (( $+functions[_yum_command] )) || _yum_command() 
 {
-  	local -a _yum_cmds
-  	_yum_cmds=(
-		"install:install the latest version of a package or group of packages"
-		"erase:remove an installed package (with its dependencies)"
-		"remove:remove an installed package (with its dependencies)"
-		"clean:clean local yum cache"
-		"deplist:gives a list of all dependencies for a package"
-		"check-update:check if any updates are available"
-		"info:get description of available packages"
-		"list:is used to list various information about packages"
-		"groupinfo:get info on package groups"
-		"groupinstall:install a package group or groups"
-		"groupremove:remove a package group or groups"
-		"grouplist:list package groups"
-		"groupupdate:update a package group or groups"
-		"localinstall:install packages with local rpm files"
-		"localupdate:update packages with local rpm files"
-		"makecache:makes a local yum cache"
-		"provides:find out which package provides some feature or file"
-		"whatprovides:find out which package provides some feature or file"
-		"resolvedep:list packages providing the specified dependencies"
-		"search:find any packages matching pattern"
-		"shell:enter the 'yum shell'"
-		"update:update one or more packages"
-		"upgrade:upgrade one or more packages"
-  	)
-
-  	if (( CURRENT == 1 )); then
-		_describe -t commands 'yum command' _yum_cmds || compadd "$@"
-  	else
-    	local curcontext="$curcontext"
-
-	    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
-		# Deal with any aliases
-		case $cmd in
-			remove) cmd="erase";;
-			whatprovides) cmd="provides";;
-			upgrade) cmd="update";;
-		esac
-		
-    	if (( $#cmd )); then
-    		curcontext="${curcontext%:*:*}:yum-${cmd}:"
-	
-	      	local update_policy
-		  	zstyle -s ":completion:${curcontext}:" cache-policy update_policy
-		  	if [[ -z "$update_policy" ]]; then
-				zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
-	  		fi
-
-      		_call_function ret _yum_$cmd || _message 'no more arguments'
-    	else
-      		_message "unknown yum command: $words[1]"
-    	fi
-    	return ret
-  	fi
+  local -a _yum_cmds
+  _yum_cmds=(
+  "install:install the latest version of a package or group of packages"
+  "erase:remove an installed package (with its dependencies)"
+  "remove:remove an installed package (with its dependencies)"
+  "clean:clean local yum cache"
+  "deplist:gives a list of all dependencies for a package"
+  "check-update:check if any updates are available"
+  "info:get description of available packages"
+  "list:is used to list various information about packages"
+  "groupinfo:get info on package groups"
+  "groupinstall:install a package group or groups"
+  "groupremove:remove a package group or groups"
+  "grouplist:list package groups"
+  "groupupdate:update a package group or groups"
+  "localinstall:install packages with local rpm files"
+  "localupdate:update packages with local rpm files"
+  "makecache:makes a local yum cache"
+  "provides:find out which package provides some feature or file"
+  "whatprovides:find out which package provides some feature or file"
+  "resolvedep:list packages providing the specified dependencies"
+  "search:find any packages matching pattern"
+  "shell:enter the 'yum shell'"
+  "update:update one or more packages"
+  "upgrade:upgrade one or more packages"
+  "update-to:update one or more packages taking obsoletes into account"
+  "upgrade-to:upgrade one or more packages taking obsoletes into account"
+  "history:view past transactions"
+  "help:produce help for all or given command"
+  "load-transaction:load a saved transaction from a textfile"
+  "load-ts:load a saved transaction from a textfile"
+  "check:Check for problems in the rpmdb"
+  "reinstall:reinstall a package"
+  "downgrade:downgrade a package"
+  "repolist:Display the configured software repositories"
+  "distribution-synchronization:Synchronize installed packages to the latest available versions"
+  "distro-sync:Synchronize installed packages to the latest available versions"
+  )
+
+  if (( CURRENT == 1 )); then
+    _describe -t commands 'yum command' _yum_cmds || compadd "$@"
+  else
+    local curcontext="$curcontext"
+
+    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
+    # Deal with any aliases
+    case $cmd in
+      remove) cmd="erase";;
+      whatprovides) cmd="provides";;
+      upgrade) cmd="update";;
+      upgrade-to) cmd="update";;
+      update-to) cmd="update";;
+      load-ts) cmd="load-transaction";;
+      distro-sync) cmd="distribution-synchronization";;
+    esac
+
+    if (( $#cmd )); then
+      curcontext="${curcontext%:*:*}:yum-${cmd}:"
+
+      local update_policy
+      zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+      if [[ -z "$update_policy" ]]; then
+        zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
+      fi
+
+      if [ "$cmd" = "help" ]; then
+        if (( CURRENT == 2 )); then
+          local -a _yum_cmd_names
+          _yum_cmd_names=(${_yum_cmds%%:*})
+          _describe -t commands 'commands' _yum_cmd_names
+        else
+          _message 'no more arguments'
+        fi
+      else
+        _call_function ret _yum_$cmd || _message 'no more arguments'
+      fi
+    else
+      _message "unknown yum command: $words[1]"
+    fi
+    return ret
+  fi
+}
+
+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    local -a chkargs
+    #chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    #chkargs=("dependencies" "duplicates" "all") # according to help
+    chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    _describe -t arguments 'check arguments' chkargs
+  fi
+  return 0
+}
+
+# Expand next argument after 'yum repolist'
+_yum_repolist() {
+  if (( CURRENT == 2 )); then
+    local -a suggests
+    suggests=("all" "enabled" "disabled")
+    _describe -t arguments 'repolist arguments' suggests
+  fi
+  return 0
+}
+
+_ids() {
+  # the last argument will be the first valid transaction ID to be suggested
+  # all other arguments are forwarded to compadd
+  #
+  # maxid is the last transaction ID known to yum
+  # minusone is the number of arguments provided to _ids minus one
+  local maxid
+  local minusone
+
+  maxid=$(yum history stats | grep Transactions | sed "s/.*: //")
+  ((minusone=$#-1))
+  compadd "${(@)@[1,$minusone]}" $(echo {$@[$#]..$maxid})
 }
 
+_ranges() {
+  if compset -P '*..'; then
+    _ids ${(S)IPREFIX#..}
+  else
+    _ids -S '..' 1
+  fi
+}
+
+# Expand next argument after 'yum history'
+_yum_history() {
+  if (( CURRENT == 2 )); then
+    local -a historycommands
+    historycommands=('info' 'list' 'packages-list' 'packages-info' 'summary' 'addon-info' 'redo' 'undo' 'roll-back' 'new' 'sync' 'stats')
+    _describe -t commands 'yum history command' historycommands
+  fi
+  if (( CURRENT == 3 )); then
+    local -a ID_commands
+    local -a ID_range_commands
+    local -a package_commands
+    local -a alts
+    alts=()
+    #ID_commands=('summary' 'info' 'list' 'stats' 'addon-info')
+    ID_commands=('addon-info')
+    ID_range_commands=('summary' 'info' 'list' 'stats')
+    package_commands=('summary' 'info' 'list' 'stats' 'packages-list' 'packages-info')
+    #package_commands=('packages-list' 'packages-info')
+    # packages-list, packages-info   : needs package name
+    # summary, info, list, stats     : ID, ID range, package name
+    # addon-info                     : ID
+    # redo, undo, roll-back, sync    : unknown
+
+    [[ -n "${ID_commands[(r)$words[2]]}" ]] && alts+=('special:special IDs:(last)')
+    [[ -n "${ID_commands[(r)$words[2]]}" ]] && alts+=('regular:IDs:_ids 1')
+    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=('regular:transaction ranges:_ranges')
+    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=('special:all transactions:(all)')
+    [[ -n "${package_commands[(r)$words[2]]}" ]] && alts+=("packages:packages:_yum_act_on_installed_pkgs")
+
+    (( ${+alts[1]} )) && _alternative "$alts[@]" || \
+      _message "unknown expansion for: yum history $words[2]"
+  fi
+  if (( CURRENT == 4 )); then
+    if [ "$words[2]" = "addon-info" ]; then
+      local -a historyargs
+      historyargs=(saved_tx)
+      _describe 'additional option' historyargs
+    fi
+  fi
+}
+
+
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
-	if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
-		! _retrieve_cache ALL;
-	then
-		_all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache ALL _all_pkgs
-	fi
+  if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
+    ! _retrieve_cache ALL;
+then
+  _all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache ALL _all_pkgs
+fi
 }
 
 # Fills the installed pkg cache
 _yum_installed_pkgs()
 {
-	if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
-		! _retrieve_cache INSTALLED;
-	then
-		_installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache INSTALLED _installed_pkgs
-	fi
+  if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
+    ! _retrieve_cache INSTALLED;
+then
+  _installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache INSTALLED _installed_pkgs
+fi
 }
 
 # Fills the available pkg cache
 _yum_available_pkgs()
 {
-	if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
-		! _retrieve_cache AVAILABLE;
-	then
-		_available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache AVAILABLE _available_pkgs
-	fi
+  if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
+    ! _retrieve_cache AVAILABLE;
+then
+  _available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache AVAILABLE _available_pkgs
+fi
 }
 
 # Fills the upgrade pkg cache
 _yum_upgrade_pkgs()
 {
-	if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
-		! _retrieve_cache UPGRADE;
-	then
-		_upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache UPGRADE _upgrade_pkgs
-	fi
+  if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
+    ! _retrieve_cache UPGRADE;
+then
+  _upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache UPGRADE _upgrade_pkgs
+fi
 }
 
 # Gets the list of defined repos
 yum_repos() {
-    local trepo
-    local -a tarray
-    tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
-    local -i eindex=0
-    local -i dindex=0
-    for line in $tarray; do
-        if [[ "$line" = "enabled=1" ]]; then
-            enabled_yum_repos=($enabled_yum_repos $trepo)
-        elif [[ "$line" = "enabled=0" ]]; then
-            disabled_yum_repos=($disabled_yum_repos $trepo)
-        elif [[ "$line" != "main" ]]; then
-            trepo=$line
-        fi
-    done
+  local trepo
+  local -a tarray
+  tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
+  local -i eindex=0
+  local -i dindex=0
+  for line in $tarray; do
+    if [[ "$line" = "enabled=1" ]]; then
+      enabled_yum_repos=($enabled_yum_repos $trepo)
+    elif [[ "$line" = "enabled=0" ]]; then
+      disabled_yum_repos=($disabled_yum_repos $trepo)
+    elif [[ "$line" != "main" ]]; then
+      trepo=$line
+    fi
+  done
 }
 
 (( $+functions[_yum_disabled_repos_list] )) || _yum_disabled_repos_list()
 {
-	compset -P '*,'
-	compset -S ',*'
-	yum_repos			
-	compadd "$@" -a -- disabled_yum_repos
+  compset -P '*,'
+  compset -S ',*'
+  yum_repos			
+  compadd "$@" -a -- disabled_yum_repos
 }
 
 (( $+functions[_yum_enabled_repos_list] )) || _yum_enabled_repos_list()
 {
-	compset -P '*,'
-	compset -S ',*'
-	yum_repos			
-	compadd "$@" -a -- enabled_yum_repos
+  compset -P '*,'
+  compset -S ',*'
+  yum_repos			
+  compadd "$@" -a -- enabled_yum_repos
+}
+
+# Suggest installed packages
+_yum_act_on_installed_pkgs() {
+  _yum_installed_pkgs
+  compadd "$@" -a -- _installed_pkgs
+}
+
+# Completion function for distribution-synchronization|distro-sync
+(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+{
+  _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for erase|remove
 (( $+functions[_yum_erase] )) || _yum_erase()
 {
-	_yum_installed_pkgs
-	compadd "$@" -a -- _installed_pkgs
+  _yum_act_on_installed_pkgs "$@"
+}
+
+# Completion function for downgrade
+(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+{
+  _yum_act_on_installed_pkgs "$@"
+}
+
+# Completion function for reinstall
+(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+{
+  _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for install
 (( $+functions[_yum_install] )) || _yum_install()
 {
-        if ! [[ $PREFIX == */* ]]; then
-          _yum_available_pkgs
-        fi
+  if ! [[ $PREFIX == */* ]]; then
+    _yum_available_pkgs
+  fi
 
-        local ret=1
-        _tags files packages
-        while _tags; do
-          if _requested files; then
-            compadd "$@" -a -- _available_pkgs
-          fi
-          if _requested packages; then
-            _call_function - _yum_localinstall
-          fi
-          (( ret )) || break
-        done
-        return ret
+  local ret=1
+  _tags files packages
+  while _tags; do
+    if _requested files; then
+      compadd "$@" -a -- _available_pkgs
+    fi
+    if _requested packages; then
+      _call_function - _yum_localinstall
+    fi
+    (( ret )) || break
+  done
+  return ret
+}
+
+# Completion function for load-transaction
+(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+{
+  _files
 }
 
 # Completion function for localinstall
 (( $+functions[_yum_localinstall] )) || _yum_localinstall()
 {
-	_files -/ -g '(#i)*.rpm(-.)'
+  _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for localupdate
 (( $+functions[_yum_localupdate] )) || _yum_localupdate()
 {
-	_files -/ -g '(#i)*.rpm(-.)'
+  _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for update/upgrade
 (( $+functions[_yum_update] )) || _yum_update()
 {
-	_yum_upgrade_pkgs
-	compadd "$@" -a -- _upgrade_pkgs
+  _yum_upgrade_pkgs
+  compadd "$@" -a -- _upgrade_pkgs
 }
 
 # Completion function for deplist
 (( $+functions[_yum_deplist] )) || _yum_deplist()
 {
-	_yum_available_pkgs
-	compadd "$@" -a -- _available_pkgs
+  _yum_available_pkgs
+  compadd "$@" -a -- _available_pkgs
 }
 
 _yum_all()
 {
-	_yum_all_pkgs
-	compadd "$@" -a -- _all_pkgs
+  _yum_all_pkgs
+  compadd "$@" -a -- _all_pkgs
 }
 _yum_list_or_info()
 {
-	local -a listlist
-	listlist=(
-		"all:all packages in repositories"
-		"available:packages available in repositories"
-		"updates:packages with updates available"
-		"installed:installed packages"
-		"extras:packages installed that are not available in any yum repository"
-		"obsoletes:packages installed that are obsoleted"
-		"recent:packages recently added to repositories"
-	)
-	
-  	if (( CURRENT == 2 )); then
-		_describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
-	else
-	    local subcmd
-		subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
-		# offer packages selected by the subcommand
-		case $subcmd in
-			all) _yum_all;;
-			installed) _yum_erase;;
-			available) _yum_install;;
-			updates) _yum_update;;
-		esac
-	fi
+  local -a listlist
+  listlist=(
+  "all:all packages in repositories"
+  "available:packages available in repositories"
+  "updates:packages with updates available"
+  "installed:installed packages"
+  "extras:packages installed that are not available in any yum repository"
+  "obsoletes:packages installed that are obsoleted"
+  "recent:packages recently added to repositories"
+  )
+
+  if (( CURRENT == 2 )); then
+    _describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
+  else
+    local subcmd
+    subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
+    # offer packages selected by the subcommand
+    case $subcmd in
+      all) _yum_all;;
+      installed) _yum_erase;;
+      available) _yum_install;;
+      updates) _yum_update;;
+    esac
+  fi
 }
 
 # Completion function for list
 (( $+functions[_yum_list] )) || _yum_list()
 {
-	_yum_list_or_info
+  _yum_list_or_info
 }
 
 # Completion function for info
 (( $+functions[_yum_info] )) || _yum_info()
 {
-	_yum_list_or_info
+  _yum_list_or_info
 }
 
 # Completion function for provides|whatprovides
 (( $+functions[_yum_provides] )) || _yum_provides()
 {
-	_files	
+  _files	
 }
 
 # Completion function for resolvedep
 (( $+functions[_yum_resolvedep] )) || _yum_resolvedep()
 {
-	_files	
+  _files	
 }
 
 # Completion function for clean
 (( $+functions[_yum_clean] )) || _yum_clean()
 {
-	local -a cleanlist
-	cleanlist=(
-		"all:all cache"
-		"cache:all cache"
-		"dbcache:DB cache"
-		"headers:cache headers"
-		"packages:cache packages"
-		"metadata:cache meta-data"
-	)
-	
-  	if (( CURRENT == 2 )); then
-		_describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist 
-	fi
+  local -a cleanlist
+  cleanlist=(
+  "all:all cache"
+  "cache:all cache"
+  "dbcache:DB cache"
+  "headers:cache headers"
+  "packages:cache packages"
+  "metadata:cache meta-data"
+  )
+
+  if (( CURRENT == 2 )); then
+    _describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist 
+  fi
 }
 
 _yum_caching_policy() 

[-- Attachment #3: just_changes3.patch --]
[-- Type: text/x-patch, Size: 6236 bytes --]

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index f453806..722f0f5 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -53,6 +53,18 @@ _yum()
 		"shell:enter the 'yum shell'"
 		"update:update one or more packages"
 		"upgrade:upgrade one or more packages"
+		"update-to:update one or more packages taking obsoletes into account"
+		"upgrade-to:upgrade one or more packages taking obsoletes into account"
+		"history:view past transactions"
+		"help:produce help for all or given command"
+		"load-transaction:load a saved transaction from a textfile"
+		"load-ts:load a saved transaction from a textfile"
+		"check:Check for problems in the rpmdb"
+		"reinstall:reinstall a package"
+		"downgrade:downgrade a package"
+		"repolist:Display the configured software repositories"
+		"distribution-synchronization:Synchronize installed packages to the latest available versions"
+		"distro-sync:Synchronize installed packages to the latest available versions"
   	)
 
   	if (( CURRENT == 1 )); then
@@ -66,6 +78,10 @@ _yum()
 			remove) cmd="erase";;
 			whatprovides) cmd="provides";;
 			upgrade) cmd="update";;
+			upgrade-to) cmd="update";;
+			update-to) cmd="update";;
+			load-ts) cmd="load-transaction";;
+			distro-sync) cmd="distribution-synchronization";;
 		esac
 		
     	if (( $#cmd )); then
@@ -77,7 +93,17 @@ _yum()
 				zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
 	  		fi
 
+		    if [ "$cmd" = "help" ]; then
+		      if (( CURRENT == 2 )); then
+		        local -a _yum_cmd_names
+		        _yum_cmd_names=(${_yum_cmds%%:*})
+		        _describe -t commands 'commands' _yum_cmd_names
+		      else
+		        _message 'no more arguments'
+		      fi
+		    else
       		_call_function ret _yum_$cmd || _message 'no more arguments'
+		    fi
     	else
       		_message "unknown yum command: $words[1]"
     	fi
@@ -85,6 +111,92 @@ _yum()
   	fi
 }
 
+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    local -a chkargs
+    #chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    #chkargs=("dependencies" "duplicates" "all") # according to help
+    chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    _describe -t arguments 'check arguments' chkargs
+  fi
+  return 0
+}
+
+# Expand next argument after 'yum repolist'
+_yum_repolist() {
+  if (( CURRENT == 2 )); then
+    local -a suggests
+    suggests=("all" "enabled" "disabled")
+    _describe -t arguments 'repolist arguments' suggests
+  fi
+  return 0
+}
+
+_ids() {
+  # the last argument will be the first valid transaction ID to be suggested
+  # all other arguments are forwarded to compadd
+  #
+  # maxid is the last transaction ID known to yum
+  # minusone is the number of arguments provided to _ids minus one
+  local maxid
+  local minusone
+
+  maxid=$(yum history stats | grep Transactions | sed "s/.*: //")
+  ((minusone=$#-1))
+  compadd "${(@)@[1,$minusone]}" $(echo {$@[$#]..$maxid})
+}
+
+_ranges() {
+  if compset -P '*..'; then
+    _ids ${(S)IPREFIX#..}
+  else
+    _ids -S '..' 1
+  fi
+}
+
+# Expand next argument after 'yum history'
+_yum_history() {
+  if (( CURRENT == 2 )); then
+    local -a historycommands
+    historycommands=('info' 'list' 'packages-list' 'packages-info' 'summary' 'addon-info' 'redo' 'undo' 'roll-back' 'new' 'sync' 'stats')
+    _describe -t commands 'yum history command' historycommands
+  fi
+  if (( CURRENT == 3 )); then
+    local -a ID_commands
+    local -a ID_range_commands
+    local -a package_commands
+    local -a alts
+    alts=()
+    #ID_commands=('summary' 'info' 'list' 'stats' 'addon-info')
+    ID_commands=('addon-info')
+    ID_range_commands=('summary' 'info' 'list' 'stats')
+    package_commands=('summary' 'info' 'list' 'stats' 'packages-list' 'packages-info')
+    #package_commands=('packages-list' 'packages-info')
+    # packages-list, packages-info   : needs package name
+    # summary, info, list, stats     : ID, ID range, package name
+    # addon-info                     : ID
+    # redo, undo, roll-back, sync    : unknown
+
+    [[ -n "${ID_commands[(r)$words[2]]}" ]] && alts+=('special:special IDs:(last)')
+    [[ -n "${ID_commands[(r)$words[2]]}" ]] && alts+=('regular:IDs:_ids 1')
+    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=('regular:transaction ranges:_ranges')
+    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=('special:all transactions:(all)')
+    [[ -n "${package_commands[(r)$words[2]]}" ]] && alts+=("packages:packages:_yum_act_on_installed_pkgs")
+
+    (( ${+alts[1]} )) && _alternative "$alts[@]" || \
+      _message "unknown expansion for: yum history $words[2]"
+  fi
+  if (( CURRENT == 4 )); then
+    if [ "$words[2]" = "addon-info" ]; then
+      local -a historyargs
+      historyargs=(saved_tx)
+      _describe 'additional option' historyargs
+    fi
+  fi
+}
+
+
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
@@ -163,11 +275,34 @@ yum_repos() {
 	compadd "$@" -a -- enabled_yum_repos
 }
 
+# Suggest installed packages
+_yum_act_on_installed_pkgs() {
+	_yum_installed_pkgs
+	compadd "$@" -a -- _installed_pkgs
+}
+
+# Completion function for distribution-synchronization|distro-sync
+(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+{
+  _yum_act_on_installed_pkgs "$@"
+}
+
 # Completion function for erase|remove
 (( $+functions[_yum_erase] )) || _yum_erase()
 {
-	_yum_installed_pkgs
-	compadd "$@" -a -- _installed_pkgs
+  _yum_act_on_installed_pkgs "$@"
+}
+
+# Completion function for downgrade
+(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+{
+  _yum_act_on_installed_pkgs "$@"
+}
+
+# Completion function for reinstall
+(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+{
+  _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for install
@@ -191,6 +326,12 @@ yum_repos() {
         return ret
 }
 
+# Completion function for load-transaction
+(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+{
+	_files
+}
+
 # Completion function for localinstall
 (( $+functions[_yum_localinstall] )) || _yum_localinstall()
 {

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

* Re: PATCH Completion for _yum (contains FIXMEs)
  2016-11-10 10:18     ` Paul Seyfert
@ 2016-11-10 15:49       ` Oliver Kiddle
  2016-11-12  0:19         ` PATCH Completion for _yum Paul Seyfert
  0 siblings, 1 reply; 19+ messages in thread
From: Oliver Kiddle @ 2016-11-10 15:49 UTC (permalink / raw)
  To: Paul Seyfert; +Cc: zsh-workers

Paul Seyfert wrote:
>
> Now done as you suggest. Nice indeed (and I learned what the first
> packages in 'packages:packages:...' is good for).

The normal convention is for the descriptions to be in singular form. So
that would be 'packages:package:...'

Thanks for the update. I've got a few comments to add to what Daniel
already said.

+		"repolist:Display the configured software repositories"
+		"distribution-synchronization:Synchronize installed packages to the latest available versions"
+		"distro-sync:Synchronize installed packages to the latest available versions"

Another convention is lowercase for the descriptions, so "display",
"synchronize", etc.

+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    local -a chkargs
+    #chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    #chkargs=("dependencies" "duplicates" "all") # according to help
+    chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    _describe -t arguments 'check arguments' chkargs

In quite a few cases, you're using _describe to add matches without
per-match descriptions. The whole point of _describe is to make it easy
to add matches that do have per-match descriptions. For this, you can
just use _wanted with compadd which is much more light-weight:
  local expl
  _wanted arguments expl 'check argument' compadd dependencies \
      duplicates provides all

+  return 0

Completion functions should only return 0 if they added matches.
Otherwise, completion goes on and tries approximate completion and other
fallbacks you may have configured. Often you don't need a return
statement because if the last command is _wanted or _describe then its
return status will be passed on. In complex cases, start with local
ret=1, put && ret=0 after all commands that may add matches and finish
the function with return ret.

+_ids() {

It's probably unwise to define yum specific functions with generic names
like _ids and _ranges. A common convention would be _yum_ids with
_yum-check being for completion after "yum check".

+  # the last argument will be the first valid transaction ID to be suggested
+  # all other arguments are forwarded to compadd
+  #
+  # maxid is the last transaction ID known to yum
+  # minusone is the number of arguments provided to _ids minus one
+  local maxid
+  local minusone
+
+  maxid=$(yum history stats | grep Transactions | sed "s/.*: //")
+  ((minusone=$#-1))
+  compadd "${(@)@[1,$minusone]}" $(echo {$@[$#]..$maxid})

I'm getting some stderr output from yum history stats in my terminal
from this. I don't think you need the echo inside a subshell, the
brace-expansion alone should work.

+# Expand next argument after 'yum history'
+_yum_history() {
+  if (( CURRENT == 2 )); then
+    local -a historycommands
+    historycommands=('info' 'list' 'packages-list' 'packages-info' 'summary' 'addon-info' 'redo' 'undo' 'roll-back' 'new' 'sync' 'stats')
+    _describe -t commands 'yum history command' historycommands
+  fi
+  if (( CURRENT == 3 )); then

A minor point, but you can use elif here.

+    (( ${+alts[1]} )) && _alternative "$alts[@]" || \
+      _message "unknown expansion for: yum history $words[2]"

This will print the message in the case where _alternative is run but
there were no matches which I don't think is what you want. A full
if…then…else should be used.

And rather than printing a message, I think it is best to call _default
as the fallback so that the user gets filename completion. In the case
of a new subcommand being added in a new version of yum falling back to
default completion is more graceful.

Oliver


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

* Re: PATCH Completion for _yum
  2016-11-10 15:49       ` Oliver Kiddle
@ 2016-11-12  0:19         ` Paul Seyfert
       [not found]           ` <31607.1478915523@hydra.kiddle.eu>
  0 siblings, 1 reply; 19+ messages in thread
From: Paul Seyfert @ 2016-11-12  0:19 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 1031 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Hi,

Thanks for your input, updated versions attached.
I also noticed I forgot two $@ to forward -J and -X from _alternative
through _range to _ids.

Cheers,
Paul
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAEBCAAGBQJYJmAWAAoJEPOmP9OjPXmr1fcP/1jtz2d0wPI7GFgkE1+ipTOR
1cfT1Rh6uWwpGWk01lmgy62lA/01Yo9lG+C+2xwgRktE/bw0S+ct+wlXcZ90JaGL
SLJiKRAHo3iO0Oad4HOxsqG4BdWzw4aN8ICfTuXe2Ub/hFJFOfjxZba7jVOkN5CS
rk54p3MTsMSIqmlxdVZRl33dQlKwazpisJsqTsyZa0YwSUtQR7t7cYG27eNNRkmA
qGAIBCTw6D3bp7EPfzpJ/FX5K+BSw19u4SCZLdjsdAmaBRsvcIwHbgDwRqJ206eY
jqtrMLcgNuQgxnGLPdK+qsgzK3hDHG0Ab6GT1ijbJlW6QbdG8Njzhb5PlwvRA9va
S6mWt6/tzf5MV1N6ttiRDmWJiFuyR12zASpj+e/mBq28om5LDbdtzBkSQBFEen0z
eqULgq2NDAx1Q+lvpjoYY8i+QrAxRkk4wuHg7sCJNfsrtpkSOmH29U1KO0wVYhMd
rIk33wSx+5Vy3AaRMJumnKV3wwJ8Ea9hTvaiQx13/yMbMUUpHny5coisY2yR47gH
UxSij89NmyJVlrg3j+v/X8xEpr/Cu1GKJFj66ldGDlRhHBOMCOyJ2vMp0UYnY/Uh
heye+hTDHSExuD17VMwwE5e7u526VFQVCCZgi1aKV10SDvJa3dlyLHKJq/6zbXoc
QD5nZTa/cGmu/FbD1LpK
=Z7CB
-----END PGP SIGNATURE-----

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: just_changes4.patch --]
[-- Type: text/x-patch; name="just_changes4.patch", Size: 6660 bytes --]

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index f453806..5919d4a 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -53,6 +53,18 @@ _yum()
 		"shell:enter the 'yum shell'"
 		"update:update one or more packages"
 		"upgrade:upgrade one or more packages"
+		"update-to:update one or more packages taking obsoletes into account"
+		"upgrade-to:upgrade one or more packages taking obsoletes into account"
+		"history:view past transactions"
+		"help:produce help for all or given command"
+		"load-transaction:load a saved transaction from a textfile"
+		"load-ts:load a saved transaction from a textfile"
+		"check:Check for problems in the rpmdb"
+		"reinstall:reinstall a package"
+		"downgrade:downgrade a package"
+		"repolist:display the configured software repositories"
+		"distribution-synchronization:synchronize installed packages to the latest available versions"
+		"distro-sync:synchronize installed packages to the latest available versions"
   	)
 
   	if (( CURRENT == 1 )); then
@@ -66,6 +78,10 @@ _yum()
 			remove) cmd="erase";;
 			whatprovides) cmd="provides";;
 			upgrade) cmd="update";;
+			upgrade-to) cmd="update";;
+			update-to) cmd="update";;
+			load-ts) cmd="load-transaction";;
+			distro-sync) cmd="distribution-synchronization";;
 		esac
 		
     	if (( $#cmd )); then
@@ -77,7 +93,18 @@ _yum()
 				zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
 	  		fi
 
+		    if [ "$cmd" = "help" ]; then
+		      if (( CURRENT == 2 )); then
+		        local -a _yum_cmd_names
+		        _yum_cmd_names=(${_yum_cmds%%:*})
+		        _describe -t commands 'commands' _yum_cmd_names
+		      else
+            # help takes one argument
+		        _message 'no more arguments'
+		      fi
+		    else
       		_call_function ret _yum_$cmd || _message 'no more arguments'
+		    fi
     	else
       		_message "unknown yum command: $words[1]"
     	fi
@@ -85,6 +112,101 @@ _yum()
   	fi
 }
 
+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    ##chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    ##chkargs=("dependencies" "duplicates" "all") # according to help
+    #chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    local expl
+    _wanted arguments expl 'check argument' compadd dependencies \
+         duplicates provides all
+  else
+    return 1
+  fi
+}
+
+# Expand next argument after 'yum repolist'
+_yum_repolist() {
+  if (( CURRENT == 2 )); then
+    local expl
+    _wanted arguments expl 'repolist arguments' compadd all enabled disabled
+  else
+    return 1
+  fi
+}
+
+_yum_ids() {
+  # the last argument will be the first valid transaction ID to be suggested
+  # all other arguments are forwarded to compadd
+  #
+  # maxid is the last transaction ID known to yum
+  # minusone is the number of arguments provided to _yum_ids minus one
+  local maxid
+  local minusone
+
+  maxid=$(yum history stats | grep Transactions | sed "s/.*: //")
+
+  # `$#' is the number of arguments
+  ((minusone=$#-1))
+
+  # `$@' are the arguments
+  # `${(@)@[...]}' selects a subrange from $@
+  # `${(@)@[1,$minusone]}' are all except the last argument
+  # `$@[$#]' is the last argument, e.g. the first suggestable ID
+  compadd "${(@)@[1,$minusone]}" {$@[$#]..$maxid}
+}
+
+_yum_ranges() {
+  if compset -P '*..'; then
+    _yum_ids $@ ${(S)IPREFIX#..}
+  else
+    _yum_ids $@ -S '..' 1
+  fi
+}
+
+# Expand next argument after 'yum history'
+_yum_history() {
+  local expl
+  if (( CURRENT == 2 )); then
+    _wanted arguments expl "yum history command" compadd info list \
+      packages-list packages-info summary addon-info redo undo \
+      roll-back new sync stats
+  elif (( CURRENT == 3 )); then
+    local -a ID_commands
+    local -a ID_range_commands
+    local -a package_commands
+    local -a alts
+    alts=()
+    #ID_commands=('summary' 'info' 'list' 'stats' 'addon-info')
+    ID_commands=('addon-info')
+    ID_range_commands=('summary' 'info' 'list' 'stats')
+    package_commands=('summary' 'info' 'list' 'stats' 'packages-list' 'packages-info')
+    #package_commands=('packages-list' 'packages-info')
+    # packages-list, packages-info   : needs package name
+    # summary, info, list, stats     : ID, ID range, package name
+    # addon-info                     : ID
+    # redo, undo, roll-back, sync    : unknown
+
+    [[ -n "${ID_commands[(r)$words[2]]}" ]] && alts+=('special:special ID:(last)')
+    [[ -n "${ID_commands[(r)$words[2]]}" ]] && alts+=('regular:ID:_yum_ids 1')
+    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=('regular:transaction range:_yum_ranges')
+    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=('special:all transactions:(all)')
+    [[ -n "${package_commands[(r)$words[2]]}" ]] && alts+=("package:package:_yum_act_on_installed_pkgs")
+
+    if (( ${+alts[1]} )) ; then
+      _alternative "$alts[@]"
+    else
+      _default
+    fi
+  elif (( CURRENT == 4 )); then
+    if [ "$words[2]" = "addon-info" ]; then
+      _wanted arguments expl 'additional option' compadd saved_tx
+    fi
+  fi
+}
+
+
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
@@ -163,11 +285,34 @@ yum_repos() {
 	compadd "$@" -a -- enabled_yum_repos
 }
 
+# Suggest installed packages
+_yum_act_on_installed_pkgs() {
+	_yum_installed_pkgs
+	compadd "$@" -a -- _installed_pkgs
+}
+
+# Completion function for distribution-synchronization|distro-sync
+(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+{
+  _yum_act_on_installed_pkgs "$@"
+}
+
 # Completion function for erase|remove
 (( $+functions[_yum_erase] )) || _yum_erase()
 {
-	_yum_installed_pkgs
-	compadd "$@" -a -- _installed_pkgs
+  _yum_act_on_installed_pkgs "$@"
+}
+
+# Completion function for downgrade
+(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+{
+  _yum_act_on_installed_pkgs "$@"
+}
+
+# Completion function for reinstall
+(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+{
+  _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for install
@@ -191,6 +336,12 @@ yum_repos() {
         return ret
 }
 
+# Completion function for load-transaction
+(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+{
+	_files
+}
+
 # Completion function for localinstall
 (( $+functions[_yum_localinstall] )) || _yum_localinstall()
 {

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0001-extend-yum-completion.patch --]
[-- Type: text/x-patch; name="0001-extend-yum-completion.patch", Size: 22487 bytes --]

From c99e182878d5f1da4a1add0983fb4532188606f6 Mon Sep 17 00:00:00 2001
From: Paul Seyfert <paul.seyfert@mib.infn.it>
Date: Sun, 23 Oct 2016 01:42:46 +0200
Subject: [PATCH] extend yum completion

adding the following yum commands:
 * update-to (just what update expands)
 * upgrade-to (just what update expands)
 * history (the actual tricky one)
 * help (printing the available commands)
 * load-transaction (_files)
 * load-ts (_files)
 * check (just what the man page suggested)
 * reinstall (just what erase does - suggest installed packages)
 * downgrade (just what erase does - suggest installed packages)
 * repolist (just what the man page suggested)
 * distribution-synchronization (just what erase does - suggest installed packages)
 * distro-sync (just what erase does - suggest installed packages)

A few history commands don't get expanded.
Taken from the man page of yum 3.2.29.
Reindented file.
---
 Completion/Redhat/Command/_yum | 527 ++++++++++++++++++++++++++---------------
 1 file changed, 339 insertions(+), 188 deletions(-)

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index f453806..be56813 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -3,293 +3,444 @@
 # Main dispatcher
 _yum() 
 {
-	local curcontext="$curcontext" state lstate line
-
-	_arguments -s \
-	   '(- *)'{-h,--help}'[show the help message]' \
-	   '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
-	   '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
-	   '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
-	   '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
-	   '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
-	   '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
-	   '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
-	   '--installroot=[set install root]:install root:_files -/' \
-	   '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
-	   '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
-	   {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
-	   '--version[show yum version]' \
-	   '--obsoletes[enable obsoletes processing during updates]' \
-	   '--nogpgcheck[disable gpg signature checking]' \
-	   '--noplugins[disable yum plugins]' \
-	   '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
-	   '*::yum command:_yum_command'
+  local curcontext="$curcontext" state lstate line
+
+  _arguments -s \
+    '(- *)'{-h,--help}'[show the help message]' \
+    '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
+    '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
+    '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
+    '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
+    '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
+    '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
+    '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
+    '--installroot=[set install root]:install root:_files -/' \
+    '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
+    '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
+    {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
+    '--version[show yum version]' \
+    '--obsoletes[enable obsoletes processing during updates]' \
+    '--nogpgcheck[disable gpg signature checking]' \
+    '--noplugins[disable yum plugins]' \
+    '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
+    '*::yum command:_yum_command'
 }
 
 (( $+functions[_yum_command] )) || _yum_command() 
 {
-  	local -a _yum_cmds
-  	_yum_cmds=(
-		"install:install the latest version of a package or group of packages"
-		"erase:remove an installed package (with its dependencies)"
-		"remove:remove an installed package (with its dependencies)"
-		"clean:clean local yum cache"
-		"deplist:gives a list of all dependencies for a package"
-		"check-update:check if any updates are available"
-		"info:get description of available packages"
-		"list:is used to list various information about packages"
-		"groupinfo:get info on package groups"
-		"groupinstall:install a package group or groups"
-		"groupremove:remove a package group or groups"
-		"grouplist:list package groups"
-		"groupupdate:update a package group or groups"
-		"localinstall:install packages with local rpm files"
-		"localupdate:update packages with local rpm files"
-		"makecache:makes a local yum cache"
-		"provides:find out which package provides some feature or file"
-		"whatprovides:find out which package provides some feature or file"
-		"resolvedep:list packages providing the specified dependencies"
-		"search:find any packages matching pattern"
-		"shell:enter the 'yum shell'"
-		"update:update one or more packages"
-		"upgrade:upgrade one or more packages"
-  	)
-
-  	if (( CURRENT == 1 )); then
-		_describe -t commands 'yum command' _yum_cmds || compadd "$@"
-  	else
-    	local curcontext="$curcontext"
-
-	    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
-		# Deal with any aliases
-		case $cmd in
-			remove) cmd="erase";;
-			whatprovides) cmd="provides";;
-			upgrade) cmd="update";;
-		esac
-		
-    	if (( $#cmd )); then
-    		curcontext="${curcontext%:*:*}:yum-${cmd}:"
-	
-	      	local update_policy
-		  	zstyle -s ":completion:${curcontext}:" cache-policy update_policy
-		  	if [[ -z "$update_policy" ]]; then
-				zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
-	  		fi
-
-      		_call_function ret _yum_$cmd || _message 'no more arguments'
-    	else
-      		_message "unknown yum command: $words[1]"
-    	fi
-    	return ret
-  	fi
+  local -a _yum_cmds
+  _yum_cmds=(
+  "install:install the latest version of a package or group of packages"
+  "erase:remove an installed package (with its dependencies)"
+  "remove:remove an installed package (with its dependencies)"
+  "clean:clean local yum cache"
+  "deplist:gives a list of all dependencies for a package"
+  "check-update:check if any updates are available"
+  "info:get description of available packages"
+  "list:is used to list various information about packages"
+  "groupinfo:get info on package groups"
+  "groupinstall:install a package group or groups"
+  "groupremove:remove a package group or groups"
+  "grouplist:list package groups"
+  "groupupdate:update a package group or groups"
+  "localinstall:install packages with local rpm files"
+  "localupdate:update packages with local rpm files"
+  "makecache:makes a local yum cache"
+  "provides:find out which package provides some feature or file"
+  "whatprovides:find out which package provides some feature or file"
+  "resolvedep:list packages providing the specified dependencies"
+  "search:find any packages matching pattern"
+  "shell:enter the 'yum shell'"
+  "update:update one or more packages"
+  "upgrade:upgrade one or more packages"
+  "update-to:update one or more packages taking obsoletes into account"
+  "upgrade-to:upgrade one or more packages taking obsoletes into account"
+  "history:view past transactions"
+  "help:produce help for all or given command"
+  "load-transaction:load a saved transaction from a textfile"
+  "load-ts:load a saved transaction from a textfile"
+  "check:Check for problems in the rpmdb"
+  "reinstall:reinstall a package"
+  "downgrade:downgrade a package"
+  "repolist:display the configured software repositories"
+  "distribution-synchronization:synchronize installed packages to the latest available versions"
+  "distro-sync:synchronize installed packages to the latest available versions"
+  )
+
+  if (( CURRENT == 1 )); then
+    _describe -t commands 'yum command' _yum_cmds || compadd "$@"
+  else
+    local curcontext="$curcontext"
+
+    cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
+    # Deal with any aliases
+    case $cmd in
+      remove) cmd="erase";;
+      whatprovides) cmd="provides";;
+      upgrade) cmd="update";;
+      upgrade-to) cmd="update";;
+      update-to) cmd="update";;
+      load-ts) cmd="load-transaction";;
+      distro-sync) cmd="distribution-synchronization";;
+    esac
+
+    if (( $#cmd )); then
+      curcontext="${curcontext%:*:*}:yum-${cmd}:"
+
+      local update_policy
+      zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+      if [[ -z "$update_policy" ]]; then
+        zstyle ":completion:${curcontext}:" cache-policy _yum_caching_policy
+      fi
+
+      if [ "$cmd" = "help" ]; then
+        if (( CURRENT == 2 )); then
+          local -a _yum_cmd_names
+          _yum_cmd_names=(${_yum_cmds%%:*})
+          _describe -t commands 'commands' _yum_cmd_names
+        else
+          # help takes one argument
+          _message 'no more arguments'
+        fi
+      else
+        _call_function ret _yum_$cmd || _message 'no more arguments'
+      fi
+    else
+      _message "unknown yum command: $words[1]"
+    fi
+    return ret
+  fi
+}
+
+# Expand next argument after 'yum check'
+_yum_check() {
+  if (( CURRENT == 2 )); then
+    ##chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
+    ##chkargs=("dependencies" "duplicates" "all") # according to help
+    #chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
+    local expl
+    _wanted arguments expl 'check argument' compadd dependencies \
+      duplicates provides all
+  else
+    return 1
+  fi
+}
+
+# Expand next argument after 'yum repolist'
+_yum_repolist() {
+  if (( CURRENT == 2 )); then
+    local expl
+    _wanted arguments expl 'repolist arguments' compadd all enabled disabled
+  else
+    return 1
+  fi
+}
+
+_yum_ids() {
+  # the last argument will be the first valid transaction ID to be suggested
+  # all other arguments are forwarded to compadd
+  #
+  # maxid is the last transaction ID known to yum
+  # minusone is the number of arguments provided to _yum_ids minus one
+  local maxid
+  local minusone
+
+  maxid=$(yum history stats | grep Transactions | sed "s/.*: //")
+
+  # `$#' is the number of arguments
+  ((minusone=$#-1))
+
+  # `$@' are the arguments
+  # `${(@)@[...]}' selects a subrange from $@
+  # `${(@)@[1,$minusone]}' are all except the last argument
+  # `$@[$#]' is the last argument, e.g. the first suggestable ID
+  compadd "${(@)@[1,$minusone]}" {$@[$#]..$maxid}
 }
 
+_yum_ranges() {
+  if compset -P '*..'; then
+    _yum_ids $@ ${(S)IPREFIX#..}
+  else
+    _yum_ids $@ -S '..' 1
+  fi
+}
+
+# Expand next argument after 'yum history'
+_yum_history() {
+  local expl
+  if (( CURRENT == 2 )); then
+    _wanted arguments expl "yum history command" compadd info list \
+      packages-list packages-info summary addon-info redo undo \
+      roll-back new sync stats
+  elif (( CURRENT == 3 )); then
+    local -a ID_commands
+    local -a ID_range_commands
+    local -a package_commands
+    local -a alts
+    alts=()
+    #ID_commands=('summary' 'info' 'list' 'stats' 'addon-info')
+    ID_commands=('addon-info')
+    ID_range_commands=('summary' 'info' 'list' 'stats')
+    package_commands=('summary' 'info' 'list' 'stats' 'packages-list' 'packages-info')
+    #package_commands=('packages-list' 'packages-info')
+    # packages-list, packages-info   : needs package name
+    # summary, info, list, stats     : ID, ID range, package name
+    # addon-info                     : ID
+    # redo, undo, roll-back, sync    : unknown
+
+    [[ -n "${ID_commands[(r)$words[2]]}" ]] && alts+=('special:special ID:(last)')
+    [[ -n "${ID_commands[(r)$words[2]]}" ]] && alts+=('regular:ID:_yum_ids 1')
+    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=('regular:transaction range:_yum_ranges')
+    [[ -n "${ID_range_commands[(r)$words[2]]}" ]] && alts+=('special:all transactions:(all)')
+    [[ -n "${package_commands[(r)$words[2]]}" ]] && alts+=("package:package:_yum_act_on_installed_pkgs")
+
+    if (( ${+alts[1]} )) ; then
+      _alternative "$alts[@]"
+    else
+      _default
+    fi
+  elif (( CURRENT == 4 )); then
+    if [ "$words[2]" = "addon-info" ]; then
+      _wanted arguments expl 'additional option' compadd saved_tx
+    fi
+  fi
+}
+
+
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
-	if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
-		! _retrieve_cache ALL;
-	then
-		_all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache ALL _all_pkgs
-	fi
+  if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
+    ! _retrieve_cache ALL;
+then
+  _all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache ALL _all_pkgs
+fi
 }
 
 # Fills the installed pkg cache
 _yum_installed_pkgs()
 {
-	if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
-		! _retrieve_cache INSTALLED;
-	then
-		_installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache INSTALLED _installed_pkgs
-	fi
+  if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
+    ! _retrieve_cache INSTALLED;
+then
+  _installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache INSTALLED _installed_pkgs
+fi
 }
 
 # Fills the available pkg cache
 _yum_available_pkgs()
 {
-	if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
-		! _retrieve_cache AVAILABLE;
-	then
-		_available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache AVAILABLE _available_pkgs
-	fi
+  if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
+    ! _retrieve_cache AVAILABLE;
+then
+  _available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache AVAILABLE _available_pkgs
+fi
 }
 
 # Fills the upgrade pkg cache
 _yum_upgrade_pkgs()
 {
-	if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
-		! _retrieve_cache UPGRADE;
-	then
-		_upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-		_store_cache UPGRADE _upgrade_pkgs
-	fi
+  if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
+    ! _retrieve_cache UPGRADE;
+then
+  _upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+  _store_cache UPGRADE _upgrade_pkgs
+fi
 }
 
 # Gets the list of defined repos
 yum_repos() {
-    local trepo
-    local -a tarray
-    tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
-    local -i eindex=0
-    local -i dindex=0
-    for line in $tarray; do
-        if [[ "$line" = "enabled=1" ]]; then
-            enabled_yum_repos=($enabled_yum_repos $trepo)
-        elif [[ "$line" = "enabled=0" ]]; then
-            disabled_yum_repos=($disabled_yum_repos $trepo)
-        elif [[ "$line" != "main" ]]; then
-            trepo=$line
-        fi
-    done
+  local trepo
+  local -a tarray
+  tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
+  local -i eindex=0
+  local -i dindex=0
+  for line in $tarray; do
+    if [[ "$line" = "enabled=1" ]]; then
+      enabled_yum_repos=($enabled_yum_repos $trepo)
+    elif [[ "$line" = "enabled=0" ]]; then
+      disabled_yum_repos=($disabled_yum_repos $trepo)
+    elif [[ "$line" != "main" ]]; then
+      trepo=$line
+    fi
+  done
 }
 
 (( $+functions[_yum_disabled_repos_list] )) || _yum_disabled_repos_list()
 {
-	compset -P '*,'
-	compset -S ',*'
-	yum_repos			
-	compadd "$@" -a -- disabled_yum_repos
+  compset -P '*,'
+  compset -S ',*'
+  yum_repos			
+  compadd "$@" -a -- disabled_yum_repos
 }
 
 (( $+functions[_yum_enabled_repos_list] )) || _yum_enabled_repos_list()
 {
-	compset -P '*,'
-	compset -S ',*'
-	yum_repos			
-	compadd "$@" -a -- enabled_yum_repos
+  compset -P '*,'
+  compset -S ',*'
+  yum_repos			
+  compadd "$@" -a -- enabled_yum_repos
+}
+
+# Suggest installed packages
+_yum_act_on_installed_pkgs() {
+  _yum_installed_pkgs
+  compadd "$@" -a -- _installed_pkgs
+}
+
+# Completion function for distribution-synchronization|distro-sync
+(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+{
+  _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for erase|remove
 (( $+functions[_yum_erase] )) || _yum_erase()
 {
-	_yum_installed_pkgs
-	compadd "$@" -a -- _installed_pkgs
+  _yum_act_on_installed_pkgs "$@"
+}
+
+# Completion function for downgrade
+(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+{
+  _yum_act_on_installed_pkgs "$@"
+}
+
+# Completion function for reinstall
+(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+{
+  _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for install
 (( $+functions[_yum_install] )) || _yum_install()
 {
-        if ! [[ $PREFIX == */* ]]; then
-          _yum_available_pkgs
-        fi
+  if ! [[ $PREFIX == */* ]]; then
+    _yum_available_pkgs
+  fi
 
-        local ret=1
-        _tags files packages
-        while _tags; do
-          if _requested files; then
-            compadd "$@" -a -- _available_pkgs
-          fi
-          if _requested packages; then
-            _call_function - _yum_localinstall
-          fi
-          (( ret )) || break
-        done
-        return ret
+  local ret=1
+  _tags files packages
+  while _tags; do
+    if _requested files; then
+      compadd "$@" -a -- _available_pkgs
+    fi
+    if _requested packages; then
+      _call_function - _yum_localinstall
+    fi
+    (( ret )) || break
+  done
+  return ret
+}
+
+# Completion function for load-transaction
+(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+{
+  _files
 }
 
 # Completion function for localinstall
 (( $+functions[_yum_localinstall] )) || _yum_localinstall()
 {
-	_files -/ -g '(#i)*.rpm(-.)'
+  _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for localupdate
 (( $+functions[_yum_localupdate] )) || _yum_localupdate()
 {
-	_files -/ -g '(#i)*.rpm(-.)'
+  _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for update/upgrade
 (( $+functions[_yum_update] )) || _yum_update()
 {
-	_yum_upgrade_pkgs
-	compadd "$@" -a -- _upgrade_pkgs
+  _yum_upgrade_pkgs
+  compadd "$@" -a -- _upgrade_pkgs
 }
 
 # Completion function for deplist
 (( $+functions[_yum_deplist] )) || _yum_deplist()
 {
-	_yum_available_pkgs
-	compadd "$@" -a -- _available_pkgs
+  _yum_available_pkgs
+  compadd "$@" -a -- _available_pkgs
 }
 
 _yum_all()
 {
-	_yum_all_pkgs
-	compadd "$@" -a -- _all_pkgs
+  _yum_all_pkgs
+  compadd "$@" -a -- _all_pkgs
 }
 _yum_list_or_info()
 {
-	local -a listlist
-	listlist=(
-		"all:all packages in repositories"
-		"available:packages available in repositories"
-		"updates:packages with updates available"
-		"installed:installed packages"
-		"extras:packages installed that are not available in any yum repository"
-		"obsoletes:packages installed that are obsoleted"
-		"recent:packages recently added to repositories"
-	)
-	
-  	if (( CURRENT == 2 )); then
-		_describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
-	else
-	    local subcmd
-		subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
-		# offer packages selected by the subcommand
-		case $subcmd in
-			all) _yum_all;;
-			installed) _yum_erase;;
-			available) _yum_install;;
-			updates) _yum_update;;
-		esac
-	fi
+  local -a listlist
+  listlist=(
+    "all:all packages in repositories"
+    "available:packages available in repositories"
+    "updates:packages with updates available"
+    "installed:installed packages"
+    "extras:packages installed that are not available in any yum repository"
+    "obsoletes:packages installed that are obsoleted"
+    "recent:packages recently added to repositories"
+  )
+
+  if (( CURRENT == 2 )); then
+    _describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
+  else
+    local subcmd
+    subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
+    # offer packages selected by the subcommand
+    case $subcmd in
+      all) _yum_all;;
+      installed) _yum_erase;;
+      available) _yum_install;;
+      updates) _yum_update;;
+    esac
+  fi
 }
 
 # Completion function for list
 (( $+functions[_yum_list] )) || _yum_list()
 {
-	_yum_list_or_info
+  _yum_list_or_info
 }
 
 # Completion function for info
 (( $+functions[_yum_info] )) || _yum_info()
 {
-	_yum_list_or_info
+  _yum_list_or_info
 }
 
 # Completion function for provides|whatprovides
 (( $+functions[_yum_provides] )) || _yum_provides()
 {
-	_files	
+  _files	
 }
 
 # Completion function for resolvedep
 (( $+functions[_yum_resolvedep] )) || _yum_resolvedep()
 {
-	_files	
+  _files	
 }
 
 # Completion function for clean
 (( $+functions[_yum_clean] )) || _yum_clean()
 {
-	local -a cleanlist
-	cleanlist=(
-		"all:all cache"
-		"cache:all cache"
-		"dbcache:DB cache"
-		"headers:cache headers"
-		"packages:cache packages"
-		"metadata:cache meta-data"
-	)
-	
-  	if (( CURRENT == 2 )); then
-		_describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist 
-	fi
+  local -a cleanlist
+  cleanlist=(
+    "all:all cache"
+    "cache:all cache"
+    "dbcache:DB cache"
+    "headers:cache headers"
+    "packages:cache packages"
+    "metadata:cache meta-data"
+  )
+
+  if (( CURRENT == 2 )); then
+    _describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist 
+  fi
 }
 
 _yum_caching_policy() 
-- 
2.1.4


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

* caching mechanism and Re: PATCH Completion for _yum
       [not found]           ` <31607.1478915523@hydra.kiddle.eu>
@ 2016-11-22 19:05             ` Oliver Kiddle
  2016-12-13 10:10               ` Oliver Kiddle
  0 siblings, 1 reply; 19+ messages in thread
From: Oliver Kiddle @ 2016-11-22 19:05 UTC (permalink / raw)
  To: Zsh workers; +Cc: Paul Seyfert

I took another more detailed look at _yum as there was a few further
things that had bothered me like it not supporting groupinstall or
completing some options like --skip-broken. This patch updates that
and a few other minor things like using _values so duplicates are
not completed and using _sequence for a list. I'm not sure how much
use these changes will ever get with RedHat moving to dnf. At least
yum's command line interface isn't going to change much in future.

One thing I noticed was that the use of the cache mechanism seemed
broken. This is code that has been copied from elsewhere but appears
widely in other functions.

We seem to either have:
  if _cache_invalid svn-cmds || ! _retrieve_cache svn-cmds; then
 - seems logical: regenerate if cache is invalid or we fail to restore it
or:
  if ( [[ ${+_dput_cfhosts} -eq 0 ]] || _cache_invalid dputhosts ) && ! _retrieve_cache dputhosts; then
 - which makes no sense to me.

I think the intention is to reuse a cache that is stored in a shell
variable on the basis that it should be fairly recent. I just stuffed
something like the following at the top and reverted to the other form:
+  (( $#_yum_all_pkgs )) && return

I also think that the _example_caching_policy function in the
documentation seems broken for the case of no cache file existing
at all. Or should we handle that case internally instead?

Oliver

diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index 69a8de9..c155358 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -9,19 +9,40 @@ _yum() {
     '(-t --tolerant)'{-t,--tolerant}'[be tolerant of errors]' \
     '(-C --cacheonly)'{-C,--cacheonly}'[run entirely from cache]' \
     '(-c --config)'{-c,--config=}'[config file location]:Yum conf file:_files' \
-    '(-R --randomwait)'{-R,--randomwait=}'[maximum command wait time (in minutes)]:max wait time' \
+    '(-R --randomwait)'{-R,--randomwait=}'[specify maximum command wait time]:max wait time (minutes)' \
     '(-d --debuglevel)'{-d,--debuglevel=}'[debug level (0-10)]:debug level' \
+    '--showduplicates[show duplicates, in repos, in list/search commands]' \
     '(-e --errorlevel)'{-e,--errorlevel=}'[error level (0-10)]:error level' \
-    '(-y --assumeyes)'{-y,--assumeyes}'[answer yes for all questions]' \
+    '--rpmverbosity=[specify rpm debug level]:debug level' \
+    '(-q --quiet -v --verbose)'{-q,--quiet}'[quiet operation]' \
+    '(-q --quiet -v --verbose)'{-v,--verbose}'[verbose operation]' \
+    '(-y --assumeyes --assumeno)'{-y,--assumeyes}'[answer yes to all questions]' \
+    '(-y --assumeyes --assumeno)--assumeno[answer no to all questions]' \
+    '(- *)--version[display version information]' \
     '--installroot=[set install root]:install root:_files -/' \
-    '*--enablerepo=[enable or or more repositories]:repos to enable:_yum_disabled_repos_list' \
-    '*--disablerepo=[disable one or more repositories]:disable repos:_yum_enabled_repos_list' \
-    {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
-    '--version[show yum version]' \
+    '*--enablerepo=[enable or or more repositories]:repository:_sequence _yum_disabled_repos' \
+    '*--disablerepo=[disable one or more repositories]:repository:_sequence _yum_enabled_repos' \
+    \*{-x,--exclude=}'[exclude package by name or glob]:package:_yum_all_pkgs' \
+    '--disableexcludes=[disable exclude]:exclude:(all main)' \
+    '--disableincludes=[disable include]:include' \
     '--obsoletes[enable obsoletes processing during updates]' \
-    '--nogpgcheck[disable gpg signature checking]' \
     '--noplugins[disable yum plugins]' \
-    '--disablepresto[disable Presto plugin and don''''t download any deltarpms]' \
+    '--nogpgcheck[disable gpg signature checking]' \
+    '--disableplugin=[disable plugin]:plugin' \
+    '--enableplugin=[enable plugin]:plugin' \
+    '--skip-broken[skip packages with depsolving problems]' \
+    '--color=[control whether color is used]:(always auto never)' \
+    '--releasever=[set value of $releasever in yum config and repo files]:value' \
+    "--downloadonly[don't update, just download]" \
+    '--downloaddir=[specify alternate directory to store packages]:directort:_directories' \
+    '--setopt=[set arbitrary config and repo options]:option' \
+    '--bugfix[include bugfix relevant packages in updates]' \
+    '--security[include security relevant packages in updates]' \
+    '--advisory=[include packages needed to fix the given advisory]:advisory' \
+    '--bzs=[include packages needed to fix the given BZ]:BZ' \
+    '--cves=[include packages needed to fix the given CVE]:CVE' \
+    '--sec-severity=[include security relevant packages matching specific severity]:severity' \
+    {*-x,*--exclude=}'[exclude package(s) by name or glob]:exclude packages' \
     '*::yum command:_yum_command'
 }
 
@@ -58,7 +79,7 @@ _yum() {
   "help:produce help for all or given command"
   "load-transaction:load a saved transaction from a textfile"
   "load-ts:load a saved transaction from a textfile"
-  "check:Check for problems in the rpmdb"
+  "check:check for problems in the rpmdb"
   "reinstall:reinstall a package"
   "downgrade:downgrade a package"
   "repolist:display the configured software repositories"
@@ -67,9 +88,9 @@ _yum() {
   )
 
   if (( CURRENT == 1 )); then
-    _describe -t commands 'yum command' _yum_cmds || compadd "$@"
+    _describe -t commands 'yum command' _yum_cmds
   else
-    local curcontext="$curcontext"
+    local curcontext="$curcontext" ret=1
 
     cmd="${${_yum_cmds[(r)$words[1]:*]%%:*}}"
     # Deal with any aliases
@@ -94,45 +115,36 @@ _yum() {
 
       if [ "$cmd" = "help" ]; then
         if (( CURRENT == 2 )); then
-          local -a _yum_cmd_names
-          _yum_cmd_names=(${_yum_cmds%%:*})
-          _describe -t commands 'commands' _yum_cmd_names
+          _describe -t commands 'yum commands' _yum_cmds && ret=0
         else
           # help takes one argument
           _message 'no more arguments'
         fi
-      else
-        _call_function ret _yum_$cmd || _message 'no more arguments'
+      elif ! _call_function ret _yum-$cmd; then
+	_default && ret=0
       fi
     else
-      _message "unknown yum command: $words[1]"
+      # fallback to default completion for unknown commands
+      _default && ret=0
     fi
     return ret
   fi
 }
 
 # Expand next argument after 'yum check'
-_yum_check() {
-  if (( CURRENT == 2 )); then
+_yum-check() {
     ##chkargs=("dependencies" "duplicates" "obsoletes" "provides" "all") # according to man page
     ##chkargs=("dependencies" "duplicates" "all") # according to help
     #chkargs=("dependencies" "duplicates" "provides" "all") # what works for me
-    local expl
-    _wanted arguments expl 'check argument' compadd dependencies \
-      duplicates provides all
-  else
-    return 1
-  fi
+  _values -w 'check argument' dependencies duplicates provides all
 }
 
 # Expand next argument after 'yum repolist'
-_yum_repolist() {
-  if (( CURRENT == 2 )); then
-    local expl
-    _wanted arguments expl 'repolist arguments' compadd all enabled disabled
-  else
-    return 1
-  fi
+_yum-repolist() {
+  _yum_get_repos
+  _alternative \
+    'filters:filter:(all enabled disabled)' \
+    'repositories:repository:compadd -a yum_enabled_repos yum_disabled_repos'
 }
 
 _yum_ids() {
@@ -140,35 +152,32 @@ _yum_ids() {
   # all other arguments are forwarded to compadd
   #
   # maxid is the last transaction ID known to yum
-  # minusone is the number of arguments provided to _yum_ids minus one
   local maxid
-  local minusone
 
-  maxid=$(yum history stats | grep Transactions | sed "s/.*: //")
-
-  # `$#' is the number of arguments
-  ((minusone=$#-1))
+  maxid=${${(M)${(f)"$(_call_program transactions yum history stats)"}:#Transactions:*}##* }
 
   # `$@' are the arguments
   # `${(@)@[...]}' selects a subrange from $@
-  # `${(@)@[1,$minusone]}' are all except the last argument
+  # `${(@)@[1,-2]}' are all except the last argument
   # `$@[$#]' is the last argument, e.g. the first suggestable ID
-  compadd "${(@)@[1,$minusone]}" {$@[$#]..$maxid}
+  compadd "${(@)@[1,-2]:/-J/-V}" -M "B:0=" {$@[$#]..$maxid}
 }
 
 _yum_ranges() {
-  if compset -P '*..'; then
-    _yum_ids $@ ${(S)IPREFIX#..}
+  if compset -P 1 '*..'; then
+    _yum_ids "$@" ${(S)IPREFIX#..}
+  elif compset -S '..*'; then
+    _yum_ids "$@" 1
   else
-    _yum_ids $@ -S '..' 1
+    _yum_ids "$@" -S '..' 1
   fi
 }
 
 # Expand next argument after 'yum history'
-_yum_history() {
+_yum-history() {
   local expl
   if (( CURRENT == 2 )); then
-    _wanted arguments expl "yum history command" compadd info list \
+    _wanted commands expl "yum history command" compadd info list \
       packages-list packages-info summary addon-info redo undo \
       roll-back new sync stats
   elif (( CURRENT == 3 )); then
@@ -209,49 +218,45 @@ _yum_history() {
 # Fills the all pkg cache
 _yum_all_pkgs()
 {
-  if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
-    ! _retrieve_cache ALL;
-then
-  _all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-  _store_cache ALL _all_pkgs
-fi
+  (( $#_yum_all_pkgs )) && return
+  if _cache_invalid yum-all-packages || ! _retrieve_cache yum-all-packages; then
+    _yum_all_pkgs=( ${(M)${${(f)"$(_call_program packages yum -C list all)"}// *}:#*.*} )
+    _store_cache yum-all-packages _yum_all_pkgs
+  fi
 }
 
 # Fills the installed pkg cache
 _yum_installed_pkgs()
 {
-  if ( [[ ${+_installed_pkgs} -eq 0 ]] || _cache_invalid INSTALLED ) &&
-    ! _retrieve_cache INSTALLED;
-then
-  _installed_pkgs=( $(yum -C list installed | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-  _store_cache INSTALLED _installed_pkgs
-fi
+  (( $#_yum_installed_pkgs )) && return
+  if _cache_invalid yum-installed || ! _retrieve_cache yum-installed; then
+    _yum_installed_pkgs=( ${(M)${${(f)"$(_call_program packages yum -C list installed)"}// *}:#*.*} )
+    _store_cache yum-installed _yum_installed_pkgs
+  fi
 }
 
 # Fills the available pkg cache
 _yum_available_pkgs()
 {
-  if ( [[ ${+_available_pkgs} -eq 0 ]] || _cache_invalid AVAILABLE ) &&
-    ! _retrieve_cache AVAILABLE;
-then
-  _available_pkgs=( $(yum -C list available | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-  _store_cache AVAILABLE _available_pkgs
-fi
+  (( $#_yum_available_pkgs )) && return
+  if _cache_invalid yum-available || ! _retrieve_cache yum-available; then
+    _yum_available_pkgs=( ${(M)${${(f)"$(_call_program packages yum -C list available)"}// *}:#*.*} )
+    _store_cache yum-available _yum_available_pkgs
+  fi
 }
 
 # Fills the upgrade pkg cache
 _yum_upgrade_pkgs()
 {
-  if ( [[ ${+_upgrade_pkgs} -eq 0 ]] || _cache_invalid UPGRADE ) &&
-    ! _retrieve_cache UPGRADE;
-then
-  _upgrade_pkgs=( $(yum -C list upgrade | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
-  _store_cache UPGRADE _upgrade_pkgs
-fi
+  (( $#_yum_upgrade_pkgs )) && return
+  if _cache_invalid yum-upgrade || ! _retrieve_cache yum-upgrade; then
+    _yum_upgrade_pkgs=( ${(M)${${(f)"$(_call_program packages yum -C list upgrade)"}// *}:#*.*} )
+    _store_cache yum-upgrade _yum_upgrade_pkgs
+  fi
 }
 
 # Gets the list of defined repos
-yum_repos() {
+_yum_get_repos() {
   local trepo
   local -a tarray
   tarray=( $(egrep -h '(^\[.*\]|^enabled.*=)' /etc/yum.repos.d/*.repo /etc/yum.conf | sed -e 's/ //g' | sed -e 's/\[//g' | sed -e 's/\].*$//g' 2>/dev/null) )
@@ -259,63 +264,86 @@ yum_repos() {
   local -i dindex=0
   for line in $tarray; do
     if [[ "$line" = "enabled=1" ]]; then
-      enabled_yum_repos=($enabled_yum_repos $trepo)
+      yum_enabled_repos=($enabled_yum_repos $trepo)
     elif [[ "$line" = "enabled=0" ]]; then
-      disabled_yum_repos=($disabled_yum_repos $trepo)
+      yum_disabled_repos=($yum_disabled_repos $trepo)
     elif [[ "$line" != "main" ]]; then
       trepo=$line
     fi
   done
 }
 
-(( $+functions[_yum_disabled_repos_list] )) || _yum_disabled_repos_list()
-{
-  compset -P '*,'
-  compset -S ',*'
-  yum_repos			
-  compadd "$@" -a -- disabled_yum_repos
+_yum_disabled_repos() {
+  _yum_get_repos
+  compadd "$@" -a -- yum_disabled_repos
 }
 
-(( $+functions[_yum_enabled_repos_list] )) || _yum_enabled_repos_list()
-{
-  compset -P '*,'
-  compset -S ',*'
-  yum_repos			
-  compadd "$@" -a -- enabled_yum_repos
+_yum_enabled_repos() {
+  _yum_get_repos
+  compadd "$@" -a -- yum_enabled_repos
 }
 
 # Suggest installed packages
 _yum_act_on_installed_pkgs() {
+  local expl
   _yum_installed_pkgs
-  compadd "$@" -a -- _installed_pkgs
+  _wanted packages expl 'package' compadd "$@" -a -- _yum_installed_pkgs
 }
 
 # Completion function for distribution-synchronization|distro-sync
-(( $+functions[_yum_distribution-synchronization] )) || _yum_distribution-synchronization()
+(( $+functions[_yum-distribution-synchronization] )) || _yum-distribution-synchronization()
 {
   _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for erase|remove
-(( $+functions[_yum_erase] )) || _yum_erase()
+(( $+functions[_yum-erase] )) || _yum-erase()
 {
   _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for downgrade
-(( $+functions[_yum_downgrade] )) || _yum_downgrade()
+(( $+functions[_yum-downgrade] )) || _yum-downgrade()
 {
   _yum_act_on_installed_pkgs "$@"
 }
 
 # Completion function for reinstall
-(( $+functions[_yum_reinstall] )) || _yum_reinstall()
+(( $+functions[_yum-reinstall] )) || _yum-reinstall()
 {
   _yum_act_on_installed_pkgs "$@"
 }
 
+(( $+functions[_yum-groupinfo] )) || _yum-groupinfo()
+{
+  local expl
+  _wanted groups expl group compadd \
+      ${${(M)${(f)"$(_call_program groups yum grouplist -C)"}:#   *}#   }
+}
+
+(( $+functions[_yum-groupinstall] )) || _yum-groupinstall()
+{
+  local expl
+  _wanted groups expl group compadd \
+      ${${(M)${(f)"$(_call_program groups yum grouplist -C)"}:#   *}#   }
+}
+
+(( $+functions[_yum-groupremove] )) || _yum-groupremove()
+{
+  local expl
+  _wanted groups expl group compadd \
+      ${${(M)${(f)"$(_call_program groups yum grouplist -C installed)"}:#   *}#   }
+}
+
+(( $+functions[_yum-groupupdate] )) || _yum-groupupdate()
+{
+  local expl
+  _wanted groups expl group compadd \
+      ${${(M)${(f)"$(_call_program groups yum grouplist -C installed)"}:#   *}#   }
+}
+
 # Completion function for install
-(( $+functions[_yum_install] )) || _yum_install()
+(( $+functions[_yum-install] )) || _yum-install()
 {
   if ! [[ $PREFIX == */* ]]; then
     _yum_available_pkgs
@@ -325,7 +353,7 @@ _yum_act_on_installed_pkgs() {
   _tags files packages
   while _tags; do
     if _requested files; then
-      compadd "$@" -a -- _available_pkgs
+      compadd "$@" -a -- _yum_available_pkgs
     fi
     if _requested packages; then
       _call_function - _yum_localinstall
@@ -336,42 +364,45 @@ _yum_act_on_installed_pkgs() {
 }
 
 # Completion function for load-transaction
-(( $+functions[_yum_load-transaction] )) || _yum_load-transaction()
+(( $+functions[_yum-load-transaction] )) || _yum-load-transaction()
 {
   _files
 }
 
 # Completion function for localinstall
-(( $+functions[_yum_localinstall] )) || _yum_localinstall()
+(( $+functions[_yum-localinstall] )) || _yum-localinstall()
 {
   _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for localupdate
-(( $+functions[_yum_localupdate] )) || _yum_localupdate()
+(( $+functions[_yum-localupdate] )) || _yum-localupdate()
 {
   _files -/ -g '(#i)*.rpm(-.)'
 }
 
 # Completion function for update/upgrade
-(( $+functions[_yum_update] )) || _yum_update()
+(( $+functions[_yum-update] )) || _yum-update()
 {
+  local expl
   _yum_upgrade_pkgs
-  compadd "$@" -a -- _upgrade_pkgs
+  _wanted packages expl package compadd "$@" -a _yum_upgrade_pkgs
 }
 
 # Completion function for deplist
-(( $+functions[_yum_deplist] )) || _yum_deplist()
+(( $+functions[_yum-deplist] )) || _yum-deplist()
 {
+  local expl
   _yum_available_pkgs
-  compadd "$@" -a -- _available_pkgs
+  _wanted packages expl package compadd "$@" -a _yum_available_pkgs
 }
 
 _yum_all()
 {
   _yum_all_pkgs
-  compadd "$@" -a -- _all_pkgs
+  compadd "$@" -a -- _yum_all_pkgs
 }
+
 _yum_list_or_info()
 {
   local -a listlist
@@ -386,60 +417,50 @@ _yum_list_or_info()
   )
 
   if (( CURRENT == 2 )); then
-    _describe -t yum-list-subcmds "Yum info/list sub-commands" listlist || _yum_all
+    _describe -t filters "filter" listlist || _yum_all
   else
-    local subcmd
-    subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
     # offer packages selected by the subcommand
-    case $subcmd in
-      all) _yum_all;;
-      installed) _yum_erase;;
-      available) _yum_install;;
-      updates) _yum_update;;
+    case $words[2] in
+      installed) _yum-erase;;
+      available) _yum-install;;
+      updates) _yum-update;;
+      *extras|obsoletes|recent)
+        _wanted packages expl package compadd \
+	    ${(M)${${(f)"$(_call_program packages yum -C list $words[2])"}// *}:#*.*}
+      ;;
+      *) _yum_all;;
     esac
   fi
 }
 
 # Completion function for list
-(( $+functions[_yum_list] )) || _yum_list()
+(( $+functions[_yum-list] )) || _yum-list()
 {
   _yum_list_or_info
 }
 
 # Completion function for info
-(( $+functions[_yum_info] )) || _yum_info()
+(( $+functions[_yum-info] )) || _yum-info()
 {
   _yum_list_or_info
 }
 
 # Completion function for provides|whatprovides
-(( $+functions[_yum_provides] )) || _yum_provides()
-{
-  _files	
-}
-
-# Completion function for resolvedep
-(( $+functions[_yum_resolvedep] )) || _yum_resolvedep()
+(( $+functions[_yum-provides] )) || _yum-provides()
 {
   _files	
 }
 
 # Completion function for clean
-(( $+functions[_yum_clean] )) || _yum_clean()
+(( $+functions[_yum-clean] )) || _yum-clean()
 {
-  local -a cleanlist
-  cleanlist=(
-    "all:all cache"
-    "cache:all cache"
-    "dbcache:DB cache"
-    "headers:cache headers"
-    "packages:cache packages"
-    "metadata:cache meta-data"
-  )
-
-  if (( CURRENT == 2 )); then
-    _describe -t yum-clean-subcmds "Yum clean sub-commands" cleanlist
-  fi
+  _values -w "Yum clean sub-commands" \
+    "all[all cache]" \
+    "cache[all cache]" \
+    "dbcache[DB cache]" \
+    "headers[cache headers]" \
+    "packages[cache packages]" \
+    "metadata[cache meta-data]"
 }
 
 _yum_caching_policy() {
@@ -447,8 +468,8 @@ _yum_caching_policy() {
   local -a oldp
 
   # rebuild if cache is more than a week old
-  oldp=( "$1"(mw+1) )
-  (( $#oldp )) && return 0
+  oldp=( "$1"(mw-1) )
+  (( $#oldp )) || return 0
 
   _yumrepomds=( /var/cache/yum/**/repomd.xml )
 



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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-11-22 19:05             ` caching mechanism and " Oliver Kiddle
@ 2016-12-13 10:10               ` Oliver Kiddle
  2016-12-13 16:18                 ` Jun T.
  2016-12-13 16:38                 ` caching mechanism and Re: PATCH Completion for _yum Bart Schaefer
  0 siblings, 2 replies; 19+ messages in thread
From: Oliver Kiddle @ 2016-12-13 10:10 UTC (permalink / raw)
  To: Zsh workers

On 22 Nov, I wrote:
> One thing I noticed was that the use of the cache mechanism seemed
> broken. This is code that has been copied from elsewhere but appears
> widely in other functions.
>
> We seem to either have:
>   if _cache_invalid svn-cmds || ! _retrieve_cache svn-cmds; then
>  - seems logical: regenerate if cache is invalid or we fail to restore it
> or:
>   if ( [[ ${+_dput_cfhosts} -eq 0 ]] || _cache_invalid dputhosts ) && ! _retrieve_cache dputhosts; then
>  - which makes no sense to me.

I went through correcting other cases of this particular broken logic.
Substituting instead this logic:
  if (( ! $+_dput_cfhosts[1] )) && { _cache_invalid dputhosts ||
      ! _retrieve_cache dputhosts }

Whether we want to be keeping caches also in a global variable is a
different question but I've renamed them to all have _cache as a prefix.

I'm also not keen on the functions setting a zstyle for the
default cache policy. Couldn't the default just be a parameter
to _cache_invalid? Some of the style lookups eschewed $curcontext so it
is not making it easier to use right.

The naming convention for these policy functions also doesn't help
people to get the sense of the return status right. How about something
like _finkpkgs_cache_stale instead of _finkpkgs_caching_policy?

Patch also has a few other minor tweaks/fixes. _path_commands wasn't
and still doesn't work for all common man implementations. The Debian
uninstalled package bit must have predated the :| operator because it
was using fgrep. :| is noticably faster.

Oliver

diff --git a/Completion/Darwin/Command/_fink b/Completion/Darwin/Command/_fink
index 04a067e..6f73224 100644
--- a/Completion/Darwin/Command/_fink
+++ b/Completion/Darwin/Command/_fink
@@ -2,36 +2,37 @@
 
 _fink_get_packages_with_cache(){
   local cache_policy
-  zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
+  zstyle -s ":completion:${curcontext}:packages" cache-policy cache_policy
   if [[ -z "$cache_policy" ]]; then
-    zstyle ":completion:${curcontext}:" cache-policy _finkpkgs_caching_policy
+    zstyle ":completion:${curcontext}:packages" cache-policy _finkpkgs_caching_policy
   fi
 
-  typeset -g -a _fink_pkgs
+  typeset -g -a _cache_fink_pkgs
   local expl
 
-  if ( (( #_fink_pkgs == 0 )) || _cache_invalid finkpkgs) \
-       && ! _retrieve_cache finkpkgs; then
-    _fink_pkgs=(${(f)"$(
+  if (( ! $+_cache_fink_pkgs[1] )) && { _cache_invalid fink-pkgs ||
+      ! _retrieve_cache fink-pkgs }
+  then
+    _cache_fink_pkgs=(${(f)"$(
       command fink list --tab \
       | command grep -v '\[virtual package\]' \
       | command sed 's/^   / n /' \
       | command cut -f1,2
     )"})
-    _store_cache finkpkgs _fink_pkgs
+    _store_cache fink-pkgs _cache_fink_pkgs
   fi
 
   if (( # > 0 )); then
     local i
     for i in "$@"; do
       case "$i" in
-        -i) packages+=(${${(M)_fink_pkgs:#?i?*}#*	}) ;;
-        -o) packages+=(${${(M)_fink_pkgs:#(i)*}#*	}) ;;
-        -n) packages+=(${${(M)_fink_pkgs:# n *}#*	}) ;;
+        -i) packages+=(${${(M)_cache_fink_pkgs:#?i?*}#*	}) ;;
+        -o) packages+=(${${(M)_cache_fink_pkgs:#(i)*}#*	}) ;;
+        -n) packages+=(${${(M)_cache_fink_pkgs:# n *}#*	}) ;;
       esac
     done
   else
-    packages=(${_fink_pkgs#*	})
+    packages=( ${_cache_fink_pkgs#*	} )
   fi
 }
 
@@ -47,7 +48,7 @@ _fink_get_packages_without_cache(){
 
 _fink_get_packages(){
   # variable packages will be set
-  if zstyle -t ":completion:${curcontext}:" use-cache; then
+  if zstyle -t ":completion:${curcontext}:packages" use-cache; then
     _fink_get_packages_with_cache "$@"
   else
     _fink_get_packages_without_cache "$@"
diff --git a/Completion/Darwin/Type/_mac_applications b/Completion/Darwin/Type/_mac_applications
index 51fa0c4..d1982a3 100644
--- a/Completion/Darwin/Type/_mac_applications
+++ b/Completion/Darwin/Type/_mac_applications
@@ -3,5 +3,5 @@
 _retrieve_mac_apps
 
 local expl
-_wanted commands expl 'Mac OS X application' \
-    compadd "$@" - "${(@)${_mac_apps[@]:t}%.app}"
+_wanted commands expl 'macOS application' \
+    compadd "$@" - "${(@)${_cache_mac_apps[@]:t}%.app}"
diff --git a/Completion/Darwin/Type/_mac_files_for_application b/Completion/Darwin/Type/_mac_files_for_application
index 299d8ff..f4e36c0 100644
--- a/Completion/Darwin/Type/_mac_files_for_application
+++ b/Completion/Darwin/Type/_mac_files_for_application
@@ -39,7 +39,7 @@ _mac_files_for_application() {
 
   local app_path
   _retrieve_mac_apps
-  app_path="${_mac_apps[(r)*/$1(|.app)]:-$1}"
+  app_path="${_cache_mac_apps[(r)*/$1(|.app)]:-$1}"
 
   local -a glob_patterns
   glob_patterns=()
diff --git a/Completion/Darwin/Type/_retrieve_mac_apps b/Completion/Darwin/Type/_retrieve_mac_apps
index f24d36c..6fdfa32 100644
--- a/Completion/Darwin/Type/_retrieve_mac_apps
+++ b/Completion/Darwin/Type/_retrieve_mac_apps
@@ -1,6 +1,6 @@
 #autoload
 
-# Find paths of applications and preserve them into _mac_apps.
+# Find paths of applications and preserve them in _cache_mac_apps.
 # Used by _mac_applications and _mac_files_for_application.
 
 _mac_apps_caching_policy () {
@@ -14,14 +14,14 @@ _mac_apps_caching_policy () {
 # _mac_apps_*_retrieve
 # 
 # Get search applications from directories specified in app_dir_root.
-# Paths to applications are stored in _mac_apps.
+# Paths to applications are stored in _cache_mac_apps.
 
 _mac_apps_spotlight_retrieve () {
   typeset mdfind_query="kMDItemContentType == 'com.apple.application-*'"
 
   for i in ${app_dir_root}; do
-    _mac_apps+=(${(f)"$(_call_program command \
-        mdfind -onlyin ${(q)i} ${(q)mdfind_query})"})
+    _cache_mac_apps+=( ${(f)"$(_call_program command \
+        mdfind -onlyin ${(q)i} ${(q)mdfind_query})"} )
   done
 }
 
@@ -43,7 +43,7 @@ _mac_apps_old_retrieve () {
 
   if ! zstyle -t ":completion:${curcontext}:commands" ignore-bundle; then
     app_result=( ${^app_dir}*/Contents/(MacOS|MacOSClassic)(N) )
-    _mac_apps+=( ${app_result[@]%/Contents/MacOS*} )
+    _cache_mac_apps+=( ${app_result[@]%/Contents/MacOS*} )
   fi
 
   # Get single file applications
@@ -54,24 +54,24 @@ _mac_apps_old_retrieve () {
     envvars="$(builtin typeset -x)"
     nargs=$(( $(command sysctl -n kern.argmax) - $#envvars - 2048 ))
     app_result="$(zargs --max-chars $nargs ${app_cand[@]} -- grep -l APPL)"
-    _mac_apps+=( ${${(f)app_result}%/..namedfork/rsrc} )
+    _cache_mac_apps+=( ${${(f)app_result}%/..namedfork/rsrc} )
   fi
 }
 
 
 _retrieve_mac_apps() {
   local cache_policy
-  zstyle -s ":completion:*:*:$service:*" cache-policy cache_policy
+  zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
   if [[ -z "$cache_policy" ]]; then
-    zstyle ":completion:*:*:$service:*" cache-policy _mac_apps_caching_policy
+    zstyle ":completion:${curcontext}:" cache-policy _mac_apps_caching_policy
   fi
 
-  if ( (( ${#_mac_apps} == 0 )) || _cache_invalid Mac_applications ) \
-        && ! _retrieve_cache Mac_applications; then
-
+  if (( ! $+_cache_mac_apps[1] )) && { _cache_invalid mac-applications ||
+      ! _retrieve_cache mac-applications }
+  then
     # Get application search method
     typeset retrieve
-    if ! zstyle -s ":completion:*:*:${service}:commands" search-method retrieve
+    if ! zstyle -s ":completion:${curcontext}:commands" search-method retrieve
     then
       if [[ -d /.Spotlight-V100 ]]; then
         # / is indexed to use Spotlight
@@ -80,7 +80,7 @@ _retrieve_mac_apps() {
         # Fall back to the old way
         retrieve=_mac_apps_old_retrieve 
       fi
-      zstyle ":completion:*:*:${service}:commands" search-method $retrieve
+      zstyle ":completion:${curcontext}:commands" search-method $retrieve
     fi
 
     # Get root directories to search applications
@@ -96,10 +96,10 @@ _retrieve_mac_apps() {
       zstyle ":completion:*" application-path $app_dir_root
     fi
 
-    typeset -g -Ua _mac_apps
+    typeset -g -Ua _cache_mac_apps
     $retrieve
 
-    _store_cache Mac_applications _mac_apps
+    _store_cache mac-applications _cache_mac_apps
   fi
 }
 
diff --git a/Completion/Debian/Command/_dcut b/Completion/Debian/Command/_dcut
index fb1ac7e..28f0dd8 100644
--- a/Completion/Debian/Command/_dcut
+++ b/Completion/Debian/Command/_dcut
@@ -7,21 +7,23 @@
 # be offered. If host is given, the second argument should be completed as
 # command and if not, it should be completed as command specific option.
 
-function _dput_hosts() {
+_dput_hosts() {
   local expl
 
-  if ( [[ ${+_dput_cfhosts} -eq 0 ]] || _cache_invalid dputhosts ) && ! _retrieve_cache dputhosts; then
+  if (( ! $+_cache_dput_cfhosts[1] )) && { _cache_invalid dput-hosts ||
+      ! _retrieve_cache dput-hosts }
+  then
     local cmd
     if _pick_variant dputng="usage: dput" dput -H ; then
-      cmd=(dirt hosts)
+      cmd=( dirt hosts )
     else
-      cmd=(dput -H)
+      cmd=( dput -H )
     fi
-     _dput_cfhosts=(${${(M)${(f)"$($cmd)"}:#*=>*}/ =>*/})
-    _store_cache dputhosts _dput_cfhosts
+    _cache_dput_cfhosts=( ${${(M)${(f)"$(_call_program dput-hosts $cmd)"}:#*=>*}/ =>*/} )
+    _store_cache dput-hosts _cache_dput_cfhosts
   fi
 
-  _wanted dputhosts expl 'target host' compadd -a _dput_cfhosts
+  _wanted dput-hosts expl 'target host' compadd -a _cache_dput_cfhosts
 }
 
 function _dcut_commands() {
diff --git a/Completion/Debian/Command/_dput b/Completion/Debian/Command/_dput
index bf6c2ba..d7765d3 100644
--- a/Completion/Debian/Command/_dput
+++ b/Completion/Debian/Command/_dput
@@ -44,18 +44,20 @@ _dput() {
 _dput_hosts() {
   local expl
 
-  if ( [[ ${+_dput_cfhosts} -eq 0 ]] || _cache_invalid dputhosts ) && ! _retrieve_cache dputhosts; then
+  if (( ! $+_cache_dput_cfhosts[1] )) && { _cache_invalid dput-hosts ||
+      ! _retrieve_cache dput-hosts }
+  then
     local cmd
     if _pick_variant dputng="usage: dput" dput -H ; then
-      cmd=(dirt hosts)
+      cmd=( dirt hosts )
     else
-      cmd=(dput -H)
+      cmd=( dput -H )
     fi
-     _dput_cfhosts=(${${(M)${(f)"$($cmd)"}:#*=>*}/ =>*/})
-    _store_cache dputhosts _dput_cfhosts
+    _cache_dput_cfhosts=( ${${(M)${(f)"$(_call_program dput-hosts $cmd)"}:#*=>*}/ =>*/} )
+    _store_cache dput-hosts _cache_dput_cfhosts
   fi
 
-  _wanted dputhosts expl 'target host' compadd -a _dput_cfhosts
+  _wanted dput-hosts expl 'target host' compadd -a _cache_dput_cfhosts
 }
 
 _dput "$@"
diff --git a/Completion/Debian/Type/_deb_packages b/Completion/Debian/Type/_deb_packages
index bdc0cb0..ae77968 100644
--- a/Completion/Debian/Type/_deb_packages
+++ b/Completion/Debian/Type/_deb_packages
@@ -3,96 +3,89 @@
 # Usage: _deb_packages expl...  (installed|deinstalled|xinstalled|held|uninstalled|avail|available|source)
 
 _deb_packages_update_avail () {
-  if ( [[ ${+_deb_packages_cache_avail} -eq 0 ]] ||
-      _cache_invalid DEBS_avail ) && ! _retrieve_cache DEBS_avail;
+  cachevar=_cache_deb_packages_avail
+  if (( ! $+_cache_deb_packages_avail[1] )) &&
+      { _cache_invalid debs-avail || ! _retrieve_cache debs-avail }
   then
-    _deb_packages_cache_avail=(
-      ${(f)"$(apt-cache --generate pkgnames 2>/dev/null)"}
+    _cache_deb_packages_avail=(
+      ${(f)"$(_call_program packages apt-cache --generate pkgnames)"}
     )
-
-    _store_cache DEBS_avail _deb_packages_cache_avail
+    _store_cache debs-avail $cachevar
   fi
-  cachevar=_deb_packages_cache_avail
 }
 
 _deb_packages_update_installed () {
-  if ( [[ ${+_deb_packages_cache_installed} -eq 0 ]] ||
-      _cache_invalid DEBS_installed ) && ! _retrieve_cache DEBS_installed;
+  cachevar=_cache_deb_packages_installed
+  if (( ! $+_cache_deb_packages_installed[1] )) &&
+      { _cache_invalid debs-installed || ! _retrieve_cache debs-installed }
   then
-    _deb_packages_cache_installed=()
-    dpkg --get-selections | while read package state ; do
-        [[ $state = (install|hold) ]] && _deb_packages_cache_installed+=$package
-    done
-    _store_cache DEBS_installed _deb_packages_cache_installed
+    _cache_deb_packages_installed=(
+      ${${(M)${(f)"$(_call_program packages dpkg --get-selections)"}:#*([^e]install|hold)}%%[[:blank:]]*}
+    )
+    _store_cache debs-installed $cachevar
   fi
-  cachevar=_deb_packages_cache_installed
 }
 
 _deb_packages_update_held () {
-  if ( [[ ${+_deb_packages_cache_held} -eq 0 ]] ||
-      _cache_invalid DEBS_held ) && ! _retrieve_cache DEBS_held;
+  cachevar=_cache_deb_packages_held
+  if (( ! $+_cache_deb_packages_held[1] )) && { _cache_invalid debs-held ||
+      ! _retrieve_cache debs-held }
   then
-    _deb_packages_cache_held=()
-    dpkg --get-selections | while read package state ; do
-        [[ $state = hold ]] && _deb_packages_cache_held+=$package
-    done
-    _store_cache DEBS_held _deb_packages_cache_held
+    _cache_deb_packages_held=(
+      ${${(M)${(f)"$(_call_program packages dpkg --get-selections)"}:#*hold}%%[[:blank:]]*}
+    )
+    _store_cache debs-held $cachevar
   fi
-  cachevar=_deb_packages_cache_held
 }
 
 _deb_packages_update_deinstalled () {
-  if ( [[ ${+_deb_packages_cache_deinstalled} -eq 0 ]] ||
-      _cache_invalid DEBS_deinstalled ) && ! _retrieve_cache DEBS_deinstalled;
+  cachevar=_cache_deb_packages_deinstalled
+  if (( ! $+_cache_deb_packages_deinstalled[1] )) &&
+      { _cache_invalid debs-deinstalled || ! _retrieve_cache debs-deinstalled }
   then
-    _deb_packages_cache_deinstalled=()
-    dpkg --get-selections | while read package state ; do
-        [[ $state = deinstall ]] && _deb_packages_cache_deinstalled+=$package
-    done
-    _store_cache DEBS_deinstalled _deb_packages_cache_deinstalled
+    _cache_deb_packages_deinstalled=(
+      ${${(M)${(f)"$(_call_program packages dpkg --get-selections)"}:#*deinstalled}%%[[:blank:]]*}
+    )
+    _store_cache debs-deinstalled $cachevar
   fi
-  cachevar=_deb_packages_cache_deinstalled
 }
 
 _deb_packages_update_xinstalled () {
-  if ( [[ ${+_deb_packages_cache_xinstalled} -eq 0 ]] ||
-      _cache_invalid DEBS_xinstalled ) && ! _retrieve_cache DEBS_xinstalled;
+  cachevar=_cache_deb_packages_xinstalled
+  if (( ! $+_cache_deb_packages_xinstalled[1] )) &&
+      { _cache_invalid debs-xinstalled || ! _retrieve_cache debs-xinstalled }
   then
-    _deb_packages_cache_xinstalled=()
-    dpkg --get-selections | while read package state ; do
-        _deb_packages_cache_xinstalled+=$package
-    done
-    _store_cache DEBS_xinstalled _deb_packages_cache_xinstalled
+    _cache_deb_packages_xinstalled=(
+      ${${(f)"$(_call_program packages dpkg --get-selections)"}%%[[:blank:]]*}
+    )
+    _store_cache debs-xinstalled $cachevar
   fi
-  cachevar=_deb_packages_cache_xinstalled
 }
 
 _deb_packages_update_uninstalled () {
-  _deb_packages_update_avail
-  _deb_packages_update_installed
-  if (( ! $+_deb_packages_cache_uninstalled )); then
-    # Package lists too large to efficiently diff with zsh expansion
-    _deb_packages_cache_uninstalled=(
-      $( print -l $_deb_packages_cache_avail |
-         fgrep -xvf =(print -l $_deb_packages_cache_installed) )
+  if (( ! $+_cache_deb_packages_uninstalled )); then
+    _deb_packages_update_avail
+    _deb_packages_update_installed
+    _cache_deb_packages_uninstalled=(
+      ${_cache_deb_packages_avail:|_cache_deb_packages_installed}
     )
   fi
-  cachevar=_deb_packages_cache_uninstalled
+  cachevar=_cache_deb_packages_uninstalled
 }
 
 _deb_packages_update_source () {
-  if ( [[ ${+_deb_packages_cache_source} -eq 0 ]] ||
-      _cache_invalid DEBS_source ) && ! _retrieve_cache DEBS_source;
+  cachevar=_cache_deb_packages_source
+  if (( ! $+_cache_deb_packages_source[1] )) &&
+      { _cache_invalid debs-source || ! _retrieve_cache debs-source }
   then
-    _deb_packages_cache_source=(
+    _cache_deb_packages_source=(
       # requires apt >= 1.1.8
       # if dpkg --compare-versions "$(dpkg-query --show --showformat '${Version}\n' apt)" '>=' '1.1.8' ; then ...; else ...; fi
       ${(f)"$(/usr/lib/apt/apt-helper cat-file $(apt-get indextargets --format '$(FILENAME)' 'Created-By: Sources' 2>/dev/null) 2>/dev/null | sed -ne 's/^Package: //p' | uniq)"}
     )
 
-    _store_cache DEBS_source _deb_packages_cache_source
+    _store_cache debs-source $cachevar
   fi
-  cachevar=_deb_packages_cache_source
 }
 
 _deb_packages () {
diff --git a/Completion/Redhat/Command/_rpm b/Completion/Redhat/Command/_rpm
index b24213e..8031dbf 100644
--- a/Completion/Redhat/Command/_rpm
+++ b/Completion/Redhat/Command/_rpm
@@ -234,16 +234,16 @@ _rpm () {
 	  ${${(M)${(f)"$(_call_programs targets rpm --showrc)"}:#compatible archs*}##*: } && ret=0
       ;;
     groups)
-      if ( (( ! $+_rpm_groups )) || _cache_invalid rpm-groups ) &&
-	  ! _retrieve_cache rpm-groups
+      if (( ! $+_cache_rpm_groups[1] )) && { _cache_invalid rpm-groups ||
+	  ! _retrieve_cache rpm-groups }
       then
-	typeset -gaU _rpm_groups
-	_rpm_groups=(
-	    ${(f)"$(_call_program groups rpm -qa --queryformat '%\{group}\\n' 2>/dev/null)"}
+	typeset -gaU _cache_rpm_groups
+	_cache_rpm_groups=(
+	  ${(f)"$(_call_program groups rpm -qa --queryformat '%\{group}\\n')"}
 	)
-	_store_cache RPM-groups _rpm_groups
+	_store_cache rpm-groups _cache_rpm_groups
       fi
-      _wanted groups expl 'group' _multi_parts / _rpm_groups && ret=0
+      _wanted groups expl 'group' _multi_parts / _cache_rpm_groups && ret=0
     ;;
     package_or_file)
       state=package_file
@@ -256,14 +256,14 @@ _rpm () {
       fi
       ;;
     package)
-      if ( [[ ${+_rpms} -eq 0 ]] || _cache_invalid RPMs ) &&
-	 ! _retrieve_cache RPMs;
+      if (( ! $+_cache_rpms[1] )) && { _cache_invalid rpm-packages ||
+	  ! _retrieve_cache rpm-packages }
       then
-	_rpms=( $(_call_program packages rpm -qa 2>/dev/null) )
-	_store_cache RPMs _rpms
+	_cache_rpms=( $(_call_program packages rpm -qa) )
+	_store_cache rpm-packages _cache_rpms
       fi
       _wanted packages expl 'package' \
-	  compadd -M 'r:|-=* r:|=*' - "$_rpms[@]" && ret=0
+	  compadd -M 'r:|-=* r:|=*' -a _cache_rpms && ret=0
       ;;
     spec_files)
       _wanted specfiles expl 'spec file' \
@@ -316,9 +316,9 @@ _rpm () {
 
 # set a sensible default caching policy
 local update_policy
-zstyle -s ":completion:*:*:rpm:*" cache-policy update_policy
+zstyle -s ":completion:${curcontext}:" cache-policy update_policy
 if [[ -z "$update_policy" ]]; then
-  zstyle ":completion:*:*:rpm:*" cache-policy _rpms_caching_policy
+  zstyle ":completion:${curcontext}:" cache-policy _rpms_caching_policy
 fi
 
 _rpms_caching_policy () {
diff --git a/Completion/Solaris/Command/_pkg5 b/Completion/Solaris/Command/_pkg5
index bcd4e3d..b427788 100644
--- a/Completion/Solaris/Command/_pkg5
+++ b/Completion/Solaris/Command/_pkg5
@@ -1,49 +1,53 @@
 #compdef pkg
 
 _pkg5_pkgs() {
-	local cache_policy cache_id=pkg5_installed_pkgs:$HOST:${pkg5_root//\//+}
-	typeset -a -g _pkg5_installed_pkgs
+	local cache_policy cache_id=pkg5-installed-pkgs:$HOST:${pkg5_root//\//+}
+	typeset -a -g _cache_pkg5_installed_pkgs
 
-	zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
+	zstyle -s ":completion:${curcontext}:packages" cache-policy cache_policy
 	if [[ -z "$cache_policy" ]]; then
-		zstyle ":completion:${curcontext}:" cache-policy _pkg5_installed_caching_policy
+		zstyle ":completion:${curcontext}:packages" cache-policy _pkg5_installed_caching_policy
 	fi
 
-	if ( [[ $#_pkg5_installed_pkgs -eq 0 ]] || _cache_invalid $cache_id ) && ! _retrieve_cache $cache_id; then
-		_pkg5_installed_pkgs=( $(
+	if (( ! $+_cache_pkg5_installed_pkgs[1] )) && { _cache_invalid $cache_id ||
+	    ! _retrieve_cache $cache_id }
+	then
+		_cache_pkg5_installed_pkgs=( $(
 			pkg -R $pkg5_root list -H | while read pkg junk; do
 				pkga=( ${(s:/:)pkg} )
 				for i in {1..$#pkga}; do
 					print ${(j:/:)${pkga[$i,-1]}}
 				done
 			done) )
-		_store_cache $cache_id _pkg5_installed_pkgs
+		_store_cache $cache_id _cache_pkg5_installed_pkgs
 	fi
 
-	compadd "$@" - ${_pkg5_installed_pkgs}
+	_wanted packages expl package compadd "$@" -a - _cache_pkg5_installed_pkgs
 }
 
 _pkg5_pkgs_a() {
-	local cache_policy cache_id=pkg5_known_pkgs:$HOST:${pkg5_root//\//+}
-	typeset -a -g _pkg5_known_pkgs
+	local cache_policy cache_id=pkg5-known-pkgs:$HOST:${pkg5_root//\//+}
+	typeset -a -g _cache_pkg5_known_pkgs
 
-	zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
+	zstyle -s ":completion:${curcontext}:packages" cache-policy cache_policy
 	if [[ -z "$cache_policy" ]]; then
-		zstyle ":completion:${curcontext}:" cache-policy _pkg5_known_caching_policy
+		zstyle ":completion:${curcontext}:packages" cache-policy _pkg5_known_caching_policy
 	fi
 
-	if ( [[ $#_pkg5_known_pkgs -eq 0 ]] || _cache_invalid $cache_id ) && ! _retrieve_cache $cache_id; then
-		_pkg5_known_pkgs=( $(
+	if (( ! $+_cache_pkg5_known_pkgs[1] )) && { _cache_invalid $cache_id ||
+	    ! _retrieve_cache $cache_id }
+	then
+		_cache_pkg5_known_pkgs=( $(
 			pkg -R $pkg5_root list -aH --no-refresh | while read pkg junk; do
 				pkga=( ${(s:/:)pkg} )
 				for i in {1..$#pkga}; do
 					print ${(j:/:)${pkga[$i,-1]}}
 				done
 			done) )
-		_store_cache $cache_id _pkg5_known_pkgs
+		_store_cache $cache_id _cache_pkg5_known_pkgs
 	fi
 
-	compadd "$@" - ${_pkg5_known_pkgs}
+	_wanted packages expl package compadd "$@" -a - _cache_pkg5_known_pkgs
 }
 
 _pkg5_avoided_pkgs() {
@@ -130,7 +134,7 @@ _pkg5() {
 			return
 		fi
 		service="$words[1]"
-		curcontext="${curcontext%:*}=$service:"
+		curcontext="${curcontext%:*}-$service:"
 	fi
 
 	pkg5_root=${${${opt_args[-R]}:-$PKG_IMAGE}:-/}
diff --git a/Completion/Solaris/Type/_svcs_fmri b/Completion/Solaris/Type/_svcs_fmri
index 80d3516..19d460d 100644
--- a/Completion/Solaris/Type/_svcs_fmri
+++ b/Completion/Solaris/Type/_svcs_fmri
@@ -3,12 +3,12 @@
 _svcs_fmri() {
 	local type="$argv[$#]"
 	local fmri_abbrevs m i
-	typeset -a -g _smf_fmris
+	typeset -a -g _cache_smf_fmris
 
 	local update_policy
-	zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+	zstyle -s ":completion:${curcontext}:fmri" cache-policy update_policy
 	if [[ -z "$update_policy" ]]; then
-		zstyle ":completion:${curcontext}:" cache-policy _smf_caching_policy
+		zstyle ":completion:${curcontext}:fmri" cache-policy _smf_caching_policy
 	fi
 	# The cache really must be per-host
 	local cache_id=smf_fmri:$HOST
@@ -22,14 +22,15 @@ _svcs_fmri() {
 		# Grab all FMRIs that have a word beginning with $PREFIX,
 		# making sure not to return the portion of the FMRI before
 		# $PREFIX.  Use the cache if it exists and the user wants to.
-		if ( [[ $#_smf_fmris -eq 0 ]] || _cache_invalid $cache_id ) \
-			&& ! _retrieve_cache $cache_id; then
-			_smf_fmris=( ${(f)"$(svcs -a -H -o fmri)"} )
-			_store_cache $cache_id _smf_fmris
+		if (( ! $+_cache_smf_fmris[1] )) && { _cache_invalid $cache_id ||
+		    ! _retrieve_cache $cache_id }
+	        then
+			_cache_smf_fmris=( ${(f)"$(_call_program fmris svcs -a -H -o fmri)"} )
+			_store_cache $cache_id _cache_smf_fmris
 		fi
 		# Each element of the array is removed which doesn't match
 		# (^|.*/)$PREFIX.*
-		fmri_abbrevs=( ${(M)_smf_fmris:#((#s)|*[/:])$PREFIX*} )
+		fmri_abbrevs=( ${(M)_cache_smf_fmris:#((#s)|*[/:])$PREFIX*} )
 
 		# Go through the remaining elements and remove the characters
 		# in front of $PREFIX.
diff --git a/Completion/Unix/Command/_bogofilter b/Completion/Unix/Command/_bogofilter
index ff36e83..7a98395 100644
--- a/Completion/Unix/Command/_bogofilter
+++ b/Completion/Unix/Command/_bogofilter
@@ -49,20 +49,23 @@ _bogoutil() {
 	"($_bogoutil_actions)"{-V,--version}'[version]' \
   	'*:tokens:->tokens' && ret=0
 
-  zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+  zstyle -s ":completion:${curcontext}:tokens" cache-policy update_policy
   if [[ -z "$update_policy" ]]; then
-    zstyle ":completion:${curcontext}:" cache-policy _bogoutil_caching_policy
+    zstyle ":completion:${curcontext}:tokens" cache-policy _bogoutil_caching_policy
   fi
 
   case $state in
-  	(tokens)
-  	if ( [[ -z "$bogotokens" ]] || _cache_invalid bogotokens ) &&
-  	  ! _retrieve_cache bogotokens; then
-          bogotokens=(${${(f)"$(_call_program bogotokens bogoutil -d ~/.bogofilter/wordlist.db -c 50)"}%% *})
-  	  _store_cache bogotokens bogotokens
-  	fi
-          _wanted tokens expl "token" compadd -a bogotokens && ret=0
-  	;;
+    (tokens)
+      if (( ! $+_cache_bogotokens[1] )) && { _cache_invalid bogotokens ||
+	  ! _retrieve_cache bogotokens }
+      then
+	_cache_bogotokens=(
+	  ${${(f)"$(_call_program bogotokens bogoutil -d ~/.bogofilter/wordlist.db -c 50)"}%% *}
+	)
+	_store_cache bogotokens _cache_bogotokens
+      fi
+      _wanted tokens expl "token" compadd -a _cache_bogotokens && ret=0
+    ;;
   esac
 
   return ret
diff --git a/Completion/Unix/Type/_path_commands b/Completion/Unix/Type/_path_commands
index 66795ae..2e1976a 100644
--- a/Completion/Unix/Type/_path_commands
+++ b/Completion/Unix/Type/_path_commands
@@ -3,61 +3,63 @@
 (( $+functions[_path_commands_caching_policy] )) ||
 _path_commands_caching_policy() {
 
-local file
-local -a oldp dbfiles
+local file ret=0
+local -a oldp dbdirs
 
 # rebuild if cache is more than a week old
 oldp=( "$1"(Nmw+1) )
 (( $#oldp )) && return 0
 
-dbfiles=(/usr/share/man/index.(bt|db|dir|pag)(N) \
-  /usr/man/index.(bt|db|dir|pag)(N) \
-  /var/cache/man/index.(bt|db|dir|pag)(N) \
-  /var/catman/index.(bt|db|dir|pag)(N) \
-  /usr/share/man/*/whatis(N))
-
-for file in $dbfiles; do
+dbdirs=( $manpath /usr/share/man /usr/man /var/cache/man /var/catman{,/man} /usr/share/man/(^man*)(N) )
+for file in $dbdirs/(windex|whatis|index.(bt|db|dir|pag))(N); do
   [[ $file -nt $1 ]] && return 0
+  ret=1
 done
 
-return 1
+return ret
 }
 
 _call_whatis() { 
-  case "$(whatis --version)" in
-  ("whatis from "*)
-    local -A args
-    zparseopts -D -A args s: r:
-    apropos "${args[-r]:-"$@"}" | fgrep "($args[-s]"
-    ;;
-  (*) whatis "$@";;
+  case "$OSTYPE:$(whatis --version)" in
+  (solaris*)
+    apropos -s 1 | tr -s $'\t ' ' ' | cut -d ' ' -f 1,3-
+  ;;
+  (freebsd*) ;&
+  (*:"whatis from "*)
+    apropos '.*' | grep "([16]"
+  ;;
+  (*)
+    whatis -s 1 -r '.*'
+    whatis -s 6 -r '.*'
+  ;;
   esac
 }
 
 _path_commands() {
 local need_desc expl ret=1
 
-if zstyle -t ":completion:${curcontext}:" extra-verbose; then
+if zstyle -t ":completion:${curcontext}:commands" extra-verbose; then
   local update_policy first
-  if [[ $+_command_descriptions -eq 0 ]]; then
+  if (( ! $+_cache_command_descriptions )); then
     first=yes
-    typeset -A -g _command_descriptions
+    typeset -A -g _cache_command_descriptions
   fi
-  zstyle -s ":completion:${curcontext}:" cache-policy update_policy
-  [[ -z "$update_policy" ]] && zstyle ":completion:${curcontext}:" \
+  zstyle -s ":completion:${curcontext}:commands" cache-policy update_policy
+  [[ -z "$update_policy" ]] && zstyle ":completion:${curcontext}:commands" \
     cache-policy _path_commands_caching_policy
-  if ( [[ -n $first ]] || _cache_invalid command-descriptions ) && \
-    ! _retrieve_cache command-descriptions; then
+  if [[ -n $first ]] && { _cache_invalid command-descriptions ||
+      ! _retrieve_cache command-descriptions }
+  then
     local line
-    for line in "${(f)$(_call_program command-descriptions _call_whatis -s 1 -r .\\\*\; _call_whatis -s 6 -r .\\\* 2>/dev/null)}"; do
+    for line in "${(f)$(_call_program command-descriptions _call_whatis)}"; do
       [[ -n ${line:#(#b)([^ ]#) #\([^ ]#\)( #\[[^ ]#\]|)[ -]#(*)} ]] && continue;
       [[ -z $match[1] || -z $match[3] || -z ${${match[1]}:#*:*} ]] && continue;
-      _command_descriptions[$match[1]]=$match[3]
+      _cache_command_descriptions[$match[1]]=$match[3]
     done
-    _store_cache command-descriptions _command_descriptions
+    _store_cache command-descriptions _cache_command_descriptions
   fi
 
-  (( $#_command_descriptions )) && need_desc=yes
+  (( $+_cache_command_descriptions )) && need_desc=yes
 fi
 
 if [[ -n $need_desc ]]; then
@@ -65,7 +67,7 @@ if [[ -n $need_desc ]]; then
   local desc cmd sep
   compadd "$@" -O matches -k commands
   for cmd in $matches; do
-    desc=$_command_descriptions[$cmd]
+    desc=$_cache_command_descriptions[$cmd]
     if [[ -z $desc ]]; then
       cmds+=$cmd
     else
@@ -73,7 +75,7 @@ if [[ -n $need_desc ]]; then
       descs+="$cmd:$desc"
     fi
   done
-  zstyle -s ":completion:${curcontext}:" list-separator sep || sep=--
+  zstyle -s ":completion:${curcontext}:commands" list-separator sep || sep=--
   zformat -a descs " $sep " $descs
   descs=("${(@r:COLUMNS-1:)descs}")
   _wanted commands expl 'external command' \
@@ -98,7 +100,7 @@ if [[ -o path_dirs ]]; then
   fi
 fi
 
-return $ret
+return ret
 }
 
 _path_commands "$@"
diff --git a/Completion/Unix/Type/_perl_modules b/Completion/Unix/Type/_perl_modules
index d27a7f7..0ecce8d 100644
--- a/Completion/Unix/Type/_perl_modules
+++ b/Completion/Unix/Type/_perl_modules
@@ -39,9 +39,9 @@ _perl_modules () {
   local update_policy sufpat=".pm" with_pod
   local restrict_hierarchy=''
   local -i strip_perl_prefix
-  zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+  zstyle -s ":completion:${curcontext}:modules" cache-policy update_policy
   if [[ -z "$update_policy" ]]; then
-    zstyle ":completion:${curcontext}:" cache-policy \
+    zstyle ":completion:${curcontext}:modules" cache-policy \
       _perl_modules_caching_policy
   fi
 
@@ -71,11 +71,11 @@ _perl_modules () {
     perl_modules=_unknown_perl_modules$with_pod
   fi
 
-  if ( [[ ${(P)+perl_modules} -eq 0 ]] || _cache_invalid ${perl_modules#_} ) &&
-     ! _retrieve_cache ${perl_modules#_};
+  if [[ ${(P)+perl_modules} -eq 0 ]] && { _cache_invalid ${perl_modules#_} ||
+      ! _retrieve_cache ${perl_modules#_} }
   then
     if zstyle -t ":completion:${curcontext}:modules" try-to-use-pminst &&
-       (( ${+commands[pminst]} ));
+        (( ${+commands[pminst]} ))
     then
       set -A $perl_modules $(pminst)
     else
diff --git a/Completion/Unix/Type/_python_modules b/Completion/Unix/Type/_python_modules
index e82f8ef..9404bfe 100644
--- a/Completion/Unix/Type/_python_modules
+++ b/Completion/Unix/Type/_python_modules
@@ -16,27 +16,26 @@ _python_modules () {
     (*)       python="python" ;;
   esac
   local cache_id=${${python//[^[:alnum:]]/_}#_}_modules
-  local array_name=_${cache_id}
+  local array_name=_cache_${cache_id}
 
-  zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+  zstyle -s ":completion:${curcontext}:modules" cache-policy update_policy
   [[ -z "$update_policy" ]] && \
-    zstyle ":completion:${curcontext}:" \
+    zstyle ":completion:${curcontext}:modules" \
       cache-policy _python_module_caching_policy
 
-  if ( [[ ${(P)+array_name} -eq 0 ]] || _cache_invalid $cache_id ) &&
-      ! _retrieve_cache $cache_id; then
-
-   local script='import pkgutil
+  if [[ ${(P)+array_name} -eq 0 ]] && { _cache_invalid $cache_id ||
+      ! _retrieve_cache $cache_id }
+  then
+    local script='import pkgutil
 for importer, name, ispkg in pkgutil.iter_modules(): print(name)'
 
     typeset -agU $array_name
-    set -A $array_name \
-      $(_call_program modules $python -c ${(q)script} 2>/dev/null)
+    set -A $array_name $(_call_program modules $python -c ${(q)script})
 
     _store_cache $cache_id $array_name
   fi
 
-  _wanted modules expl module compadd "$@" -a -- $array_name
+  _wanted modules expl module compadd "$@" -a - $array_name
 }
 
 _python_modules "$@"
diff --git a/Completion/openSUSE/Command/_zypper b/Completion/openSUSE/Command/_zypper
index 25a32c3..cd3f411 100644
--- a/Completion/openSUSE/Command/_zypper
+++ b/Completion/openSUSE/Command/_zypper
@@ -15,24 +15,20 @@
 #
 # Main dispatcher
 
-function _zypper_caching_policy () {
-    # rebuild if zsh's cache is older than zypper's
-    if test /var/cache/zypp/raw -nt "$1"; then
-        return 0
-    else
-        return 1
-    fi
+_zypper_caching_policy() {
+    # rebuild if cache is absent or older than zypper's
+    [[ ! /var/cache/zypp/raw -ot "$1" ]]
 }
 
 _zypper() {
     typeset -A opt_args
-    local context curcontext="$curcontext" state line
+    local curcontext="$curcontext"
 
     if (( CURRENT > 2 )) && [[ ${words[2]} != "help" ]]; then
         # Remember the subcommand name
         local cmd=${words[2]}
         # Set the context for the subcommand.
-        curcontext="${curcontext%:*:*}:zypper-subcommand"
+        curcontext="${curcontext%:*:*}:zypper-$cmd"
         # Narrow the range of words we are looking at to exclude `zypper'
         (( CURRENT-- ))
         shift words
@@ -65,26 +61,25 @@ _zypper() {
 _all_repos() {
     local -a repos
     repos=( $(zypper -q lr | tail -n +3 | cut -d'|' -f 2) )
-    _describe -t repos 'Available repositories' repos && return
+    _describe -t repos 'available repository' repos && return
 }
 
 _enabled_repos() {
     repos=( $(zypper -x lr | grep 'enabled="1"' | cut -d\" -f 2) )
-    _describe -t repos 'Available repositories' repos && return
+    _describe -t repos 'available repository' repos && return
 }
 
 _disabled_repos() {
     repos=( $(zypper -x lr | grep 'enabled="0"' | cut -d\" -f 2) )
-    _describe -t repos 'Available repositories' repos && return
+    _describe -t repos 'available repository' repos && return
 }
 
 _zypper_cmd_do() {
     typeset -A opt_args
-    local context state line
+    local expl
     local hline
     local -a cmdlist
     local tag=0
-    local curcontext="$curcontext"
 
     zstyle ":completion:${curcontext}:" use-cache on
     zstyle ":completion:${curcontext}:" cache-policy _zypper_caching_policy
@@ -107,7 +102,7 @@ _zypper_cmd_do() {
         case ${words[CURRENT - 1]} in
             --from)
                 repos=( $(zypper -x lr | grep 'enabled="1"' | cut -d\" -f 2) )
-                _describe -t repos 'Available repositories' repos && return
+                _describe -t repos 'available repository' repos && return
                ;;
             (--enable|-e)
                 case $cmd in
@@ -128,7 +123,7 @@ _zypper_cmd_do() {
                 case $cmd in
                     (if|info|se|search|in|install) 
                         types=( pattern srcpackage package patch )
-                        _describe -t types 'Package types' types && return
+                        _describe -t types 'package type' types && return
                     ;;
                 esac
                 ;;
@@ -142,9 +137,8 @@ _zypper_cmd_do() {
                 _all_repos
                 ;;
             (in|install)
-                local expl
                 _description files expl 'RPM files' 
-                _files "$expl[@]" -g '*.(#i)rpm(.)'
+                _files "$expl[@]" -g '*.(#i)rpm(-.)'
                 ;;
         esac
         
@@ -152,27 +146,29 @@ _zypper_cmd_do() {
         if [[ ${words[CURRENT]} =~ "^[0-9a-zA-Z]" ]] ; then
           local -a pkglist
 
-          if ( [[ ${+_zypp_all_raw} -eq 0 ]] || _cache_invalid ZYPPER_ALL_RAW ) && ! _retrieve_cache ZYPPER_ALL_RAW;
+	  if (( ! $+_cache_zypp_all_raw[1] )) && { _cache_invalid zypper-all-raw ||
+	      ! _retrieve_cache zypper-all-raw }
           then
-              _zypp_all_raw=$(zypper -x -q se | grep '<solvable' | cut -d \" -f 2,4)
-              _zypp_all=( $(echo $_zypp_all_raw | grep 'installed' | cut -d\" -f 2) )
-              _zypp_not_installed=( $(echo $_zypp_all_raw | grep 'not-installed' | cut -d\" -f 2 ) )
-              _zypp_installed=( $(echo $_zypp_all_raw | grep '^installed' | cut -d\" -f 2 ) )
-              _store_cache ZYPPER_ALL_RAW _zypp_all_raw _zypp_all _zypp_not_installed _zypp_installed
+              _cache_zypp_all_raw=$(zypper -x -q se | grep '<solvable' | cut -d \" -f 2,4)
+              _cache_zypp_all=( $(echo $_zypp_all_raw | grep 'installed' | cut -d\" -f 2) )
+              _cache_zypp_not_installed=( $(echo $_zypp_all_raw | grep 'not-installed' | cut -d\" -f 2 ) )
+              _cache_zypp_installed=( $(echo $_zypp_all_raw | grep '^installed' | cut -d\" -f 2 ) )
+              _store_cache zypper-all-raw _cache_zypp_all_raw _cache_zypp_all \
+		  _cache_zypp_not_installed _cache_zypp_installed
           fi
 
           case $cmd in
               (in|install)
-                  pkglist=( $_zypp_not_installed )
-                  compadd $pkglist && return
+                  pkglist=( $_cache_zypp_not_installed )
+                  _wanted packaged expl package compadd -a pkglist
                   ;;
               (rm|remove|up|update)
-                  pkglist=( $_zypp_installed )
-                  compadd $pkglist && return
+                  pkglist=( $_cache_zypp_installed )
+                  compadd -a pkglist
                   ;;
               (if|info|se|search)
-                  pkglist=( $_zypp_all )
-                  compadd $pkglist && return
+                  pkglist=( $_cache_zypp_all )
+                  compadd -a pkglist
                   ;;
           esac
         fi


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-13 10:10               ` Oliver Kiddle
@ 2016-12-13 16:18                 ` Jun T.
  2016-12-13 17:21                   ` Bart Schaefer
  2016-12-13 16:38                 ` caching mechanism and Re: PATCH Completion for _yum Bart Schaefer
  1 sibling, 1 reply; 19+ messages in thread
From: Jun T. @ 2016-12-13 16:18 UTC (permalink / raw)
  To: zsh-workers


2016/12/13 19:10, Oliver Kiddle <okiddle@yahoo.co.uk> wrote:

>>  if ( [[ ${+_dput_cfhosts} -eq 0 ]] || _cache_invalid dputhosts ) && ! _retrieve_cache dputhosts; then
>> - which makes no sense to me.
> 
> I went through correcting other cases of this particular broken logic.
> Substituting instead this logic:
>  if (( ! $+_dput_cfhosts[1] )) && { _cache_invalid dputhosts ||
>      ! _retrieve_cache dputhosts }

I guess what is intended by the original code is to be sure to regenerate
the data if the cache is invalid, even if the variable _dput_cfhosts
already exists in the current zsh.

But,

> Whether we want to be keeping caches also in a global variable is a
> different question

keeping the data in a variable may not be a good idea.
Suppose one zsh (zsh-A), which is still running, has created a cache long
time ago (and the cache is now invalid). If another zsh refreshes the cache,
zsh-A will not refresh its _dput_cfhosts next time it needs it, since the
cache is now valid.



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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-13 10:10               ` Oliver Kiddle
  2016-12-13 16:18                 ` Jun T.
@ 2016-12-13 16:38                 ` Bart Schaefer
  1 sibling, 0 replies; 19+ messages in thread
From: Bart Schaefer @ 2016-12-13 16:38 UTC (permalink / raw)
  To: Zsh workers

On Dec 13, 11:10am, Oliver Kiddle wrote:
}
} I'm also not keen on the functions setting a zstyle for the
} default cache policy. Couldn't the default just be a parameter
} to _cache_invalid? Some of the style lookups eschewed $curcontext so it
} is not making it easier to use right.

Using $curcontext would end up meaning that there are different copies
of the cache for different paths into the completion.  That's probably
not what's intended.

} The naming convention for these policy functions also doesn't help
} people to get the sense of the return status right. How about something
} like _finkpkgs_cache_stale instead of _finkpkgs_caching_policy?

To be honest I've always thought that the design of the caching system
was unnecessarily convoluted.  It's trying to be object-oriented and
template-like and probably mirrors something that was originally done
in another language in another context.  (Adam isn't still hanging
around here, is he?)

(This is somewhat ironic considering that the patch which proposed
the cache says "I think you'll agree the interface is very simple."
Two rounds of discussion with Sven W. later, ...)

It was also probably not the best idea to put the caching functions
in the doc in alphabetical order (or else they should have all been
named with _cache at the start instead of at the end); they should
have been in their own section with some explanation of the gestalt.


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-13 16:18                 ` Jun T.
@ 2016-12-13 17:21                   ` Bart Schaefer
  2016-12-14 11:38                     ` Oliver Kiddle
  0 siblings, 1 reply; 19+ messages in thread
From: Bart Schaefer @ 2016-12-13 17:21 UTC (permalink / raw)
  To: zsh-workers

On Dec 14,  1:18am, Jun T. wrote:
}
} I guess what is intended by the original code is to be sure to regenerate
} the data if the cache is invalid, even if the variable _dput_cfhosts
} already exists in the current zsh.

Yes, that's almost certainly the case.

} > Whether we want to be keeping caches also in a global variable is a
} > different question
} 
} keeping the data in a variable may not be a good idea.

Some sort of cross-session synchronization would be needed to do this in
a foolproof way.  Hmm, another thing Sebastian was working on recently.

Here's the original message that started all of this:

http://www.zsh.org/mla/workers/1999/msg02907.html

Followed by several messages in 2000 which unfortunately aren't all
linked in the same archive thread but all of which have "caching" in
the subject.

I don't think we've been consistent about using *this* caching mechanism
for doing the intended sort of caching across all completions.  Various
completions put stuff directly into their own global variables, IIRC.


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-13 17:21                   ` Bart Schaefer
@ 2016-12-14 11:38                     ` Oliver Kiddle
  2016-12-14 14:23                       ` Jun T.
  0 siblings, 1 reply; 19+ messages in thread
From: Oliver Kiddle @ 2016-12-14 11:38 UTC (permalink / raw)
  To: zsh-workers

"Jun T." wrote:

> >>  if ( [[ ${+_dput_cfhosts} -eq 0 ]] || _cache_invalid dputhosts ) &&
> >>  ! _retrieve_cache dputhosts; then
> >> - which makes no sense to me.

> I guess what is intended by the original code is to be sure to
> regenerate
> the data if the cache is invalid, even if the variable _dput_cfhosts
> already exists in the current zsh.

That's not what that logic does though. Simplify the line to
  if ( blah blah... ) && ! _retrieve_cache dputhosts

and you will see that it only regenerates the cache if _retrieve_cache
fails. In practice the effect is that no cache is ever considered stale.

> > Whether we want to be keeping caches also in a global variable is a
> > different question

> keeping the data in a variable may not be a good idea.

I'm uneasy about it either way. What about someone who wants to set
use-cache to false? It also seems a pity not to keep the variable
between _complete and various runs of _correct/_approximate. Perhaps
_retrieve_cache could install something in comppostfuncs to clear
them. Or it could track them in an associative array with a snapshot
of $SECONDS and expire old ones before adding new ones to limit memory
usage.

Also note that we widely cache completion data in variables without
using the _store_cache mechanism. A search for typeset\ -g will give you
some idea.

Bart wrote:
> Using $curcontext would end up meaning that there are different copies
> of the cache for different paths into the completion.  That's probably
> not what's intended.

No, there's only ever one copy of the cache. There might be different
policies for different contexts (and multiple policy zstyles all
specifying the same default). Someone might want to force an update
for yum remove but accept an old cache for yum info.

> To be honest I've always thought that the design of the caching system
> was unnecessarily convoluted.  It's trying to be object-oriented and

Never much liked it myself, either. And I've tended to ignore it for
functions I've written. It often seems like overkill - only applicable if
regenerating the cache really takes a noticable amount of time.

> the cache says "I think you'll agree the interface is very simple."
> Two rounds of discussion with Sven W. later, ...)

After the initial part of suggesting things be configurable with styles,
it looks like Sven tried to suggest simplifications, specifically:

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

Adam's argument against this comes in 12499 but, with reference to a
current _perl_modules, I'm not sure I buy the argument. Even if it has
validity we should be able to allow the common case to be as simple as
Sven suggests.

Sven also stated:
      We decided some time ago that they [completion functions]
      shouldn't set styles themselves, only look them up.

That was apparently ignored.

How about we fold the zstyle lookup into _retrieve_cache and add options
for specifying a default policy and the tag? Use of _cache_invalid could
be deprecated though with some care to allow old usage to still work.
A function for the policy is often not the simplest thing either. How
about allowing a reference file or age or ... ? So usage:

_retrieve_cache [ -t tag ] -p policy_func | -f file | -a age cache_key var...

The lack of a policy would be supported only for backward compatibility.

The cache-policy style would need extending to cover files an ages.
That's a bit messy but a prefix of / o + in the style value could serve
that purpose.

I'd also suggest adopting a _cache_ prefix on all the variables. Should
we perhaps even enforce that in some way?

Another option would be to deprecate the old mechanism completely?

Oliver


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-14 11:38                     ` Oliver Kiddle
@ 2016-12-14 14:23                       ` Jun T.
  2016-12-14 15:03                         ` Oliver Kiddle
  0 siblings, 1 reply; 19+ messages in thread
From: Jun T. @ 2016-12-14 14:23 UTC (permalink / raw)
  To: zsh-workers


2016/12/14 20:38, Oliver Kiddle <okiddle@yahoo.co.uk> wrote:

> "Jun T." wrote:
> 
>>>> if ( [[ ${+_dput_cfhosts} -eq 0 ]] || _cache_invalid dputhosts ) &&
>>>> ! _retrieve_cache dputhosts; then
>>>> - which makes no sense to me.
> 
>> I guess what is intended by the original code is to be sure to
>> regenerate
>> the data if the cache is invalid, even if the variable _dput_cfhosts
>> already exists in the current zsh.
> 
> That's not what that logic does though. Simplify the line to
>  if ( blah blah... ) && ! _retrieve_cache dputhosts
> 
> and you will see that it only regenerates the cache if _retrieve_cache
> fails. In practice the effect is that no cache is ever considered stale.

E = _dput_cfhosts exists
I = _cache_invalid
R = _retrieve_cache

orig = (!E or I) and !R
new  = !E and (I or !R)

!E I !R  orig  new
T  T  T   T     T
T  T  F   F     T   (1)
T  F  T   T     T
T  F  F   F     F
F  T  T   T     F   (2)
F  T  F   F     F
F  F  T   F     F
F  F  F   F     F

If _cache_invalid returns 0, then _retrieve_cache should return 1
(we can't retrieve from an invalid cache, unless another zsh has
refreshed the cache between the two calls).
So the case (1) above is impossible, and the only difference is the
case (2), i.e., _dput_cfhosts exists but cache is invalid (and
_retrieve_cache returns 1).


Jun


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-14 14:23                       ` Jun T.
@ 2016-12-14 15:03                         ` Oliver Kiddle
  2016-12-14 15:23                           ` Jun T.
  0 siblings, 1 reply; 19+ messages in thread
From: Oliver Kiddle @ 2016-12-14 15:03 UTC (permalink / raw)
  To: zsh-workers

"Jun T." wrote:
>
> If _cache_invalid returns 0, then _retrieve_cache should return 1
> (we can't retrieve from an invalid cache, unless another zsh has

_cache_invalid returning 0 implies that the cache has been deemed stale
not that it is invalid. So _retrieve_cache will happily use it and
return 0.

This also bears out in practice: _yum was never updating its cache.

"invalid" is a poor choice of name for it - so another reason why I
wouldn't mind getting rid of it.

Oliver


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-14 15:03                         ` Oliver Kiddle
@ 2016-12-14 15:23                           ` Jun T.
  2016-12-14 17:46                             ` Oliver Kiddle
  0 siblings, 1 reply; 19+ messages in thread
From: Jun T. @ 2016-12-14 15:23 UTC (permalink / raw)
  To: zsh-workers


2016/12/15 00:03, Oliver Kiddle <okiddle@yahoo.co.uk> wrote:

> "Jun T." wrote:
>> 
>> If _cache_invalid returns 0, then _retrieve_cache should return 1
>> (we can't retrieve from an invalid cache, unless another zsh has
> 
> _cache_invalid returning 0 implies that the cache has been deemed stale
> not that it is invalid. So _retrieve_cache will happily use it and
> return 0.

_retrieve_cache, line 21:

    _cache_invalid "$_cache_ident" && return 1


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-14 15:23                           ` Jun T.
@ 2016-12-14 17:46                             ` Oliver Kiddle
  2016-12-14 20:09                               ` Bart Schaefer
  2016-12-15  9:38                               ` Peter Stephenson
  0 siblings, 2 replies; 19+ messages in thread
From: Oliver Kiddle @ 2016-12-14 17:46 UTC (permalink / raw)
  To: zsh-workers

"Jun T." wrote:
>
> _retrieve_cache, line 21:
>     _cache_invalid "$_cache_ident" && return 1

Hmm. I wonder why I had problems with _yum then. Probably isn't worth
spending more time on that aspect of it. I should've pointed out that I'm
happy for a stale cache to cause a variable based cache to be discarded
if that's what you're basically arguing for...
.. just as long as it doesn't involve a difficult to understand conditional
expression that needs repeating in lots of functions.

So, any thoughts on the more important questions that follow later in 40181?

I had held 40173 back anyway. (is printf - warranting a 5.3.1 by the way?) 

Oliver


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-14 17:46                             ` Oliver Kiddle
@ 2016-12-14 20:09                               ` Bart Schaefer
  2016-12-15  9:38                               ` Peter Stephenson
  1 sibling, 0 replies; 19+ messages in thread
From: Bart Schaefer @ 2016-12-14 20:09 UTC (permalink / raw)
  To: zsh-workers

On Dec 14, 12:38pm, Oliver Kiddle wrote:
}
} > > Whether we want to be keeping caches also in a global variable is a
} > > different question
} 
} > keeping the data in a variable may not be a good idea.
} 
} I'm uneasy about it either way. What about someone who wants to set
} use-cache to false? It also seems a pity not to keep the variable
} between _complete and various runs of _correct/_approximate.

Well, the point of it being a global is that it *is* kept, not just
between _complete and others, but for the whole shell session, unless
overwritten by _retrieve_cache, which should only happen if the cache
is invalid.

The basic idea -- take any variable the caller wants, and stuff its
value in a file in a quickly-reloadable format -- is a good one; I
just think the way the styles are used to configure it is a lot more
convoluted than necessary.

} Sven also stated:
}       We decided some time ago that they [completion functions]
}       shouldn't set styles themselves, only look them up.
} 
} That was apparently ignored.

There are a couple of cases where it's more convenient to do a test-
and-set of a style rather than having to repeat the default values in
multiple places, if you know the order in which the style calls will
be made.  But I would say that normally that should happen only in the
circumstance where an autoload file is first setting the style and
then redefining its own function, so the setting happens only once.

} Another option would be to deprecate the old mechanism completely?

I've no problem with that, either -- though more recently a lot of
work was put into making the cache file write/read as fast as possible,
so it would be nice to preserve that.


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

* Re: caching mechanism and Re: PATCH Completion for _yum
  2016-12-14 17:46                             ` Oliver Kiddle
  2016-12-14 20:09                               ` Bart Schaefer
@ 2016-12-15  9:38                               ` Peter Stephenson
  2016-12-15 17:15                                 ` Before 5.3.1 (was Re: caching mechanism and Re: PATCH Completion for _yum) Bart Schaefer
  1 sibling, 1 reply; 19+ messages in thread
From: Peter Stephenson @ 2016-12-15  9:38 UTC (permalink / raw)
  To: zsh-workers

On Wed, 14 Dec 2016 18:46:41 +0100
Oliver Kiddle <okiddle@yahoo.co.uk> wrote:
> I had held 40173 back anyway. (is printf - warranting a 5.3.1 by the way?) 

We haven't had any big changes, so I can probably produce a 5.3.1 this
weekend; if I start waiting for other things it's going to drift on to
the point where it becomes less useful as a quick update.

pws


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

* Before 5.3.1 (was Re: caching mechanism and Re: PATCH Completion for _yum)
  2016-12-15  9:38                               ` Peter Stephenson
@ 2016-12-15 17:15                                 ` Bart Schaefer
  0 siblings, 0 replies; 19+ messages in thread
From: Bart Schaefer @ 2016-12-15 17:15 UTC (permalink / raw)
  To: zsh-workers

On Dec 15,  9:38am, Peter Stephenson wrote:
} Subject: Re: caching mechanism and Re: PATCH Completion for _yum
}
} On Wed, 14 Dec 2016 18:46:41 +0100
} Oliver Kiddle <okiddle@yahoo.co.uk> wrote:
} > I had held 40173 back anyway. (is printf - warranting a 5.3.1 by the way?) 
} 
} We haven't had any big changes, so I can probably produce a 5.3.1 this
} weekend; if I start waiting for other things it's going to drift on to
} the point where it becomes less useful as a quick update.

I'll commit the following just to make Ray happy:


diff --git a/Test/V10private.ztst b/Test/V10private.ztst
index 7ebf5a8..78ecd48 100644
--- a/Test/V10private.ztst
+++ b/Test/V10private.ztst
@@ -15,11 +15,6 @@
  (zmodload -u zsh/param/private && zmodload zsh/param/private)
 0:unload and reload the module without crashing
 
- ZTST_verbose=0 $ZTST_exe +Z -f $ZTST_srcdir/ztst.zsh private.TMP/B02
-0:typeset still works with zsh/param/private module loaded
-*>*
-*>*
-
  typeset scalar_test=toplevel
  () {
   print $scalar_test
@@ -295,6 +290,15 @@ F:future revision will create a global with this assignment
  () { private -h SECONDS }
 0:private parameter may hide a special parameter
 
+ if (( UID )); then
+   ZTST_verbose=0 $ZTST_exe +Z -f $ZTST_srcdir/ztst.zsh private.TMP/B02
+ else
+   ZTST_skip="cannot re-run typeset tests when tests run as superuser"
+ fi
+0:typeset still works with zsh/param/private module loaded
+*>*
+*>*
+
 %clean
 
   rm -r private.TMP

-- 
Barton E. Schaefer


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

end of thread, other threads:[~2016-12-15 17:15 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-26 17:37 PATCH Completion for _yum (contains FIXMEs) Paul Seyfert
2016-10-27  1:30 ` Daniel Shahaf
2016-10-31 12:09   ` Paul Seyfert
2016-11-10 10:18     ` Paul Seyfert
2016-11-10 15:49       ` Oliver Kiddle
2016-11-12  0:19         ` PATCH Completion for _yum Paul Seyfert
     [not found]           ` <31607.1478915523@hydra.kiddle.eu>
2016-11-22 19:05             ` caching mechanism and " Oliver Kiddle
2016-12-13 10:10               ` Oliver Kiddle
2016-12-13 16:18                 ` Jun T.
2016-12-13 17:21                   ` Bart Schaefer
2016-12-14 11:38                     ` Oliver Kiddle
2016-12-14 14:23                       ` Jun T.
2016-12-14 15:03                         ` Oliver Kiddle
2016-12-14 15:23                           ` Jun T.
2016-12-14 17:46                             ` Oliver Kiddle
2016-12-14 20:09                               ` Bart Schaefer
2016-12-15  9:38                               ` Peter Stephenson
2016-12-15 17:15                                 ` Before 5.3.1 (was Re: caching mechanism and Re: PATCH Completion for _yum) Bart Schaefer
2016-12-13 16:38                 ` caching mechanism and Re: PATCH Completion for _yum Bart Schaefer

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).