Subject: PATCH: update BSD completions
From: Oliver Kiddle <[email-masked]>
To: Zsh workers <[email-masked]>
Date: Sun, 17 Jul 2016 12:01:51 +0200
List-Id: Zsh Workers List <zsh-workers.zsh.org>

This updates various completion functions to reflect updates to FreeBSD
commands. Mostly just new options.

Oliver

diff --git a/Completion/BSD/Command/_bsdconfig b/Completion/BSD/Command/_bsdconfig
index 8c7597e..f882555 100644
--- a/Completion/BSD/Command/_bsdconfig
+++ b/Completion/BSD/Command/_bsdconfig
@@ -2,6 +2,7 @@
 
 local -a shortcuts
 shortcuts=(
+  api
   'console:utilities to customize the behavior of the system console'
   'defaultrouter:default router/gateway'
   'diskmgmt:manage disk partitions and/or labels using sade(8)'
@@ -12,6 +13,7 @@ shortcuts=(
   'groupedit:edit/view groups'
   'groupmgmt:utilities to add/change/view/delete group accounts'
   'hostname:set hostname/domainname'
+  includes
   'kern_securelevel:set kern.securelevel variable'
   'mouse:utilities for configuring, exploring, and enabling console mouse support'
   'mouse_disable:disable mouse support'
@@ -43,13 +45,19 @@ shortcuts=(
   'userdel:delete users'
   'useredit:edit/view users'
   'usermgmt:utilities to add/edit/view/delete user accounts'
+  vt_font
+  vt_keymap
+  vt_repeat
+  vt_saver
+  vt_screenmap
+  vt_ttys
 )
 
 _arguments -s -w -A '-*' : \
   '-d[debug mode]' \
   '-D[send debug info to file]: :{ compset -P 1 +; _files }' \
   '-f[load file as script then exit]: : _files' \
-  '-h[print usage then exit]' \
+  '-h[display help information]' \
   '-S[secure X11 mode]' \
   '-X[use Xdialog(1)]' \
-  '1:bsdconfig(8) menus:(( $shortcuts ))'
+  '1:bsdconfig(8) menu:(( $shortcuts ))'
diff --git a/Completion/BSD/Command/_fetch b/Completion/BSD/Command/_fetch
index 3136763..ac1264b 100644
--- a/Completion/BSD/Command/_fetch
+++ b/Completion/BSD/Command/_fetch
@@ -1,30 +1,43 @@
 #compdef fetch
-# Deprecated arguments are removed from the completion
 
-_arguments -s \
-	'-1[stop and return exit code 0 at the first successfully retrieved file]' \
-	'-4[forces fetch to use IPv4 addresses only]' \
-	'-6[forces fetch to use IPv6 addresses only]' \
-	'-A[do not automatically follow "temporary" (302) redirects]' \
-	'-a[automatically retry the transfer upon soft failures]' \
-	'-B[specify the read buffer size in bytes]:bytes:' \
-	'-d[use a direct connection even if a proxy is configured]' \
-	'-F[in combination with the -r flag, forces a restart]' \
-	'-l[if the target is a file-scheme URL, make a symbolic link to the target]' \
-	'-M' \
-	'-m[mirror mode]' \
-	'-N[use file instead of ~/.netrc to look up login names and pass- words for FTP sites]' \
-	'-n[do not preserve the modification time]' \
-	'-o[set the output file name]:file:_files' \
-	'-P' \
-	'-p[use passive FTP]' \
-	'-q[quiet mode]' \
-	'-R[do not delete the output file in any circumstances]' \
-	'-r[restart a previously interrupted transfer]' \
-	'-S[require the file size reported by the server to match the specified value]' \
-	'-s[print the size in bytes, without fetching it]' \
-	'-T[set timeout value]:seconds:' \
-	'-U[when using passive FTP, allocate the port for the data connection from the low port range]' \
-	'-v[increase verbosity level]' \
-	'-w[wait successive retries]:seconds:' \
-	'*:URL to fetch:_urls'
+# Deprecated arguments are prefixed with ! so they aren't listed but their arguments are completed
+_arguments -s -S \
+  '(-1 --one-file)'{-1,--one-file}'[stop and return exit code 0 at the first successfully retrieved file]' \
+  '(-4 --ipv4-only)'{-4,--ipv4-only}'[forces fetch to use IPv4 addresses only]' \
+  '(-6 --ipv6-only)'{-6,--ipv6-only}'[forces fetch to use IPv6 addresses only]' \
+  '(-A --no-redirect)'{-A,--no-redirect}"[don't automatically follow "temporary" (302) redirects]" \
+  '(-a --retry)'{-a,--retry}'[automatically retry the transfer upon soft failures]' \
+  '(-B --buffer-size)'{-B+,--buffer-size=}'[specify the read buffer size in bytes]:buffer size (bytes)' \
+  '--bind-address=[specify address to which outgoing connections will be bound]:host:_hosts' \
+  '--ca-cert=[specify certificate bundle containing trusted CA certificates]:file:_files' \
+  '--ca-path=[specify directory containing trusted CA hashes]:path:_directories' \
+  '--cert=[specify PEM encoded client key for authentication]:file:_files -g "*.pem(-.)"' \
+  '--crl=[specify certificate revocation list file]:file:_files' \
+  '(-d --direct)'{-d,--direct}'[use a direct connection even if a proxy is configured]' \
+  '(-F --force-restart)'{-F,--force-restart}'[in combination with the -r flag, forces a restart]' \
+  '(-i --if-modified-since)'{-i+,--if-modified-since=}'[only retrieve if remote file newer than specified local file]:file:_files' \
+  '--key=[specify PEM encoded client key]:key file:_files -g "*.pem(-.)"' \
+  '(-l --symlink)'{-l,--symlink}'[if the target is a file-scheme URL, make a symbolic link to the target]' \
+  '-M' \
+  '(-m --mirror -r --restart)'{-m,--mirror}'[mirror mode]' \
+  '(-N --netrc)'{-N+,--netrc=}'[use file instead of ~/.netrc to look up login names and pass- words for FTP sites]' \
+  '(-n --no-mtime)'{-n,--no-mtime}"[don't preserve the modification time]" \
+  '--no-passive[force FTP code to use active mode]' \
+  '--no-proxy=[hosts on which to disable proxoes]:host:_sequence _hosts' \
+  '--no-sslv3' '--no-tlsv1' --no-verify-hostname --no-verify-peer \
+  '(-o --output)'{-o+,--output=}'[set the output file name]:file:_files' \
+  '-P' \
+  '(-p --passive)'{-p,--passive}'[use passive FTP]' \
+  '--referer=:URL:_urls' \
+  '(-q --quiet)'{-q,--quiet}'[quiet mode]' \
+  '(-R --keep-output)'{-R,--keep-output}"[don't delete the output file in any circumstances]" \
+  '(-r --restart -m --mirror)'{-r,--restart}'[restart a previously interrupted transfer]' \
+  '(-S --require-size)'{-S+,--require-size=}'[require the file size reported by the server to match the specified value]' \
+  '(-s --print-size)'{-s,--print-size}'[print the size in bytes, without fetching it]' \
+  '(-T --timeout)'{-T+,--timeout=}'[set timeout value]:seconds:' \
+  '(-U --passive-portrange-default)'{-U,--passive-portrange-default}'[when using passive FTP, allocate the port for the data connection from the low port range]' \
+  '--user-agent=:user agent' \
+  '(-v --verbose)'{-v,--verbose}'[increase verbosity level]' \
+  '(-w --retry-delay)'{-w+,--retry-delay=}'[wait successive retries]:delay (seconds)' \
+  '!(*)-h+:host:_hosts' '!(*)-f+:file:_files' '!(*)-c+:remote directory:_directories' \
+  '*:URL to fetch:_urls'
diff --git a/Completion/BSD/Command/_freebsd-update b/Completion/BSD/Command/_freebsd-update
index 11235ba..36b4a01 100644
--- a/Completion/BSD/Command/_freebsd-update
+++ b/Completion/BSD/Command/_freebsd-update
@@ -7,14 +7,17 @@ flags=(
   '(install rollback)upgrade[fetch files necessary for upgrading to a new release]'
   '(upgrade rollback)install[install the most recently fetched updates or upgrade]'
   '(upgrade install)rollback[uninstall the most recently installed updates]'
+  'IDS[compare the system against an index of "known good" files]'
 )
 
-_arguments -s \
+_arguments \
   '-b[operate on a system mounted at basedir]:basedir:_files -/' \
   '-d[store working files in workdir]:workdir:_files -/' \
   '-f[read configuration options from conffile]:conf file:_files' \
-  '-k[trust an RSA key with SHA256 of KEY]:RSA key:' \
-  '-r[specify the new release]:new release:' \
+  '-F[force freebsd-update fetch to proceed where it normally would not]' \
+  '-k[trust an RSA key with SHA256 of KEY]:RSA key' \
+  '-r[specify the new release]:new release' \
   '-s[fetch files from the specified server or server pool]:server:_hosts' \
-  '-f[mail output of cron command, if any, to address]:address:' \
+  '-t[mail output of cron command, if any, to address]:address' \
+  '--currently-running[assume specified release as current]:release' \
   ':command:_values -S " " -w "commands" $flags[@]'
diff --git a/Completion/BSD/Command/_fstat b/Completion/BSD/Command/_fstat
index 3e8d617..5487e6c 100644
--- a/Completion/BSD/Command/_fstat
+++ b/Completion/BSD/Command/_fstat
@@ -1,15 +1,12 @@
 #compdef fstat
 
-local pids
-pids=(${${${(f)"$(/usr/bin/procstat -ah)"}/[[:space:]]#/}/[[:space:]]*[[:space:]](ELF[[:digit:]]#[[:space:]]|-[[:space:]]#)/:})
-
 _arguments -s \
 '-f[restrict examination to files open in the same file systems as the named file arguments]' \
-'-M[extract values associated with the name list from the specified core]:core:_files' \
-'-N[extract the name list from the specified system]:system:' \
+'-M+[extract values associated with the name list from the specified core]:core:_files' \
+'-N+[extract the name list from the specified system]:system' \
 '-m[include memory-mapped files in the listing]' \
 '-n[numerical format]' \
-'-p[report all files open by the specified process]:process id:(($pids))' \
-'-u[report all files open by the specified user]:user:_users' \
+'-p+[report all files open by the specified process]:process id:_pids' \
+'-u+[report all files open by the specified user]:user:_users' \
 '-v[verbose mode]' \
 '*:files:_files'
diff --git a/Completion/BSD/Command/_gstat b/Completion/BSD/Command/_gstat
index 55b7db7..7baaf0d 100644
--- a/Completion/BSD/Command/_gstat
+++ b/Completion/BSD/Command/_gstat
@@ -1,11 +1,11 @@
 #compdef gstat
 
-_arguments -s -w : \
+_arguments -s : \
   '-a[only display providers that are at least 0.1% busy]' \
   '-b[batch mode]' \
   '-c[enable the display geom(4) consumers]' \
   '-d[enable the display delete operations]' \
-  '-f[filter by regex]:regex' \
+  '-f+[filter by regex]:regex' \
   '-o[enable the display for other operations]' \
-  '-I[display refresh rate]:interval' \
+  '-I+[display refresh rate]:interval (ms)' \
   '-p[only display physical providers]'
diff --git a/Completion/BSD/Command/_jexec b/Completion/BSD/Command/_jexec
index f065ea1..279812b 100644
--- a/Completion/BSD/Command/_jexec
+++ b/Completion/BSD/Command/_jexec
@@ -9,7 +9,8 @@ _jexec_normal() {
 }
 
 _jexec() {
-  _arguments -s -w -A "-*" : \
+  _arguments -s -S -A "-*" : \
+    '-l[execute in a clean environment]' \
     '(-U)-u[host environment user whom command runs as]:host user:_users' \
     '(-u)-U[jail environment user whom command runs as]:jail user:_users' \
     '1:jail:_jails' \
diff --git a/Completion/BSD/Command/_kld b/Completion/BSD/Command/_kld
index 34f26f1..9452895 100644
--- a/Completion/BSD/Command/_kld
+++ b/Completion/BSD/Command/_kld
@@ -24,14 +24,17 @@ _kld() {
   unset _cache_sysctlvars
 
   case "$service" in
-  kldload)
-    _arguments -s \
+    kldload)
+      _arguments -s -S -A "-*" \
+        "-n[don't try to load module if already loaded]"
         '-v[be verbose]' \
+        '-q[silence any extraneous warnings]' \
         '*:module to load:_kld_module'
     ;;
 
-  kldunload)
-    _arguments -s \
+    kldunload)
+      _arguments -s -S -A "-*" \
+        '-f[force the unload]' \
         '-v[be verbose]' \
         '(-n)-i:module id to unload:_kld_unload_id' \
         '(-i)-n:module to unload:_kld_unload' \
diff --git a/Completion/BSD/Command/_procstat b/Completion/BSD/Command/_procstat
index f8bc542..e160576 100644
--- a/Completion/BSD/Command/_procstat
+++ b/Completion/BSD/Command/_procstat
@@ -1,17 +1,24 @@
 #compdef procstat
 
-local pids
-#get list of pids and associated process name as comment
-pids=(${${${(f)"$(/usr/bin/procstat -ah)"}/[[:space:]]#/}/[[:space:]]*[[:space:]](ELF[[:digit:]]#[[:space:]]|-[[:space:]]#)/:})
-
-_arguments -s \
-'-b[display binary information for the process]' \
-'-c[display command line arguments for the process]' \
-'-f[display file descriptor information for the process]' \
-'-k[display the stacks of kernel threads in the process]' \
-'-s[display security credential information for the process]' \
-'-t[display thread information for the process]' \
-'-v[display virtual memory mappings for the process]' \
-'-h[suppress table headers]' \
-'-a[all processes]' \
-':process id:(($pids))'
+_arguments -s -A "-*" -S \
+  '-b[show binary information]' \
+  '-c[show command line arguments]' \
+  '-e[show environment variables]' \
+  '-f[show file descriptor information]' \
+  '-i[show signal pending and disposition]' \
+  '-k[show stacks of kernel threads]' \
+  '-l[show resource limits]' \
+  '-r[show resource usage]' \
+  '-s[show security credential information]' \
+  '-S[show cpuset information]' \
+  '-t[show thread information]' \
+  '-v[show virtual memory mappings]' \
+  '-x[show ELF auxiliary vector]' \
+  '-h[suppress table headers]' \
+  '(1)-a[all processes]' \
+  '-w+[repeat information after specified interval]:delay (seconds)' \
+  '-C[print additional capability information for file descriptors]' \
+  '-H[statistics per-thread rather than per-process]' \
+  '-n[numeric form for signals]' \
+  '1::core file:_path_files -g "*core*(-.)"' \
+  '*:process id:_pids'
diff --git a/Completion/BSD/Command/_sysrc b/Completion/BSD/Command/_sysrc
index d8bc4ef..651c18b 100644
--- a/Completion/BSD/Command/_sysrc
+++ b/Completion/BSD/Command/_sysrc
@@ -1,39 +1,50 @@
 #compdef sysrc
+
 _sysrc_caching_policy() {
   local -a oldp
   oldp=( "$1"(Nm+1) )
   (( $#oldp ))
 }
 
-
 _sysrc() {
-  _arguments -A '-*' : \
+  local curcontext="$curcontext" state line ret=1
+  typeset -A opt_args
+  local -a rc_conf_vars
+
+  _arguments -C -s -A '-*' : \
+    '(-l)-e[print variables as sh(1) compatible syntax]' \
+    '-E[list only existing files]' \
+    '(-l)-q[quiet mode]' \
+    '(-L)-s+[process additional rc.conf.d entries for specified service name]:service name:_services' \
+    '(-L)*-f+[operate on specified file(s), not \`rc_conf_files'\'']: : _files' \
+    '(-l)-v[verbose mode]' \
+    '*:configuration variable:->confvars' \
+    - set \
+    '(-A)-a[list all non-default configuration variables]' \
+    '(-a)-A[list all configuration variables]' \
     '-c[check only, return success if vars are set]' \
     '-d[print variable(s) description]' \
     '-D[print default value(s) only]' \
-    '-e[print variables as sh(1) compatible syntax]' \
-    '*-f[operate on specified file(s), not \`rc_conf_files'\'']: : _files' \
     '-F[print only the last rc.conf(5) file each directive is in]' \
-    '-h[print short usage message]' \
-    '--help[print full usage message]' \
+    '(- *)-h[print short usage message]' \
+    '(- *)--help[print full usage message]' \
     '-i[ignore unknown variables]' \
-    '-j[jail to operate within]:jails:_jails' \
+    '-j+[jail to operate within]:jails:_jails' \
     '-n[print only variable values]' \
     '-N[print only variable names]' \
-    '-q[quiet mode]' \
-    '-R[specify an alternative root]:alternative root:_files -/' \
-    '-v[verbose mode]' \
-    '--version[print version information]' \
+    '-R+[specify an alternative root]:alternative root:_files -/' \
+    '(- *)--version[print version information]' \
     '-x[remove specified variables from specified file(s)]' \
-    '*:configuration variable:->confvars' \
-    - set1 \
-    '-a[list all non-default configuration variables]' \
-    - set2 \
-    '-A[list all configuration variables]'
+    - lists \
+    '(-e -q -v)-l[list config files used at startup]' \
+    - lista \
+    '(-s -f)-L[list all configuration files including rc.conf.d entries]' && ret=0
 
   if [[ $state  == confvars ]]; then
-    local k v opt curcontext="${curcontext%:*}:values"; local -a rc_conf_vars
-    if [[ -prefix *=* ]]; then
+    local k v opt
+    if (( $+opt_args[lista--L] )); then
+      _services && ret=0
+    elif [[ -prefix *=* ]]; then
       # do you really want to go down this hole?
       _message -e values value
     else
@@ -65,13 +76,15 @@ _sysrc() {
 
       if (( $#rc_conf_vars )); then
         if [[ $opt == N ]]; then
-          _values -w -C variable ${^rc_conf_vars%%\[*}'::value'
+          _values -w -C variable ${^rc_conf_vars%%\[*}'::value' && ret=0
         else
-          _values -w -C variable ${^rc_conf_vars}'::value'
+          _values -w -C variable ${^rc_conf_vars}'::value' && ret=0
         fi
       fi
     fi
   fi
+
+  return ret
 }
 
 _sysrc "$@"
diff --git a/Completion/BSD/Command/_systat b/Completion/BSD/Command/_systat
index c8348c7..35b8421 100644
--- a/Completion/BSD/Command/_systat
+++ b/Completion/BSD/Command/_systat
@@ -1,12 +1,13 @@
 #compdef systat
 
-local -a screens args opts
+local -a screens opts
 local pre
 case $OSTYPE in
   freebsd*)
     pre=-
     screens=(
       'pigs:processes consuming the most CPU time'
+      'sctp:SCTP statistics'
       icmp{6,}':ICMP statistics'
       ip{6,}':IP and UDP statistics'
       'tcp:TCP statistics'
diff --git a/Completion/Unix/Command/_cat b/Completion/Unix/Command/_cat
index e223d90..57b1970 100644
--- a/Completion/Unix/Command/_cat
+++ b/Completion/Unix/Command/_cat
@@ -30,6 +30,9 @@ elif [[ "$OSTYPE" == (freebsd|dragonfly|darwin)* ]]; then
     '-v[display non-printing chars as ^X or M-a]'
     '(-)*:files:_files'
   )
+  [[ $OSTYPE = freebsd* ]] && args+=(
+    '-l[set a lock on the stdout file descriptor]'
+  )
 
 else
   # POSIX reqires '-u', and most OSes may support '-n'
diff --git a/Completion/Unix/Command/_sysctl b/Completion/Unix/Command/_sysctl
index 9d9e8b9..cf88c3d 100644
--- a/Completion/Unix/Command/_sysctl
+++ b/Completion/Unix/Command/_sysctl
@@ -1,21 +1,39 @@
 #compdef sysctl
 
+local -a args
+
 case $OSTYPE in
+  freebsd<10->.*)
+    args+=(
+      '-f+[specify file of name/value pairs to process first]:file:_files'
+      '-T[display only variables that are setable via loader]'
+      '-W[display only writable variables that are not statistical]'
+    )
+  ;|
+  dragonfly*|freebsd<8->.*)
+    args+=( "-i[silently exit if variable doesn't exist]" )
+  ;|
   *freebsd<5->.*|freebsd4.[4-9]*)
     local -a sysctlvars
     sysctlvars=( $(_call_program sysctl-variables sysctl -aN) )
-    _arguments -s -A "-*" \
+    _arguments -s -S -A "-*" $args \
+      '(-a -o *)-A[equivalent to -o -a (for compatibility)]' \
       '(*)-a[list all]' \
       '-b[binary output]' \
+      '-d[print the description of the variable instead of its value]' \
+      '(-N -n)-e[separate name and value with =]' \
+      '-h[format output for human readability]' \
       '(-n)-N[show only variable names]' \
       '(-N)-n[show only variable values]' \
       '(-x)-o[show opaques as well (values suppressed)]' \
+      '-q[suppress some warnings]' \
+      '(* -o)-X[equivalent to -x -a (for compatibility)]' \
       '(-o)-x[show opaques as well (entire values)]' \
       '(-a)*:sysctl variable:_multi_parts -i . sysctlvars'
   ;;
   freebsd[0-4].*|darwin*|dragonfly*)
     : ${(A)_cache_sysctlvars:=${${$(sysctl -A 2>/dev/null):#[^a-z]*}%%:*}}
-    _arguments -s -A "-*" \
+    _arguments -s -A "-*" $args \
       '(-w -X *)-a[list all]' \
       '(-w -X *)-A[show all opaques (values suppressed)]' \
       '(-w)-b[binary output]' \
diff --git a/Completion/Unix/Command/_vmstat b/Completion/Unix/Command/_vmstat
index 02fa6be..7082cbb 100644
--- a/Completion/Unix/Command/_vmstat
+++ b/Completion/Unix/Command/_vmstat
@@ -18,40 +18,38 @@ case $OSTYPE in
       '1:delay' '2:count'
     )
   ;;
-  freebsd*)
+  freebsd*|openbsd*)
     specs=(
-      '-a[include statistics about all interrupts]'
       '-c[number of times to refresh the display]:count'
       '-f[report on the number fork syscalls since boot and pages of virtual memory for each]'
-      '-h[human readable memory columns output]'
-      '-H[scriptable memory columns output]'
       '-i[report the number of interrupts taken by devices since boot]'
       '-M[source file to extract values associated with the name list from]:core:_files'
       '-N[source file to extract the name list from]:system:_files'
+      '-w[specify delay between each display]:delay (seconds)'
+      '*:disk:_files'
+    )
+  ;|
+  freebsd*)
+    specs+=(
+      '-a[include statistics about all interrupts]'
+      '-h[human readable memory columns output]'
+      '-H[scriptable memory columns output]'
       '-m[report on the usage of kernel dynamic memory allocated using malloc(9) by type]'
       '-n[change the maximum number of disks to display]:number of disks to display'
+      '-o[list virtual memory objects]'
       '-P[report per-cpu system/user/idle cpu statistics]'
       '-p[specify which types of devices to display]: :->devices'
       '-s[display the contents of the SUM structure]:sum'
-      '-w[delay N seconds between each display]:delay'
       '-z[report on memory used by the kernel zone allocator, uma(9), by zone]'
-      '*:disks:_files'
     )
   ;;
   openbsd*)
-    specs=(
-      '-c[number of times to refresh the display]:count'
-      '-f[report on the number fork syscalls since boot and pages of virtual memory for each]'
-      '-i[report the number of interrupts taken by devices since boot]'
-      '-M[source file to extract values associated with the name list from]:core:_files'
+    specs+=(
       '-m[report usage of kernel dynamic memory listed first by size of allocation then type of usage]'
-      '-N[source file to extract the name list from]:system:_files'
       '-s[display the contents of the UVMEXP structure]:uvmexp'
       '-t[report on the number of page in and page reclaims since boot]'
       '-v[print more verbose information]'
-      '-w[delay N seconds between each display]:delay'
       '-z[include statistics about all interrupts]'
-      '*:disks:_files'
     )
   ;;
 esac
diff --git a/Completion/Unix/Command/_zfs b/Completion/Unix/Command/_zfs
index f3869da..553996d 100644
--- a/Completion/Unix/Command/_zfs
+++ b/Completion/Unix/Command/_zfs
@@ -149,7 +149,7 @@ _zfs() {
 		"atime:value:(on off)"
 		"canmount:value:(on off noauto)"
 		"checksum:value:(on off fletcher2 fletcher4 sha256 sha256+mac)"
-		"compression:value:(on off lzjb gzip gzip-{1..9} zle)"
+		"compression:value:(on off lzjb lz4 gzip gzip-{1..9} zle)"
 		"copies:value:(1 2 3)"
 		"dedup:value:(on off verify sha256 sha256,verify)"
 		"devices:value:(on off)"
@@ -247,7 +247,7 @@ _zfs() {
 			':filesystem/volume/snapshot:_zfs_dataset -t fs -t vol'
 		;;
 
-	("snapshot")
+	(snap(|shot))
 		_arguments -A "-*" \
 			'-r[Recursively snapshot all descendant datasets]' \
 			'*-o[Set property]:property:_values -s , "property" $create_properties' \
@@ -418,30 +418,16 @@ _zfs() {
 
 	("allow")
 		_arguments -A "-*" \
-			- set1 \
-			':filesystem/volume:_zfs_dataset -t fs -t vol' \
-			- set2 \
-			'(-g)-u[User]:user:_users' \
-			'(-u)-g[Group]:group:_groups' \
-			'-l[Allow for named dataset]' \
-			'-d[Allow for descendent datasets]' \
+			'(1 -g -e -c -s)-u[delegate to user]:user:_users' \
+			'(1 -u -e -c -s)-g[delegate to group]:group:_groups' \
+			'(1 -g -u -c -s)-e[delegate to everyone]' \
+			'(1 -u -g -e -l -d -s)-c[set permissions for newly-created descendant filesystems]' \
+			'(1 -u -g -e -l -d -c)-s[define or modify permission sets]:permission set' \
+			'(1 -c -s)-l[allow for named dataset]' \
+			'(1 -c -s)-d[allow for descendent datasets]' \
+			'1::filesystem/volume:_zfs_dataset -t fs -t vol' \
 			':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
 			':filesystem/volume:_zfs_dataset -t fs -t vol' \
-			- set3 \
-			'-e[Everyone]' \
-			'-l[Allow for named dataset]' \
-			'-d[Allow for descendent datasets]' \
-			':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
-			':filesystem/volume:_zfs_dataset -t fs -t vol' \
-			- set4 \
-			'-c[Create-time permissions]' \
-			':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
-			':filesystem/volume:_zfs_dataset -t fs -t vol' \
-			- set5 \
-			'-s[Define or modify permission sets]' \
-			':setname:' \
-			':permissions or sets:_values -s , "permission or set" $delegatable_perms' \
-			':filesystem/volume:_zfs_dataset -t fs -t vol'
 		;;
 
 	("unallow")
diff --git a/Completion/Unix/Type/_zfs_dataset b/Completion/Unix/Type/_zfs_dataset
index 5fa3e9e..6c625e9 100644
--- a/Completion/Unix/Type/_zfs_dataset
+++ b/Completion/Unix/Type/_zfs_dataset
@@ -58,14 +58,14 @@ if [[ ${#rdst} -gt 0 ]]; then
 fi
 
 if [[ -n $type[(r)clone] ]]; then
-	datasetlist=( ${="$(zfs list -H -o name,origin -t filesystem | awk "\$2 != \"-\" {print \$1}")":#no cloned filesystems available} )
+	datasetlist=( ${="$(zfs list -H -o name,origin -t filesystem 2>/dev/null | awk "\$2 != \"-\" {print \$1}")":#no cloned filesystems available} )
 else
-	datasetlist=( ${="$(zfs list -H -o name $typearg)":#no datasets available} )
+	datasetlist=( ${="$(zfs list -H -o name $typearg 2>/dev/null)":#no datasets available} )
 fi
 
 expl_type=${typearg[2,-1]//,/\/}
 if [[ -n $type[(r)mtpt] ]]; then
-	mlist=( ${="$(zfs list -H -o mountpoint $typearg)":#no mountpoints available} )
+	mlist=( ${="$(zfs list -H -o mountpoint $typearg 2>/dev/null)":#no mountpoints available} )
 	datasetlist=( $datasetlist $mlist )
 	expl_type="$expl_type/mountpoint"
 fi