about summary refs log tree commit diff
path: root/Completion/Unix/Command
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Unix/Command')
-rw-r--r--Completion/Unix/Command/_adb6
-rw-r--r--Completion/Unix/Command/_ant5
-rw-r--r--Completion/Unix/Command/_arping22
-rw-r--r--Completion/Unix/Command/_attr8
-rw-r--r--Completion/Unix/Command/_augeas5
-rw-r--r--Completion/Unix/Command/_awk138
-rw-r--r--Completion/Unix/Command/_basename27
-rw-r--r--Completion/Unix/Command/_bzr2
-rw-r--r--Completion/Unix/Command/_cat27
-rw-r--r--Completion/Unix/Command/_cdrdao6
-rw-r--r--Completion/Unix/Command/_chown4
-rw-r--r--Completion/Unix/Command/_cp3
-rw-r--r--Completion/Unix/Command/_cpio11
-rw-r--r--Completion/Unix/Command/_cscope29
-rw-r--r--Completion/Unix/Command/_cvs5
-rw-r--r--Completion/Unix/Command/_darcs2
-rw-r--r--Completion/Unix/Command/_date98
-rw-r--r--Completion/Unix/Command/_dbus13
-rw-r--r--Completion/Unix/Command/_devtodo4
-rw-r--r--Completion/Unix/Command/_df13
-rw-r--r--Completion/Unix/Command/_dmesg32
-rw-r--r--Completion/Unix/Command/_dmidecode17
-rw-r--r--Completion/Unix/Command/_doas22
-rw-r--r--Completion/Unix/Command/_dsh3
-rw-r--r--Completion/Unix/Command/_entr9
-rw-r--r--Completion/Unix/Command/_env53
-rw-r--r--Completion/Unix/Command/_espeak73
-rw-r--r--Completion/Unix/Command/_feh4
-rw-r--r--Completion/Unix/Command/_find20
-rw-r--r--Completion/Unix/Command/_fmt60
-rw-r--r--Completion/Unix/Command/_fsh1
-rw-r--r--Completion/Unix/Command/_gcc4
-rw-r--r--Completion/Unix/Command/_gdb2
-rw-r--r--Completion/Unix/Command/_getent2
-rw-r--r--Completion/Unix/Command/_git1652
-rw-r--r--Completion/Unix/Command/_global6
-rw-r--r--Completion/Unix/Command/_gpg2
-rw-r--r--Completion/Unix/Command/_gphoto2113
-rw-r--r--Completion/Unix/Command/_graphicsmagick4
-rw-r--r--Completion/Unix/Command/_grep91
-rw-r--r--Completion/Unix/Command/_groff2
-rw-r--r--Completion/Unix/Command/_growisofs8
-rw-r--r--Completion/Unix/Command/_gs2
-rw-r--r--Completion/Unix/Command/_gsettings47
-rw-r--r--Completion/Unix/Command/_head2
-rw-r--r--Completion/Unix/Command/_hg2
-rw-r--r--Completion/Unix/Command/_iftop21
-rw-r--r--Completion/Unix/Command/_imagemagick4
-rw-r--r--Completion/Unix/Command/_initctl4
-rw-r--r--Completion/Unix/Command/_iostat132
-rw-r--r--Completion/Unix/Command/_ip12
-rw-r--r--Completion/Unix/Command/_java6
-rw-r--r--Completion/Unix/Command/_joe2
-rw-r--r--Completion/Unix/Command/_kvno10
-rw-r--r--Completion/Unix/Command/_less7
-rw-r--r--Completion/Unix/Command/_lha2
-rw-r--r--Completion/Unix/Command/_libvirt238
-rw-r--r--Completion/Unix/Command/_ln1
-rw-r--r--Completion/Unix/Command/_locale84
-rw-r--r--Completion/Unix/Command/_localedef92
-rw-r--r--Completion/Unix/Command/_locate192
-rw-r--r--Completion/Unix/Command/_look34
-rw-r--r--Completion/Unix/Command/_lp2
-rw-r--r--Completion/Unix/Command/_ls113
-rw-r--r--Completion/Unix/Command/_lsof2
-rw-r--r--Completion/Unix/Command/_lzop3
-rw-r--r--Completion/Unix/Command/_make24
-rw-r--r--Completion/Unix/Command/_man60
-rw-r--r--Completion/Unix/Command/_md5sum5
-rw-r--r--Completion/Unix/Command/_mencal2
-rw-r--r--Completion/Unix/Command/_module22
-rw-r--r--Completion/Unix/Command/_mosh1
-rw-r--r--Completion/Unix/Command/_mount20
-rw-r--r--Completion/Unix/Command/_mpc2
-rw-r--r--Completion/Unix/Command/_mutt7
-rw-r--r--Completion/Unix/Command/_mysql_utils2
-rw-r--r--Completion/Unix/Command/_nkf2
-rw-r--r--Completion/Unix/Command/_nm1
-rw-r--r--Completion/Unix/Command/_nmap4
-rw-r--r--Completion/Unix/Command/_openstack192
-rw-r--r--Completion/Unix/Command/_paste19
-rw-r--r--Completion/Unix/Command/_patch31
-rw-r--r--Completion/Unix/Command/_patchutils4
-rw-r--r--Completion/Unix/Command/_pbm2
-rw-r--r--Completion/Unix/Command/_perforce948
-rw-r--r--Completion/Unix/Command/_perl2
-rw-r--r--Completion/Unix/Command/_pgrep3
-rw-r--r--Completion/Unix/Command/_php2
-rw-r--r--Completion/Unix/Command/_picocom2
-rw-r--r--Completion/Unix/Command/_pkg-config37
-rw-r--r--Completion/Unix/Command/_postfix153
-rw-r--r--Completion/Unix/Command/_prove2
-rw-r--r--Completion/Unix/Command/_rake2
-rw-r--r--Completion/Unix/Command/_rar2
-rw-r--r--Completion/Unix/Command/_readelf4
-rw-r--r--Completion/Unix/Command/_rlogin5
-rw-r--r--Completion/Unix/Command/_rm22
-rw-r--r--Completion/Unix/Command/_rrdtool26
-rw-r--r--Completion/Unix/Command/_rsync23
-rw-r--r--Completion/Unix/Command/_ruby7
-rw-r--r--Completion/Unix/Command/_screen2
-rw-r--r--Completion/Unix/Command/_script71
-rw-r--r--Completion/Unix/Command/_sed6
-rw-r--r--Completion/Unix/Command/_service49
-rw-r--r--Completion/Unix/Command/_sisu2
-rw-r--r--Completion/Unix/Command/_sort14
-rw-r--r--Completion/Unix/Command/_sqsh2
-rw-r--r--Completion/Unix/Command/_ssh155
-rw-r--r--Completion/Unix/Command/_stgit12
-rw-r--r--Completion/Unix/Command/_strip7
-rw-r--r--Completion/Unix/Command/_su127
-rw-r--r--Completion/Unix/Command/_subversion68
-rw-r--r--Completion/Unix/Command/_sudo6
-rw-r--r--Completion/Unix/Command/_surfraw2
-rw-r--r--Completion/Unix/Command/_swaks40
-rw-r--r--Completion/Unix/Command/_swift123
-rw-r--r--Completion/Unix/Command/_sysctl26
-rw-r--r--Completion/Unix/Command/_tail2
-rw-r--r--Completion/Unix/Command/_tcpdump200
-rw-r--r--Completion/Unix/Command/_texinfo243
-rw-r--r--Completion/Unix/Command/_tin2
-rw-r--r--Completion/Unix/Command/_tmux1831
-rw-r--r--Completion/Unix/Command/_top177
-rw-r--r--Completion/Unix/Command/_touch45
-rw-r--r--Completion/Unix/Command/_tree101
-rw-r--r--Completion/Unix/Command/_truss76
-rw-r--r--Completion/Unix/Command/_uniq4
-rw-r--r--Completion/Unix/Command/_units6
-rw-r--r--Completion/Unix/Command/_user_admin206
-rw-r--r--Completion/Unix/Command/_vim45
-rw-r--r--Completion/Unix/Command/_vmstat26
-rw-r--r--Completion/Unix/Command/_w3m4
-rw-r--r--Completion/Unix/Command/_wget3
-rw-r--r--Completion/Unix/Command/_wiggle2
-rw-r--r--Completion/Unix/Command/_xargs1
-rw-r--r--Completion/Unix/Command/_xmlsoft7
-rw-r--r--Completion/Unix/Command/_xxd18
-rw-r--r--Completion/Unix/Command/_xz2
-rw-r--r--Completion/Unix/Command/_yafc28
-rw-r--r--Completion/Unix/Command/_zfs34
-rw-r--r--Completion/Unix/Command/_zip119
-rw-r--r--Completion/Unix/Command/_zpool2
142 files changed, 6213 insertions, 2945 deletions
diff --git a/Completion/Unix/Command/_adb b/Completion/Unix/Command/_adb
index 879e26045..6b56d1748 100644
--- a/Completion/Unix/Command/_adb
+++ b/Completion/Unix/Command/_adb
@@ -217,7 +217,7 @@ _adb_pm_list () {
     (permissions)
       _arguments -s '-g[organize by group]' \
       		    '-f[print all information]' \
-      		    '-d[only list dangerous pemissions]' \
+		    '-d[only list dangerous permissions]' \
       		    '-u[only list user visible permissions]' \
       		    '-s[short summary]' \
       		    ':'
@@ -282,7 +282,7 @@ _adb_activity_manager_handler () {
       _arguments -s '-r[print raw results]' \
       		    '-e[set argument NAME to VALUE]:<NAME> <VALUE>:' \
       		    '-p[write profiling data to FILE]:<FILE>:' \
-      		    '-w[wait for instrumenation to finish]' \
+		    '-w[wait for instrumentation to finish]' \
       		    ':'
       ;;
     (profile)
@@ -307,7 +307,7 @@ _adb_package_manager_handler () {
       (( $+functions[_adb_installed_packages] )) && _adb_installed_packages
       ;;
     (setInstallLocation)
-      _wanted set_installlcation expl 'install location' compadd -d "(0:auto 1:internal 2:external)" 0 1 2
+      _wanted install-locations expl 'install location' compadd -d "(0:auto 1:internal 2:external)" 0 1 2
       ;;
     (getInstallLocation)
       ;;
diff --git a/Completion/Unix/Command/_ant b/Completion/Unix/Command/_ant
index ee9f7d910..080ce6857 100644
--- a/Completion/Unix/Command/_ant
+++ b/Completion/Unix/Command/_ant
@@ -41,6 +41,7 @@ _arguments -C \
   '(- *)-version[display version information]' \
   '(- *)-diagnostics[print information helpful to diagnosis or report problems]' \
   '(-q -quiet)'{-q,-quiet}'[be extra quiet]' \
+  '(-s -silent)'{-s,-silent}'[print nothing but task outputs and build failures]' \
   '(-v -verbose)'{-v,-verbose}'[be extra verbose]' \
   '(-d -debug)'{-d,-debug}'[print debugging information]' \
   '(-e -emacs)'{-e,-emacs}'[produce logging information without adornments]' \
@@ -50,7 +51,7 @@ _arguments -C \
   '*-listener[add an instance of specified class as a project listener]:class:->class' \
   '-noinput[do not allow interactive input]' \
   '(-f -file -buildfile -s -find)'{-f,-file,-buildfile}'[use specified build file]:build file:_files -g "*.xml(-.)"' \
-  '*-D[specify property with value to use]:property:->property' \
+  '*-D+[specify property with value to use]:property:->property' \
   '(-k -keep-going)'{-keep-going,-k}'[execute all targets that do not depend on failed target(s)]' \
   '-propertyfile[load all properties from specified file with -D properties taking precedence]:property file:_files -g "*.properties(-.)"' \
   '-inputhandler[specify class which will handle input requests]:class:->class' \
@@ -82,7 +83,7 @@ case $state in
       "classpath:$state:_path_files -r': ' -/" && ret=0
   ;;
   property)
-    if compset -P '*='; then
+    if compset -P 1 '*='; then
       _default && ret=0
     else
       _message -e properties 'property name'
diff --git a/Completion/Unix/Command/_arping b/Completion/Unix/Command/_arping
index 5edda2123..bd9bc8ccc 100644
--- a/Completion/Unix/Command/_arping
+++ b/Completion/Unix/Command/_arping
@@ -1,6 +1,6 @@
 #compdef arping
 
-if _pick_variant iputils=iputils unix -V; then
+if _pick_variant iputils=iputils thabets -V; then
 
 _arguments -s \
   '-f[quit on first reply]' \
@@ -18,25 +18,35 @@ _arguments -s \
 
 else
 
-_arguments -s \
-  '(-)-h[display help information]' \
+_arguments -s -S  -A "-*" \
+  '(-)'{-h,--help}'[display help information]' \
   '-q[only display error messages]' \
   '-a[audible ping]' \
   '*-v[verbose output]' \
   '-r[raw output: only the MAC/IP address displayed]' \
   '-R[like -r but shows "the other one"]' \
   '-d[find duplicate replies]' \
+  '-D[display answers as exclamation marks and missing packets as dots]' \
+  '-e[like -a but beep when there is no reply]' \
+  "-F[don't try to be smart about the interface name]" \
+  '-m+[specify type of timestamp for incoming packets]:timestamp type' \
   '(:)-B[255.255.255.255]' \
   '-0[source 0.0.0.0]' \
   '-b[source 255.255.255.255]' \
-  '-S[set source IP]:source IP address:_hosts' \
-  '-T[target IP]:target IP address:_hosts' \
+  '-S+[set source IP]:source IP address:_hosts' \
+  '-T+[target IP]:target IP address:_hosts' \
   '-p[turn on promiscuous mode]' \
   '-s[set source MAC address]:source MAC address' \
   '-t[set target MAC address]:target MAC address' \
   '-c[send this many requests]:count' \
-  '-I[interface]:interface:_net_interfaces' \
+  '-C[only wait for specified replies]:reply count' \
+  '-i+[interface]:interface:_net_interfaces' \
   '-A[only count addresses matching requested address]' \
+  '-P[send ARP replies instead of requests]' \
+  '-u[show index=received/sent instead of just index=received when pinging MACs]' \
+  '-U[send unsolicited ARP]' \
+  '-w+[specify time to wait between pings (ms)]:time (ms)' \
+  '-W+[specify time to wait between pings (seconds)]:time (seconds)' \
   '(-B):address:_hosts'
  
 fi
diff --git a/Completion/Unix/Command/_attr b/Completion/Unix/Command/_attr
index c7ca1b850..df1fb7da4 100644
--- a/Completion/Unix/Command/_attr
+++ b/Completion/Unix/Command/_attr
@@ -21,11 +21,11 @@ case $service in
       '(-d --dump -n --name)'{-n+,--name=}'[dump the value of the named extended attribute]' \
       '(-n --name -d --dump)'{-d,--dump}'[dump the values of all extended attributes]' \
       '(-e --encoding)'{-e+,--encoding=}'[encode values after retrieving them]:encoding:(text hex base64)' \
-      '(-h --no-derference)'{-h,--no-dereference}'[do not follow symbolic links]' \
+      '(-h --no-dereference)'{-h,--no-dereference}"[don't follow symbolic links]" \
       '(-m --match)'{-m+,--match=}'[only include attributes with names matching regex]:regular expression' \
-      '--absolute-names[do not string leasing slash characters]' \
+      "--absolute-names[don't strip leading slash characters]" \
       '--only-values[dump only attribute values]' \
-      '(-R --recursive)'{-R,--recursive}'[list attributes of all files and directories recurively]' \
+      '(-R --recursive)'{-R,--recursive}'[list attributes of all files and directories recursively]' \
       '(-P --physical -L --logical)'{-L,--logical}'[follow all symbolic links]' \
       '(-L --logical -P --physical)'{-P,--physical}'[skip all symbolic links]' \
       '(* -)--version[display version information]' \
@@ -39,7 +39,7 @@ case $service in
       '(-v --value)'{-v+,--value=}'[specify value for the attribute]' \
       '(-x --remove)'{-x+,--remove=}'[remove specified extended attribute]' \
       '(-n --name -v --value)--restore[restore extended attributes from dump file]:dump file:_files' \
-      '(-h --no-derference)'{-h,--no-dereference}'[do not follow symbolic links]' \
+      '(-h --no-dereference)'{-h,--no-dereference}"[don't follow symbolic links]" \
       '(* -)--version[display version information]' \
       '(* -)--help[display help information]' \
       '*:file:_files'
diff --git a/Completion/Unix/Command/_augeas b/Completion/Unix/Command/_augeas
index 622fa3467..f9c052122 100644
--- a/Completion/Unix/Command/_augeas
+++ b/Completion/Unix/Command/_augeas
@@ -9,6 +9,8 @@ _arguments -C -s \
   '(-n --new)'{-n,--new}'[leave files untouched but save changes with a .augnew extension]' \
   '(-r --root)'{-r,--root=}'[specify filesystem root]:root directory:_files -/' \
   \*{-I+,--include=}'[add directory containing lenses to search path]:directory:_files -/' \
+  \*{-t+,--transform=}'[add a file transform]:xfm' \
+  '(-l --load-file)'{-l+,--load-file=}'[load individual file in the tree]:file:_files' \
   '(-f --file *)'{-f+,--file=}'[read commands from specified file]:file:_files' \
   '(-i --interactive)'{-i,--interactive}'[read commands from the terminal]' \
   '(-e --echo)'{-e,--echo}'[echo commands read from a file or stdin]' \
@@ -17,6 +19,7 @@ _arguments -C -s \
   '(-L --noload)'{-L,--noload}'[do not load any files into the tree on startup]' \
   '(-A --noautoload)'{-A,--noautoload}'[do not autoload modules from the search path]' \
   '--span[load span positions for nodes related to a file]' \
+  '--timing[after executing each command, show how long it took]' \
   '(- *)--version[print version information]' \
   '(-)'{-h,--help}'[print help information]' \
   '*:: :->subcommands' && ret=0
@@ -25,7 +28,7 @@ _arguments -C -s \
 
 if [[ CURRENT -eq 1 || $words[1] == help ]]; then
   local -a subcmds
-  subcmds=( ${${${(f)"$(_call_program subcommands augtool help 2>/dev/null)"}[2,-2]## #}// #- /:} )
+  subcmds=( ${${${(M)${(f)"$(_call_program subcommands augtool help 2>/dev/null)"}:#  *}## #}// #- /:} )
   _describe -t subcommands "augtool command" subcmds && ret=0
   return ret
 fi
diff --git a/Completion/Unix/Command/_awk b/Completion/Unix/Command/_awk
index c493c3b04..9050c2f7d 100644
--- a/Completion/Unix/Command/_awk
+++ b/Completion/Unix/Command/_awk
@@ -1,21 +1,119 @@
-#compdef awk
-
-# completions for awk
-# This only aims to complete POSIX awk options, as described in
-# awk(P). Most awk implementations, such as gawk and mawk, will have
-# additional options that this does not complete. Also, currently
-# this completion does not allow everything that POSIX allows. For
-# example, awk(P) states that the user may specify assignments
-# without using the -v option; this does not support that.
+#compdef awk gawk nawk
+
+# For gawk ver.3 and 4, in addition to POSIX.
+#
+# gawk's options '-W ...' (such as '-W help') are not supported.
+# gawk3 has some synonyms for long options (e.g., --compat is a synonym
+# for --traditional). These are not supported either.
 #
-# In addition, the "program text" completion is not perfect. For
-# instance, type "awk -" and then hit tab. You will be presented
-# both with the dashed options and with the "program text" option.
-# Fixing this is beyond my current _arguments expertise--help
-# appreciated.
-
-_arguments -S -s '-F+[define input field separator to be an extended regular expression]:extended regular expression:' \
-    '*-v+[assign values to variables]:assignment:' \
-    '(1)-f+[program file]:program file:_files' \
-    '1:program text:' \
-    '*:input files:_files'
+# 'gawk -f<TAB>' will complete files in AWKPATH in addition to those in
+# the current directory. If this is annoying, you may try
+#   zstyle ':completion:*:*:gawk:option-f-1:*' tag-order program-files
+
+local variant curcontext="$curcontext" state state_descr line ret=1
+local -A opt_args
+local -a args
+
+_pick_variant -r variant gawk4='GNU Awk 4' gawk3='GNU Awk 3' posix --version
+
+args=(
+  {-F+,--field-separator}'[define input field separator by extended regex]:extended regular expression:'
+  '*'{-v+,--assign}'[assign values to variables]:assignment:'
+  '(1)*'{-f+,--file}'[read program file]:program file:->script'
+  '1: :_guard "^-*" "program text"'
+  '*:input files:_files'
+)
+
+case $variant in
+  (gawk*)
+    args+=(
+      {-c,--traditional}'[run in compatibility mode]'
+      '(- : *)'{-C,--copyright}'[print copyright info and exit]'
+      {-d-,--dump-variables=-}'[print a sorted list of global variables]::output file:_files'
+      {-e,--source}'[pass program text in arg]:program text:'
+      '(1)'{-E+,--exec}'[like -f, but safer for CGI]:program file:->script'
+      '(- : *)'{-h,--help}'[print usage message and exit]'
+      {-L-,--lint=-}'[warn about dubious or non-portable constructs]::flag:((fatal\:"treat warnings as fatal error" invalid\:"warn only about things that are actually invalid"))'
+      {-n,--non-decimal-data}'[auto-detect octal/hexadecimal values in input]'
+      {-N,--use-lc-numeric}"[force use of locale's decimal point character]"
+      {-O,--optimize}'[enable optimization]'
+      {-p-,--profile=-}'[output profiling data to file]::output file:_files'
+      {-P,--posix}'[run in strict POSIX mode]'
+      {-r,--re-interval}'[enable interval expressions in regex matching]'
+      {-t,--lint-old}'[warn about non-portable constructs]'
+      '(- : *)'{-V,--version}'[print version info and exit]'
+    )
+    ;|
+  (gawk4)
+    args+=(
+      {-b,--characters-as-bytes}'[treat all input data as single-byte characters]'
+      {-D-,--debug=-}'[enable debugging]::debugger command file:_files'
+      {-g,--gen-pot}'[scan awk program and generate .po file on stdout]'
+      '*'{-i+,--include}'[load source library]:library file:->script'
+      '*'{-l+,--load}'[load dynamic extension]:extension:->extension'
+      {-M,--bignum}'[select arbitrary-precision arithmetic on numbers]'
+      {-o-,--pretty-print=-}'[pretty-print awk program]::output file:_files'
+      {-S,--sandbox}'[disable system(), redirections and dynamic extensions]'
+    )
+    ;;
+  (gawk3)
+    # one letter options are new in gawk4
+    args=( ${args:#(|\*)(|\(*\))-[cCdEhLnNtOpPreV]*} )
+    args+=(
+      '--gen-po[scan awk program and generate .po file on stdout]'
+    )
+    ;;
+  (*)
+    # remove long options
+    args=( ${args:#*--*} )
+esac
+
+_arguments -S -s -C : $args && ret=0
+
+# Complete files in . (current directory) and AWKPATH/AWKLIBPATH.
+# Use different tag/description for files in . even if . is in AWKPATH.
+_files_in_curdir_or_path() {
+  local expl pat1 pat2
+  if [[ -n $6 ]]; then  # $6 = 'so', 'dll' or ''
+    pat1="-g *.$6"
+    pat2="-g *.$6"
+  fi
+  if [[ $words[CURRENT] == */* || $variant != gawk* || \
+	-n $opt_args[(I)(-c|--traditional|-P|--posix)] ]]; then
+    _wanted $2 expl $3 _files $pat1 && ret=0
+  else
+    local prog='BEGIN {print ENVIRON["'$1'"]}'
+    local -aU paths
+    # split AWKPATH into paths, and replace null element by '.'.
+    paths=( "${(@)${(@s.:.)$(_call_program get-awk-env \
+			    $words[1] ${(q)prog})}:/#%/.}" )
+    if (( $paths[(I).] )); then
+      # If '.' is in paths, remove it; we will handle it separately
+      paths=( ${(@)paths:#.} )
+    else
+      # If '.' is not in paths, we should not complete files in '.'
+      pat1='-g *(-/)'
+    fi
+    if (( $#paths )); then
+      _alternative "${2}:${3}:_files ${(b)pat1}" \
+		  "${4}:${5}:_files -W paths ${(b)pat2}" && ret=0
+    else
+      _wanted $2 expl $3 _files $pat1 && ret=0
+    fi
+  fi
+}
+
+case $state in
+  (script)
+    _files_in_curdir_or_path AWKPATH program-files 'program file' \
+			    library-files 'library in AWKPATH'
+    ;;
+  (extension)
+    local ext=so
+    [[ $OSTYPE == cygwin* ]] && ext=dll
+    _files_in_curdir_or_path AWKLIBPATH extensions 'extension' \
+			    library-files 'extension in AWKLIBPATH' $ext
+    ;;
+esac
+
+return ret
diff --git a/Completion/Unix/Command/_basename b/Completion/Unix/Command/_basename
new file mode 100644
index 000000000..a826b56b0
--- /dev/null
+++ b/Completion/Unix/Command/_basename
@@ -0,0 +1,27 @@
+#compdef basename gbasename
+
+local args variant
+_pick_variant -r variant gnu=GNU $OSTYPE --version
+
+case $variant in
+  gnu)
+    args=( -s -S -A "-*"
+      '(2 -a --multiple)'{-a,--multiple}'[support multiple arguments, handling each]'
+      '(2 -a --multiple -s --suffix)'{-s+,--suffix=}'[remove a trailing suffix]:suffix'
+      '(-z --zero)'{-z,--zero}'[separate output with NUL rather than newline]'
+      '(- *)--version[display version information]'
+      '(- *)--help[display help information]'
+    )
+  ;;
+  darwin*|dragonfly*|freebsd*)
+    args=( -s -S -A "-*"
+      '(2)-a[support multiple arguments, handling each]'
+      '(-a 2)-s+[remove a trailing suffix]:suffix'
+    )
+  ;;
+esac
+
+_arguments $args \
+  '1:file:_files' \
+  '(*)2:suffix' \
+  '*:file:_files'
diff --git a/Completion/Unix/Command/_bzr b/Completion/Unix/Command/_bzr
index 28ebd145c..1b755b4ec 100644
--- a/Completion/Unix/Command/_bzr
+++ b/Completion/Unix/Command/_bzr
@@ -375,7 +375,7 @@ case $cmd in
 (gannotate|gblame|gpraise)
     args+=(
 	'--all[show annotations on all lines]'
-	'--plain[do not hightlight annotation lines]'
+	"--plain[don't highlight annotation lines]"
 	'*:files:_bzr_versionedFiles'
 	)
     ;;
diff --git a/Completion/Unix/Command/_cat b/Completion/Unix/Command/_cat
index e223d90d9..46180f2c8 100644
--- a/Completion/Unix/Command/_cat
+++ b/Completion/Unix/Command/_cat
@@ -19,8 +19,9 @@ if _pick_variant gnu=GNU unix --version; then
     '*:files:_files'
   )
 
-elif [[ "$OSTYPE" == (freebsd|dragonfly|darwin)* ]]; then
+elif [[ "$OSTYPE" == (*bsd|dragonfly|darwin)* ]]; then
   args=(
+    -A "-*"
     '(-n)-b[number non-blank output lines]'
     '(-v)-e[display $ at the end of each line (implies -v)]'
     '-n[number all output lines]'
@@ -28,9 +29,27 @@ elif [[ "$OSTYPE" == (freebsd|dragonfly|darwin)* ]]; then
     '(-v)-t[display tab as ^I (implies -v)]'
     '-u[do not buffer output]'
     '-v[display non-printing chars as ^X or M-a]'
-    '(-)*:files:_files'
+    '*:files:_files'
+  )
+  [[ $OSTYPE = (free|net)bsd* ]] && args+=(
+    '-l[set a lock on the stdout file descriptor]'
+  )
+  [[ $OSTYPE = netbsd* ]] && args+=(
+    '-B+[read with buffer of specified size]:size (bytes)'
+    '-f[only attempt to display regular files]'
+  )
+elif [[ $OSTYPE = solaris* ]]; then
+  args=(
+    -A "-*"
+    '(-b)-n[number all output lines]'
+    '(-n)-b[number non-blank output lines]'
+    "-u[don't buffer output]"
+    '-s[be silent about non-existent files]'
+    '-v[display non-printing chars as ^X or M-a]'
+    '-e[display $ at the end of each line (requires -v)]'
+    '-t[display tab as ^I and formfeeds and ^L (requires -v)]'
+    '*:files:_files'
   )
-
 else
   # POSIX reqires '-u', and most OSes may support '-n'
   args=(
@@ -40,4 +59,4 @@ else
   )
 fi
 
-_arguments -s -S : $args
+_arguments -s -S $args
diff --git a/Completion/Unix/Command/_cdrdao b/Completion/Unix/Command/_cdrdao
index ad1bf4034..ceb86267c 100644
--- a/Completion/Unix/Command/_cdrdao
+++ b/Completion/Unix/Command/_cdrdao
@@ -211,7 +211,7 @@ __cdrdao-simulate-or-write () {
     $_cdrdao_common_toc_device_args \
     $_cdrdao_speed_arg \
     '--multi[do not close the session after successful write]' \
-    '--overburn[allow overburing of medium]' \
+    '--overburn[allow overburning of medium]' \
     '--full-burn[force burning to the outer disk edge]' \
     $_cdrdao_capacity_arg \
     $_cdrdao_eject_arg \
@@ -262,14 +262,14 @@ _cdrdao-copy () {
 __cdrdao-device () {
   # Use cdrdao scanbus and also check what OS we're running under and provide
   # additional stuff, like devices (/dev/sg0)
-  local -a devices
+  local -a expl devices
   devices=(${${(f)"$(_call_program devices cdrdao scanbus -v 0 2>&1)"}%% :*})
 
   _wanted devices expl 'device' compadd -a devices
 }
 
 __cdrdao-drivers () {
-  local suf
+  local expl suf
   local -Ua drivers
   drivers=(${(f)"$(_call_program drivers cut -d'\|' -f4 /usr/share/cdrdao/drivers -s)"})
   if compset -P \*:; then
diff --git a/Completion/Unix/Command/_chown b/Completion/Unix/Command/_chown
index 641b5a773..5750c65ab 100644
--- a/Completion/Unix/Command/_chown
+++ b/Completion/Unix/Command/_chown
@@ -45,8 +45,8 @@ _arguments -C -s "$args[@]" '*:files:->files' && ret=0
 case $state in
   owner)
     if [[ $service = chgrp ]] || compset -P '*[:.]'; then
-      if (( EGID && $+commands[groups] && ! $+funcstack[(r)_sudo] )); then  # except for root
-       _wanted groups expl 'group' compadd $(groups) && return 0
+      if (( EGID && $+commands[groups] && ! $+_comp_priv_prefix )); then  # except for sudo
+       _wanted groups expl 'group' compadd -- $(groups) && return 0
       fi
       _groups && ret=0
     else
diff --git a/Completion/Unix/Command/_cp b/Completion/Unix/Command/_cp
index 7087b4e6c..5c3f37983 100644
--- a/Completion/Unix/Command/_cp
+++ b/Completion/Unix/Command/_cp
@@ -57,7 +57,8 @@ else
     '(dragonfly|freebsd)*' '-l[link files instead of copying]' \
     '(darwin|dragonfly|freebsd|netbsd)*' '-v[show file names as they are copied]' \
     'darwin*' "-X[don't copy extended attributes or resource forks]" \
-    '(dragonfly|freebsd)*' "-x[don't traverse file systems]"
+    '(dragonfly|freebsd)*' "-x[don't traverse file systems]" \
+    'freebsd<10->.*' '-s[make symbolic links instead of copies of non-directories]'
   do
     [[ $OSTYPE = $~pattern ]] && args+=( $arg )
   done
diff --git a/Completion/Unix/Command/_cpio b/Completion/Unix/Command/_cpio
index 6b07a214a..699b1d8f2 100644
--- a/Completion/Unix/Command/_cpio
+++ b/Completion/Unix/Command/_cpio
@@ -1,6 +1,7 @@
 #compdef cpio
 
-local args ig curcontext="$curcontext" state line
+local -a args
+local ig curcontext="$curcontext" state line
 local expl ret=1
 local fmts='(bar bin odc newc crc tar ustar hpbin hpodc)'
 
@@ -106,10 +107,10 @@ fi
 _arguments -C -s "$args[@]" && ret=0
 
 if [[ $state = afile ]]; then
-  if compset -P '*:'; then
-    # TODO: doesn't need to be rsh.
-    _wanted files expl 'remote files' \
-       compadd $(rsh ${words[CURRENT]%:*} echo ${words[CURRENT]#*:}\*) && ret=0
+  if [[ $ig != gnu ]]; then
+    _files && ret=0
+  elif compset -P 1 '*:'; then
+    _remote_files -- ssh && ret=0
   elif compset -P '*@'; then
     _wanted hosts expl 'remote host name' _hosts && ret=0
   else
diff --git a/Completion/Unix/Command/_cscope b/Completion/Unix/Command/_cscope
new file mode 100644
index 000000000..8c3839d10
--- /dev/null
+++ b/Completion/Unix/Command/_cscope
@@ -0,0 +1,29 @@
+#compdef cscope
+
+_arguments -s -S \
+  '-b[build the cross-reference only]' \
+  '-C[ignore letter case when searching]' \
+  "-c[use only ASCII characters in the cross-ref file (don't compress)]" \
+  "-d[don't update the cross-reference]" \
+  '-e[suppress the <Ctrl>-e command prompt between files]' \
+  '-F+[read symbol reference lines from specified file]:symbol-reference file:_files' \
+  '-f+[specify cross-reference file]:cross-reference file [cscope.out]:_files' \
+  '(-)'{-h,--help}'[display help information]' \
+  '*-I+[specify directory to search for #include files]:include directory:_directories' \
+  '-i+[specify file containing a list if files to browse]:file [cscope.file]:_files' \
+  "-k[kernel mode - don't use /usr/include for #include files]" \
+  '-L[do a single search with line-oriented output]' \
+  '-l[line-oriented interface]' \
+  -{0,1,2,3,4,5,6,7,8,9}'+:pattern' \
+  '-P+[prepend path to relative file names in pre-built cross-ref file]:path:_directories' \
+  '-p+[specify number of path components to display]:path components [1]' \
+  '-q[build an inverted index for quick symbol searching]' \
+  '-R[recurse directories for files]' \
+  '-s+[specify directory to search for additional source files]:directory:_directories' \
+  '-T[use only the first eight characters to match against C symbols]' \
+  '-U[check file time stamps]' \
+  '-u[unconditionally build the cross-reference file]' \
+  '-v[be more verbose in line mode]' \
+  '-X[remove the cscope reference file and inverted indexes at end]' \
+  '(-)'{-V,--version}'[display version information]' \
+  '*:file:_files'
diff --git a/Completion/Unix/Command/_cvs b/Completion/Unix/Command/_cvs
index 31997ec09..0552d2175 100644
--- a/Completion/Unix/Command/_cvs
+++ b/Completion/Unix/Command/_cvs
@@ -3,10 +3,7 @@
 # redefine _cvs.
 
 _cvs() {
-  local extra
-
   # "+Qqrwtnlvb:T:e:d:Hfz:s:xa"
-
   _arguments -s \
     '-R[read only access]' \
     '-a[authenticate]' \
@@ -598,7 +595,7 @@ _cvs_tempdir() {
 
 (( $+functions[_cvs_user_variable] )) ||
 _cvs_user_variable() {
-  if compset -P '*='; then
+  if compset -P 1 '*='; then
     _default
   else
     _message -e variables "variable"
diff --git a/Completion/Unix/Command/_darcs b/Completion/Unix/Command/_darcs
index d40ecda28..74734711d 100644
--- a/Completion/Unix/Command/_darcs
+++ b/Completion/Unix/Command/_darcs
@@ -13,6 +13,8 @@
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ## GNU General Public License for more details.
 
+local expl
+
 if (($CURRENT == 2)); then
   # We're completing the first word after "darcs" -- the command.
   _wanted command expl 'darcs command' \
diff --git a/Completion/Unix/Command/_date b/Completion/Unix/Command/_date
index ff3bac398..a3e933710 100644
--- a/Completion/Unix/Command/_date
+++ b/Completion/Unix/Command/_date
@@ -1,57 +1,99 @@
 #compdef date gdate
 
-local -a args alts
+local curcontext="$curcontext" state state_descr line ret=1
+local -A opt_args
+local -a opts args
+
+opts=( -s -w -C )
 
 if _pick_variant gnu="Free Software Foundation" unix --version; then
+  local d='(-d --date -f --file -r --reference -s --set)'
+  local f='(-I --iso-8601 -R --rfc-email --rfc-3339)'
   args=(
-    '-d[output specified date]:time string'
-    '-f[output dates specified in file]:file:_files'
-    '-I-[iso-8601]:precision:(date hours minutes seconds)'
-    '-r[reference]:file:_files'
-    '-R[RFC2822 format]'
-    '-s[set]:time string'
-    '--rfc-3339=-[output date and time in RFC 3339 format]:output type:(date seconds ns)'
-    --
-    '*=FILE*:file:_files'
-    '*=DATEFILE*:date file:_files'
+    $d{-d+,--date=}'[output date specified by string]:time string'
+    '--debug[annotate parsed date and warn about questionable usage]'
+    $d{-f+,--file=}'[output dates specified in file]:file:_files'
+    $d{-r+,--reference=}'[output last modification time of specified file]:file:_files'
+    $d{-s+,--set=}'[set time]:time string'
+    $f{-I-,--iso-8601=-}'[display in ISO 8601 format]::precision:(date hours minutes seconds ns)'
+    $f{-R,--rfc-email}'[display in RFC5322 format]'
+    $f'--rfc-3339=-[display in RFC 3339 format]:precision:(date seconds ns)'
+    '(-u --utc --universal)'{-u,--utc,--universal}'[display or set time in UTC]'
+    '(- :)--help[output help and exit]'
+    '(- :)--version[output version info and exit]'
   )
 else
+  args=( '-u[display or set time in UTC]' )
   case "$OSTYPE" in
     solaris*)
-      args=( '-a:adjustment' )
+      args+=( '-a:adjustment' )
     ;;
-    darwin*|dragonfly*|netbsd*|openbsd*)
-      args+=( '-r[specify reference time]:seconds since epoch' )
-    ;|
-    freebsd*|darwin*|dragonfly*|netbsd*|openbsd*)
-      args=(
-	'-n[only set time on current machine]'
-	'-d:daylight saving time value'
+    freebsd*|dragonfly*|darwin*|netbsd*|openbsd*)
+      opts+=( -A '-*' )
+      args+=(
 	'-j[do not try to set date]'
-	'-t:minutes west of GMT'
+	'2:format or date:->fmt_date'
+      )
+    ;|
+    freebsd*|dragonfly*|darwin*|netbsd*)
+      args+=( '-n[only set time on current machine]' )
+    ;|
+    freebsd*|dragonfly*|darwin*|openbsd*)
+      args+=(
+	'-d+:daylight saving time value'
+	'-t+:minutes west of GMT'
+      )
+    ;|
+    dragonfly*|darwin*|netbsd*|openbsd*)
+      args+=(
+	'-r+[output date specified by reference time]:seconds since epoch'
       )
     ;|
     freebsd*)
+      local -a alts
       alts=(
 	'seconds:sec:_guard "(0x[0-9a-fA-F]#|[0-9]#)" "seconds since epoch"'
 	'files:file:_files'
       )
       args+=(
-	'-r[reference time: file modification or literal time]:reference: _alternative $alts'
-	'-R[RFC2822 format]'
+	'-r+[reference time: file modification or literal time]:reference: _alternative $alts'
       )
     ;|
     freebsd*|dragonfly*|darwin*)
-      args+=( '-f:parsing format' '-v:adjustment value' )
+      args+=(
+	'-f+[use specified format for input]:parsing format:_date_formats:new date:'
+	'*-v+[adjust and print (but not set) date]:[+-]value[ymwdHMS]:'
+      )
     ;;
+    freebsd*|dragonfly*)
+      args+=( '-R[display in RFC2822 format]' )
+    ;|
+    openbsd*|netbsd*) args+=( '-a[gradually skew]' )
+    ;|
     openbsd*)
       args+=( '-z[specify timezone for output]:time zone:_time_zone')
     ;|
-    openbsd*|netbsd*) args=( '-a[gradually skew]' ) ;;
+    netbsd*)
+      args+=( '-d[output date specified by string]:time string:' )
+    ;;
   esac
 fi
 
-_arguments \
-  '-u[display or set time in UTC]' \
-  ': :_guard "^--*" "format or date"' \
-  "$args[@]"
+_arguments $opts : $args \
+  '1:format or date:->fmt_date' && ret=0
+
+case $state in
+  (fmt_date)
+    local expl
+    if compset -P '+'; then
+      _wanted date-formats expl 'output format' _date_formats && ret=0
+    elif [[ $words[CURRENT] != -* ]]; then
+      # TODO: in most cases it should be possible to determine which
+      # (or both or neither) of the +format and/or date is allowed
+      # depending on the options already on the command line
+      _message -e date-formats '+format or date' && ret=0
+    fi
+    ;;
+esac
+
+return ret
diff --git a/Completion/Unix/Command/_dbus b/Completion/Unix/Command/_dbus
index bdd7613f0..3f106cb5c 100644
--- a/Completion/Unix/Command/_dbus
+++ b/Completion/Unix/Command/_dbus
@@ -13,24 +13,27 @@ case $service in
       '--print-reply=-::format:(literal)' \
       '--reply-timeout=-:timeout (ms)' \
       '--type=-:type:(method_call signal)' \
+      '(* -)--help' \
       ':object path:->objectpaths' \
       ':message name:->methods' \
       ':content:->contents' && ret=0
   ;;
   dbus-monitor)
     _arguments -A "--*" -C \
-      '(--session)--system' '(--system)--session' \
+      '*:watch expression:->expressions' \
+      - '(bus)' \
+      --system --session \
       '--address=-:bus address:->addresses' \
-      '(--profile)--monitor' '(--monitor)--profile' \
-      '*:watch expression:->expressions' && ret=0
+      - '(format)' \
+      --monitor --profile --pcap --binary && ret=0
   ;;
 esac
 
 case $state in
   addresses)
     compset -P '*;'
-    if compset -P '*='; then
-      _files  && ret=0
+    if compset -P 1 '*='; then
+      _files && ret=0
     else
       _message -e addresses address
     fi
diff --git a/Completion/Unix/Command/_devtodo b/Completion/Unix/Command/_devtodo
index dbc64f870..2380399b9 100644
--- a/Completion/Unix/Command/_devtodo
+++ b/Completion/Unix/Command/_devtodo
@@ -32,11 +32,11 @@ arg_generic=(
 	'--help[display help]'
 	'--version[display version]'
 	'--title[todo title]:string: '
-	'--date-format[strftime time formet]:time string: '
+	'--date-format[strftime time format]:time string:_date_formats'
 	'*--format[define format]:format:_todo_format'
 	'*--use-format[output format]:format:_todo_format'
 	'--sort[sort database]:sort expression:_todo_sort'
-	'--paranoid[paranoid parmissions etc]'
+	'--paranoid[paranoid permissions etc]'
 	'--database-loaders[loader order]:database loader: '
 	'--backup[backup database]:count: '
 	'--timeout[display timeout]:seconds: '
diff --git a/Completion/Unix/Command/_df b/Completion/Unix/Command/_df
index a98180a2c..677b8c727 100644
--- a/Completion/Unix/Command/_df
+++ b/Completion/Unix/Command/_df
@@ -5,12 +5,6 @@ local -A opt_args
 
 if _pick_variant gnu=GNU unix --version; then
   args=(
-    '(-B --block-size -k)'{-B+,--block-size=}'[specify block size]:size (bytes)'
-    '(-B --block-size -k)-k[like --block-size=1K]'
-    '(-P --portability)'{-P,--portability}'[use the POSIX output format]'
-    '(-h --human-readable -H --si)'{-h,--human-readable}'[print sizes in human readable format]'
-    '(-h --human-readable -H --si)'{-H,--si}'[human readable fomat, but use powers of 1000 not 1024]'
-    '(-i --inodes)'{-i,--inodes}'[list inode information instead of block usage]'
     '--total[produce a grand total]'
     '(-T --print-type)'{-T,--print-type}'[print file system type]'
     '(-a --all)'{-a,--all}'[include dummy file systems]'
@@ -23,6 +17,13 @@ if _pick_variant gnu=GNU unix --version; then
     '(- : *)--help[display help and exit]'
     '(- : *)--version[output version information and exit]'
     '*:files:_files'
+    - '(format)'
+    {-B+,--block-size=}'[specify block size]:size (bytes)'
+    '-k[like --block-size=1K]'
+    {-P,--portability}'[use the POSIX output format]'
+    {-h,--human-readable}'[print sizes in human readable format]'
+    {-H,--si}'[human readable format, but use powers of 1000 not 1024]'
+    {-i,--inodes}'[list inode information instead of block usage]'
   )
 elif [[ "$OSTYPE" == (darwin|freebsd|dragonfly)* ]]; then
   args=(
diff --git a/Completion/Unix/Command/_dmesg b/Completion/Unix/Command/_dmesg
new file mode 100644
index 000000000..3dd059214
--- /dev/null
+++ b/Completion/Unix/Command/_dmesg
@@ -0,0 +1,32 @@
+#compdef dmesg
+
+local args
+
+case $OSTYPE in
+  linux*) args=( -S --  ) ;;
+  darwin*|dragonfly*|*bsd*)
+    args=(
+      '-M[extract values from core]:core file:_files'
+      '-N[extract name list from kernel image]:system:_files'
+    )
+  ;|
+  dragonfly*|freebsd*)
+    args=(
+      '-a[show all data, including syslog and console]'
+      '-c[clear the buffer after printing]'
+    )
+  ;|
+  openbsd*)
+    args+=(
+      '-s[show console message buffer instead]'
+    )
+  ;;
+  dragonfly*)
+    args+=(
+      '\*-f[follow buffer, displaying new data as it arrives]'
+      '-n[use specified kernel core]:number'
+    )
+  ;;
+esac
+
+_arguments -s $args
diff --git a/Completion/Unix/Command/_dmidecode b/Completion/Unix/Command/_dmidecode
index 0ff56113d..b48608dae 100644
--- a/Completion/Unix/Command/_dmidecode
+++ b/Completion/Unix/Command/_dmidecode
@@ -1,10 +1,13 @@
 #compdef dmidecode
 
-_arguments \
-  '(-d --dev-mem)'{-d,--dev-mem}':memory device:_files' \
+_arguments -s \
+  '(-d --dev-mem --from-dump)'{-d+,--dev-mem=}'[read memory from specified file]:memory device [/dev/mem]:_files' \
+  '(-)'{-h,--help}'[display usage information]' \
   '(-q --quiet -u --dump)'{-q,--quiet}'[be less verbose]' \
-  '(-t --type -u --dump -s --string)'{-s,--string}':DMI string:(bios-vendor bios-version bios-release-date system-manufacturer system-product-name system-version system-serial-number system-uuid baseboard-manufacturer baseboard-product-name baseboard-version baseboard-serial-number baseboard-asset-tag chassis-manufacturer chassis-type chassis-version chassis-serial-number chassis-asset-tag processor-family processor-manufacturer processor-version processor-frequency)' \
-  '(-t --type)'{-t,--type}':types to display:(bios system baseboard chassis processor memory cache connector slot)' \
-  '(-q --quiet -u --dump -s --string)'{-u,--dump}'[do not decode]' \
-  '(-h --help)'{-h,--help}'[display usage information]' \
-  '(-V --version)'{-V,--version}'[display version information]'
+  '(--type -u --dump --dump-bin -s --string)'{-s+,--string=}':DMI string:(bios-vendor bios-version bios-release-date system-manufacturer system-product-name system-version system-serial-number system-uuid baseboard-manufacturer baseboard-product-name baseboard-version baseboard-serial-number baseboard-asset-tag chassis-manufacturer chassis-type chassis-version chassis-serial-number chassis-asset-tag processor-family processor-manufacturer processor-version processor-frequency)' \
+  '(-s --string --dump-bin)*'{-t+,--type=}'[only display entries of specified type]:entry type:(bios system baseboard chassis processor memory cache connector slot)' \
+  '(-q --quiet -u --dump -s --string)'{-u,--dump}"[don't decode entries]" \
+  '--dump-bin=[dump DMI data to a binary file]:file:_files' \
+  '(-d --dev-mem)--from-dump=[read DMI data from a binary file]:file:_files' \
+  "--no-sysfs[don't attempt to read DMI data from sysfs files]" \
+  '(-)'{-V,--version}'[display version information]'
diff --git a/Completion/Unix/Command/_doas b/Completion/Unix/Command/_doas
new file mode 100644
index 000000000..94395557c
--- /dev/null
+++ b/Completion/Unix/Command/_doas
@@ -0,0 +1,22 @@
+#compdef doas
+
+local environ e cmd
+local -a _comp_priv_prefix
+
+zstyle -a ":completion:${curcontext}:" environ environ
+
+for e in "${environ[@]}"
+do local -x "$e"
+done
+
+cmd="$words[1]"
+_arguments -s -S -A '-*' : \
+  - optL \
+  '-L[clear any persisted authorizations]' \
+  - default \
+  '-a+[specify authentication style]:authentication style' \
+  '(-n -s)-C+[check config file and report on command matching]:config:_files' \
+  '(-C)-n[non-interactive: fail rather than prompt for a password]' \
+  '(-C *)-s[run a shell]' \
+  '-u+[run command as specified user]:user:_users' \
+  '*::arguments:{ _comp_priv_prefix=( $cmd -n ${(kv)opt_args[-u]} ) ; _normal }'
diff --git a/Completion/Unix/Command/_dsh b/Completion/Unix/Command/_dsh
index 688e024ce..fc7680062 100644
--- a/Completion/Unix/Command/_dsh
+++ b/Completion/Unix/Command/_dsh
@@ -2,6 +2,7 @@
 
 local curcontext="$curcontext" state line expl
 typeset -A opt_args
+local -a _comp_priv_prefix
 
 _arguments -s -C -S \
   '(-v --verbose -q --quiet)'{-v,--verbose}'[verbose output]' \
@@ -24,7 +25,7 @@ _arguments -s -C -S \
   '*::args: _normal' && return
 
 if [[ $state = groups ]]; then
-  if ! zstyle -s ":completion:$curcontext:dsh-groups" dsh-groups grp; then
+  if ! zstyle -s ":completion:${curcontext}:dsh-groups" dsh-groups grp; then
     [[ -e ~/.dsh/group ]] && grp="~/.dsh/group" || return 1
   fi
   _path_files -W ~/.dsh/group && return
diff --git a/Completion/Unix/Command/_entr b/Completion/Unix/Command/_entr
new file mode 100644
index 000000000..8a830ae71
--- /dev/null
+++ b/Completion/Unix/Command/_entr
@@ -0,0 +1,9 @@
+#compdef entr
+
+_arguments -s -S \
+  '-c[execute clear before invoking utility]' \
+  '-d[track directories and exit if a new file is added]' \
+  '-p[postpone first execution of the utility]' \
+  '-r[reload a persistent child process]' \
+  '(-):command name:_command_names -e' \
+  '*::arguments:_normal'
diff --git a/Completion/Unix/Command/_env b/Completion/Unix/Command/_env
index 96261bba8..9b2a1e011 100644
--- a/Completion/Unix/Command/_env
+++ b/Completion/Unix/Command/_env
@@ -1,13 +1,46 @@
 #compdef env
 
-if _pick_variant gnu=Free\ Soft unix --version; then
-  _arguments \
-    '(--ignore-environment -i)'{-i,--ignore-environment}'[start with empty environment]' \
-    '*'{-u,--unset=}'[remove variable from the environment]:env var to remove:compadd ${(k)parameters[(R)*export*]}' \
-    '--help[help]' \
-    '--version[version]' \
-    '(-):command: _command_names -e' \
-    '*::arguments: _normal'
-else
-  _precommand
+local context state line variant args ret=1
+
+_pick_variant -r variant gnu=Free\ Soft $OSTYPE --version
+case $variant in
+  gnu)
+    args=(
+      '(-)'{-i,--ignore-environment}'[start with empty environment]'
+      '(--ignore-environment -i --help --version)*'{-u,--unset=}'[remove variable from the environment]:env var to remove:_parameters -g "*export*"'
+      '(- *)--help[display help information]'
+      '(- *)--version[display version information]'
+    )
+  ;;
+  freebsd*)
+    args=(
+      '(-i)*-u[remove variable from the environment]:env var to remove:_parameters -g "*export*"'
+      '-P[specify alternate executable search PATH]:path:_dir_list'
+      '-S[perform word splitting]'
+      '*-v[verbose output]'
+    )
+  ;&
+  *)
+    if (( $words[(i)-] < CURRENT )); then
+      words[(i)-]=()
+      (( CURRENT-- ))
+    else
+      args+=(
+	'(-i)'{-,-i}'[start with empty environment]'
+      )
+    fi
+  ;;
+esac
+
+_arguments $args \
+  '*::arguments:->normal' && ret=0
+
+if [[ -n $state ]]; then
+  while [[ $words[1] = *=* ]]; do
+    shift words
+    (( CURRENT-- ))
+  done
+  _normal && ret=0
 fi
+
+return ret
diff --git a/Completion/Unix/Command/_espeak b/Completion/Unix/Command/_espeak
index d868c7912..4ab443bba 100644
--- a/Completion/Unix/Command/_espeak
+++ b/Completion/Unix/Command/_espeak
@@ -1,33 +1,46 @@
 #compdef espeak
 
-#TODO: complete non-existing filenames for -w and --phonout
-#TODO: describe special cases for -k
-#TODO: complete --punct better?
+local curcontext="$curcontext" state line expl ret=1
+typeset -A opt_args
 
-_arguments \
-    '-h[help]' \
-    '-f[file to speak]:text file:_files' \
-    '--stdin[speak from stdin]' \
-    '-q[quiet, no sound output]' \
-    '-a[amplitude]:integer:(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
-18 19 20)' \
-    '-l[line length]:integer: ' \
-    '-p[pitch]:integer:(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
-19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
-43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
-67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
-91 92 93 94 95 96 97 98 99)' \
-    '-s[speed]:words per minute: ' \
-    '-v[voice]:voice name:(afrikaans bosnian catalan czech welsh-test danish-test german greek default en-scottish english lancashire english_rp english_wmids english-us en-westindies esperanto spanish spanish-latin-american finnish french french greek-ancient hindi-test croatian hungarian armenian armenian-west indonesian-test icelandic-test italian test/jbo kurdish latin latvian macedonian-test dutch-test norwegian-test test/pap polish brazil portugal romanian russian_test slovak albanian serbian swedish swahihi-test tamil turkish vietnam-test Mandarin cantonese-test)' \
-    '-b[8-bit text]' \
-    '-m[SSML or other XML text]' \
-    '-w[wav output]:filename: ' \
-    '-x[output phoneme mnemonics]' \
-    '-X[output phoneme mnemonics and translation trace]' \
-    '--stdout[output speech to stdout]' \
-    '-k[capital letter indication]:integer:' \
-    '--punct=-::characters: ' \
-    '--voices=-[list available voices]::language code:(af bs ca cs cy da de el en en-sc en-uk en-uk-north en-uk-rp en-uk-wmids en-us en-wi eo es es-la fi fr fr-be grc hi hr hu hy hy id is it jbo ku la lv mk nl no pap pl pt pt-pt ro ru sk sq sr sv sw ta tr vi zh zh-yue)' \
-    '--path=-[espeak-data path]:path:_files -/' \
-    '--compile=-[compile]::voicename or debug: ' \
-    '--phonout=-[output filename for -x/-X]:filename: ' 
+_arguments -C \
+  '(1 --stdin)-f+[specify file to speak]:text file:_files' \
+  '(1 -f)--stdin[speak from stdin]' \
+  '(-q)-a+[specify amplitude]:amplitude (0-200) [100]' \
+  '(-q)-g+[specify pause between words]:pause (10ms) [1]' \
+  '-k[capital letter indication]:integer:((1\:sound 2\:the\ word\ "capitals"))' \
+  '-l[specify line length below which clause is ended]:length' \
+  '(-q)-p+[specify pitch adjustment]:adjustment (0-99)' \
+  '(-q)-s+[specify speed]:speed (words per minute) [175]' \
+  '(-q)-v+[voice]:voice name:->voices' \
+  '(--stdout -q)-w+[write speech to wav file]:wav file:_files -g "*.wav(-.)"' \
+  '-b+[specify input encoding]:encoding:((1\:UTF-8 2\:8-bit 3\:16-bit))' \
+  '-m[interpret SSML markup, ignore other XML]' \
+  '(-a -g -p -s -v -w -z --split --stdout)-q[quiet, no sound output]' \
+  '(-x --ipa)-x[output phoneme mnemonics]' \
+  '(-X --ipa)-X[output phoneme mnemonics and translation trace]' \
+  '(-q)-z[suppress final sentence pause at the end of the text]' \
+  '--compile=-[compile pronunciation rules and dictionary]::voicename or debug' \
+  '(-x -X)--ipa=-[output phonemes using International Phonetic Alphabet]::options:((1\:use\ ties 2\:use\ ZWJ 3\:separate\ with\ _))' \
+  '--path=[specify espeak-data path]:path:_files -/' \
+  '--pho[output mbrola phoneme data]' \
+  '--phonout=[output filename for -x/-X/--ipa]:filename:_files' \
+  '--punct=-[speak names of punctuation characters]::characters' \
+  '(-q --stdout)--split=[periodically start new wav file]:period (minutes)' \
+  '(-w -q --split)--stdout[output speech to stdout]' \
+  '--voices=-[list available voices]::language code:->languages' \
+  '(-)'{-h,--help}'[display help information]' \
+  '(-)--version[display version information]' && ret=0
+
+case $state in
+  voices)
+    _wanted voices expl voice compadd \
+        ${${${(f)"$(_call_program voices $words[1] --voices)"}[2,-1]#?(#c22)}%% *} && ret=0
+  ;;
+  languages)
+    _wanted languages expl language compadd \
+        ${${${(f)"$(_call_program voices $words[1] --voices)"}[2,-1]#?(#c4)}%% *} && ret=0
+  ;;
+esac
+
+return ret
diff --git a/Completion/Unix/Command/_feh b/Completion/Unix/Command/_feh
index 322b1a33c..a094e33c7 100644
--- a/Completion/Unix/Command/_feh
+++ b/Completion/Unix/Command/_feh
@@ -77,7 +77,7 @@ argument_postfix=(
 	'recursive'   '[recurse into subdirectories]'
 	'randomize'   '[randomize file list before displaying]'
 	'filelist'    '[read file list from this file]:file:_files'
-	'preload'     '[eliminate unlaodable images before displaying]'
+	'preload'     '[eliminate unloadable images before displaying]'
 	'full-screen' '[make the window fullscreen]'
 	'geometry'    '[limit window size]:geometry: '
 	'auto-zoom'   '[zoom picture to screen size]'
@@ -114,7 +114,7 @@ argument_postfix=(
 	'thumb-width' '[montage mode: Thumbnail width]:pixels: '
 	'thumb-height' '[montage mode: Thumbnail height]:pixels: '
 	'limit-width' '[montage mode: Limit montage width]:pixels: '
-	'limit-height' '[montage mode: Limit montage heihgt]:pixels: '
+	'limit-height' '[montage mode: Limit montage height]:pixels: '
 	'bg'          '[montage mode: Background image]:file:_files'
 	'alpha'       '[montage mode: Thumbnail transparency level]:integer: '
 	'font'        '[index mode: Thumbnail info font]:font: '
diff --git a/Completion/Unix/Command/_find b/Completion/Unix/Command/_find
index e736f32cb..3854d6cce 100644
--- a/Completion/Unix/Command/_find
+++ b/Completion/Unix/Command/_find
@@ -1,7 +1,7 @@
 #compdef find gfind
 
-local curcontext="$curcontext" state_descr variant
-local -a state line args alts
+local curcontext="$curcontext" state_descr variant default
+local -a state line args alts disp smatch
 
 _pick_variant -r variant gnu=GNU $OSTYPE -version
 
@@ -101,7 +101,7 @@ case $variant in
       '-D[print diagnostics]:debug option:(help tree search stat rates opt exec)'
       '-O+[enable query optimisation]:level:(1 2 3)'
       '*-daystart'
-      '-regextype:regexp syntax:(emacs posix-awk posix-basic posix-egrep posix-extended)'
+      '-regextype:regexp syntax:(help findutils-default awk egrep ed emacs gnu-awk grep posix-awk posix-basic posix-egrep posix-extended posix-minimal-basic sed)'
       '*-warn'
       '*-nowarn'
       '*-xautofs'
@@ -147,13 +147,21 @@ _arguments -C $args \
   '*-user:user:_users' \
   '*-xdev' \
   '*-a' '*-o' \
-  '*:directory:_files -/'
+  '(-D -E -H -L -O -P -f -s -x --help --version)*:directory:_files -/'
 
 if [[ $state = times ]]; then
   if ! compset -P '[+-]' || [[ -prefix '[0-9]' ]]; then
-    disp=( 'before' 'exactly' 'since' )
     compstate[list]+=' packed'
-    alts=( "senses:sense:compadd -V times -S '' -d disp - + '' -" )
+    if zstyle -t ":completion:${curcontext}:senses" verbose; then
+      zstyle -s ":completion:${curcontext}:senses" list-separator sep || sep=--
+      default=" [default exactly]"
+      disp=( "- $sep before" "+ $sep since" )
+      smatch=( - + )
+    else
+      disp=( before exactly since )
+      smatch=( - '' + )
+    fi
+    alts=( "senses:sense${default}:compadd -V times -S '' -d disp -a smatch" )
   fi
   alts+=( "times:${state_descr}:_dates -f d" )
   _alternative $alts
diff --git a/Completion/Unix/Command/_fmt b/Completion/Unix/Command/_fmt
new file mode 100644
index 000000000..759396637
--- /dev/null
+++ b/Completion/Unix/Command/_fmt
@@ -0,0 +1,60 @@
+#compdef fmt
+
+local variant
+local -a args
+local copt="[preserve indentation of first two lines]"
+local wopt="[specify maximum line width]:width [75]"
+local sopt="[don't join short lines\: split only]"
+
+args=( -A "-*" "(1 2)-w+$wopt" '*:file:_files' )
+_pick_variant -r variant gnu=GNU unix --version
+case $variant in
+  gnu)
+    args=(
+      '(-c --crown-margin)'{-c,--crown-margin}$copt
+      '(-w --width)'{-w+,--width=}$wopt
+      '(-p --prefix)'{-p+,--prefix=}'[only reformat lines with specified prefix]:prefix'
+      '(-s --split-only)'{-s,--split-only}$sopt
+      '(-t --tagged-paragraph)'{-t,--tagged-paragraph}'[indentation of first line different from second]'
+      '(-u --uniform-spacing)'{-u,--uniform-spacing}'[use one space between words, two after sentences]'
+      '(-g --goal)'{-g,--goal=}'[specify goal width]:goal width [93% of width]'
+      '(- *)--help[display help information]'
+      '(- *)--version[display version information]'
+      '*:file:_files'
+    )
+  ;;
+  solaris*)
+    args=(
+      "-c$copt"
+      "-s$sopt"
+    )
+  ;;
+  netbsd*)
+    args+=(
+      '-C[center the text]'
+      '(1 2)-g+[specify goal width]:goal width'
+      '(1 2)-m+[specify maximum width]:maximum width'
+      '-r[format all lines]'
+    )
+  ;|
+  darwin*|dragonfly*|freebsd*|openbsd*)
+    args+=(
+      '-c[center the text line by line]'
+      '-m[sensible formatting of mail header lines]'
+      '-n[format lines beginning with a . (dot) character]'
+      "-p[change in indentation doesn't start new paragraph]"
+      '-s[collapse whitespace inside lines]'
+      '-d+[specify sentence-ending characters]:sentence ends [.?!]'
+      '-l+[replace initial spaces with tabs]:tab width [8]'
+      '-t+[specify tab width of input files]:tab width [8]'
+    )
+  ;& # fall-through
+  netbsd*)
+    args+=( ':: :_guard "[0-9]#" goal width' )
+    (( ${(M)#words[1,CURRENT-1]:#[0-9]##} )) && args+=(
+      ':: :_guard "[0-9]#" maximum width'
+    )
+  ;;
+esac
+
+_arguments -s -S $args
diff --git a/Completion/Unix/Command/_fsh b/Completion/Unix/Command/_fsh
index d9ced5feb..c39373117 100644
--- a/Completion/Unix/Command/_fsh
+++ b/Completion/Unix/Command/_fsh
@@ -1,6 +1,7 @@
 #compdef fsh
 
 local curcontext="$curcontext" state line ret=1
+local -a _comp_priv_prefix
 
 _arguments -C \
   '(- : *)'{-h,--help}'[display help information]' \
diff --git a/Completion/Unix/Command/_gcc b/Completion/Unix/Command/_gcc
index 1276054db..e188c7e9f 100644
--- a/Completion/Unix/Command/_gcc
+++ b/Completion/Unix/Command/_gcc
@@ -94,7 +94,7 @@ romp)
   ;;
 mips*)
   args=(
-    '-mcpu=:CPU type:(r2000 r3000 r4000 r4400 r4600 r6000_'
+    '-mcpu=:CPU type:(r2000 r3000 r4000 r4400 r4600 r6000)'
     -mabicalls -membedded-data
     -membedded-pic -mfp32 -mfp64 -mgas -mgp32 -mgp64
     -mgpopt -mhalf-pic -mhard-float -mint64 -mips1
@@ -353,7 +353,7 @@ args+=(
   '-print-file-name=-[Display the full path to library <library>]:library:->library'
   '-print-prog-name=-[Display the full path to compiler component <program>]:program:'
   '*-specs=-[Override built-in specs with the contents of <file>]:file:_files'
-  '-std=-[Assume that the input sources are for <standard>]:standard:(c90 c89 c99 c11 gnu90 gnu89 gnu99 gnu11 c++98 c++03 gnu++98 gnu++03 c++11 gnu++11 c++1y gnu++1y)'
+  '-std=-[assume that the input sources are for specified standard]:standard:(c90 c89 c99 c11 gnu90 gnu89 gnu99 gnu11 c++98 c++03 gnu++98 gnu++03 c++11 gnu++11 c++1y gnu++1y c++14 gnu++14 c++1z gnu++1z)'
   '*-include:include file:_files -g \*.h\(-.\)'
   '*-imacros:macro input file:_files -g \*.h\(-.\)'
   '*-idirafter:second include path directory:_files -/'
diff --git a/Completion/Unix/Command/_gdb b/Completion/Unix/Command/_gdb
index d5eed5ae4..510e6f1fa 100644
--- a/Completion/Unix/Command/_gdb
+++ b/Completion/Unix/Command/_gdb
@@ -37,7 +37,7 @@ else
   (-[csx]) _files && return 0 ;;
   (-e)     _description files expl executable
            _files "$expl[@]" -g '*(-*)' && return 0 ;;
-  (-b)     _baudrate && return 0 ;;
+  (-b)     _baudrates && return 0 ;;
   esac
 
   w=( "${(@)words[2,-1]}" )
diff --git a/Completion/Unix/Command/_getent b/Completion/Unix/Command/_getent
index b9aff6642..7f4e8bc9c 100644
--- a/Completion/Unix/Command/_getent
+++ b/Completion/Unix/Command/_getent
@@ -29,6 +29,8 @@ case $state in
       databases=( "${(@)${(@f)$(_call_program databases $words[1] --help \
                    2>/dev/null)}[(r)Supported*,-1]}" )
       databases=( "${=${(@)databases[2,${(@)databases[(i)]}-1]}}" )
+    elif [[ $OSTYPE = freebsd* ]]; then
+      databases=( ${=${(f)"$(_call_program databases $words[1] 2>&1)"}[-1]} )
     else
       databases=( passwd group hosts ipnodes services protocols ethers networks netmasks )
     fi
diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git
index 2fa004a5e..a46e3b55d 100644
--- a/Completion/Unix/Command/_git
+++ b/Completion/Unix/Command/_git
@@ -53,7 +53,7 @@ _git-add () {
     ignore_missing='--ignore-missing[check if files (even missing) are ignored in dry run]'
   fi
 
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '(-n --dry-run)'{-n,--dry-run}'[do not actually add files; only show which ones would be added]' \
     '(-v --verbose)'{-v,--verbose}'[show files as they are added]' \
     '(-f --force)'{-f,--force}'[allow adding otherwise ignored files]' \
@@ -67,6 +67,7 @@ _git-add () {
     '--refresh[do not add files, but refresh their stat() info in index]' \
     '--ignore-errors[continue adding if an error occurs]' \
     $ignore_missing \
+    '--chmod[override the executable bit of the listed files]:override:(-x +x)' \
     '*:: :->file' && return
 
   case $state in
@@ -101,9 +102,10 @@ _git-am () {
   _arguments -S \
     '(-s --signoff)'{-s,--signoff}'[add Signed-off-by: line to the commit message]' \
     '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=-}'[GPG-sign the commit]::key id' \
-    '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
+    "(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[don't GPG-sign the commit]" \
     '(-k --keep)'{-k,--keep}'[pass -k to git mailinfo]' \
     '--keep-non-patch[pass -b to git mailinfo]' \
+    '(-m --message-id)'{-m,--message-id}'[pass -m flag to git-mailinfo]' \
     '(          --no-keep-cr)--keep-cr[pass --keep-cr to git mailsplit]' \
     '(--keep-cr             )--no-keep-cr[do not pass --keep-cr to git mailsplit]' \
     '(-c --scissors --no-scissors)'{-c,--scissors}'[strip everything before a scissors line]' \
@@ -150,12 +152,12 @@ _git-archive () {
     esac
   fi
 
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '--format=-[format of the resulting archive]:archive format:__git_archive_formats' \
     '(- :)'{-l,--list}'[list available archive formats]' \
     '(-v --verbose)'{-v,--verbose}'[report progress to stderr]' \
     '--prefix=-[prepend the given path prefix to each filename]:path prefix:_directories -r ""' \
-    '--output=[write archive to argument instead of stdout]:archive:_files' \
+    '(-o --output)'{-o+,--output=}'[write archive to specified file]:archive:_files' \
     '--worktree-attributes[look for attributes in .gitattributes in working directory too]' \
     $backend_args \
     '--remote=[archive remote repository]:remote repository:__git_any_repositories' \
@@ -190,6 +192,13 @@ _git-bisect () {
   # subcommand might be removed from the UI level.
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
+  local good bad
+
+  if good=$(_call_program commands git bisect terms --term-good); then
+    bad=$(_call_program commands git bisect terms --term-bad)
+  else
+    good=( good old ) bad=( new bad )
+  fi
 
   _arguments -C \
     '--help[display git-bisect manual page]' \
@@ -203,15 +212,16 @@ _git-bisect () {
       commands=(
         help:'display a short usage description'
         start:'reset bisection state and start a new bisection'
-        bad:'mark current or given revision as bad'
-        good:'mark current or given revision as good'
+        ${^bad}:'mark current or given revision as bad'
+        ${^good}:'mark current or given revision as good'
         skip:'choose a nearby commit'
         next:'find next bisection to test and check it out'
         reset:'finish bisection search and return to the given branch (or master)'
         visualize:'show the remaining revisions in gitk'
         view:'show the remaining revisions in gitk'
         replay:'replay a bisection log'
-        log:'show the log of the current bisection'
+        terms:'show currently used good/bad terms'
+        log:'show log of the current bisection'
         run:'run evaluation script')
 
       _describe -t commands command commands && ret=0
@@ -222,6 +232,9 @@ _git-bisect () {
       case $line[1] in
         (start)
           _arguments -C \
+	    --term-{good,old}'=[specify alternate term for good revisions]:term' \
+	    --term-{bad,new}'=[specify alternate term for bad revisions]:term' \
+	    '--no-checkout[set BISECT_HEAD reference instead of doing checkout at each iteration]' \
             ':bad revision:__git_commits' \
             '*: :->revision-or-path' && ret=0
           case $state in
@@ -236,11 +249,7 @@ _git-bisect () {
               ;;
           esac
           ;;
-        (bad)
-          _arguments \
-            ': :__git_commits' && ret=0
-          ;;
-        (good|skip)
+        (${(~j.|.)bad}|${(~j.|.)good}|skip)
           # TODO: skip can take revlists.
           _arguments \
             '*: :__git_commits' && ret=0
@@ -257,12 +266,15 @@ _git-bisect () {
           _arguments \
             '*:: : _normal' && ret=0
           ;;
+        (terms)
+	  _arguments --term-good --term-bad && ret=0
+	  ;;
         (view|visualize)
           local -a log_options revision_options
           __git_setup_log_options
           __git_setup_revision_options
 
-          _arguments -w -C -s \
+          _arguments -C -s \
             $log_options \
             $revision_options && ret=0
         (*)
@@ -279,14 +291,14 @@ _git-bisect () {
 _git-branch () {
   declare l c m d e
 
-  l='--color --no-color -r -a -v --verbose --abbrev --no-abbrev --list'
-  c='-l -f --force -t --track --no-track -u --set-upstream --set-upstream-to --unset-upstream --contains --merged --no-merged'
+  l='--color --no-color -r --remotes -a -v --verbose --abbrev --no-abbrev --list --points-at --sort'
+  c='-l --create-reflog -f --force -t --track --no-track -u --set-upstream --set-upstream-to --unset-upstream --contains --merged --no-merged'
   m='-m --move -M'
   d='-d --delete -D'
   e='--edit-description'
 
   declare -a dependent_creation_args
-  if (( words[(I)-r] == 0 )); then
+  if (( words[(I)(-r|--remotes)] == 0 )); then
     dependent_creation_args=(
       "($l $m $d): :__git_branch_names"
       "::start-point:__git_revisions")
@@ -297,7 +309,7 @@ _git-branch () {
     dependent_creation_args=
     dependent_deletion_args=(
       '-r[delete only remote-tracking branches]')
-    if (( words[(I)-r] )); then
+    if (( words[(I)(-r|--remotes)] )); then
       dependent_deletion_args+='*: :__git_ignore_line_inside_arguments __git_remote_branch_names'
     else
       dependent_deletion_args+='*: :__git_ignore_line_inside_arguments __git_branch_names'
@@ -312,18 +324,18 @@ _git-branch () {
       '::new branch name:__git_branch_names')
   fi
 
-  _arguments -w -S -s \
+  _arguments -S -s \
     "($c $m $d $e --no-color :)--color=-[turn on branch coloring]:: :__git_color_whens" \
     "($c $m $d $e : --color)--no-color[turn off branch coloring]" \
     "($c $m $d $e --no-column)"'--column=[display tag listing in columns]:column.branch option:((always\:"always show in columns" never\:"never show in columns" auto\:"show in columns if the output is to the terminal" column\:"fill columns before rows (default)" row\:"fill rows before columns" plain\:"show in one column" dense\:"make unequal size columns to utilize more space" nodense\:"make equal size columns"))' \
     "($c $m $d $e --column)"'--no-column[do not display in columns]' \
     "($c $m $d $e )*--list[list only branches matching glob]:pattern" \
-    "($c $m    $e  -a)-r[list or delete only remote-tracking branches]" \
-    "($c $m $d $e: -r)-a[list both remote-tracking branches and local branches]" \
-    "($c $m $d $e : -v -vv --verbose)"{-v,-vv--verbose}'[show SHA1 and commit subject line for each head]' \
+    "($c $m    $e  -a)"{-r,--remotes}'[list or delete only remote-tracking branches]' \
+    "($c $m $d $e: -r --remotes)-a[list both remote-tracking branches and local branches]" \
+    "($c $m $d $e : -v -vv --verbose)"{-v,-vv,--verbose}'[show SHA1 and commit subject line for each head]' \
     "($c $m $d $e :)--abbrev=[set minimum SHA1 display-length]: :__git_guard_number length" \
     "($c $m $d $e :)--no-abbrev[do not abbreviate sha1s]" \
-    "($l $m $d $e)-l[create the branch's reflog]" \
+    "($l $m $d $e)"{-l,--create-reflog}"[create the branch's reflog]" \
     "($l $m $d $e -f --force)"{-f,--force}"[force the creation of a new branch]" \
     "($l $m $d $e -t --track)"{-t,--track}"[set up configuration so that pull merges from the start point]" \
     "($l $m $d $e)--no-track[override the branch.autosetupmerge configuration variable]" \
@@ -331,7 +343,7 @@ _git-branch () {
     "($l $m $d $e -u --set-upstream --set-upstream-to --unset-upstream)--unset-upstream[remove upstream configuration]" \
     "($l $m $d $e)--contains=[only list branches which contain the specified commit]: :__git_committishs" \
     "($l $m $d $e)--merged=[only list branches which are fully contained by HEAD]: :__git_committishs" \
-    "($l $m $d $e)--no-merged=[do not list branches which are fully contained by HEAD]: :__git_committishs" \
+    "($l $m $d $e)--no-merged=[don't list branches which are fully contained by HEAD]: :__git_committishs" \
     "($c $l $m $d)--edit-description[edit branch description]" \
     $dependent_creation_args \
     "($l $c $d $m $e)"{-m,--move}"[rename a branch and the corresponding reflog]" \
@@ -340,6 +352,9 @@ _git-branch () {
     "($l $c $m $d $e)"{-d,--delete}"[delete a fully merged branch]" \
     "($l $c $m $d $e)-D[delete a branch]" \
     {-q,--quiet}"[be more quiet]" \
+    '*--sort=[specify field to sort on]: :__git_ref_sort_keys' \
+    '--points-at=[only list tags of the given object]: :__git_commits' \
+    "($c $m $d $e -i --ignore-case)"{-i,--ignore-case}'[sorting and filtering are case-insensitive]' \
     $dependent_deletion_args
 }
 
@@ -376,7 +391,7 @@ _git-bundle () {
             local revision_options
             __git_setup_revision_options
 
-            _arguments -w -S -s \
+            _arguments -S -s \
               $revision_options \
               ': :_files' \
               '*: :__git_commit_ranges2' && ret=0
@@ -429,22 +444,24 @@ _git-checkout () {
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
 
-  _arguments -w -C -s \
-    '(-q --quiet)'{-q,--quiet}'[suppress feedback messages]' \
+  _arguments -C -s \
+    '(-q --quiet --progress)'{-q,--quiet}'[suppress progress reporting]' \
     '(-f --force -m --merge --conflict --patch)'{-f,--force}'[force branch switch/ignore unmerged entries]' \
-    '(-q --quiet        --theirs --patch)--ours[check out stage #2 for unmerged paths]' \
-    '(-q --quiet --ours          --patch)--theirs[check out stage #3 for unmerged paths]' \
-    '(   -B --orphan --ours --theirs --conflict --patch --detach)-b+[create a new branch based at given commit]: :__git_branch_names' \
-    '(-b    --orphan --ours --theirs --conflict --patch --detach)-B+[create or update branch based at given commit]: :__git_branch_names' \
+    '(-q --quiet -2 --ours -3 --theirs --patch)'{-2,--ours}'[check out stage #2 for unmerged paths]' \
+    '(-q --quiet -2 --ours -3 --theirs --patch)'{-3,--theirs}'[check out stage #3 for unmerged paths]' \
+    '(   -B --orphan -2 --ours -3 --theirs --conflict --patch --detach)-b+[create a new branch based at given commit]: :__git_branch_names' \
+    '(-b    --orphan -2 --ours -3 --theirs --conflict --patch --detach)-B+[create or update branch based at given commit]: :__git_branch_names' \
     '(-t --track --orphan --patch --detach)'{-t,--track}'[set up configuration so pull merges from the base commit]' \
     '(--patch)--no-track[override the branch.autosetupmerge configuration variable]' \
     $new_branch_reflog_opt \
     '(-b -B -t --track --patch --orphan)--detach[detach the HEAD at named commit]' \
     '(-b -B -t --track --patch --detach)--orphan=[create a new orphan branch based at given commit]: :__git_branch_names' \
-    '--ignore-skip-worktree-bits[ignores patterns and adds back any files in <paths>]' \
     '(-q --quiet -f --force -m --merge --conflict --patch)'{-m,--merge}'[3way merge current branch, working tree and new branch]' \
     '(-q --quiet -f --force -m --merge --patch)--conflict=[same as --merge, using given merge style]:style:(merge diff3)' \
     '(-)'{-p,--patch}'[interactively select hunks in diff between given tree-ish and working tree]' \
+    "--ignore-skip-worktree-bits[don't limit pathspecs to sparse entries only]" \
+    "--ignore-other-worktrees[don't check if another worktree is holding the given ref]" \
+    '(-q --quiet)--progress[force progress reporting]' \
     '(-)--[start file arguments]' \
     '*:: :->branch-or-tree-ish-or-file' && ret=0
 
@@ -457,28 +474,25 @@ _git-checkout () {
       [[ $line[CURRENT] = -* ]] && return
       if (( CURRENT == 1 )) && [[ -z $opt_args[(I)--] ]]; then
         # TODO: Allow A...B
-        local branch_arg='' \
+        local \
               remote_branch_noprefix_arg='remote-branch-names-noprefix::__git_remote_branch_names_noprefix' \
-              tree_ish_arg='tree-ishs::__git_tree_ishs' \
+              tree_ish_arg='tree-ishs::__git_commits_prefer_recent' \
               file_arg='modified-files::__git_modified_files'
 
         if [[ -n ${opt_args[(I)-b|-B|--orphan|--detach]} ]]; then
-          remote_branch_noprefix_arg=
-          file_arg=
+          _alternative $tree_ish_arg && ret=0
         elif [[ -n $opt_args[(I)--track] ]]; then
-          branch_arg='remote-branches::__git_remote_branch_names'
-          remote_branch_noprefix_arg=
-          tree_ish_arg=
-          file_arg=
+          _alternative remote-branches::__git_remote_branch_names && ret=0
         elif [[ -n ${opt_args[(I)--ours|--theirs|-m|--conflict|--patch]} ]]; then
-          remote_branch_noprefix_arg=
+          _alternative $tree_ish_arg $file_arg && ret=0
+        else
+          _alternative \
+            $file_arg \
+            $tree_ish_arg \
+            $remote_branch_noprefix_arg \
+            && ret=0
         fi
 
-        _alternative \
-          $branch_arg \
-          $remote_branch_noprefix_arg \
-          $tree_ish_arg \
-          $file_arg && ret=0
       elif [[ -n ${opt_args[(I)-b|-B|-t|--track|--orphan|--detach]} ]]; then
         _nothing
       elif [[ -n $line[1] ]] && __git_is_treeish $line[1]; then
@@ -500,19 +514,21 @@ _git-cherry-pick () {
     '(- :)--quit[end revert or cherry-pick sequence]' \
     '(- :)--continue[resume revert or cherry-pick sequence]' \
     '(- :)--abort[cancel revert or cherry-pick sequence]' \
+    '--allow-empty[preserve initially empty commits]' \
     '--allow-empty-message[allow replaying a commit with an empty message]' \
     '--keep-redundant-commits[keep cherry-picked commits that will become empty]' \
     '(-e --edit --ff)'{-e,--edit}'[edit commit before committing the revert]' \
     '(--ff)-x[append information about what commit was cherry-picked]' \
     '(-m --mainline)'{-m+,--mainline=}'[specify mainline when cherry-picking a merge commit]:parent number' \
+    '--rerere-autoupdate[update index with reused conflict resolution if possible]' \
     '(-n --no-commit --ff)'{-n,--no-commit}'[do not make the actually commit]' \
     '(-s --signoff --ff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \
     '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=-}'[GPG-sign the commit]::key id' \
-    '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
+    "(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[don't GPG-sign the commit]" \
     '*'{-s+,--strategy=}'[use given merge strategy]:merge strategy:__git_merge_strategies' \
-    '*'{-X+,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]' \
+    '*'{-X+,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]:option' \
     '(-e --edit -x -n --no-commit -s --signoff)--ff[fast forward, if possible]' \
-    ': : __git_commit_ranges -O expl:git_commit_opts'
+    '*: : __git_commit_ranges -O expl:git_commit_opts'
 }
 
 (( $+functions[_git-citool] )) ||
@@ -525,12 +541,12 @@ _git-clean () {
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
 
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '-d[also remove untracked directories]' \
     '(-f --force)'{-f,--force}'[required when clean.requireForce is true (default)]' \
     '(-i --interactive)'{-i,--interactive}'[show what would be done and clean files interactively]' \
     '(-n --dry-run)'{-n,--dry-run}'[only show what would and what would not be removed]' \
-    '(-q --quiet)'{-q,--quiet}'[only report errors]' \
+    '(-q --quiet)'{-q,--quiet}"[don't print names of files removed]" \
     '*'{-e+,--exclude=}'[skip files matching specified pattern]:pattern' \
     '(-X   )-x[also remove ignored files]' \
     '(   -x)-X[remove only ignored files]' \
@@ -585,12 +601,14 @@ _git-clone () {
   # TODO: Argument to -o should be a remote name.
   # TODO: Argument to -b should complete branch names in the repository being
   # cloned (see __git_references())
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '(-l --local --no-local)'{-l,--local}'[clone locally, hardlink refs and objects if possible]' \
     '(-l --local --no-local)--no-local[override --local, as if file:/// URL was given]' \
     '--no-hardlinks[copy files instead of hardlinking when doing a local clone]' \
     '(-s --shared)'{-s,--shared}'[share the objects with the source repository (warning: see man page)]' \
+    '(-j --jobs)'{-j+,--jobs=}'[specify number of submodules cloned in parallel]:jobs' \
     '--reference[reference repository]:repository:_directories' \
+    '--reference-if-able[reference repository]:repository:_directories' \
     '--dissociate[make the newly-created repository independent of the --reference repository]' \
     '(-q --quiet)'{-q,--quiet}'[operate quietly]' \
     '(-v --verbose)'{-v,--verbose}'[always display the progressbar]' \
@@ -604,10 +622,16 @@ _git-clone () {
     '--template=[directory to use as a template for the object database]: :_directories' \
     '*'{-c,--config}'[<key>=<value> set a configuration variable in the newly created repository]' \
     '--depth[create a shallow clone, given number of revisions deep]: :__git_guard_number depth' \
+    '--shallow-since=[shallow clone since a specific time]:time' \
+    '*--shallow-exclude=[shallow clone excluding commits reachable from specified remote revision]:revision' \
     '(--no-single-branch)--single-branch[clone only history leading up to the main branch or the one specified by -b]' \
     '(--single-branch)--no-single-branch[clone history leading up to each branch]' \
+    '--shallow-submodules[any cloned submodules will be shallow]' \
     '--recursive[initialize all contained submodules]' \
+    '--recurse-submodules[initialize submodules in the clone]' \
     '--separate-git-dir[place .git dir outside worktree]:path to .git dir:_path_files -/' \
+    '(-4 --ipv4 -6 --ipv6)'{-4,--ipv4}'[use IPv4 addresses only]' \
+    '(-4 --ipv4 -6 --ipv6)'{-6,--ipv6}'[use IPv6 addresses only]' \
     ': :->repository' \
     ': :_directories' && ret=0
 
@@ -626,7 +650,7 @@ _git-clone () {
 
 (( $+functions[_git-column] )) ||
 _git-column () {
-  _arguments -w -S -s \
+  _arguments -s \
     '--command=[look up layout mode using config vars column.<name> and column.ui]' \
     '--mode=[specify layout mode. See configuration variable column.ui for option syntax]' \
     '--raw-mode=[same as --mode but take mode encoded as a number]' \
@@ -649,19 +673,20 @@ _git-commit () {
   fi
 
   # TODO: --interactive isn't explicitly listed in the documentation.
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-a --all --interactive -o --only -i --include *)'{-a,--all}'[stage all modified and deleted paths]' \
     '--fixup=[construct a commit message for use with rebase --autosquash]:commit to be amended:__git_recent_commits' \
     '--squash=[construct a commit message for use with rebase --autosquash]:commit to be amended:__git_recent_commits' \
     $reset_author_opt \
-    '(        --porcelain --dry-run)--short[output dry run in short format]' \
-    '(--short             --dry-run)--porcelain[output dry run in porcelain-ready format]' \
-    '(--short --porcelain --dry-run -z --null)'{-z,--null}'[separate dry run entry output with NUL]' \
+    '(        --porcelain --dry-run)--short[dry run with short output format]' \
+    '--branch[show branch information]' \
+    '(--short             --dry-run)--porcelain[dry run with machine-readable output format]' \
+    '(--short --porcelain --dry-run -z --null)'{-z,--null}'[dry run with NULL-separated output format]' \
     {-p,--patch}'[use the interactive patch selection interface to chose which changes to commit]' \
     '(--reset-author)--author[override the author name used in the commit]:author name' \
     '--date=[override the author date used in the commit]:date' \
     '(-s --signoff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \
-    '(-n --no-verify)'{-n,--no-verify}'[do not look for suspicious lines the commit introduces]' \
+    '(-n --no-verify)'{-n,--no-verify}'[bypass pre-commit and commit-msg hooks]' \
     '--allow-empty[allow recording an empty commit]' \
     '--allow-empty-message[allow recording a commit with an empty message]' \
     '--cleanup=[specify how the commit message should be cleaned up]:mode:((verbatim\:"do not change the commit message at all"
@@ -683,7 +708,7 @@ _git-commit () {
     '(         --no-status)--status[include the output of git status in the commit message template]' \
     '(--status            )--no-status[do not include the output of git status in the commit message template]' \
     '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
-    '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
+    "(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[don't GPG-sign the commit]" \
     '(-a --all --interactive -o --only -i --include *)--interactive[interactively update paths in the index file]' \
     $amend_opt \
     '*: :__git_ignore_line_inside_arguments __git_changed_files' \
@@ -697,7 +722,7 @@ _git-commit () {
 
 (( $+functions[_git-describe] )) ||
 _git-describe () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(*)--dirty=-[describe HEAD, adding mark if dirty]::mark' \
     '--all[use any ref found in "$GIT_DIR/refs/"]' \
     '--tags[use any ref found in "$GIT_DIR/refs/tags"]' \
@@ -722,9 +747,10 @@ _git-diff () {
   __git_setup_diff_options
   __git_setup_diff_stage_options
 
-  _arguments -w -C -s \
+  _arguments -C -s \
     $* \
     $diff_options \
+    '(--exit-code)--quiet[disable all output]' \
     $diff_stage_options \
     '(--cached --staged)'{--cached,--staged}'[show diff between index and named commit]' \
     '(-)--[start file arguments]' \
@@ -818,9 +844,13 @@ _git-fetch () {
   local -a fetch_options
   __git_setup_fetch_options
 
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     $fetch_options \
-    '--multiple[allow several repository arguments]' \
+    '--shallow-since=[deepen history of shallow repository based on time]:time' \
+    '*--shallow-exclude=[deepen history of shallow clone by excluding revision]:revision' \
+    '--deepen[deepen history of shallow clone]:number of commits' \
+    '(-n --no-tags -t --tags)'{-n,--no-tags}'[disable automatic tag following]' \
+    '(--all -m --multiple)'{-m,--multiple}'[fetch from multiple remotes]' \
     '*:: :->repository-or-group-or-refspec' && ret=0
 
   case $state in
@@ -851,7 +881,7 @@ _git-format-patch () {
   # TODO: -- is wrong.
   # TODO: Should filter out --name-only, --name-status, and --check from
   # $diff_options.
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     $diff_options \
     '--[limit the number of patches to prepare]: :__git_guard_number "number of patches to prepare"' \
     '(-o --output-directory --stdout)'{-o+,--output-directory=}'[store resulting files in given directory]: :_directories' \
@@ -859,7 +889,7 @@ _git-format-patch () {
     '(-n --numbered -N --no-numbered -k --keep-subject)'{-N,--no-numbered}'[name output in \[PATCH\] format]' \
     '--start-number=[start numbering patches at given number]: :__git_guard_number "patch number"' \
     '--numbered-files[use only number for file name]' \
-    '(-n --numbered -N --no-numbered -k --keep-subject --subject-prefix)'{-k,--keep-subject}'[do not strip/add \[PATCH\] from the first line of the commit message]' \
+    '(-n --numbered -N --no-numbered -k --keep-subject --rfc --subject-prefix)'{-k,--keep-subject}"[don't strip/add \[PATCH\] from the first line of the commit message]" \
     '(-s --signoff)'{-s,--signoff}'[add Signed-off-by: line to the commit message]' \
     '(-o --output-directory)--stdout[output the generated mbox on standard output (implies --mbox)]' \
     '(         --no-attach --inline)--attach=-[create attachments instead of inlining patches]::boundary' \
@@ -871,7 +901,8 @@ _git-format-patch () {
     '--in-reply-to=[make the first mail a reply to the given message]:message id' \
     '--ignore-if-in-upstream[do not include a patch that matches a commit in the given range]' \
     '(-v --reroll-count)'{-v+,--reroll-count=}'[mark the series as the <n>-th iteration of the topic]: :__git_guard_number iteration' \
-    '(-k --keep-subject)--subject-prefix=[use the given prefix instead of \[PATCH\]]:prefix' \
+    '(-k --keep-subject --subject-prefix)--rfc[use \[RFC PATCH\] instead of \[PATCH\]]' \
+    '(-k --keep-subject --rfc)--subject-prefix=[use the given prefix instead of \[PATCH\]]:prefix' \
     '*--to=[add To: header to email headers]: :_email_addresses' \
     '*--cc=[add Cc: header to email headers]: :_email_addresses' \
     '--from=[add From: header to email headers]: :_email_addresses' \
@@ -882,9 +913,10 @@ _git-format-patch () {
     '(--signature                --signature-file)--no-signature[do not add a signature]' \
     '(--signature --no-signature                 )--signature-file=[use contents of file as signature]' \
     '--suffix=[use the given suffix for filenames]:filename suffix' \
-    '--quiet[suppress the output of the names of generated files]' \
+    '(-q --quiet)'{-q,--quiet}'[suppress the output of the names of generated files]' \
     '--no-binary[do not output contents of changes in binary files, only note that they differ]' \
     '--root[treat the revision argument as a range]' \
+    '--zero-commit[output all-zero hash in From header]' \
     ': :->commit-or-commit-range' && ret=0
 
   case $state in
@@ -902,12 +934,12 @@ _git-format-patch () {
 
 (( $+functions[_git-gc] )) ||
 _git-gc () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '--aggressive[more aggressively optimize]' \
     '--auto[check whether housekeeping is required]' \
     '(        --no-prune)--prune=[prune loose objects older than given date]: :__git_datetimes' \
     '(--prune           )--no-prune[do not prune any loose objects]' \
-    '--quiet[suppress all progress reports]'
+    '(-q --quiet)'{-q,--quiet}'[suppress progress reporting]'
 }
 
 (( $+functions[_git-grep] )) ||
@@ -929,9 +961,11 @@ _git-grep () {
   _arguments -C -A '-*' \
     '(-O --open-files-in-pager --no-index)--cached[search blobs registered in index file instead of working tree]' \
     '(--cached)--no-index[search files in current directory, not just tracked files]' \
-    '(--exclude-standard)--no-exclude-standard[also search in ignored files]' \
+    '(--exclude-standard)--no-exclude-standard[search also in ignored files]' \
     '(--no-exclude-standard)--exclude-standard[exclude files standard ignore mechanisms]' \
-    '--untracked[search in untracked files]' \
+    '--recurse-submodules[recursively search in each submodule]' \
+    "--parent-basename=[prepend parent project's basename to output]:basename" \
+    '--untracked[search also in untracked files]' \
     '(-a --text)'{-a,--text}'[process binary files as if they were text]' \
     '(--textconv --no-textconv)--textconv[honor textconv filter settings]' \
     '(--textconv --no-textconv)--no-textconv[do not honor textconv filter settings]' \
@@ -960,20 +994,21 @@ _git-grep () {
     '(-A --after-context)'{-A+,--after-context=}'[show <num> trailing lines, and separate groups of matches]: :__git_guard_number lines' \
     '(-B --before-context)'{-B+,--before-context=}'[show <num> leading lines, and separate groups of matches]: :__git_guard_number lines' \
     '(-A --after-context -B --before-context -C --context)'{-C+,--context=}'[show <num> leading and trailing lines, and separate groups of matches]: :__git_guard_number lines' \
+    '--threads=[use specified number of threads]:number of threads' \
     '(-p --show-function)'{-p,--show-function}'[show preceding line containing function name of match]' \
     '(-W --function-context)'{-W,--function-context}'[show whole function where a match was found]' \
     '(1)*-f+[read patterns from given file]:pattern file:_files' \
     '(1)*-e+[use the given pattern for matching]:pattern' \
     $pattern_operators \
     '--all-match[all patterns must match]' \
-    ':pattern' \
+    ': :_guard "^-*" pattern' \
     '*:: :->tree-or-file' && ret=0
 
   # TODO: If --cached, --no-index, -O, or --open-files-in-pager was given,
   # don't complete treeishs.
   case $state in
     (tree-or-file)
-      integer first_tree last_tree start end
+      integer first_tree last_tree start end i
 
       (( start = words[(I)(-f|-e)] > 0 ? 1 : 2 ))
       (( end = $#line - 1 ))
@@ -1070,7 +1105,7 @@ _git-gui () {
 
 (( $+functions[_git-init] )) ||
 _git-init () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-q --quiet)'{-q,--quiet}'[do not print any results to stdout]' \
     '--bare[create a bare repository]' \
     '--template=[directory to use as a template for the object database]: :_directories' \
@@ -1088,10 +1123,9 @@ _git-log () {
   __git_setup_log_options
   __git_setup_revision_options
 
-  _arguments -w -C -s \
+  _arguments -C -s \
     $log_options \
     $revision_options \
-    '-L+[trace the evolution of a line range or regex within a file]:range' \
     '(-)--[start file arguments]' \
     '1: :->first-commit-ranges-or-files' \
     '*: :->commit-ranges-or-files' && ret=0
@@ -1134,12 +1168,15 @@ _git-merge () {
   __git_setup_merge_options
   local -a git_commit_opts=(--all --not HEAD --not)
 
-  _arguments -w -S -s \
+  _arguments -S -s \
     $merge_options \
     '-m+[set the commit message to be used for the merge commit]:merge message' \
+    '(--edit --no-edit)-e[open an editor to change the commit message]' \
     '(                    --no-rerere-autoupdate)--rerere-autoupdate[allow the rerere mechanism to update the index]' \
     '(--rerere-autoupdate                       )--no-rerere-autoupdate[do not allow the rerere mechanism to update the index]' \
     '--abort[restore the original branch and abort the merge operation]' \
+    '--continue[continue the current in-progress merge]' \
+    '--progress[force progress reporting]' \
     '*: : __git_commits -O expl:git_commit_opts'
 }
 
@@ -1148,7 +1185,8 @@ _git-mv () {
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
 
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
+    '(-v --verbose)'{-v,--verbose}'[output additional information]' \
     '(-f --force)'{-f,--force}'[rename/move even if targets exist]' \
     '-k[skip rename/move that would lead to errors]' \
     '(-n --dry-run)'{-n,--dry-run}'[only show what would happen]' \
@@ -1189,7 +1227,9 @@ _git-notes () {
         merge:'merge the given notes ref into the current ref'
         show:'show notes for a given object'
         remove:'remove notes for a given object'
-        prune:'remove all notes for non-existing/unreachable objects')
+        prune:'remove all notes for non-existing/unreachable objects'
+        get-ref:'print the current notes ref'
+      )
 
       _describe -t commands command commands && ret=0
       ;;
@@ -1197,14 +1237,14 @@ _git-notes () {
       curcontext=${curcontext%:*}-$line[1]:
 
       case $line[1] in
-        (list|show|edit|remove)
+        (list|show)
           _arguments \
             ': :__git_commits' && ret=0
           ;;
         (add)
           # TODO: Only complete commits that don't have notes already, unless
           # -f or --force has been given.
-          _arguments -w -S -s \
+          _arguments -S -s \
             '*'{-m+,--message=}'[use given note message]:message' \
             '*'{-F+,--file=}'[take note message from given file]:note message file:_files' \
             '(-C --reuse-message)'{-C+,--reuse-message=}'[take note message from given blob object]: :__git_blobs' \
@@ -1214,24 +1254,35 @@ _git-notes () {
           ;;
         (copy)
           # TODO: --for-rewrite is undocumented.
-          _arguments -w -S -s \
+          _arguments -S -s \
             '(-f --force)'{-f,--force}'[replace existing note]' \
             '(:)--stdin[read objects from stdin]' \
             '(:--stdin)--for-rewrite=[load rewriting config for given command]:command:(amend rebase)' \
             ': :__git_commits' \
             ': :__git_commits' && ret=0
           ;;
+	(edit)
+	  _arguments --allow-empty ':object:__git_commits' && ret=0
+	  ;;
         (merge)
-          _arguments -w -S -s \
+          _arguments -S -s \
             '(-s --strategy)--abort[abort an in-progress notes merge]' \
             '(-s --strategy)--commit[finalize an in-progress notes merge]' \
-            {-q,--quiet}'[be quiet]' \
-            {-v,--verbose}'[be more verbose]' \
+	    '(-q --quiet)'{-q,--quiet}'[be quiet]' \
+            '(-v --verbose)'{-v,--verbose}'[be more verbose]' \
             '(--abort --commit)'{-s,--strategy=}'[resolve conflicts using the given strategy]' \
             ': :__git_notes_refs' && ret=0
           ;;
+	(prune)
+	  _arguments -s \
+	    '(-v --verbose)'{-v,--verbose}'[be more verbose]' \
+	    '(-n --dry-run)'{-n,--dry-run}"[don't remove anything, just report what would be deleted]" && ret=0
+          ;;
+	(remove)
+	  _arguments --ignore-missing --stdin ':object:__git_commits' && ret=0
+	  ;;
         (append)
-          _arguments -w -S -s \
+          _arguments -S -s \
             '*'{-m+,--message=}'[use given note message]:message' \
             '*'{-F+,--file=}'[take note message from given file]:note message file:_files' \
             '(-C --reuse-message)'{-C+,--reuse-message=}'[take note message from given blob object]: :__git_blobs' \
@@ -1258,9 +1309,12 @@ _git-pull () {
     $merge_options \
     '(-r --rebase --no-rebase)'{-r=-,--rebase=-}'[perform a rebase after fetching]::rebase after fetching:((true\:"rebase after fetching"
                                                                                                         false\:"merge after fetching"
-                                                                                                        preserve\:"rebase and preserve merges"))' \
+                                                                                                        preserve\:"rebase and preserve merges"
+													interactive\:"allow list of commits to be edited"))' \
     '(-r --rebase            )--no-rebase[do not perform a rebase after fetching]' \
+    '--autostash[automatically stash/stash pop before and after rebase]' \
     $fetch_options \
+    '(--no-tags -t --tags)--no-tags[disable automatic tag following]' \
     ': :__git_any_repositories' \
     '*: :__git_ref_specs_fetchy'
 }
@@ -1268,22 +1322,28 @@ _git-pull () {
 (( $+functions[_git-push] )) ||
 _git-push () {
   local ret=1
+  local -a sign
+  sign=(
+    {yes,true}'\:always,\ and\ fail\ if\ unsupported\ by\ server'
+    {no,false}'\:never'
+    if-asked'\:iff\ supported\ by\ server'
+  )
   # NOTE: For --receive-pack we use _files to complete, even though this will
   # only complete files on the local end, not the remote end.  Still, it may be
   # helpful to get some sort of completion going, perhaps modifying the path
   # later on to match the remote end.
-  _arguments -w -S -s \
+  _arguments -S -s \
     '--all[push all refs under refs/heads/]' \
     '--prune[remove remote branches that do not have a local counterpart]' \
     '--mirror[push all refs under refs/heads/ and refs/tags/ and delete non-existing refs]' \
     '(-n --dry-run)'{-n,--dry-run}'[do everything except actually send the updates]' \
     '--porcelain[produce machine-readable output]' \
-    '--delete[delete all listed refs from the remote repository]' \
+    '(-d --delete)'{-d,--delete}'[delete all listed refs from the remote repository]' \
     '--tags[all tags under refs/tags are pushed]' \
     '--follow-tags[also push missing annotated tags reachable from the pushed refs]' \
     '(--receive-pack --exec)'{--receive-pack=-,--exec=-}'[path to git-receive-pack on remote]:remote git-receive-pack:_files' \
     '(--force-with-lease --no-force-with-lease)*--force-with-lease=-[allow refs that are not ancestors to be updated if current ref matches expected value]::ref and expectation:->lease' \
-    '(--force-with-lease --no-force-with-lease)--no-force-with-lease=-[cancel all previous force-with-lease specifications]' \
+    '(--force-with-lease --no-force-with-lease)--no-force-with-lease[cancel all previous force-with-lease specifications]' \
     '(-f --force)'{-f,--force}'[allow refs that are not ancestors to be updated]' \
     '(:)--repo=[default repository to use]:repository:__git_any_repositories' \
     '(-u --set-upstream)'{-u,--set-upstream}'[add upstream reference for each branch that is up to date or pushed]' \
@@ -1292,9 +1352,19 @@ _git-push () {
     '(-q --quiet -v --verbose --progress)'{-q,--quiet}'[suppress all output]' \
     '(-q --quiet -v --verbose)'{-v,--verbose}'[output additional information]' \
     '(-q --quiet)--progress[output progress information]' \
-    '(--verify)--no-verify[bybass the pre-push hook]' \
-    '--recurse-submodules=[submodule handling]:submodule handling:((check\:"refuse pushing of supermodule if submodule commit cannot be found on the remote"
-                                                                    on-demand\:"push all changed submodules"))' \
+    '(--verify)--no-verify[bypass the pre-push hook]' \
+    '--recurse-submodules=[submodule handling]:submodule handling:((
+        check\:"refuse to push if submodule commit not to be found on remote"
+        on-demand\:"push all changed submodules"
+	only\:"submodules will be recursively pushed while the superproject is left unpushed"
+	no\:"no submodule handling"))' \
+    "(--no-signed --signed)--sign=-[GPG sign the push]::signing enabled:(($^^sign))" \
+    '(--no-signed --sign)--signed[GPG sign the push]' \
+    "(--sign --signed)--no-signed[don't GPG sign the push]" \
+    '--atomic[request atomic transaction on remote side]' \
+    '(-o --push-option)'{-o+,--push-option=}'[transmit string to server to pass to pre/post-receive hooks]:string' \
+    '(-4 --ipv4 -6 --ipv6)'{-4,--ipv4}'[use IPv4 addresses only]' \
+    '(-4 --ipv4 -6 --ipv6)'{-6,--ipv6}'[use IPv6 addresses only]' \
     ': :__git_any_repositories' \
     '*: :__git_ref_specs_pushy' && ret=0
 
@@ -1322,18 +1392,22 @@ _git-rebase () {
       '(--autosquash                )--no-autosquash[do not check for auto-squash boundaries]')
   fi
 
-  _arguments -A '-*' \
-    '(- :)--continue[continue after resolving merge conflict]' \
-    '(- :)--abort[abort current rebase]' \
-    '--keep-empty[keep empty commits in the result]' \
-    '(- :)--skip[skip the current patch]' \
+  _arguments \
+    - actions \
+    '(-)--continue[continue after resolving merge conflict]' \
+    '(-)--abort[abort current rebase]' \
+    '(-)--edit-todo[edit interactive instruction sheet in an editor]' \
+    '(-)--skip[skip the current patch]' \
+    '(-)--quit[abort but keep HEAD where it is]' \
+    - options \
     '(-m --merge)'{-m,--merge}'[use merging strategies to rebase]' \
     '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=-}'[GPG-sign the commit]::key id' \
-    '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
+    "(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[don't GPG-sign the commit]" \
     '*'{-s+,--strategy=}'[use given merge strategy]:merge strategy:__git_merge_strategies' \
-    '*'{-X+,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]' \
+    '*'{-X+,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]:option' \
     '(-q --quiet -v --verbose --stat -n --no-stat)'{-q,--quiet}'[suppress all output]' \
     '(-q --quiet -v --verbose --stat -n --no-stat)'{-v,--verbose}'[output additional information]' \
+    '--rerere-autoupdate[allow rerere to update index with resolved conflicts]' \
     '--no-verify[bypass the pre-rebase hook]' \
     '-C-[ensure that given lines of surrounding context match]: :__git_guard_number "lines of context"' \
     '(-f --force-rebase)'{-f,--force-rebase}'[force rebase even if current branch descends from commit rebasing onto]' \
@@ -1341,13 +1415,15 @@ _git-rebase () {
     '(-i --interactive)--whitespace=-[detect a new or modified line that has whitespace errors]: :__git_apply_whitespace_strategies' \
     '(-i --interactive)--committer-date-is-author-date[use author date as committer date]' \
     '(-i --interactive --ignore-whitespace --whitespace --committer-date-is-author-date)'{-i,--interactive}'[make a list of commits to be rebased and open in $EDITOR]' \
-    '--edit-todo[edit interactive instruction sheet in an editor]' \
     '(-p --preserve-merges --interactive)'{-p,--preserve-merges}'[try to recreate merges instead of ignoring them]' \
     {-x+,--exec=}'[with -i\: append "exec <cmd>" after each line]:command:_command_names -e' \
+    '(-k --keep-empty)'{-k,--keep-empty}'[keep empty commits in the result]' \
     '(1)--root[rebase all reachable commits]' \
     $autosquash_opts \
     '(--autostash --no-autostash)--autostash[stash uncommitted changes before rebasing and apply them afterwards]' \
     '(--autostash --no-autostash)--no-autostash[do not stash uncommitted changes before rebasing and apply them afterwards]' \
+    '--fork-point[use merge-base --fork-point to refine upstream]' \
+    '--ignore-date[use current timestamp for author date]' \
     '--no-ff[cherry-pick all rebased commits with --interactive, otherwise synonymous to --force-rebase]' \
     '--onto=[start new branch with HEAD equal to given revision]:newbase:__git_revisions' \
     ':upstream branch:__git_revisions' \
@@ -1359,16 +1435,15 @@ _git-reset () {
   local curcontext=$curcontext state line ret=1
   typeset -A opt_args
 
-  _arguments -w -C -s \
+  _arguments -C -s -S \
       '(       --mixed --hard --merge --keep -p --patch -- *)--soft[do not touch the index file nor the working tree]' \
       '(--soft         --hard --merge --keep -p --patch -- *)--mixed[reset the index but not the working tree (default)]' \
-      '(--soft         --hard --merge --keep -p --patch -- *)-N[keep --intent-to-add entries in the index]' \
+      '(--soft         --hard --merge --keep -p --patch -- *)'{-N,--intent-to-add}'[record only the fact that removed paths will be added later]' \
       '(--soft --mixed        --merge --keep -p --patch -- *)--hard[match the working tree and index to the given tree]' \
       '(--soft --mixed --hard         --keep -p --patch -- *)--merge[reset out of a conflicted merge]' \
       '(--soft --mixed --hard --merge        -p --patch -- *)--keep[like --hard, but keep local working tree changes]' \
       '(-p --patch)'{-p,--patch}'[select diff hunks to remove from the index]' \
       '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
-      '(- 1)--[start file arguments]' \
       '(--soft --mixed --hard --merge --keep):: :__git_commits' \
       '(--soft --mixed --hard --merge --keep)*:: :->file' && ret=0
 
@@ -1386,17 +1461,20 @@ _git-reset () {
 
 (( $+functions[_git-revert] )) ||
 _git-revert () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(- :)--quit[end revert or cherry-pick sequence]' \
     '(- :)--continue[resume revert or cherry-pick sequence]' \
     '(- :)--abort[cancel revert or cherry-pick sequence]' \
     '(-e --edit --no-edit)'{-e,--edit}'[edit the commit before committing the revert]' \
     '(-e --edit --no-edit)--no-edit[do not edit the commit message before committing the revert]' \
     '(-m --mainline)'{-m+,--mainline=}'[pick which parent is mainline]:parent number' \
+    '--rerere-autoupdate[update the index with reused conflict resolution if possible]' \
     '(-n --no-commit)'{-n,--no-commit}'[do not commit the reversion]' \
     '(-s --signoff)'{-s,--signoff}'[add Signed-off-by line at the end of the commit message]' \
+    '--strategy=[use given merge strategy]:merge strategy:__git_merge_strategies' \
+    '*'{-X,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]:option' \
     '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=-}'[GPG-sign the commit]::key id' \
-    '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
+    "(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[don't GPG-sign the commit]" \
     ': :__git_commits'
 }
 
@@ -1405,13 +1483,13 @@ _git-rm () {
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
 
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '(-f --force)'{-f,--force}'[override the up-to-date check]' \
     '(-n --dry-run)'{-n,--dry-run}'[do not actually remove the files, just show if they exist in the index]' \
     '-r[allow recursive removal when a leading directory-name is given]' \
     '--cached[only remove files from the index]' \
     '--ignore-unmatch[exit with 0 status even if no files matched]' \
-    '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
+    '(-q --quiet)'{-q,--quiet}"[don't list removed files]" \
     '*:: :->file' && ret=0
 
   case $state in
@@ -1433,7 +1511,7 @@ _git-shortlog () {
 
   # TODO: should take all arguments found in setup_revisions() (probably more
   # or less what git-rev-list takes).
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '(: -)'{-h,--help}'[print a short usage message and exit]' \
     '(-n --numbered)'{-n,--numbered}'[sort according to number of commits]' \
     '(-s --summary)'{-s,--summary}'[suppress commit description]' \
@@ -1495,9 +1573,10 @@ _git-show () {
   __git_setup_log_options
   __git_setup_revision_options
 
-  _arguments -w -C -s \
+  _arguments -C -s \
     $log_options \
     $revision_options \
+    '(-q --quiet)'{-q,--quiet}'[suppress diff output]' \
     '*:: :->object' && ret=0
 
   case $state in
@@ -1517,15 +1596,24 @@ _git-show () {
 _git-stash () {
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
+  local -a save_arguments
+
+  save_arguments=(
+    '(-p --patch -a --all -u --include-untracked)'{-p,--patch}'[interactively select hunks from diff between HEAD and working tree to stash]'
+    '(-k --keep-index --no-keep-index)'{-k,--keep-index}'[all changes already added to the index are left intact]'
+    '(-k --keep-index)--no-keep-index[all changes already added to the index are undone]'
+    '(-q --quiet)'{-q,--quiet}'[suppress all output]'
+    '(-p --patch -a --all -u --include-untracked)'{-u,--include-untracked}'[include untracked files]'
+    '(-p --patch -a --all -u --include-untracked)'{-a,--all}'[include ignored files]'
+  )
 
   _arguments -C \
-    ': :->command' \
-    '*:: :->option-or-argument' && ret=0
+    '*::: :->args' \
+    ${save_arguments//#\(/(* } && ret=0
 
-  case $state in
-    (command)
+  if [[ -n $state ]]; then
+    if (( CURRENT == 1 )); then
       local -a commands
-      local -a save_arguments
 
       commands=(
         save:'save your local modifications to a new stash'
@@ -1536,24 +1624,16 @@ _git-stash () {
         branch:'branch off at the commit at which the stash was originally created'
         clear:'remove all the stashed states'
         drop:'remove a single stashed state from the stash list'
-        create:'create a stash without storing it in the ref namespace')
-
-      save_arguments=(
-        '(--keep-index)--patch[interactively select hunks from diff between HEAD and working tree to stash]' \
-          '(             --no-keep-index)--keep-index[all changes already added to the index are left intact]' \
-          '(--keep-index                )--no-keep-index[all changes already added to the index are undone]' \
-          '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
-          '(-u --include-untracked)'{-u,--include-untracked}'[include untracked files]' \
+        create:'create a stash without storing it in the ref namespace'
       )
+
       _describe -t commands command commands && ret=0
-      _arguments -S $save_arguments && ret=0  # "stash" defaults to "save", but without "message".
-      ;;
-    (option-or-argument)
+    else
       curcontext=${curcontext%:*}-$line[1]:
+      compset -n 1
 
       case $line[1] in
         (save)
-          _arguments -S $save_arguments && ret=0
           _arguments -S \
             $save_arguments \
             ':: :_guard "([^-]?#|)" message' && ret=0
@@ -1563,7 +1643,7 @@ _git-stash () {
           __git_setup_log_options
           __git_setup_revision_options
 
-          _arguments -s -w \
+          _arguments -s \
             $log_options \
             $revision_options && ret=0
           ;;
@@ -1571,7 +1651,7 @@ _git-stash () {
           local diff_options
           __git_setup_diff_options
 
-          _arguments -S -s -w \
+          _arguments -S -s \
             $diff_options \
             ':: :__git_stashes' && ret=0
           ;;
@@ -1601,8 +1681,8 @@ _git-stash () {
           _nothing
           ;;
       esac
-      ;;
-  esac
+    fi
+  fi
 
   return ret
 }
@@ -1615,17 +1695,17 @@ _git-status () {
     branch_opts=('(-b --branch)'{-b,--branch}'[show branch and tracking info]')
   fi
 
-  _arguments -w -S -s \
-    '(-s --short)'{-s,--short}'[output in short format]' \
+  _arguments -S -s \
+    '(-s --short --column --no-column)'{-s,--short}'[output in short format]' \
     $branch_opts \
-    '(-s --short)--porcelain[produce machine-readable output]' \
+    '(-s --short)--porcelain=-[produce machine-readable output]:version:(v1)' \
     '(-u --untracked-files)'{-u-,--untracked-files=-}'[show untracked files]::mode:((no\:"show no untracked files" \
                                                                                      normal\:"show untracked files and directories" \
                                                                                      all\:"also show untracked files in untracked directories (default)"))' \
     '--ignore-submodules[ignore changes to submodules]:: :__git_ignore_submodules_whens' \
     '--ignored[show ignored files as well]' \
-    '(--porcelain)-z[use NUL termination on output]' \
-    '(--no-column)--column=-[display in columns]::column.status option:((always\:"always show in columns" never\:"never show in columns" auto\:"show in columns if the output is to the terminal" column\:"fill columns before rows (default)" row\:"fill rows before columns" plain\:"show in one column" dense\:"make unequal size columns to utilize more space" nodense\:"make equal size columns"))' \
+    '(-z --null --column --no-column)'{-z,--null}'[use NUL termination on output]' \
+    '(--no-column -z --null)--column=-[display in columns]::column.status option:((always\:"always show in columns" never\:"never show in columns" auto\:"show in columns if the output is to the terminal" column\:"fill columns before rows (default)" row\:"fill rows before columns" plain\:"show in one column" dense\:"make unequal size columns to utilize more space" nodense\:"make equal size columns"))' \
     '(--column)--no-column[do not display in columns]' \
     '*: :__git_ignore_line_inside_arguments _files'
 }
@@ -1652,6 +1732,7 @@ _git-submodule () {
         update:'update a submodule'
         summary:'show commit summary between given commit and working tree/index'
         foreach:'evaluate shell command in each checked-out submodule'
+	absorbgitdirs:'move the git directory of a submodule into its superprojects'
         sync:'synchronize submodule settings')
 
       _describe -t commands command commands && ret=0
@@ -1687,6 +1768,7 @@ _git-submodule () {
         (deinit)
           _arguments -S \
             '(-f --force)'{-f,--force}'[remove submodule worktree even if local modifications are present]' \
+	    '(*)--all[remove all submodules]' \
             '*: :__git_ignore_line_inside_arguments __git_submodules' && ret=0
           ;;
         (update)
@@ -1694,8 +1776,10 @@ _git-submodule () {
           _arguments -S \
             '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
             '(-N --no-fetch)'{-N,--no-fetch}'[do not fetch new objects from repository]' \
-            '--merge[merge commit recorded in superproject into current branch of submodule]' \
-            '--rebase[rebase current branch onto commit recorded in superproject]' \
+	    '(--merge --rebase)--checkout[checkout commit recorded in the superproject in the submodule on a detached HEAD]' \
+	    '(--checkout --rebase)--merge[merge commit recorded in superproject into current branch of submodule]' \
+	    '(--checkout --merge)--rebase[rebase current branch onto commit recorded in superproject]' \
+	    '--no-recommend-shallow[ignore submodule.<name>.shallow from .gitmodules]' \
             '--reference=[remote repository to clone]: :__git_any_repositories' \
             '--recursive[traverse submodules recursively]' \
             '--remote[use the status of the submodule''s remote-tracking branch]' \
@@ -1706,8 +1790,8 @@ _git-submodule () {
         (summary)
           _arguments -C -A '-*' \
             '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
-            '--cached[use commit stored in the index]' \
-            '--files[compare commit in index with submodule HEAD commit]' \
+            '(--files)--cached[use commit stored in the index]' \
+            '(--cached)--files[compare commit in index with submodule HEAD commit]' \
             '(-n --summary-limit)'{-n,--summary-limit=}'[limit summary size]: :__git_guard_number "limit"' \
             '(-)--[start submodule arguments]' \
             '*:: :->commit-or-submodule' && ret=0
@@ -1737,8 +1821,13 @@ _git-submodule () {
             '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
             '*: :__git_ignore_line_inside_arguments __git_submodules' && ret=0
           ;;
+	(absorbgitdirs)
+	  _arguments -S \
+            '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
+	    '*:path:_directories'
+	;;
         (*)
-          _nothing
+          _default
           ;;
       esac
       ;;
@@ -1747,28 +1836,120 @@ _git-submodule () {
   return ret
 }
 
+(( $+functions[_git-subtree] )) ||
+_git-subtree () {
+  local curcontext="$curcontext" state state_descr line ret=1
+  declare -A opt_args
+
+  # TODO: -P should only complete paths inside the current repository.
+  _arguments -C \
+    '(-q --quiet)'{-q,--quiet}'[suppress progress output]' \
+    '(-P --prefix)'{-P+,--prefix=}'[the path to the subtree in the repository to manipulate]: :_directories' \
+    '-d[show debug messages]' \
+    ': :->command' \
+    '*::: := ->option-or-argument' && ret=0
+
+  case $state in
+    (command)
+      declare -a commands
+
+      commands=(
+        add:'create the subtree by importing its contents'
+        merge:'merge recent changes up to specified commit into the subtree'
+        pull:'fetch from remote repository and merge recent changes into the subtree'
+        push:'does a split and `git push`'
+        split:'extract a new synthetic project history from a subtree')
+
+      _describe -t commands command commands && ret=0
+    ;;
+    (option-or-argument)
+      curcontext=${curcontext%:*}-$line[1]:
+      case $line[1] in
+        (add)
+          _arguments \
+            '(-q --quiet)'{-q,--quiet}'[suppress progress output]' \
+            '(-m --message)'{-m+,--message=}'[use the given message as the commit message for the merge commit]:message' \
+            '(-P --prefix)'{-P+,--prefix=}'[the path to the subtree in the repository to manipulate]: :_directories' \
+            '--squash[import only a single commit from the subproject]' \
+            ': :__git_any_repositories_or_references' \
+            ':: :__git_ref_specs' && ret=0
+          # TODO: the use of __git_ref_specs isn't quite right: it will
+          # complete "foo:bar" values which git-subtree(1) doesn't take.  What
+          # we should complete here is what's on *one* side of the colon in
+          # __git_ref_specs.
+	;;
+        (merge)
+          _arguments -S \
+            '(-q --quiet)'{-q,--quiet}'[suppress progress output]' \
+            '(-P --prefix)'{-P+,--prefix=}'[the path to the subtree in the repository to manipulate]: :_directories' \
+            '(-m --message)'{-m+,--message=}'[use the given message as the commit message for the merge commit]:message' \
+            '--squash[import only a single commit from the subproject]' \
+            ': :__git_references' && ret=0
+	;;
+        (pull)
+          _arguments -S \
+            '(-q --quiet)'{-q,--quiet}'[suppress progress output]' \
+            '(-P --prefix)'{-P+,--prefix=}'[the path to the subtree in the repository to manipulate]: :_directories' \
+            '(-m --message)'{-m+,--message=}'[use the given message as the commit message for the merge commit]:message' \
+            '--squash[import only a single commit from the subproject]' \
+            ': :__git_any_repositories' \
+            ':: :__git_ref_specs' && ret=0
+	;;
+        (push)
+          _arguments -S \
+            '(-q --quiet)'{-q,--quiet}'[suppress progress output]' \
+            '(-P --prefix)'{-P+,--prefix=}'[the path to the subtree in the repository to manipulate]: :_directories' \
+            '(-m --message)'{-m+,--message=}'[use the given message as the commit message for the merge commit]:message' \
+            ': :__git_any_repositories' \
+            ':: :__git_ref_specs' && ret=0
+	;;
+        (split)
+          _arguments -S \
+	    '--annotate[add a prefix to commit message of new commits]:prefix' \
+            '(-q --quiet)'{-q,--quiet}'[suppress progress output]' \
+            '(-P --prefix)'{-P+,--prefix=}'[specify path to the subtree in the repository to manipulate]: :_directories' \
+            '(-b --branch)'{-b,--branch=}'[create a new branch]' \
+            '--onto=[try connecting new tree to an existing one]: :__git_ref_specs' \
+            '(-m --message)'{-m+,--message=}'[specify commit message for the merge]:message' \
+            '--ignore-joins[ignore prior --rejoin commits]' \
+            '--onto=[try connecting new tree to an existing one]: :__git_ref_specs' \
+            '--rejoin[merge the new branch back into HEAD]' \
+            '*: :__git_references' && ret=0
+	;;
+        (*)
+          _default && ret=0
+	;;
+      esac
+    ;;
+  esac
+
+  return ret
+}
+
 (( $+functions[_git-tag] )) ||
 _git-tag () {
   local -a message_opts
 
   if (( words[(I)-[asu]] )); then
     message_opts=(
-      '(   -F)-m+[specify tag message]:message'
-      '(-m   )-F+[read tag message from given file]:message file:_files')
+      '(-m --message -F --file)'{-m+,--message=}'[specify tag message]:message'
+      '(-m --message -F --file)'{-F+,--file=}'[read tag message from given file]:message file:_files'
+    )
   fi
 
-  _arguments -A '-*' \
+  _arguments \
     - creation \
-      '(   -s -u --local-user)-a[create an unsigned, annotated tag]' \
-      '(-a    -u --local-user)-s[create an signed and annotated tag]' \
-      '(-a -s)'{-u+,--local-user=}'[create a tag, annotated and signed with the given key]: :__git_gpg_secret_keys' \
-      '-f[replace existing tag]' \
+      '(-a --annotate -s --sign -u --local-user)'{-a,--annotate}'[create an unsigned, annotated tag]' \
+      '(-a --annotate -s --sign -u --local-user)'{-s,--sign}'[create a signed and annotated tag]' \
+      '(-a --annotate -s --sign)'{-u+,--local-user=}'[create a tag, annotated and signed with the given key]: :__git_gpg_secret_keys' \
+      '(-f --force)'{-f,--force}'[replace existing tag]' \
+      '--create-reflog[create a reflog]' \
       '--cleanup=[cleanup message]:mode:((verbatim\:"no cleanup" whitespace\:"remove leading and trailing whitespace" strip\:"remove leading and trailing whitespace and comments"))' \
       $message_opts \
       ': :__git_tags' \
       ':: :__git_commits' \
     - deletion \
-      '-d[delete tags]' \
+      '(-d --delete)'{-d,--delete}'[delete tags]' \
       '*:: :__git_ignore_line_inside_arguments __git_tags' \
     - listing \
       '-n+[limit line output of annotation]: :__git_guard_number "limit"' \
@@ -1776,15 +1957,82 @@ _git-tag () {
       '(--no-column)--column=-[display tag listing in columns]::column.tag option:((always\:"always show in columns" never\:"never show in columns" auto\:"show in columns if the output is to the terminal" column\:"fill columns before rows (default)" row\:"fill rows before columns" plain\:"show in one column" dense\:"make unequal size columns to utilize more space" nodense\:"make equal size columns"))' \
       '(--column)--no-column[do not display in columns]' \
       '--contains=[only list tags which contain the specified commit]: :__git_commits' \
-      '--points-at=[only list tags of the given object]: :__git_commits' \
+      '--merged=-[print only tags that are merged]:: :__git_commits' \
+      '--no-merged=-[print only tags that are not merged]:: :__git_commits' \
       '--sort=[specify how the tags should be sorted]:mode:((refname\:"lexicographic order"
                                                              version\\\:refname\:"tag names are treated as version numbers"))' \
-      '::pattern' \
+      '--points-at=[only list tags of the given object]: :__git_commits' \
+      '--format=[specify format to use for the output]:format' \
+      '(-i --ignore-case)'{-i,--ignore-case}'[sorting and filtering are case-insensitive]' \
+      ':: :_guard "^-*" pattern' \
     - verification \
-      '-v[verifies gpg signutare of tags]' \
+      '(-v --verify)'{-v,--verify}'[verify gpg signutare of tags]' \
       '*:: :__git_ignore_line_inside_arguments __git_tags'
 }
 
+(( $+functions[_git-worktree] )) ||
+_git-worktree() {
+  local curcontext="$curcontext" state state_descr line ret=1
+  declare -A opt_args
+
+  _arguments -C \
+    ': :->command' \
+    '*::: := ->option-or-argument' && ret=0
+
+  case $state in
+    (command)
+      declare -a commands args
+
+      commands=(
+        add:'create a new working tree'
+        prune:'prune working tree information'
+        list:'list details of each worktree'
+	lock:'prevent a working tree from being pruned'
+	unlock:'allow working tree to be pruned, moved or deleted'
+      )
+
+      _describe -t commands command commands && ret=0
+    ;;
+    (option-or-argument)
+      curcontext=${curcontext%:*}-$line[1]:
+      case $line[1] in
+        (add)
+	  if (( $words[(I)--detach] )); then
+	    args=( ':commit:__git_commits' )
+	  else
+	    args=( ':branch:__git_branch_names' )
+	  fi
+          _arguments \
+	    '(-f --force)'{-f,--force}'[checkout branch even if already checked out in another worktree]' \
+	    '(-B --detach)-b+[create a new branch]: :__git_branch_names' \
+	    '(-b --detach)-B+[create or reset a branch]: :__git_branch_names' \
+	    '(-b -B)--detach[detach HEAD at named commit]' \
+	    '--no-checkout[suppress file checkout in new worktree]' \
+	    ':path:_files' $args && ret=0
+	;;
+        (prune)
+          _arguments \
+	    '(-n --dry-run)'{-n,--dry-run}"[don't remove, show only]" \
+	    '(-v --verbose)'{-v,--verbose}'[report pruned objects]' \
+	    '--expire[expire objects older than specified time]:time' && ret=0
+	;;
+        (list)
+	  _arguments '--porcelain[machine-readable output]' && ret=0
+	;;
+	(lock)
+	  _arguments -C '--reason=[specify reason for locking]:reason' ': :->worktrees' && ret=0
+	  [[ -z $state ]] && return ret
+	;&
+	(unlock)
+	  _wanted directories expl 'working tree' compadd -S ' ' -f -M 'r:|/=* r:|=*' \
+	      ${${(M)${(f)"$(_call_program directories git worktree list --porcelain)"}:#worktree*}#* }
+	;;
+      esac
+    ;;
+  esac
+  return ret
+}
+
 (( $+functions[_gitk] )) ||
 _gitk () {
   _git-log
@@ -1800,7 +2048,7 @@ _tig () {
 (( $+functions[_git-config] )) ||
 _git-config () {
   local name_arg value_arg
-  local curcontext=$curcontext state line expl ret=1
+  local curcontext=$curcontext state line ret=1
   declare -A opt_args
 
   if (( words[(I)--get-regexp] )); then
@@ -1823,41 +2071,77 @@ _git-config () {
     value_arg=': :->value'
   fi
 
-  _arguments -w -C -S -s \
-    '(         --system --local -f --file)--global[use user-global config file]' \
-    '(--global          --local -f --file)--system[use system-wide config file]' \
-    '(--global --system         -f --file)--local[use local config file]' \
-    '(--global --system -f --file)'{-f+,--file=}'[use given config file]:config file:_files' \
+  _arguments -C -S -s \
+    '(         --system --local -f --file --blob)--global[use user-global config file]' \
+    '(--global          --local -f --file --blob)--system[use system-wide config file]' \
+    '(--global --system         -f --file --blob)--local[use local config file]' \
+    '(--global --system --local           --blob)'{-f+,--file=}'[use given config file]:config file:_files' \
+    '(--global --system --local -f --file)--blob=[read config from given blob object]:blob:__git_blobs' \
     '(       --int --bool-or-int --path)--bool[setting is a boolean]' \
     '(--bool       --bool-or-int --path)--int[setting is an integer]' \
     '(--bool --int               --path)--bool-or-int[setting is an integer]' \
     '(--bool --int --bool-or-int       )--path[setting is a path]' \
     '(-z --null)'{-z,--null}'[end values with NUL and newline between key and value]' \
+    '(--get --get-all --get-urlmatch --replace-all --add --unset --unset-all --rename-section --remove-section -e --edit --get-color --get-colorbool)--name-only[show variable names only]' \
+    '(--includes)'--no-includes"[don't respect \"include.*\" directives]" \
+    '(--no-includes)'--includes'[respect "include.*" directives in config files when looking up values]' \
+    '(--global --system --local -f --file --blob --get-urlmatch --replace-all --add --unset --unset-all --rename-section --remove-section -e --edit --get-color --get-colorbool)--show-origin[show origin of config]' \
     $name_arg \
     $value_arg \
     '::value regex' \
     - '(actions)' \
-      '(-z --null)--replace-all[replace all values of the given key]' \
-      '(3 -z --null)--add[add new value without altering any existing ones]' \
-      '(2)--get[get the first matching value of the key]' \
-      '(2)--get-all[get all matching values of the key]' \
-      '(3 --bool --int --bool-or-int --path -z --null)--remove-section[remove the given section]' \
-      '(3 --bool --int --bool-or-int --path -z --null)--rename-section[rename the given section]'  \
-      '(2 --bool --int --bool-or-int --path -z --null)--unset[remove the first matching value of the key]' \
-      '(2 --bool --int --bool-or-int --path -z --null)--unset-all[remove all matching values of the key]' \
-      '(: --bool --int --bool-or-int --path)'{-l,--list}'[list all variables set in config file]' \
+      '(2 --name-only)--get[get the first matching value of the key]' \
+      '(2 --name-only)--get-all[get all matching values of the key]' \
       '(2)--get-regexp[like "--get-all", but interpret "name" as a regular expression]' \
-      '(2 3 --bool --int --bool-or-int --path -z --null)--get-colorbool[check if color should be used]: :->gettable-colorbool-option' \
-      '(2 3 --bool --int --bool-or-int --path -z --null)--get-color[find color setting]: :->gettable-color-option' \
-      '(-e --edit --bool --int --bool-or-int --path -z --null)'{-e,--edit}'[open config file for editing]' \
-      '(--no-includes)'--includes'[respect "include.*" directives in config files when looking up values]' \
-      '(--includes)'--no-includes'[do not respect "include.*" directives]' && ret=0
+      '(--name-only --show-origin)--get-urlmatch[get value specific for the URL]' \
+      '(-z --null --name-only --show-origin)--replace-all[replace all values of the given key]' \
+      '(3 -z --null --name-only --show-origin)--add[add new value without altering any existing ones]' \
+      '(2 --bool --int --bool-or-int --path -z --null --name-only --show-origin)--unset[remove the first matching value of the key]' \
+      '(2 --bool --int --bool-or-int --path -z --null --name-only --show-origin)--unset-all[remove all matching values of the key]' \
+      '(3 --bool --int --bool-or-int --path -z --null --name-only --show-origin)--rename-section[rename the given section]'  \
+      '(3 --bool --int --bool-or-int --path -z --null --name-only --show-origin)--remove-section[remove the given section]' \
+      '(: --bool --int --bool-or-int --path)'{-l,--list}'[list all variables set in config file]' \
+      '(-e --edit --bool --int --bool-or-int --path -z --null --name-only --show-origin)'{-e,--edit}'[open config file for editing]' \
+      '(2 3 --bool --int --bool-or-int --path -z --null --name-only --show-origin)--get-color[find color setting]: :->gettable-color-option' \
+      '(2 3 --bool --int --bool-or-int --path -z --null --name-only --show-origin)--get-colorbool[check if color should be used]: :->gettable-colorbool-option' && ret=0
+  __git_config_option-or-value "$@" && ret=0
+  return ret
+}
+
+(( $+functions[__git_config_option] )) ||
+__git_config_option () {
+  local -A opt_args=()
+  local -a line=( ${words[CURRENT]%%=*} )
+  local state=option
+  __git_config_option-or-value "$@"
+}
+
+(( $+functions[__git_config_value] )) ||
+__git_config_value () {
+  local -A opt_args=()
+  local -a line=( ${words[CURRENT]%%=*} ${words[CURRENT]#*=} )
+  local state=value
+  __git_config_option-or-value "$@"
+}
+
+# Helper to _git-config().  May be called by other functions, too, provided
+# that The caller has set $line, $state, and $opt_args as _git-config() would
+# set them:
+# 
+# - set $line[1] to the option name being completed (even if completing an
+#   option value).
+# - set $opt_args to git-config(1) options, as set by _arguments in
+#   _git-config().
+# - set $state as _arguments in _git-config() would set it.
+(( $+functions[__git_config_option-or-value] )) ||
+__git_config_option-or-value () {
+  local expl ret
 
   # TODO: Add support for merge.*. (merge driver), diff.*. (diff driver), and filter.*. (filter driver) options
   # (see gitattributes(5)).
   # TODO: .path options should take absolute paths.
-  declare -a git_options_static
-  git_options_static=(
+  declare -a git_options
+  git_options=(
     advice.pushNonFastForward:'show advice when git push refuses non-fast-forward refs::->bool:true'
     advice.pushUpdateRejected:'combined setting for advice.push*::->bool:true'
     advice.pushNonFFCurrent:'show advice when git push fails due to a non-fast-forward update to the current branch::->bool:true'
@@ -2334,7 +2618,7 @@ _git-config () {
     'svn-remote.*.pushurl:URL to push to::_urls'
     'svn-remote.*.branches:branch mappings:branch mapping:->string'
     'svn-remote.*.tags:tag mappings:tag mapping:->string'
-    tag.sort:'Default sorting method:->string'
+    tag.sort:'default sorting method:sorting method:->string'
     'tar.*.command:specify a shell command through which the tar output generated by git archive should be piped::_cmdstring'
     'tar.*.remote:enable <format> for use by remote clients via git-upload-archive::->bool'
     tar.umask:'umask to apply::->umask'
@@ -2346,11 +2630,49 @@ _git-config () {
     uploadarchive.allowUnreachable:'allow git-upload-archive to accept an archive requests that ask for unreachable objects::->bool:false'
     'url.*.insteadOf:string to start URLs with:prefix:->string'
     'url.*.pushInsteadOf:string to start URLs to push to with:prefix:->string'
-    user.email:'email address used for commits::_email_addresses'
+    user.email:'email address used for commits::_email_addresses -c'
     user.name:'full name used for commits:name:->string'
     user.signingkey:'default GPG key to use when creating signed tags::__git_gpg_secret_keys'
     web.browser:'web browser to use::__git_browsers')
 
+  declare -a git_present_options # 'present' is an adjective
+  git_present_options=(
+    ${${${(0)"$(_call_program gettable-options git config -z --list)"}%%$'\n'*}//:/\\:}
+  )
+
+  # Add to $git_options options from the config file that aren't already in $git_options.
+  () {
+    local -a -U sections_that_permit_arbitrary_subsection_names=(
+      alias
+      pager
+      pretty
+      remotes
+      ${(u)${(M)${git_options%%:*}:#*[.][*][.]*}%%.*}
+    )
+    local key
+    for key in $git_present_options ; do
+      if (( ${+git_options[(r)(#i)${(b)key}:*]} )); then
+        # $key is already in git_options
+        continue 
+      elif (( ${+sections_that_permit_arbitrary_subsection_names[(r)${(b)key%%.*}]} )); then
+        if [[ $key == *.*.* ]]; then
+          # If $key isn't an instance of a known foo.*.bar:baz $git_options entry...
+          if ! (( ${+git_options[(r)(#i)${(b)key%%.*}.[*].${(b)key##*.}:*]} )); then
+            # ... then add it.
+            git_options+="${key}:unknown option name::->unknown"
+          fi
+        else
+          # $key is of the form "foo.bar" where 'foo' is known
+          # No need to add it; "foo.<TAB>' will find 'bar' via another codepath later
+          # ### TODO: that "other codepath" will probably run git config -z again, redundantly.
+          continue
+        fi
+      else
+        git_options+="${key}:unknown option name::->unknown"
+      fi
+    done
+  }
+
   case $state in
     (section)
       __git_config_sections -b '(|)' '^' section-names 'section name' $* && ret=0
@@ -2371,8 +2693,10 @@ _git-config () {
 
       if compset -P '[^.]##.*.'; then
         declare -a match mbegin mend
-        options+=(${${${${(M)git_options_static:#(#i)${IPREFIX}[^.:]##:*}#(#i)${IPREFIX}}/#(#b)([^:]##:)([^\\:]#(\\?[^\\:]#)#:[^\\:]#(\\?[^\\:]#)#:->bool)/$match[1]whether or not to $match[2]}/#(#b)([^:]##:([^\\:]#(\\?[^\\:]#)#))*/$match[1]})
-        options+=(${${${${(M)git_options_static:#(#i)${IPREFIX%%.*}.\*.[^.:]##:*}#(#i)${IPREFIX%%.*}.\*.}/#(#b)([^:]##:)([^\\:]#(\\?[^\\:]#)#:[^\\:]#(\\?[^\\:]#)#:->bool)/$match[1]whether or not to $match[2]}/#(#b)([^:]##:([^\\:]#(\\?[^\\:]#)#))*/$match[1]})
+        # When completing 'remote.foo.<TAB>', offer 'bar' if $git_options contains 'remote.foo.bar'.
+        options+=(${${${${(M)git_options:#(#i)${IPREFIX}[^.:]##:*}#(#i)${IPREFIX}}/#(#b)([^:]##:)([^\\:]#(\\?[^\\:]#)#:[^\\:]#(\\?[^\\:]#)#:->bool)/$match[1]whether or not to $match[2]}/#(#b)([^:]##:([^\\:]#(\\?[^\\:]#)#))*/$match[1]})
+        # When completing 'remote.foo.<TAB>', offer 'bar' if $git_options contains 'remote.*.bar'.
+        options+=(${${${${(M)git_options:#(#i)${IPREFIX%%.*}.\*.[^.:]##:*}#(#i)${IPREFIX%%.*}.\*.}/#(#b)([^:]##:)([^\\:]#(\\?[^\\:]#)#:[^\\:]#(\\?[^\\:]#)#:->bool)/$match[1]whether or not to $match[2]}/#(#b)([^:]##:([^\\:]#(\\?[^\\:]#)#))*/$match[1]})
 
         declare -a labels
         labels=(
@@ -2406,8 +2730,8 @@ _git-config () {
       elif compset -P '[^.]##.'; then
         local opt
         declare -a match mbegin mend
-        for opt in ${${${${(M)git_options_static:#(#i)${IPREFIX}[^.:]##:*}#(#i)${IPREFIX}}/#(#b)([^:]##:)([^\\:]#(\\?[^\\:]#)#:[^\\:]#(\\?[^\\:]#)#:->bool)/$match[1]whether or not to $match[2]}/#(#b)([^:]##:([^\\:]#(\\?[^\\:]#)#))*/$match[1]}; do
-          if (( ${git_options_static[(I)${opt%%:*}.*]} )); then
+        for opt in ${${${${(M)git_options:#(#i)${IPREFIX}[^.:]##:*}#(#i)${IPREFIX}}/#(#b)([^:]##:)([^\\:]#(\\?[^\\:]#)#:[^\\:]#(\\?[^\\:]#)#:->bool)/$match[1]whether or not to $match[2]}/#(#b)([^:]##:([^\\:]#(\\?[^\\:]#)#))*/$match[1]}; do
+          if (( ${git_options[(I)${opt%%:*}.*]} )); then
             sections_and_options+=$opt
           else
             options+=$opt
@@ -2420,6 +2744,7 @@ _git-config () {
           'gitcvs.ext:ext-connection-method-specific options'
           'gitcvs.pserver:pserver-connection-method-specific options'
           'notes.rewrite:commands to copy notes from original for when rewriting commits')
+        # Set $sections to the applicable subsection names (e.g., 'decorate:...' if $IPREFIX == "color.")
         sections+=(${${(M)subsections:#${IPREFIX}[^.:]##(.|):*}#${IPREFIX}})
 
         # TODO: Is it fine to use functions like this before _describe below,
@@ -2428,6 +2753,8 @@ _git-config () {
         # following functions don't generate any output in the case of
         # multi-level options.
         case $IPREFIX in
+          # Note: If you add a branch to this 'case' statement,
+          # update $sections_that_permit_arbitrary_subsection_names.
           (alias.)
             __git_aliases && ret=0
             ;;
@@ -2485,6 +2812,10 @@ _git-config () {
           (svn-remote.)
             __git_svn-remotes -S . && ret=0
             ;;
+          (*.)
+            local -a existing_subsections=( ${${${(M)git_present_options:#${IPREFIX}*.*}#${IPREFIX}}%.*} )
+            _describe -t existing-subsections "existing subsections" existing_subsections -S . && ret=0
+            ;;
         esac
       else
         sections=(
@@ -2547,6 +2878,13 @@ _git-config () {
           web:'web options'
           svn:'git svn options'
           svn-remote:'git svn remotes')
+        () {
+          local i
+          for i in ${(u)git_present_options%%.*}; do
+            (( ${+sections[(r)(#i)${(b)i}:*]} )) ||
+              sections+="${i}:unknown section name"
+          done
+        }
       fi
 
       # TODO: Add equivalent of -M 'r:|.=* r:|=*' here so that we can complete
@@ -2554,11 +2892,10 @@ _git-config () {
       _describe -t option-names $label \
         sections -M 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' -S . -- \
         sections_and_options -M 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' -qS . -- \
-        options -M 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' && ret=0
+        options -M 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' "$@" && ret=0
       ;;
     (gettable-option)
-      _wanted git-options expl option compadd -M 'r:|.=* r:|=*' - \
-        ${${${(0)"$(_call_program gettable-options git config -z --list)"}%%$'\n'*}//:/\\:} && ret=0
+      _wanted git-options expl option compadd -M 'r:|.=* r:|=*' -a - git_present_options && ret=0
       ;;
     (gettable-colorbool-option)
       __git_config_sections -b '(|)' -a '(|)' '^color\.[^.]+$' gettable-colorbool-options option && ret=0
@@ -2567,7 +2904,7 @@ _git-config () {
       __git_config_sections -b '(|)' -a '(|)' '^color\.[^.]+\..*$' gettable-color-options option && ret=0
       ;;
     (value)
-      local current=${${(0)"$(_call_program current "git config $opt_args[(I)--system|--global|--local] ${(kv)opt_args[(I)-f|--file]} -z --get '$line[1]'")"}#*$'\n'}
+      local current=${${(0)"$(_call_program current "git config $opt_args[(I)--system|--global|--local]" ${(kv)opt_args[(I)-f|--file]} "-z --get ${(q)line[1]}")"}#*$'\n'}
       case $line[1] in
         (alias.*)
           if [[ -n $current ]]; then
@@ -2595,12 +2932,17 @@ _git-config () {
           ;;
       esac
       local z=$'\0'
+
+      # Set $parts to the $git_options element that corresponds to $line[1]
+      # (the option name whose value is currently being completed).  The elements
+      # of $parts are the colon-separated elements of the $git_options element.
       declare -a parts
-      parts=("${(S@0)${git_options_static[(r)(#i)${line[1]}:*]}//(#b)(*[^\\]|):/$match[1]$z}")
+      parts=("${(S@0)${git_options[(r)(#i)${line[1]}:*]}//(#b)(*[^\\]|):/$match[1]$z}")
       if (( $#parts < 2 )) && [[ $line[1] == [^.]##.*.[^.]## ]]; then
-        parts=("${(S@0)${git_options_static[(r)(#i)${line[1]%%.*}.\*.${line[1]##*.}:*]}//(#b)(*[^\\]|):/$match[1]$z}")
+        parts=("${(S@0)${git_options[(r)(#i)${line[1]%%.*}.\*.${line[1]##*.}:*]}//(#b)(*[^\\]|):/$match[1]$z}")
       fi
-      (( $#parts > 0 )) || return ret
+
+      (( $#parts >= 4 )) || return ret
       case $parts[4] in
         ('->'*)
           case ${parts[4]#->} in
@@ -2927,6 +3269,10 @@ _git-config () {
                 'values:value:(user)' \
                 'umasks: :__git_guard_number umask' && ret=0
               ;;
+            (unknown)
+              _message "$line[1] option value"
+              compadd - $current && ret=0
+              ;;
           esac
           ;;
         (*)
@@ -2946,7 +3292,7 @@ _git-config () {
 (( $+functions[_git-fast-export] )) ||
 _git-fast-export () {
   # TODO: * should be git-rev-arg and git-rev-list arguments.
-  _arguments -w -S -s \
+  _arguments -S -s \
     '--progress=[insert progress statements]: :__git_guard_number interval' \
     '--signed-tags=[specify how to handle signed tags]:action:((verbatim\:"silently export"
                                                                 warn\:"export, but warn"
@@ -2965,6 +3311,9 @@ _git-fast-export () {
     '--use-done-feature[start with a "feature done" stanza, and terminate with a "done" command]' \
     '--no-data[do not output blocb objects, instead referring to them via their SHA-1 hash]' \
     '--full-tree[output full tree for each commit]' \
+    '(--get --get-all)--name-only[show variable names only]' \
+    '*--refspec=[apply refspec to exported refs]:refspec' \
+    '--anonymize[anonymize output]' \
     '*: :__git_commit_ranges'
 }
 
@@ -2977,8 +3326,8 @@ _git-fast-import () {
                                                            now\:"use current time and timezone"' \
     '--done[terminate with error if there is no "done" command at the end of the stream]' \
     '--force[force updating modified existing branches]' \
-    '--max-pack-size=-[maximum size of each packfile]: :__git_guard_bytes' \
-    '--big-file-threshold=-[maximum size of blob to create deltas for]: :__git_guard_bytes' \
+    '--max-pack-size=-[maximum size of each packfile]: : __git_guard_bytes' \
+    '--big-file-threshold=-[maximum size of blob to create deltas for]: : __git_guard_bytes' \
     '--depth=-[maximum delta depth for blob and tree deltification]: :__git_guard_number "maximum delta depth"' \
     '--active-branches=-[maximum number of branches to maintain active at once]: :__git_guard_number "maximum number of branches"' \
     '--export-marks=-[dump internal marks table when complete]: :_files' \
@@ -3020,6 +3369,7 @@ _git-mergetool () {
     '--tool-help[print a list of merge tools that may be used with "--tool"]' \
     '(-y --no-prompt --prompt)'{-y,--no-prompt}'[do not prompt before invocation of merge resolution program]' \
     '(-y --no-prompt)--prompt[prompt before invocation of merge resolution program]' \
+    '-O-[process files in the order specified in file]:order file:_files' \
     '*:conflicted file:_files'
 }
 
@@ -3037,7 +3387,8 @@ _git-prune () {
   _arguments -S \
     '(-n --dry-run)'{-n,--dry-run}'[do not remove anything; just report what would be removed]' \
     '(-v --verbose)'{-v,--verbose}'[report all removed objects]' \
-    '--expire[only expire loose objects older than given date]: :__git_datetimes' \
+    '--progress[show progress]' \
+    '--expire=[only expire loose objects older than specified date]: :__git_datetimes' \
     '*:: :__git_heads'
 }
 
@@ -3068,7 +3419,9 @@ _git-reflog () {
         commands=(
           'expire:prune old reflog entries'
           'delete:delete entries from reflog'
-          'show:show log of ref')
+          'show:show log of ref'
+          'exists:check whether a ref has a reflog'
+	)
 
         _alternative \
           'commands:: _describe -t commands command commands' \
@@ -3096,6 +3449,7 @@ _git-reflog () {
               '(-n --dry-run)'{-n,--dry-run}'[undocumented]' \
               '--updateref[update ref with SHA-1 of top reflog entry after expiring or deleting]' \
               '--rewrite[adjust reflog entries to ensure old SHA-1 points to new SHA-1 of previous entry after expiring or deleting]' \
+              '--verbose[output additional information]' \
               '*:: :->reflog-entry' && ret=0
 
             case $state in
@@ -3110,6 +3464,9 @@ _git-reflog () {
               $revision_options \
               ':: :__git_references' && ret=0
             ;;
+	  (exists)
+	    __git_references && ret=0
+	    ;;
         esac
     esac
 
@@ -3143,14 +3500,16 @@ _git-remote () {
 
       commands=(
         'add:add a new remote'
+	'get-url:retrieves the URLs for a remote'
         'rename:rename a remote and update all associated tracking branches'
-        'rm:remove a remote and all associated tracking branches'
+	{rm,remove}':remove a remote and all associated tracking branches'
         'set-head:set or delete default branch for a remote'
         'set-branches:change list of branches tracked by a remote'
         'set-url:change URL for a remote'
         'show:show information about a given remote'
         'prune:delete all stale tracking branches for a remote'
-        'update:fetch updates for a set of remotes')
+        'update:fetch updates for a set of remotes'
+      )
 
       _describe -t commands command commands && ret=0
       ;;
@@ -3160,13 +3519,13 @@ _git-remote () {
       case $line[1] in
         (add)
           # TODO: -t and --track should really list branches at url.
-          _arguments -w -S -s \
+          _arguments -S -s \
             '(-f --fetch)'{-f,--fetch}'[run git fetch on new remote after it has been created]' \
             '(       --no-tags)--tags[tell git fetch to import every tag from remote repository]' \
             '(--tags          )--no-tags[tell git fetch to not import every tag from remote repository]' \
             '*'{-t,--track=}'[track given branch instead of default glob refspec]: :__git_branch_names' \
             '(-m --master)'{-m,--master=}'[set HEAD of remote to point to given master branch]: :__git_branch_names' \
-            '--mirror[do not use separate remotes]' \
+	    '--mirror[do not use separate remotes]::mirror type:(fetch pull)' \
             ':name:__git_remotes' \
             ':repository:->repository' && ret=0
 	  case $state in
@@ -3178,18 +3537,20 @@ _git-remote () {
 	    ;;
 	  esac
           ;;
+        (get-url)
+          _arguments -S -s \
+            '--push[list push URL instead of fetch URL]' \
+            '--all[list all URLs for the remote]' \
+            ': :__git_remotes' && ret=0
+          ;;
         (rename)
           _arguments \
             ':old name:__git_remotes' \
             ':new name:__git_remotes' && ret=0
           ;;
-        (rm)
-          _arguments \
-            ': :__git_remotes' && ret=0
-          ;;
         (set-head)
           # TODO: Second argument should be a branch at url for remote.
-          _arguments -w -S -s \
+          _arguments -S -s \
             '(- 2)'{-d,--delete}'[delete default branch]' \
             '(- 2)'{-a,--auto}'[determine default branch automatically]' \
             ': :__git_remotes' \
@@ -3197,14 +3558,14 @@ _git-remote () {
           ;;
         (set-branches)
           # TODO: Branches should be at url.
-          _arguments -w -S -s \
+          _arguments -S -s \
             '--add[add branches to those already defined]' \
             ': :__git_remotes' \
             '*: :__git_branch_names' && ret=0
           ;;
         (set-url)
           # TODO: Old URL should be one of those defined for the remote.
-          _arguments -w -S -s \
+          _arguments -S -s \
             '(3)--push[manipulate push URLs instead of fetch URLs]' \
             '--add[add URL to those already defined]' \
             '(3)--delete[delete all matching URLs]' \
@@ -3213,20 +3574,23 @@ _git-remote () {
             ':old url:_urls' && ret=0
           ;;
         (show)
-          _arguments -w -S -s \
+          _arguments -S \
             '-n[do not contact the remote for a list of branches]' \
             '*: :__git_remotes' && ret=0
           ;;
         (prune)
-          _arguments -w -S -s \
+          _arguments -S -s \
             '(-n --dry-run)'{-n,--dry-run}'[do not actually prune, only list what would be done]' \
             '*: :__git_remotes' && ret=0
           ;;
         (update)
-          _arguments -w -S -s \
+          _arguments -S -s \
             '(-p --prune)'{-p,--prune}'[prune all updated remotes]' \
             ': :__git_remote-groups' && ret=0
           ;;
+	(*) # rm, remove and fallback for any new subcommands
+	  __git_remotes && ret=0
+	  ;;
       esac
       ;;
   esac
@@ -3237,32 +3601,40 @@ _git-remote () {
 (( $+functions[_git-repack] )) ||
 _git-repack () {
   # TODO: --quiet is undocumented.
-  _arguments -w -S -s \
-    '(-A)-a[pack all objects into a single pack]' \
-    '(-a)-A[pack all objects into a single pack, but unreachable objects become loose]' \
+  _arguments -s \
+    '(-A --unpack-unreachable)-a[pack all objects into a single pack]' \
+    '(-a -k --keep-unreachable)-A[pack all objects into a single pack, but unreachable objects become loose]' \
     '-d[remove redundant packs after packing]' \
-    '-l[pass --local option to git pack-objects]' \
+    "--unpack-unreachable=[with -A, don't loosen objects older than specified date]:date" \
     '-f[pass --no-reuse-delta option to git pack-objects]' \
     '-F[pass --no-reuse-object option to git pack-objects]' \
+    "-n[don't update server information]" \
     '(-q --quiet)'{-q,--quiet}'[pass -q option to git pack-objects]' \
-    '-n[do not update server information]' \
-    '--window=-[number of objects to consider when doing delta compression]: :__git_guard_number "number of objects"' \
-    '--depth=-[maximum delta depth]: :__git_guard_number "maximum delta depth"' \
-    '--window-memory=-[scale window size dynamically to not use more than N bytes of memory]: :__git_guard_bytes' \
-    '--max-pack-size=-[maximum size of each output packfile]:maximum pack size:__git_guard_bytes'
+    '(-l --local)'{-l,--local}'[pass --local option to git pack-objects]' \
+    '(-b --write-bitmap-index)'{-b,--write-bitmap-index}'[write a bitmap index]' \
+    "--unpack-unreachable=[with -A, don't loosen objects older than specified time]:time" \
+    '(-k --keep-unreachable)'{-k,--keep-unreachable}'[with -a, repack unreachable objects]' \
+    '--window=[number of objects to consider when doing delta compression]:number of objects' \
+    '--window-memory=[scale window size dynamically to not use more than specified amount of memory]: : __git_guard_bytes' \
+    '--depth=[maximum delta depth]:maximum delta depth' \
+    '--max-pack-size=-[maximum size of each output packfile]: : __git_guard_bytes "maximum pack size"' \
+    '--pack-kept-objects[repack objects in packs marked with .keep]'
 }
 
 (( $+functions[_git-replace] )) ||
 _git-replace () {
-  _arguments -w -S -s \
-    '--edit[edit existing object as base a starting point]' \
-    '--graft[rewrite the parents of a commit]' \
-    '(- *)-f[overwrite existing replace ref]' \
-    '(- 2)-d[delete existing replace refs]' \
-    '(- : *)-l[list replace refs]:pattern' \
+  _arguments -S -s \
+    '(-d --delete -l --list -g --graft *)'{-f,--force}'[overwrite existing replace ref]' \
+    "(-d --delete -l --list -g --graft 2 *)--raw[don't pretty-print contents for --edit]" \
+    '(-d --delete -e --edit -g --graft --raw)--format=[use specified format]:format:(short medium long)' \
     ': :__git_objects' \
     ':replacement:__git_objects' \
-    '*: :__git_objects'
+    '*: :__git_objects' \
+    - '(actions)' \
+    '(: * --raw -f --force)'{-l,--list}'[list replace refs]:pattern' \
+    {-d,--delete}'[delete existing replace refs]:*:replacement:__git_objects' \
+    '(* 2 --format)'{-e,--edit}'[edit existing object and replace it with the new one]' \
+    '(--raw --format)'{-g,--graft}'[rewrite the parents of a commit]'
 }
 
 # Ancillary Commands (Interrogators)
@@ -3276,10 +3648,11 @@ _git-blame () {
   __git_setup_revision_options
 
   # TODO: Not sure about __git_cached_files.
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '-b[show blank SHA-1 for boundary commits]' \
     '--root[do not treat root commits as boundaries]' \
     '--show-stats[include additional statistics at the end of blame output]' \
+    '--progress[force progress reporting]' \
     '*-L[annotate only the given line range]: :->line-range' \
     '-l[show long rev]' \
     '-t[show raw timestamp]' \
@@ -3297,6 +3670,7 @@ _git-blame () {
     '(-n --show-number)'{-n,--show-number}'[show the line number in the original commit]' \
     '-s[suppress author name and timestamp]' \
     '-w[ignore whitespace when finding lines]' \
+    '--indent-heuristic[use indent-based heuristic to improve diffs]' \
     $revision_options \
     ':: :__git_revisions' \
     ': :__git_cached_files' && ret=0
@@ -3334,7 +3708,7 @@ _git-cherry () {
 _git-count-objects () {
   _arguments \
     '(-v --verbose)'{-v,--verbose}'[also report number of in-pack objects and objects that can be removed]' \
-    {-H,--human-readable}'[Print sizes in human readable format]'
+    {-H,--human-readable}'[print sizes in human readable format]'
 }
 
 (( $+functions[_git-difftool] )) ||
@@ -3349,13 +3723,14 @@ _git-difftool () {
     '--tool-help[print a list of diff tools that may be used with --tool]' \
     '(--symlinks)--no-symlinks[make copies of instead of symlinks to the working tree]' \
     '(---no-symlinks)--symlinks[make symlinks to instead of copies of the working tree]' \
-    '(-g --gui)'{-g,--gui}'[use diff.guitool instead of diff.tool]'
+    '(-g --gui)'{-g,--gui}'[use diff.guitool instead of diff.tool]' \
+    '--trust-exit-code[make git-difftool exit when diff tool returns a non-zero exit code]'
 }
 
 (( $+functions[_git-fsck] )) ||
 _git-fsck () {
   # TODO: -v is undocumented.
-  _arguments -w -S -s \
+  _arguments -S -s \
     '--unreachable[show objects that are unreferenced in the object database]' \
     '(--dangling --no-dangling)--dangling[print dangling objects (default)]' \
     '(--dangling --no-dangling)--no-dangling[do not print dangling objects]' \
@@ -3364,9 +3739,12 @@ _git-fsck () {
     '--cache[consider objects recorded in the index as head nodes for reachability traces]' \
     '--no-reflogs[do not consider commits referenced only by reflog entries to be reachable]' \
     '--full[check all object directories]' \
+    '--connectivity-only[check only connectivity]' \
     '--strict[do strict checking]' \
     '(-v --verbose)'{-v,--verbose}'[output additional information]' \
     '--lost-found[write dangling objects into .git/lost-found]' \
+    '--progress[show progress]' \
+    '--name-objects[show verbose names for reachable objects]' \
     '*: :__git_objects'
 }
 
@@ -3377,13 +3755,13 @@ _git-get-tar-commit-id () {
 
 (( $+functions[_git-help] )) ||
 _git-help () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(         -g --guides -i --info -m --man -w --web)'{-a,--all}'[show all available commands]' \
     '(-a --all -g --guides           -m --man -w --web)'{-i,--info}'[show all available commands]' \
     '(-a --all -g --guides -i --info          -w --web)'{-m,--man}'[show all available commands]' \
     '(-a --all -g --guides -i --info -m --man         )'{-w,--web}'[show all available commands]' \
     '(-g --guides)'{-g,--guides}'[prints a list of useful guides on the standard output]' \
-    ': :_git_commands'
+    ': : _alternative commands:command:_git_commands "guides:git guides:(attributes glossary ignore modules revisions tutorial workflows)"'
 }
 
 (( $+functions[_git-instaweb] )) ||
@@ -3391,7 +3769,7 @@ _git-instaweb () {
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
 
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '(-l --local)'{-l,--local}'[bind the web server to 127.0.0.1]' \
     '(-d --httpd)'{-d,--httpd=}'[HTTP-daemon command-line that will be executed]:command line' \
     '(-m --module-path)'{-m,--module-path=}'[module path for the Apache HTTP-daemon]:module path:_directories' \
@@ -3432,7 +3810,7 @@ _git-rerere () {
   declare -A opt_args
 
   # TODO: --rerere-autoupdate is undocumented.
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '--rerere-autoupdate[register clean resolutions in index]' \
     ': :->command' && ret=0
 
@@ -3474,7 +3852,7 @@ _git-rev-parse () {
       _message 'argument'
     else
       # TODO: Parse option specification?
-      _arguments -w -S -s \
+      _arguments -S -s \
         '(- *)'{-h,--help}'[display usage]' \
         '--keep-dashdash[do not skip first -- option]' \
         '--stop-at-non-option[stop parsing options at first non-option argument]' \
@@ -3531,7 +3909,7 @@ _git-show-branch () {
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
 
-  _arguments -w -C -S -s -A '-*' \
+  _arguments -C -S -s -A '-*' \
     '(--more        --merge-base --independent)--list[do not show any ancestry (--more=-1)]' \
     - branches \
       '(-r --remotes -a --all)'{-r,--remotes}'[show remote-tracking branches]' \
@@ -3570,15 +3948,18 @@ _git-show-branch () {
 
 (( $+functions[_git-verify-commit] )) ||
 _git-verify-commit () {
-  _arguments -w -S -s \
-    '(-v --verbose)'{-v,--verbose}'[print the contents of the commit object before validating it]' \
+  _arguments -S -s \
+    '(-v --verbose)'{-v,--verbose}'[print contents of the commit object before validating it]' \
+    '--raw[print raw gpg status output]' \
     '*: :__git_commits'
 }
 
 (( $+functions[_git-verify-tag] )) ||
 _git-verify-tag () {
-  _arguments -w -S -s \
-    '(-v --verbose)'{-v,--verbose}'[print the contents of the tag object before validating it]' \
+  _arguments -S -s \
+    '(-v --verbose)'{-v,--verbose}'[print contents of the tag object before validating it]' \
+    '--raw[print raw gpg status output]' \
+    '--format=[specify format to use for the output]:format' \
     '*: :__git_tags'
 }
 
@@ -3661,7 +4042,7 @@ _git-cvsimport () {
 
 (( $+functions[_git-cvsserver] )) ||
 _git-cvsserver () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '--base-path[path to prepend to requested CVSROOT]: :_directories' \
     '--strict-paths[do not allow recursing into subdirectories]' \
     '--export-all[do not check for gitcvs.enabled]' \
@@ -3673,7 +4054,11 @@ _git-cvsserver () {
 
 (( $+functions[_git-imap-send] )) ||
 _git-imap-send () {
-  _message 'no arguments allowed; accepts mailbox file on standard input'
+  _arguments \
+    '--curl[use libcurl to communicate with the IMAP server]' \
+    - '(out)' \
+    {-v,--verbose}'[be more verbose]' \
+    {-q,--quiet}'[be more quiet]'
 }
 
 (( $+functions[_git-quiltimport] )) ||
@@ -3681,7 +4066,8 @@ _git-quiltimport () {
   _arguments -S \
     '(-n --dry-run)'{-n,--dry-run}'[check patches and warn if they cannot be imported]' \
     '--author[default author name and email address to use for patches]: :_email_addresses' \
-    '--patches[set directory containing patches]:patch directory:_directories'
+    '--patches[set directory containing patches]:patch directory:_directories' \
+    '--series[specify quilt series file]:series file:_files'
 }
 
 (( $+functions[_git-request-pull] )) ||
@@ -3699,8 +4085,8 @@ _git-send-email () {
     '--annotate[review and edit each patch before sending it]' \
     '--bcc=[Bcc: value for each email]: :_email_addresses' \
     '--cc=[starting Cc: value for each email]: :_email_addresses' \
-    '--to-cover[Copy the To: list from the first file to the rest]' \
-    '--cc-cover[Copy the Cc: list from the first file to the rest]' \
+    '--to-cover[copy the To: list from the first file to the rest]' \
+    '--cc-cover[copy the Cc: list from the first file to the rest]' \
     '--compose[edit introductory message for patch series]' \
     '--from=[specify sender]:email address:_email_addresses' \
     '--in-reply-to=[specify contents of first In-Reply-To header]:message-id' \
@@ -3759,150 +4145,127 @@ _git-svn () {
       declare -a commands
 
       commands=(
-        init:'initialize an empty git repository with additional svn data'
-        fetch:'fetch revisions from the SVN remote'
+        blame:'show what revision and author last modified each line of a file'
+        branch:'create a branch in the SVN repository'
         clone:'same as init, followed by fetch'
-        rebase:'fetch revs from SVN parent of HEAD and rebase current work on it'
+        commit-diff:'commit diff of two tree-ishs'
+        create-ignore:'recursively finds the svn:ignore property and creates .gitignore files'
         dcommit:'commit diffs from given head onto SVN repository'
-        branch:'create a branch in the SVN repository'
-        tag:'create a tag in the SVN repository'
-        log:'output SVN log-messages'
-        blame:'show what revision and author last modified each line of a file'
+        fetch:'fetch revisions from the SVN remote'
         find-rev:'output git commit corresponding to the given SVN revision'\''s hash'
-        set-tree:'commit given commit or tree to SVN repository'
-        create-ignore:'recursively finds the svn:ignore property and creates .gitignore files'
-        show-ignore:'output corresponding toplevel .gitignore file of svn:ignore'
-        mkdirs:'recreate empty directories that Git cannot track'
-        commit-diff:'commit diff of two tree-ishs'
+        gc:'compress git-svn-related information'
         info:'show information about a file or directory'
-        proplist:'list the SVN properties stored for a file or directory'
+        init:'initialize an empty git repository with additional svn data'
+        log:'output SVN log-messages'
+        migrate:'migrate configuration/metadata/layout from previous versions of git-svn'
+        mkdirs:'recreate empty directories that Git cannot track'
         propget:'get a given SVN property for a file'
+        proplist:'list the SVN properties stored for a file or directory'
+        propset:'set the value of a property on a file or directory - will be set on commit'
+        rebase:'fetch revs from SVN parent of HEAD and rebase current work on it'
+        reset:'undo effect of fetch back to specific revision'
+        set-tree:'commit given commit or tree to SVN repository'
         show-externals:'show the subversion externals'
-        gc:'compress git-svn-related information'
-        reset:'undo effect of fetch back to specific revision')
+        show-ignore:'output svn:ignore in format of a toplevel .gitignore file'
+        tag:'create a tag in the SVN repository'
+      )
 
       _describe -t commands command commands && ret=0
       ;;
     (option-or-argument)
       curcontext=${curcontext%:*}-$line[1]:
-
-      declare -a remote_opts fc_opts init_opts cmt_opts opts
-
-      # TODO: --no-auth-cache is undocumented.
-      # TODO: --config-dir is undocumented.
-      remote_opts=(
-          '--username=[username to use for SVN transport]: :_users'
-          '--ignore-paths[regular expression of paths to not check out]:pattern'
-          '--no-auth-cache[undocumented]'
-          '--config-dir=[undocumented]:configuration directory:_directories')
-
-      # TODO: --repack-flags can be improved by actually completing the legal
-      # flags to git-repack.
-      # TODO: --noMetadata is undocumented.
-      # TODO: --useSvmProps is undocumented.
-      # TODO: --useSvnsyncProps is undocumented.
-      # TODO: --log-window-size is undocumented.
-      # TODO: --no-checkout is undocumented.
-      fc_opts=(
-        '--localtime[store Git commit times in local timezone]'
-        '--use-log-author[use author from the first From: or Signed-Off-By: line, when fetching into git]'
-        '--add-author-from[when committing to svn, append a From: line based on the git commit'\''s author string]'
-        '(                --no-follow-parent)--follow-parent[follow parent commit]'
-        '(--follow-parent                   )--no-follow-parent[do not follow parent commit]'
-        '(-A --authors-file)'{-A,--authors-file}'[specify author-conversion file]:author-conversion file:_files'
-        '--authors-prog=[program used to generate authors]: :_cmdstring'
-        '(-q --quiet)'{-q,--quiet}'[make git-svn less verbose]'
-        '--repack=[repack files (for given number of revisions)]:: :__git_guard_number "revision limit"'
-        '(--repack-flags --repack-args --repack-opts)'{--repack-flags=,--repack-args=,--repack-opts=}'[flags to pass to git-repack]:git-repack flags'
-        '--noMetadata[undocumented]'
-        '--useSvmProps[undocumented]'
-        '--useSvnsyncProps[undocumented]'
-        '--log-window-size=[undocumented]'
-        '--no-checkout[undocumented]'
-        $remote_opts)
-
-      init_opts=(
-          '(-T --trunk)'{-T-,--trunk=}'[set trunk sub-directory]:trunk sub-directory:->subdirectory'
-          '(-t --tags)*'{-t-,--tags=}'[add tags sub-directory]:tags sub-directory:->subdirectory'
-          '(-b --branches)*'{-b-,--branches=}'[add branches sub-directory]:branches sub-directory:->subdirectory'
-          '(-s --stdlayout)'{-s,--stdlayout}'[shorthand for setting trunk, tags, branches as relative paths, the SVN default]'
-          '--no-metadata[set svn-remote.*.noMetadata]'
-          '--use-svm-props[set svn-remote.*.useSvmProps]'
-          '--use-svnsync-props[set svn-remote.*.useSvnsyncProps]'
-          '--rewrite-root=[set svn-remote.*.rewriteRoot]:new root:_urls'
-          '--rewrite-uuid=[set svn-remote.*.rewriteUUID]:uuid'
-          '--prefix=[prefix to use for names of remotes]:path prefix:_directories -r ""'
-          '(               --no-minimize-url)--minimize-url[minimize URLs]'
-          '(--minimize-url                  )--no-minimize-url[do not minimize URLs]'
-          '--shared=[share repository amongst several users]:: :__git_repository_permissions'
-          '--template=[directory to use as a template for the object database]: :_directories'
-          $remote_opts)
-
-      # TODO: -C and --copy-similarity are undocumented.
-      cmt_opts=(
-        '--rmdir[remove empty directories from SVN tree after commit]'
-        '(-e --edit)'{-e,--edit}'[edit commit message before committing]'
-        '-l-[limit number of rename/copy targets to run]: :__git_guard_number'
-        '--find-copies-harder[try harder to find copies]'
-        '(-C --copy-similarity)'{-C-,--copy-similarity=}'[undocumented]: :_guard "[[\:digit:\]]#" number')
-
-      if [[ $line[1] == (fetch|clone) ]]; then
-        arguments+=(
-          '(-r --revision)'{-r,--revision}'[only fetch given revision or revision range]: :__git_svn_revisions'
-          ':: :__git_svn-remotes')
-      fi
-
-      if [[ $line[1] == (fetch|rebase|dcommit) ]]; then
-        # TODO: --fetch-all and --all are undocumented.
-        opts+=(
-          '(--fetch-all --all)'{--fetch-all,--all}'[undocumented]')
-      fi
-
-      if [[ $line[1] == (rebase|dcommit) ]]; then
-        opts+=(
-          '(-m --merge)'{-m,--merge}'[use merging strategies, if necessary]'
-          '*'{-s,--strategy=-}'[use given merge strategy]:merge strategy:__git_merge_strategies')
-      fi
-
-      if [[ $line[1] == (rebase|dcommit|branch) ]]; then
-        opts+=(
-          '(-n --dry-run)'{-n,--dry-run}'[only display what would be done]')
-      fi
-
-      if [[ $line[1] == (rebase|dcommit|log) ]]; then
-        opts+=(
-          '(-v --verbose)'{-v,--verbose}'[display extra information]')
-      fi
+      declare -a opts
 
       case $line[1] in
-        (init)
-          opts+=(
-            $init_opts)
-          ;;
-        (fetch)
-          opts+=(
-            '--parent[fetch only from SVN parent of current HEAD]'
-            $fc_opts)
-          ;;
-        (clone)
-          opts+=(
-            $init_opts
-            $fc_opts
-            ':url:_urls'
-            '::directory:_directories')
-          ;;
-        (rebase)
-          opts+=(
-            '--local[do not fetch remotely, rebase against the last fetched commit from SVN]'
-            $fc_opts)
-          ;;
-        (dcommit)
-          arguments+=(
-            '--no-rebase[do not rebase or reset after committing]'
-            '--commit-url[commit to a different SVN url]:SVN URL:_url'
-            $fc_opts
-            $cmt_opts)
-          ;;
+        (clone|dcommit|fetch|init|migrate|rebase|set-tree)
+	  # TODO: --ignore-refs is undocumented.
+	  # TODO: --no-auth-cache is undocumented.
+	  # TODO: --config-dir is undocumented.
+	  opts+=(
+	    '--config-dir=:configuration directory:_directories'
+	    '--ignore-paths[regular expression of paths to not check out]:perl regex'
+	    '--include-paths[regular expression of paths to check out]:perl regex'
+	    '--ignore-refs:ref'
+	    '--no-auth-cache'
+	    '--username=[username to use for SVN transport]: :_users'
+	  )
+	;|
+        (clone|dcommit|fetch|log|rebase|set-tree)
+	  opts+=(
+	    '(-A --authors-file)'{-A,--authors-file}'[specify author-conversion file]:author-conversion file:_files'
+	  )
+	;|
+        (clone|dcommit|fetch|rebase|set-tree)
+	  # TODO: --repack-flags can be improved by actually completing the legal
+	  # flags to git-repack.
+	  # TODO: --no-checkout is undocumented.
+	  opts+=(
+	    "--add-author-from[when committing to svn, append a From: line based on the git commit's author string]"
+	    '--authors-prog=[specify program used to generate authors]: :_cmdstring'
+	    '(--no-follow-parent)--follow-parent[follow parent commit]'
+	    "(--follow-parent)--no-follow-parent[don't follow parent commit]"
+	    '--localtime[store Git commit times in local timezone]'
+	    '--log-window-size=[fetch specified number of log entries per-request]:entries [100]'
+	    '--no-checkout'
+	    '(-q --quiet)'{-q,--quiet}'[make git-svn less verbose]'
+	    '(--repack-flags --repack-args --repack-opts)'{--repack-flags=,--repack-args=,--repack-opts=}'[flags to pass to git-repack]:git-repack flags'
+	    '--repack=[repack files (for given number of revisions)]:: :__git_guard_number "revision limit"'
+	    '--use-log-author[use author from the first From: or Signed-Off-By: line, when fetching into git]'
+	  )
+	;|
+	(clone|init)
+	  opts+=(
+	    '(-T --trunk)'{-T-,--trunk=}'[set trunk sub-directory]:trunk sub-directory:->subdirectory'
+	    '(-t --tags)*'{-t-,--tags=}'[add tags sub-directory]:tags sub-directory:->subdirectory'
+	    '(-b --branches)*'{-b-,--branches=}'[add branches sub-directory]:branches sub-directory:->subdirectory'
+	    '(-s --stdlayout)'{-s,--stdlayout}'[shorthand for setting trunk, tags, branches as relative paths, the SVN default]'
+	    '--no-metadata[get rid of git-svn-id: lines at the end of every commit]'
+	    '--rewrite-root=[set svn-remote.*.rewriteRoot]:new root:_urls'
+	    '--rewrite-uuid=[set svn-remote.*.rewriteUUID]:uuid'
+	    '--prefix=[prefix to use for names of remotes]:path prefix:_directories -r ""'
+	    '(               --no-minimize-url)--minimize-url[minimize URLs]'
+	    "(--minimize-url                  )--no-minimize-url[don't minimize URLs]"
+	    '--shared=[share repository amongst several users]:: :__git_repository_permissions'
+	    '--template=[directory to use as a template for the object database]: :_directories'
+	    '--use-svm-props[re-map repository URLs and UUIDs from mirrors created with SVN::Mirror]'
+	    '--use-svnsync-props[re-map repository URLs and UUIDs from mirrors created with svnsync]'
+	  )
+	;|
+	(commitdiff|dcommit|set-tree)
+	  # TODO: -C and --copy-similarity are undocumented.
+	  opts+=(
+	    '(-C --copy-similarity)'{-C-,--copy-similarity=}': :_guard "[[\:digit:\]]#" number'
+	    '(-e --edit)'{-e,--edit}'[edit commit message before committing]'
+	    '-l-[limit number of rename/copy targets to run]: :__git_guard_number'
+	    '--find-copies-harder[try harder to find copies]'
+	    '--rmdir[remove empty directories from SVN tree after commit]'
+	    ':: :__git_svn-remotes'
+	  )
+	;|
+	(fetch|clone)
+	  opts+=(
+	    '(-r --revision)'{-r,--revision}'[only fetch given revision or revision range]: :__git_svn_revisions'
+	    ':: :__git_svn-remotes'
+	  )
+        ;|
+        (fetch|rebase|dcommit)
+	  # TODO: --fetch-all and --all are undocumented.
+	  opts+=( '(--fetch-all --all)'{--fetch-all,--all} )
+        ;|
+        (rebase|dcommit)
+	  opts+=(
+	    '(-M -m --merge)'{-M,-m,--merge}'[use merging strategies, if necessary]'
+	    '*'{-s,--strategy=-}'[use given merge strategy]:merge strategy:__git_merge_strategies'
+	  )
+        ;|
+        (rebase|dcommit|branch|tag)
+	  opts+=(
+	    '(-n --dry-run)'{-n,--dry-run}'[only display what would be done]'
+	  )
+        ;|
+        (rebase|dcommit|log)
+	  opts+=( '(-v --verbose)'{-v,--verbose}'[display extra information]' )
+        ;|
         (branch|tag)
           # TODO: -d/--destination should complete output of
           # git config --get-all svn-remote.*.branches
@@ -3912,15 +4275,82 @@ _git-svn () {
           # git config --get-all svn-remote.*.commiturl
           opts+=(
             '(-m --message)'{-m,--message}'[specify the commit message]:message'
-            '(-d --destination)'{-d,--destination}'[location of branch or tag to create in SVN repository]: :_directories'
+            '(-d --destination)'{-d,--destination}"[location of $line[1] to create in SVN repository]: :_directories"
             '--username[specify SVN username to perform commit as]: :_users'
-            '--commit-url[specify URL to connect to destination SVN repository]: :_urls')
-
-          if [[ $line[1] != tag ]]; then
-            opts+=(
-              '(-t --tag)'{-t,--tag}'[create a tag]')
-          fi
-          ;;
+            '--commit-url[specify URL to connect to destination SVN repository]: :_urls'
+	    '--parents[create parent folders]'
+	  )
+	;|
+        (commit-diff|create-ignore|dcommit|show-ignore|mkdirs|proplist|propget|show-externals)
+          # TODO: -r and --revision is undocumented for dcommit, show-ignore and mkdirs.
+          opts+=(
+            '(-r --revision)'{-r,--revision}'[specify SVN revision]: :__git_svn_revisions'
+	  )
+	;|
+	(propset|propget)
+	  opts+=( '1:property:(svn:ignore svn:keywords svn:executable svn:eol-style svn:mime-type svn:externals svn:needs-lock)' )
+        ;|
+
+	# ;| style fall-throughs end; here on each command covered once
+        (blame)
+          opts+=(
+            '--git-format[produce output in git-blame format, with SVN revision numbers instead of git commit hashes]'
+	    '*:file:__git_cached_files'
+	  )
+	;;
+        (branch)
+	  opts+=( '(-t --tag)'{-t,--tag}'[create a tag]' )
+	;;
+        (clone)
+          opts+=(
+	    '--preserve-empty-dirs[create a placeholder file for each empty directory]'
+	    '--placeholder-filename=[specify name of placeholder files created by --preserve-empty-dirs]:filename [.gitignore]:_files'
+            ':url:_urls'
+            '::directory:_directories'
+	  )
+	;;
+        (commit-diff)
+          # TODO: -m and --message is undocumented.
+          # TODO: -F and --file is undocumented.
+          opts+=(
+            '(-m --message)'{-m-,--message=}':message'
+            '(-F --file)'{-F-,--file=}':file:_files'
+	    ':original tree:__git_tree_ishs'
+	    ':new tree result:__git_tree_ishs'
+	    ':target:_urls'
+	  )
+	;;
+        (dcommit)
+	  # TODO: --set-svn-props is undocumented
+          opts+=(
+            '--commit-url[commit to a different SVN url]:SVN URL:_url'
+	    '(-i --interactive)'{-i,--interactive}'[ask for confirmation that a patch should be sent to SVN]'
+	    '--mergeinfo[add specified merge information during the dcommit]:mergeinfo' \
+            "--no-rebase[don't rebase or reset after committing]"
+	    '--set-svn-props:arg'
+	  )
+	;;
+        (fetch)
+          opts+=(
+	    '(-p --parent)'{-p,--parent}'[fetch only from SVN parent of current HEAD]'
+	  )
+	;;
+        (info)
+          opts+=(
+	    '--url[output only value of URL field]'
+	    ':file:__git_cached_files'
+	  )
+	;;
+        (init)
+	  opts+=( ':SVN URL:_urls' ':target directory:_directories' )
+        ;;
+	(find-rev)
+	  opts+=(
+	    '(-A --after -B --before)'{-B,--before}'[with no exact match, find last commit for current branch]'
+	    '(-A --after -B --before)'{-A,--after}'[with no exact match, find closest match searching forwards]'
+	    ':revision: _alternative "svn-revisions\:svn revision number\:__git_svn_revision_numbers -p r" "git-revisions\:git revision\:__git_revisions"'
+	  )
+	;;
         (log)
           declare -a revision_options
           __git_setup_revision_options
@@ -3934,47 +4364,46 @@ _git-svn () {
             '--limit=[like --max-count, but not counting merged/excluded commits]: :__git_guard_number limit'
             '--incremental[give output suitable for concatenation]'
             '--show-commit[output git commit SHA-1, as well]'
-            '--color[undocumented]'
-            '--pager[undocumented]:pager:_cmdstring'
-            '--non-recursive[undocumented]')
-          ;;
-        (blame)
-          opts+=(
-            '--git-format[produce output in git-blame format, with SVN revision numbers instead of git commit hashes]')
-          ;;
-        (set-tree)
-          opts+=(
-            '--stdin[read list of commits to commit from stdin]')
-          ;;
-        (create-ignore|show-ignore|mkdirs|proplist|propget|show-externals)
-          # TODO: -r and --revision is undocumented for show-ignore and mkdirs.
-          opts+=(
-            '(-r --revision)'{-r,--revision}'[specify SVN revision]: :__git_svn_revisions')
-          ;;
-        (commit-diff)
-          # TODO: -m and --message is undocumented.
-          # TODO: -F and --file is undocumented.
-          # TODO: -r and --revision is undocumented.
-          opts+=(
-            '(-m --message)'{-m-,--message=}'[undocumented]:message'
-            '(-F --file)'{-F-,--file=}'[undocumented]: :_files'
-            '(-r --revision)'{-r-,--revision=}'[undocumented]: :__git_svn_revisions')
-          ;;
-        (info)
+            '--color'
+            '--pager:pager:_cmdstring'
+            '--non-recursive'
+	    ':file:__git_cached_files'
+	  )
+	;;
+        (migrate)
+          opts+=( '--minimize' )
+        ;;
+	(propset)
+	  opts+=( ':value' )
+	;&
+	(proplist|propget)
+          opts+=( '*:file:__git_cached_files' )
+	;;
+        (rebase)
           opts+=(
-            '--url[output only value of URL field]')
-          ;;
+	  '(-l --local)'{-l,--local}"[don't fetch remotely, rebase against the last fetched commit from SVN]"
+	    '(--preserve-merges -p)'{--preserve-merges,-p}'[try to recreate merges instead of ignoring them]'
+	  )
+	;;
         (reset)
           opts+=(
             '(-r --revision)'{-r,--revision}'[specify most recent SVN revision to keep]: :__git_svn_revisions'
-            '(-p --parent)'{-p,--parent}'[discard specified revision as well, keeping nearest parent instead]')
-          ;;
+            '(-p --parent)'{-p,--parent}'[discard specified revision as well, keeping nearest parent instead]'
+	  )
+	;;
+        (set-tree)
+          opts+=( '--stdin[read list of commits to commit from stdin]' )
+	;;
+	(create-ignore|gc|mkdirs|show-externals|show-ignore|tag) ;;
+        (*) # fallback to files on any new/unrecognised commands
+          opts+=( '*:file:_files' )
+        ;;
       esac
 
-      _arguments -w -C -S -s \
-        '(-h -H --help)'{-h,-H,--help}'[display usage information]' \
-        '(-V --version)'{-V,--version}'[display version information]' \
-        '--minimize-connections[undocumented]' \
+      _arguments -C -S -s \
+        '(-)'{-h,-H}'[display usage information]' \
+        '(-)'{-V,--version}'[display version information]' \
+        '--minimize-connections' \
         '(-R --svn-remote --remote)'{-R,--svn-remote,--remote}'[svn remote to use]:svn remote:__git_svn-remotes' \
         '(-i --id)'{-i,--id}'[set GIT_SVN_ID]:GIT_SVN_ID' \
         $opts && ret=0
@@ -4001,7 +4430,7 @@ _git-apply () {
   local -a apply_options
   __git_setup_apply_options
 
-  _arguments -w -S -s \
+  _arguments -S -s \
     $apply_options \
     '(--index --cached --reject)'{-3,--3way}'[fall back on 3-way merge if patch fails]' \
     '--stat[output diffstat for input (turns off "apply")]' \
@@ -4016,6 +4445,7 @@ _git-apply () {
     '--unidiff-zero[disable unified-diff-context check]' \
     '--apply[apply patches that would otherwise not be applied]' \
     '--no-add[ignore additions made by the patch]' \
+    '--allow-overlap[allow overlapping hunks]' \
     '--inaccurate-eof[work around missing-new-line-at-EOF bugs]' \
     '(-v --verbose)'{-v,--verbose}'[display progress on stderr]' \
     '--recount[do not trust line counts in hunk headers]' \
@@ -4030,33 +4460,30 @@ _git-checkout-index () {
     z_opt='-z[paths are separated with NUL character when reading from standard input]'
   fi
 
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-u --index)'{-u,--index}'[update stat information in index]' \
-    '(-q --quiet)'{-q,--quiet}'[do not complain about existing files or missing files]' \
+    '(-q --quiet)'{-q,--quiet}'[no warning for existing files and files not in index]' \
     '(-f --force)'{-f,--force}'[force overwrite of existing files]' \
     '(-a --all --stdin *)'{-a,--all}'[check out all files in index]' \
     '(-n --no-create)'{-n,--no-create}'[do not checkout new files]' \
-    '--prefix=-[prefix to use when creating files]:directory:_directories' \
-    '--stage=-[check out files from named stage]:stage:(1 2 3 all)' \
     '--temp[write content to temporary files]' \
     '(-a --all *)--stdin[read list of paths from the standard input]' \
+    '--prefix=[prefix to use when creating files]:directory:_directories' \
+    '--stage=[check out files from named stage]:stage:(1 2 3 all)' \
     $z_opt \
     '*: :__git_cached_files'
 }
 
 (( $+functions[_git-commit-tree] )) ||
 _git-commit-tree () {
-  if (( CURRENT == 2 )); then
-    _arguments \
-      '-h[display usage]' \
-      ': :__git_trees'
-  elif [[ $words[CURRENT-1] == -p ]]; then
-    local expl
-    _description commits expl 'parent commit'
-    __git_objects $expl
-  else
-    compadd - '-p'
-  fi
+  _arguments \
+    '-h[display usage]' \
+    '*-p+[specify parent commit]:parent commit:__git_objects' \
+    '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=-}'[GPG-sign the commit]::key id' \
+    "(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[don't GPG-sign the commit]" \
+    '-F+[read commit log from specified file]:file:_files' \
+    '*-m+[specify paragraph of commit log message]:message' \
+    ': :__git_trees'
 }
 
 (( $+functions[_git-hash-object] )) ||
@@ -4069,6 +4496,7 @@ _git-hash-object () {
     '-w[write object to object database]' \
     '(: --stdin-paths)--stdin[read object from standard input]' \
     '(: --stdin --path)--stdin-paths[read file names from standard input instead of from command line]' \
+    '--literally[just hash any random garbage to create corrupt objects for debugging Git]' \
     '(       --no-filters)--path=[hash object as if it were located at given path]: :_files' \
     '(--path             )--no-filters[hash contents as is, ignoring any input filters]' \
     '(--stdin --stdin-paths):file:_files'
@@ -4092,6 +4520,7 @@ _git-index-pack () {
     '--stdin[read pack from stdin and instead write to specified file]' \
     $stdin_opts \
     '--strict[die if the pack contains broken objects or links]' \
+    '--threads=[specify number of threads to use]:number of threads' \
     ':pack file:_files -g "*.pack(-.)"'
 }
 
@@ -4118,7 +4547,7 @@ _git-merge-file () {
     '(--ours          --union)--theirs[resolve conflicts favoring their side of the lines]' \
     '(--ours --theirs        )--union[resolve conflicts favoring both sides of the lines]' \
     '--marker-size[specify length of conflict markers]: :__git_guard_number "marker length"' \
-    '--diff3[undocumented]' \
+    '--diff3[use a diff3 based merge]' \
     ':current file:_files' \
     ':base file:_files' \
     ':other file:_files'
@@ -4148,7 +4577,7 @@ _git-mktag () {
 
 (( $+functions[_git-mktree] )) ||
 _git-mktree () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '-z[read NUL-terminated ls-tree -z output]' \
     '--missing[allow missing objects]' \
     '--batch[allow creation of more than one tree]'
@@ -4163,42 +4592,46 @@ _git-pack-objects () {
   fi
 
   # NOTE: --index-version is only used by the Git test suite.
-  # TODO: --reflog is undocumented.
-  # TODO: --keep-unreachable is undocumented.
-  # TODO: --unpack-unreachable is undocumented.
-  _arguments -A '-*' \
-    '(: --max-pack-size)--stdout[write pack contents to standard output]' \
+  _arguments \
+    '(-q --quiet)'{-q,--quiet}"[don't report progress]" \
+    '(-q --quiet --all-progress)--progress[show progress meter]' \
+    '(-q --quiet --progress --all-progress-implied)--all-progress[show progress meter during object writing phase]' \
+    '(-q --quiet --all-progress)--all-progress-implied[like --all-progress, but only if --progress was also passed]' \
+    '(--stdout)--max-pack-size=[specify maximum size of each output pack file]: : __git_guard_bytes "maximum pack size"' \
+    '(--incremental)--local[similar to --incremental, but only ignore unpacked non-local objects]' \
+    '(--local)--incremental[ignore objects that have already been packed]' \
+    '--window=-[limit pack window by objects]: :__git_guard_number "window size"' \
+    '--window-memory=-[specify window size in memory]: : __git_guard_bytes "window size"' \
+    '--depth=-[maximum delta depth]: :__git_guard_number "maximum delta depth"' \
+    "--no-reuse-delta[don't reuse existing deltas, but compute them from scratch]" \
+    "--no-reuse-object[don't reuse existing object data]" \
+    '--delta-base-offset[use delta-base-offset packing]' \
+    '--threads=-[specify number of threads for searching for best delta matches]: :__git_guard_number "number of threads"' \
+    '--non-empty[only create a package if it contains at least one object]' \
     '--revs[read revision arguments from standard input]' \
     '(--revs)--unpacked[limit objects to pack to those not already packed]' \
     '(--revs)--all[include all refs as well as revisions already specified]' \
+    '--reflog[include objects referred by reflog entries]' \
+    '--indexed-objects[include objects referred to by the index]' \
+    '(: --max-pack-size)--stdout[output pack to stdout]' \
     '--include-tag[include unasked-for annotated tags if object they reference is included]' \
-    '--window=-[number of objects to use per delta compression]: :__git_guard_number "window size"' \
-    '--depth=-[maximum delta depth]: :__git_guard_number "maximum delta depth"' \
-    '--window-memory=-[window size in memory]:window size:__git_guard_bytes' \
-    '(--stdout)--max-pack-size=[maximum size of each output packfile]:maximum pack size:__git_guard_bytes' \
+    '(--unpack-unreachable)--keep-unreachable[keep unreachable ]' \
+    '--pack-loose-unreachable[pack loose unreachable objects]' \
+    '(--keep-unreachable)--unpack-unreachable=-[unpack unreachable objects newer than specified time]::time' \
+    '--include-tag[include tag objects that refer to objects to be packed]' \
+    $thin_opt \
+    '--shallow[create packs suitable for shallow fetches]' \
     '--honor-pack-keep[ignore objects in local pack with .keep file]' \
-    '(              --local)--incremental[ignore objects that have already been packed]' \
-    '(--incremental        )--local[similar to --incremental, but only ignore unpacked non-local objects]' \
-    '--non-empty[only create a package if it contains at least one object]' \
-    '(           --all-progress)--progress[display progress on standard error]' \
-    '(--progress                --all-progress-implied)--all-progress[display progress output on standard error, even during write-out phase]' \
-    '(--all-progress)--all-progress-implied[like --all-progress, but only if --progress was also passed]' \
-    '-q[do not report progress]' \
-    '--no-reuse-delta[do not reuse existing deltas, but compute them from scratch]' \
-    '--no-reuse-object[do not reuse existing object data]' \
     '--compression=-[specify compression level]: :__git_compression_levels' \
-    $thin_opt \
-    '--delta-base-offset[use delta-base-offset packing]' \
-    '--threads=-[specify number of threads for searching for best delta matches]: :__git_guard_number "number of threads"' \
     '--keep-true-parents[pack parents hidden by grafts]' \
-    '(                   --unpack-unreachable)--keep-unreachable[undocumented]' \
-    '(--keep-unreachable                     )--unpack-unreachable[undocumented]' \
+    '--use-bitmap-index[use a bitmap index if available to speed up counting objects]' \
+    '--write-bitmap-index[write a bitmap index together with the pack index]' \
     ':base-name:_files'
 }
 
 (( $+functions[_git-prune-packed] )) ||
 _git-prune-packed () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-n --dry-run)'{-n,--dry-run}'[only list objects that would be removed]' \
     '(-q --quiet)'{-q,--quiet}'[do not display progress on standard error]'
 }
@@ -4227,7 +4660,7 @@ _git-read-tree () {
     exclude_per_directory_opt='--exclude-per-directory=-[specify .gitignore file]:.gitignore file:_files'
   fi
 
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(   --reset --prefix)-m[perform a merge, not just a read]' \
     '(-m         --prefix)--reset[perform a merge, not just a read, ignoring unmerged entries]' \
     '(-m --reset          2 3)--prefix=-[read the contents of specified tree-ish under specified directory]:prefix:_directories -r ""' \
@@ -4247,7 +4680,7 @@ _git-read-tree () {
 
 (( $+functions[_git-symbolic-ref] )) ||
 _git-symbolic-ref () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-d --delete)'{-d,--delete}'[delete symbolic ref]' \
     '(-q --quiet)'{-q,--quiet}'[do not issue error if specified name is not a symbolic ref]' \
     '--short[shorten the ref name (eg. refs/heads/master -> master)]' \
@@ -4274,13 +4707,11 @@ _git-update-index () {
   fi
 
   _arguments -S \
-    $refreshables \
     '(-)'{-h,--help}'[display usage information]' \
+    '-q[continue refresh even when index needs update]' \
     '--add[add files not already in index]' \
-    '(         --force-remove)--remove[remove files that are in the index but are missing from the work tree]' \
-    '(--remove               )--force-remove[remove files from both work tree and index]' \
+    '(--force-remove)--remove[remove files that are in the index but are missing from the work tree]' \
     '(-q --unmerged --ignore-missing --really-refresh)--refresh[refresh index]' \
-    '-q[run quietly]' \
     '--ignore-submodules[do not try to update submodules]' \
     '--unmerged[if unmerged changes exists, ignore them instead of exiting]' \
     '--ignore-missing[ignore missing files when refreshing the index]' \
@@ -4295,10 +4726,16 @@ _git-update-index () {
     '(-)'{-g,--again}'[run git-update-index on differing index entries]' \
     '(-)--unresolve[restore "unmerged" or "needs updating" state of files]' \
     '--info-only[only insert files object-IDs into index]' \
-    '(--remove)--force-remove[remove file from index even when working directory has no such file]' \
     '--replace[replace files already in index, if necessary]' \
+    '(--remove)--force-remove[remove named paths even if present in worktree]' \
     '(: -)--stdin[read list of paths from standard input]' \
     '--verbose[report what is being added and removed from the index]' \
+    '--clear-resolve-undo[forget saved unresolved conflicts]' \
+    '--index-version=[write index in specified on-disk format version]:version:(2 3 4)' \
+    '--split-index[enable/disable split index]' \
+    '--untracked-cache[enable/disable untracked cache]' \
+    '--test-untracked-cache[test if the filesystem supports untracked cache]' \
+    '--force-untracked-cache[enable untracked cache without testing the filesystem]' \
     $z_opt \
     '*:: :_files'
 }
@@ -4311,12 +4748,13 @@ _git-update-ref () {
     z_opt='-z[values are separated with NUL character when reading from stdin]'
   fi
 
-  _arguments -w -S -s \
+  _arguments -S -s \
     '-m[update reflog for specified name with specified reason]:reason for update' \
     '(:)-d[delete given reference after verifying its value]:symbolic reference:__git_revisions:old reference:__git_revisions' \
     '(-d --no-deref)--stdin[reads instructions from standard input]' \
     $z_opt \
     '(-d -z --stdin)--no-deref[overwrite ref itself, not what it points to]' \
+    '--create-reflog[create a reflog]' \
     ':symbolic reference:__git_revisions' \
     ':new reference:__git_revisions' \
     '::old reference:__git_revisions'
@@ -4325,7 +4763,7 @@ _git-update-ref () {
 (( $+functions[_git-write-tree] )) ||
 _git-write-tree () {
   # NOTE: --ignore-cache-tree is only used for debugging.
-  _arguments -w -S -s \
+  _arguments -S -s \
     '--missing-ok[ignore objects in index that are missing in object database]' \
     '--prefix=[write tree representing given sub-directory]:sub-directory:_directories -r ""'
 }
@@ -4334,16 +4772,24 @@ _git-write-tree () {
 
 (( $+functions[_git-cat-file] )) ||
 _git-cat-file () {
-  _arguments -w -S -s \
-    '(- 1)-t[show type of given object]' \
-    '(- 1)-s[show size of given object]' \
-    '(- 1)-e[exit with zero status if object exists]' \
-    '(- 1)-p[pretty-print given object]' \
-    '(- 1)--textconv[show content as transformed by a textconv filter]' \
-    '(- :)--batch=-[print SHA1, type, size and contents (or in <format>) of objects given on stdin]:format' \
-    '(- :)--batch-check=-[print SHA1, type and size (or in <format>) of objects given on stdin]:format' \
+  _arguments -S -s \
+    '(-t -s -e -p --allow-unknown-type 1)--textconv[show content as transformed by a textconv filter]' \
+    '(-t -s -e -p --allow-unknown-type 1)--filters[show content as transformed by filters]' \
+    '(-t -s -e -p --allow-unknown-type 1)--path=[use a specific path for --textconv/--filters]:path:_directories' \
+    - query \
+    '(-s -e -p --textconv --filters 1)-t[show type of given object]' \
+    '(-t -e -p --textconv --filters 1)-s[show size of given object]' \
+    '(-e -p --textconv --filters 1)--allow-unknown-type[allow query of broken/corrupt objects of unknown type]' \
+    '(-t -s -p -textconv --filters --allow-unknown-type 1)-e[exit with zero status if object exists]' \
+    '(-t -s -e -textconv --filters --allow-unknown-type 1)-p[pretty-print given object]' \
     '(-):object type:(blob commit tag tree)' \
-    ': :__git_objects'
+    ': :__git_objects' \
+    - batch \
+    '(--batch-check)--batch=-[print SHA1, type, size and contents (or in specified format)]::format' \
+    '(--batch)--batch-check=-[print SHA1, type and size (or in specified format)]::format' \
+    '--follow-symlinks[follow in-tree symlinks (used with --batch or --batch-check)]' \
+    '--batch-all-objects[show all objects with --batch or --batch-check]' \
+    '--buffer[disable flushing of output after each object]'
 }
 
 (( $+functions[_git-diff-files] )) ||
@@ -4352,7 +4798,7 @@ _git-diff-files () {
   __git_setup_revision_options
   __git_setup_diff_stage_options
 
-  _arguments -w -S -s \
+  _arguments -S -s \
     $revision_options \
     $diff_stage_options \
     ': :__git_changed-in-working-tree_files' \
@@ -4371,7 +4817,7 @@ _git-diff-index () {
   # to given tree-ish?  This should be done for git-diff as well, in that case.
   _arguments -S \
     $revision_options \
-    '--cached[do not consider the work tree at all]' \
+    "--cached[don't consider the work tree at all]" \
     '-m[flag non-checked-out files as up-to-date]' \
     ': :__git_tree_ishs' \
     '*: :__git_cached_files'
@@ -4388,7 +4834,7 @@ _git-diff-tree () {
   # NOTE: -r, -t, --root are actually parsed for all
   # __git_setup_revision_options, but only used by this command, so only have
   # them here.
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     $revision_options \
     '-r[recurse into subdirectories]' \
     '(-r   )-t[disply tree objects in diff output]' \
@@ -4433,10 +4879,15 @@ _git-for-each-ref () {
   # TODO: Better completion for --format: should complete %(field) stuff, that
   # is, %(refname), %(objecttype), %(objectsize), %(objectname) with optional '*'
   # in front.
-  _arguments -w -S -s \
+  _arguments -S -s \
     '--count=[maximum number of refs to iterate over]: :__git_guard_number "maximum number of refs"' \
-    '--sort=[key to sort refs by]: :__git_ref_sort_keys' \
+    '*--sort=[key to sort refs by]: :__git_ref_sort_keys' \
     '--format=-[output format of ref information]:format' \
+    '*--points-at=[print only refs which point at the given object]:object:__git_commits' \
+    '*--merged=[print only refs that are merged]:object:__git_commits' \
+    '*--no-merged=[print only refs that are not merged]:object:__git_commits' \
+    '*--contains=[print only refs which contain the commit]:object:__git_commits' \
+    '--ignore-case[sorting and filtering are case-insensitive]' \
     '(-s --shell -p --perl --python --tcl)'{-s,--shell}'[use string literals suitable for sh]' \
     '(-s --shell -p --perl --python --tcl)'{-p,--perl}'[use string literals suitable for Perl]' \
     '(-s --shell -p --perl          --tcl)'--python'[use string literals suitable for Python]' \
@@ -4449,13 +4900,13 @@ _git-ls-files () {
   local no_empty_directory_opt=
 
   if (( words[(I)--directory] )); then
-    no_empty_directory_opt='--no-empty-directory[do not list empty directories]'
+    no_empty_directory_opt="--no-empty-directory[don't list empty directories]"
   fi
 
   # TODO: --resolve-undo is undocumented.
   # TODO: Replace _files with something more intelligent based on seen options.
   # TODO: Apply excludes like we do for git-clean.
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-c --cached)'{-c,--cached}'[show cached files in output]' \
     '(-d --deleted)'{-d,--deleted}'[show deleted files in output]' \
     '(-m --modified)'{-m,--modified}'[show modified files in output]' \
@@ -4463,6 +4914,7 @@ _git-ls-files () {
     '(-i --ignored)'{-i,--ignored}'[show ignored files in output]' \
     '(-s --stage --with-tree)'{-s,--stage}'[show stage files in output]' \
     '--directory[if a whole directory is classified as "other", show just its name]' \
+    '--eol[show line endings of files]' \
     $no_empty_directory_opt \
     '(-s --stage -u --unmerged --with-tree)'{-u,--unmerged}'[show unmerged files in output]' \
     '(-k --killed)'{-k,--killed}'[show killed files in output]' \
@@ -4475,19 +4927,24 @@ _git-ls-files () {
     '(-s --stage -u --unmerged)--with-tree=[treat paths removed since given tree-ish as still present]: :__git_tree_ishs' \
     '-v[identify each files status (hmrck?)]' \
     '--full-name[force paths to be output relative to the project top directory]' \
+    '--recurse-submodules[recurse through submodules]' \
     '--abbrev=[set minimum SHA1 display-length]: :__git_guard_number length' \
+    '--debug[show debugging data]' \
     '*:: :_files'
 }
 
 (( $+functions[_git-ls-remote] )) ||
 _git-ls-remote () {
   # TODO: repository needs fixing
-  _arguments -A '-*' \
+  _arguments \
+    '(-q --quiet)'{-q,--quiet}"[don't print remote URL]" \
+    '--upload-pack=[specify path to git-upload-pack on remote side]:remote path' \
     '(-h --heads)'{-h,--heads}'[show only refs under refs/heads]' \
     '(-t --tags)'{-t,--tags}'[show only refs under refs/tags]' \
-    '(-u --upload-pack)'{-u,--upload-pack=-}'[specify path to git-upload-pack on remote side]:remote path' \
+    "--refs[don't show peeled tags]" \
     '--exit-code[exit with status 2 when no matching refs are found in the remote repository]' \
     '--get-url[expand the URL of the given repository taking into account any "url.<base>.insteadOf" config setting]' \
+    '--symref[show underlying ref in addition to the object pointed by it]' \
     ': :__git_any_repositories' \
     '*: :__git_references'
 }
@@ -4497,7 +4954,7 @@ _git-ls-tree () {
   local curcontext=$curcontext state line ret=1
   declare -A opt_args
 
-  _arguments -w -C -S -s \
+  _arguments -C -S -s \
     '(-t)-d[do not show children of given tree (implies -t)]' \
     '-r[recurse into subdirectories]' \
     '-t[show tree entries even when going to recurse them]' \
@@ -4521,7 +4978,7 @@ _git-ls-tree () {
 
 (( $+functions[_git-merge-base] )) ||
 _git-merge-base () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-a --all)'{-a,--all}'[display all common ancestors]' \
     '--octopus[compute best common ancestors of all supplied commits]' \
     '--is-ancestor[tell if A is ancestor of B (by exit status)]' \
@@ -4595,7 +5052,7 @@ _git-show-index () {
 _git-show-ref () {
   _arguments -S \
     - list \
-      '(-h --head)'{-h,--head}'[show the HEAD reference, even if it would normally be filtered out]' \
+      '--head[show the HEAD reference, even if it would normally be filtered out]' \
       '--tags[show only refs/tags]' \
       '--heads[show only refs/heads]' \
       '(-d --dereference)'{-d,--dereference}'[dereference tags into object IDs as well]' \
@@ -4610,7 +5067,7 @@ _git-show-ref () {
 
 (( $+functions[_git-unpack-file] )) ||
 _git-unpack-file () {
-  _arguments -A '-*' \
+  _arguments \
     '(:)-h[display usage information]' \
     '(-): :__git_blobs'
 }
@@ -4627,7 +5084,7 @@ _git-var () {
 
 (( $+functions[_git-verify-pack] )) ||
 _git-verify-pack () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-v --verbose)'{-v,--verbose}'[show objects contained in pack]' \
     '(-s --stat-only)'{-s,--stat-only}'[do not verify pack contents; only display histogram of delta chain length]' \
     '*:index file:_files -g "*.idx"'
@@ -4675,6 +5132,7 @@ _git-fetch-pack () {
   # TODO: Limit * to __git_head_references?
   _arguments -A '-*' \
     '--all[fetch all remote refs]' \
+    '--stdin[take the list of refs from stdin]' \
     '(-q --quiet)'{-q,--quiet}'[make output less verbose]' \
     '(-k --keep)'{-k,--keep}'[do not invoke git-unpack-objects on received data]' \
     '--thin[fetch a thin pack]' \
@@ -4682,6 +5140,7 @@ _git-fetch-pack () {
     '(--upload-pack --exec)'{--upload-pack=-,--exec=-}'[specify path to git-upload-pack on remote side]:remote path' \
     '--depth=-[limit fetching to ancestor-chains not longer than given number]: :__git_guard_number "maximum ancestor-chain length"' \
     '--no-progress[do not display progress]' \
+    '--diag-url' \
     '-v[produce verbose output]' \
     ': :__git_any_repositories' \
     '*: :__git_references'
@@ -4694,26 +5153,38 @@ _git-http-backend () {
 
 (( $+functions[_git-send-pack] )) ||
 _git-send-pack () {
-  # TODO: --mirror is undocumented.
-  # TODO: --stateless-rpc is undocumented.
-  # TODO: --helper-status is undocumented.
+  local -a sign
+  sign=(
+    {yes,true}'\:always,\ and\ fail\ if\ unsupported\ by\ server'
+    {no,false}'\:never'
+    if-asked'\:iff\ supported\ by\ server'
+  )
   _arguments -A '-*' \
+    '(-v --verbose)'{-v,--verbose}'[produce verbose output]' \
+    '(-q --quiet)'{-q,--quiet}'[be more quiet]' \
     '(--receive-pack --exec)'{--receive-pack=-,--exec=-}'[specify path to git-receive-pack on remote side]:remote path' \
+    '--remote[specify remote name]:remote' \
     '--all[update all refs that exist locally]' \
-    '--dry-run[do everything except actually sending the updates]' \
-    '--force[update remote orphaned refs]' \
-    '-v[produce verbose output]' \
+    '(-n --dry-run)'{-n,--dry-run}'[do everything except actually sending the updates]' \
+    '--mirror[mirror all refs]' \
+    '(-f --force)'{-f,--force}'[update remote orphaned refs]' \
+    "(--no-signed --signed)--sign=-[GPG sign the push]::signing enabled:(($^^sign))" \
+    '(--no-signed --sign)--signed[GPG sign the push]' \
+    "(--sign --signed)--no-signed[don't GPG sign the push]" \
+    '--progress[force progress reporting]' \
     '--thin[send a thin pack]' \
-    '--mirror[undocumented]' \
-    '--stateless-rpc[undocumented]' \
-    '--helper-status[undocumented]' \
+    '--atomic[request atomic transaction on remote side]' \
+    '--stateless-rpc[use stateless RPC protocol]' \
+    '--stdin[read refs from stdin]' \
+    '--helper-status[print status from remote helper]' \
+    '--force-with-lease=[require old value of ref to be at specified value]:refname\:expect' \
     ': :__git_any_repositories' \
     '*: :__git_remote_references'
 }
 
 (( $+functions[_git-update-server-info] )) ||
 _git-update-server-info () {
-  _arguments -w -S -s \
+  _arguments -S -s \
     '(-f --force)'{-f,--force}'[update the info files from scratch]'
 }
 
@@ -4751,6 +5222,7 @@ _git-receive-pack () {
   # TODO: --advertise-refs is undocumented.
   # TODO: --stateless-rpc is undocumented.
   _arguments -A '-*' \
+    '(-q --quiet)'{-q,--quiet}'[be quiet]' \
     '--advertise-refs[undocumented]' \
     '--stateless-rpc[undocumented]' \
     ':directory to sync into:_directories'
@@ -4809,13 +5281,11 @@ _git-upload-archive () {
 
 (( $+functions[_git-upload-pack] )) ||
 _git-upload-pack () {
-  # TODO: --advertise-refs is undocumented.
-  # TODO: --stateless-rpc is undocumented.
   _arguments -S -A '-*' \
-    '--strict[do not try <directory>/.git/ if <directory> is not a git directory' \
-    '--timeout=-[interrupt transfer after given number of seconds of inactivity]: :__git_guard_number "inactivity timeout"' \
-    '--advertise-refs[undocumented]' \
-    '--stateless-rpc[undocumented]' \
+    '--stateless-rpc[quit after a single request/response exchange]' \
+    '--advertise-refs[exit immediately after initial ref advertisement]' \
+    "--strict[don't try <directory>/.git/ if <directory> is not a git directory]" \
+    '--timeout=-[interrupt transfer after period of inactivity]: :__git_guard_number "inactivity timeout (seconds)"' \
     ': :_directories'
 }
 
@@ -4875,15 +5345,15 @@ _git-check-ref-format () {
     '(--no-allow-onelevel)--allow-onelevel[accept one-level refnames]' \
     '(--allow-onelevel)--no-allow-onelevel[do not accept one-level refnames]' \
     '--refspec-pattern[interpret <refname> as a reference name pattern for a refspec]' \
-    '--normalize[Normalize refname by removing leading slashes]' \
+    '--normalize[normalize refname by removing leading slashes]' \
     '--branch[expand previous branch syntax]' \
     ': :__git_references'
 }
 
 (( $+functions[_git-fmt-merge-msg] )) ||
 _git-fmt-merge-msg () {
-  _arguments -w -S -s \
-    '(      --no-log)--log[display one-line descriptions from actual commits being merged]' \
+  _arguments -S -s \
+    '(      --no-log)--log=-[display one-line descriptions from actual commits being merged]::number of commits [20]' \
     '(--log         )--no-log[do not display one-line descriptions from actual commits being merged]' \
     '(-m --message)'{-m+,--message=}'[use given message instead of branch names for first line in log message]:message' \
     '(-F --file)'{-F,--file}'[specify list of merged objects from file]: :_files'
@@ -4893,10 +5363,12 @@ _git-fmt-merge-msg () {
 _git-mailinfo () {
   # TODO: --no-inbody-headers is undocumented.
   _arguments -A '-*' \
-    '-k[do not strip/add \[PATCH\] from first line of commit message]' \
+    '(-b)-k[prevent removal of cruft from Subject: header]' \
+    '(-k)-b[limit stripping of bracketed strings to the word PATCH]' \
     '(-u --encoding)-u[encode commit information in UTF-8]' \
     '(-u --encoding)--encoding=-[encode commit information in given encoding]: :__git_encodings' \
     '-n[disable all charset re-coding of metadata]' \
+    '(-m --message-id)'{-m,--message-id}'[copy the Message-ID header at the end of the commit message]' \
     '(           --no-scissors)--scissors[remove everything in body before a scissors line]' \
     '(--scissors              )--no-scissors[do not remove everything in body before a scissors line]' \
     '--no-inbody-headers[undocumented]' \
@@ -4922,7 +5394,9 @@ _git-merge-one-file () {
 
 (( $+functions[_git-patch-id] )) ||
 _git-patch-id () {
-  _message 'no arguments allowed; accepts patch on standard input'
+   _arguments \
+     '--stable[use a sum of hashes unaffected by diff ordering]' \
+     '--unstable[use patch-id compatible with git 1.9 and older]'
 }
 
 # NOTE: git-sh-setup isn't a user command.
@@ -5116,8 +5590,10 @@ _git_commands () {
     stash:'stash away changes to dirty working directory'
     status:'show working-tree status'
     submodule:'initialize, update, or inspect submodules'
-    tag:'create, list, delete or verify tag object signed with GPG')
-
+    subtree:'split repository into subtrees and merge them'
+    tag:'create, list, delete or verify tag object signed with GPG'
+    worktree:'manage multiple working dirs attached to the same repository'
+  )
   ancillary_manipulator_commands=(
     config:'get and set repository or global options'
     fast-export:'data exporter'
@@ -5640,6 +6116,64 @@ __git_commit_objects_prefer_recent () {
   __git_recent_commits $argument_array_names || __git_commit_objects
 }
 
+# This function returns in $reply recently-checked-out refs' names, in order
+# from most to least recent.
+(( $+functions[__git_recent_branches__names] )) ||
+__git_recent_branches__names()
+{
+  # This parameter expansion does the following:
+  # 1. Obtains the last 1000 'checkout' operations from the reflog
+  # 2. Extracts the move-source from each
+  # 3. Eliminates duplicates
+  # 4. Eliminates commit hashes (leaving only ref names)
+  #    [This step is done again by the caller.]
+  #
+  # See workers/38592 for an equivalent long-hand implementation, and the rest
+  # of that thread for why this implementation was chosen instead.
+  #
+  # Note: since we obtain the "from" part of the reflog, we only obtain heads, not tags.
+  reply=(${${(u)${${(M)${(0)"$(_call_program reflog git reflog -1000 -z --pretty='%gs')"}:#(#s)checkout: moving from *}#checkout: moving from }%% *}:#[0-9a-f](#c40)})
+}
+
+(( $+functions[__git_recent_branches] )) ||
+__git_recent_branches() {
+  local -a branches
+  local -A descriptions
+  local -a reply
+  local -aU valid_ref_names_munged=( ${"${(f)"$(_call_program valid-ref-names 'git for-each-ref --format="%(refname)" refs/heads/')"}"#refs/heads/} )
+
+  # 1. Obtain names of recently-checked-out branches from the reflog.
+  # 2. Remove ref names that no longer exist from the list.
+  #    (We must do this because #3 would otherwise croak on them.)
+  __git_recent_branches__names; branches=( ${(@)reply:*valid_ref_names_munged} )
+
+  # 3. Early out if no matches.
+  if ! (( $+branches[1] )); then
+    # This can happen in a fresh repository (immediately after 'clone' or 'init') before
+    # any 'checkout' commands were run in it.
+    return 1
+  fi
+
+  # 4. Obtain log messages for all of them in one shot.
+  # TODO: we'd really like --sort=none here...  but git doesn't support such a thing.
+  # The \n removal is because for-each-ref prints a \n after each entry.
+  descriptions=( ${(0)"$(_call_program all-descriptions "git --no-pager for-each-ref --format='%(refname)%00%(subject)%00'" refs/heads/${(q)^branches} "--")"//$'\n'} )
+
+  # 5. Synthesize the data structure _describe wants.
+  local -a branches_colon_descriptions
+  local branch
+  for branch in ${branches} ; do
+    branches_colon_descriptions+="${branch//:/\:}:${descriptions[refs/heads/${(b)branch}]}"
+  done
+
+  _describe -V -t recent-branches "recent branches" branches_colon_descriptions
+}
+
+(( $+functions[__git_commits_prefer_recent] )) ||
+__git_commits_prefer_recent () {
+  _alternative 'recent-branches::__git_recent_branches' 'commits::__git_commits'
+}
+
 (( $+functions[__git_commits] )) ||
 __git_commits () {
   local -a argument_array_names
@@ -5732,7 +6266,7 @@ __git_recent_commits () {
 
   # Careful: most %d will expand to the empty string.  Quote properly!
   # NOTE: we could use %D directly, but it's not available in git 1.9.1 at least.
-  commits=("${(f)"$(_call_program commits git --no-pager log $commit_opts -20 --format='%h%n%d%n%s\ \(%cr\)%n%p')"}")
+  commits=("${(f)"$(_call_program commits git --no-pager log ${(q)commit_opts} -20 --format='%h%n%d%n%s\ \(%cr\)%n%p')"}")
   __git_command_successful $pipestatus || return 1
 
   for i j k parents in "$commits[@]" ; do
@@ -5792,11 +6326,11 @@ __git_recent_commits () {
   ret=1
   # Resetting expl to avoid it 'leaking' from one line to the next.
   expl=()
+  _describe -V -t commits 'recent commit object name' descr && ret=0
+  expl=()
   _wanted commit-tags expl 'commit tag' compadd "$@" -a - tags && ret=0
   expl=()
   _wanted heads expl 'head' compadd "$@" -a - heads && ret=0
-  expl=()
-  _describe -V -t commits 'recent commit object name' descr && ret=0
   return $ret
 }
 
@@ -5906,8 +6440,7 @@ __git_submodules () {
   local expl
   declare -a submodules
 
-  submodules=(${${${(f)"$(_call_program submodules git submodule 2>/dev/null)"}#?* }%% *})
-  __git_command_successful $pipestatus || return 1
+  submodules=( ${${${(f)"$(_call_program submodules git submodule)"}#?* }%% *} )
 
   _wanted submodules expl submodule compadd "$@" -a - submodules
 }
@@ -5942,7 +6475,7 @@ __git_tags_of_type () {
 
   type=$1; shift
 
-  tags=(${${(M)${(f)"$(_call_program $type-tag-refs "git for-each-ref --format='%(*objecttype)%(objecttype) %(refname)' refs/tags 2>/dev/null")"}:#$type(tag|) *}#$type(tag|) refs/tags/})
+  tags=(${${(M)${(f)"$(_call_program ${(q)type}-tag-refs "git for-each-ref --format='%(*objecttype)%(objecttype) %(refname)' refs/tags 2>/dev/null")"}:#$type(tag|) *}#$type(tag|) refs/tags/})
   __git_command_successful $pipestatus || return 1
 
   _wanted $type-tags expl "$type tag" compadd -M 'r:|/=**' "$@" -a - tags
@@ -5968,9 +6501,10 @@ __git_references () {
     _git_refs_cache_pwd=$PWD
   fi
 
-  _wanted references expl 'reference' compadd -a - _git_refs_cache
+  _wanted references expl 'reference' compadd -M 'r:|/=**' -a - _git_refs_cache
 }
 
+# ### currently unused; are some callers of __git_references supposed to call this function?
 (( $+functions[__git_local_references] )) ||
 __git_local_references () {
   local expl
@@ -5981,7 +6515,7 @@ __git_local_references () {
     _git_local_refs_cache_pwd=$PWD
   fi
 
-  _wanted references expl 'reference' compadd -a - _git_local_refs_cache
+  _wanted references expl 'reference' compadd -M 'r:|/=**' -a - _git_local_refs_cache
 }
 
 (( $+functions[__git_remote_references] )) ||
@@ -6054,12 +6588,12 @@ __git_files () {
   local pref=$gitcdup$gitprefix$PREFIX
 
   # First allow ls-files to pattern-match in case of remote repository
-  files=(${(0)"$(_call_program files git ls-files -z --exclude-standard $opts -- ${pref:+$pref\\\*} 2>/dev/null)"})
+  files=(${(0)"$(_call_program files git ls-files -z --exclude-standard ${(q)opts} -- ${(q)${pref:+$pref\\\*}} 2>/dev/null)"})
   __git_command_successful $pipestatus || return
 
   # If ls-files succeeded but returned nothing, try again with no pattern
   if [[ -z "$files" && -n "$pref" ]]; then
-    files=(${(0)"$(_call_program files git ls-files -z --exclude-standard $opts -- 2>/dev/null)"})
+    files=(${(0)"$(_call_program files git ls-files -z --exclude-standard ${(q)opts} -- 2>/dev/null)"})
     __git_command_successful $pipestatus || return
   fi
 
@@ -6176,7 +6710,7 @@ __git_tree_files () {
   shift
   (( at_least_one_tree_added = 0 ))
   for tree in $*; do
-    tree_files+=(${(ps:\0:)"$(_call_program tree-files git ls-tree -r $extra_args --name-only -z $tree 2>/dev/null)"})
+    tree_files+=(${(ps:\0:)"$(_call_program tree-files git ls-tree -r ${(q)extra_args} --name-only -z ${(q)tree} 2>/dev/null)"})
     __git_command_successful $pipestatus && (( at_least_one_tree_added = 1 ))
   done
 
@@ -6226,6 +6760,13 @@ __git_any_repositories () {
     'remote-repositories::__git_remote_repositories'
 }
 
+(( $+functions[__git_any_repositories_or_references] )) ||
+__git_any_repositories_or_references () {
+  _alternative \
+    'repositories::__git_any_repositories' \
+    'references::__git_references'
+}
+
 # Common Guards
 
 (( $+functions[__git_guard] )) ||
@@ -6247,7 +6788,7 @@ __git_guard () {
 
 __git_guard_branch-name () {
   if [[ -n $PREFIX$SUFFIX ]]; then
-    _call_program check-ref-format git check-ref-format "refs/heads/$PREFIX$SUFFIX" &>/dev/null
+    _call_program check-ref-format git check-ref-format "refs/heads/"${(q)PREFIX}${(q)SUFFIX} &>/dev/null
     (( ${#pipestatus:#0} > 0 )) && return 1
   fi
 
@@ -6277,7 +6818,7 @@ __git_guard_number () {
 
 (( $+functions[__git_guard_bytes] )) ||
 __git_guard_bytes () {
-  _guard '[[:digit:]]#([kKmMgG]|)' $*
+  _guard '[[:digit:]]#([kKmMgG]|)' ${*:-size}
 }
 
 (( $+functions[__git_datetimes] )) ||
@@ -6307,7 +6848,9 @@ __git_setup_log_options () {
     '(--decorate              )--no-decorate[do not print out ref names of any commits that are shown]'
     '(          --no-follow)--follow[follow renames]'
     '(--follow             )--no-follow[do not follow renames]'
-    '--source[show which ref each commit is reached from]')
+    '--source[show which ref each commit is reached from]'
+    '-L+[trace the evolution of a line range or regex within a file]:range'
+  )
 }
 
 (( $+functions[__git_setup_diff_options] )) ||
@@ -6339,7 +6882,8 @@ __git_setup_diff_options () {
     $diff_types'--name-only[show only names of changed files]'
     $diff_types'--name-status[show only names and status of changed files]'
     '--submodule=-[select output format for submodule differences]::format:((short\:"show pairs of commit names"
-                                                                            log\:"list commits like git submodule does"))'
+									     log\:"list commits like git submodule does"
+									     diff\:"show differences"))'
     '(        --no-color --color-words)--color=-[show colored diff]:: :__git_color_whens'
     '(--color            --color-words)--no-color[turn off colored diff]'
     '--word-diff=-[show word diff]::mode:((color\:"highlight changed words using color"
@@ -6354,7 +6898,7 @@ __git_setup_diff_options () {
     '(--full-index)--binary[in addition to --full-index, output binary diffs for git-apply]'
     '--abbrev=[set minimum SHA1 display-length]: :__git_guard_number length'
     '(-B --break-rewrites)'{-B-,--break-rewrites=-}'[break complete rewrite changes into pairs of given size]:: :__git_guard_number size'
-    '(-M --find-renames)'{-M-,--find-renames=-}'[Detect renames with given scope]:: :__git_guard_number size'
+    '(-M --find-renames)'{-M-,--find-renames=-}'[detect renames with given scope]:: :__git_guard_number size'
     '(-C --find-copies)'{-C-,--find-copies=-}'[detect copies as well as renames with given scope]:: :__git_guard_number size'
     '--find-copies-harder[try harder to find copies]'
     '(-D --irreversible-delete)'{-D,--irreversible-delete}'[omit the preimage for deletes]'
@@ -6374,7 +6918,6 @@ __git_setup_diff_options () {
     '--ignore-blank-lines[do not show hunks that add or remove blank lines]'
     '--inter-hunk-context=[combine hunks closer than n lines]:n'
     '--exit-code[report exit code 1 if differences, 0 otherwise]'
-    '(--exit-code)--quiet[disable all output]'
     '(           --no-ext-diff)--ext-diff[allow external diff helper to be executed]'
     '(--ext-diff              )--no-ext-diff[disallow external diff helper to be executed]'
     '(--textconv --no-textconv)--textconv[allow external text conversion filters to be run when comparing binary files]'
@@ -6384,7 +6927,7 @@ __git_setup_diff_options () {
     '(--no-prefix)--dst-prefix=[use given prefix for destination]:prefix'
     '(--src-prefix --dst-prefix)--no-prefix[do not show any source or destination prefix]'
 
-    '(-c,--cc)'{-c,--cc}'[combined diff format for merge commits]'
+    '(-c --cc)'{-c,--cc}'[combined diff format for merge commits]'
 
     # TODO: --output is undocumented.
     '--output[undocumented]:undocumented')
@@ -6499,7 +7042,6 @@ __git_setup_revision_options () {
     '(-v --header)'{--pretty=-,--format=-}'[pretty print commit messages]::format:__git_format_placeholders'
     '(--abbrev-commit --no-abbrev-commit)--abbrev-commit[show only partial prefixes of commit object names]'
     '(--abbrev-commit --no-abbrev-commit)--no-abbrev-commit[show the full 40-byte hexadecimal commit object name]'
-    '(--abbrev --no-abbrev)--abbrev=[set minimum SHA1 display-length (for use with --abbrev-commit)]: :__git_guard_number length'
     '(--abbrev --no-abbrev)--no-abbrev[show the full 40-byte hexadecimal commit object name]'
     '--oneline[shorthand for --pretty=oneline --abbrev-commit]'
     '--encoding=-[output log messages in given encoding]:: :__git_encodings'
@@ -6588,39 +7130,45 @@ __git_setup_merge_options () {
   merge_options=(
     '(         --no-commit)--commit[perform the merge and commit the result]'
     '(--commit            )--no-commit[perform the merge but do not commit the result]'
-    '(         --no-edit)--edit[open an editor to change the commit message]'
-    '(--edit            )--no-edit[do not open an editor to change the commit message]'
+    '(         --no-edit -e)--edit[open an editor to change the commit message]'
+    "(--edit             -e)--no-edit[don't open an editor to change the commit message]"
     '(     --no-ff)--ff[do not generate a merge commit if the merge resolved as a fast-forward]'
     '(--ff        )--no-ff[generate a merge commit even if the merge resolved as a fast-forward]'
-    '(      --no-log)--log[fill in one-line descriptions of the commits being merged in the log message]'
+    '(      --no-log)--log=-[add entries from shortlog to merge commit message]::entries to add'
     '(--log         )--no-log[do not list one-line descriptions of the commits being merged in the log message]'
     '(-n --no-stat)--stat[show a diffstat at the end of the merge]'
     '(--stat -n --no-stat)'{-n,--no-stat}'[do not show diffstat at the end of the merge]'
     '(         --no-squash)--squash[merge, but do not commit]'
     '(--squash            )--no-squash[merge and commit]'
     '--ff-only[refuse to merge unless HEAD is up to date or merge can be resolved as a fast-forward]'
-    '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=}'[GPG-sign the commit]::key id' \
-    '(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[do not GPG-sign the commit]' \
+    '(-S --gpg-sign --no-gpg-sign)'{-S-,--gpg-sign=-}'[GPG-sign the commit]::key id'
+    "(-S --gpg-sign --no-gpg-sign)--no-gpg-sign[don't GPG-sign the commit]"
     '*'{-s,--strategy=}'[use given merge strategy]:merge strategy:__git_merge_strategies'
-    '*'{-X,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]'
+    '*'{-X,--strategy-option=}'[pass merge-strategy-specific option to merge strategy]:option'
     '(--verify-signatures)--verify-signatures[verify the commits being merged or abort]'
     '(--no-verify-signatures)--no-verify-signatures[do not verify the commits being merged]'
     '(-q --quiet -v --verbose)'{-q,--quiet}'[suppress all output]'
-    '(-q --quiet -v --verbose)'{-v,--verbose}'[output additional information]')
+    '(-q --quiet -v --verbose)'{-v,--verbose}'[output additional information]'
+    '--allow-unrelated-histories[allow merging unrelated histories]'
+  )
 }
 
 (( $+functions[__git_setup_fetch_options] )) ||
 __git_setup_fetch_options () {
   fetch_options=(
-    '(: *)--all[fetch all remotes]'
+    '(: * -m --multiple)--all[fetch all remotes]'
     '(-a --append)'{-a,--append}'[append ref names and object names of fetched refs to "$GIT_DIR/FETCH_HEAD"]'
+    '(-j --jobs)'{-j+,--jobs=}'[specify number of submodules fetched in parallel]:jobs'
     '--depth=[deepen the history of a shallow repository by the given number of commits]: :__git_guard_number depth'
     '--unshallow[convert a shallow clone to a complete one]'
+    '--update-shallow[accept refs that update .git/shallow]'
+    '--refmap=[specify refspec to map refs to remote tracking branches]:refspec'
+    '(-4 --ipv4 -6 --ipv6)'{-4,--ipv4}'[use IPv4 addresses only]'
+    '(-4 --ipv4 -6 --ipv6)'{-6,--ipv6}'[use IPv6 addresses only]'
     '--dry-run[show what would be done, without making any changes]'
     '(-f --force)'{-f,--force}'[allow refs that are not ancestors to be updated]'
     '(-k --keep)'{-k,--keep}'[keep downloaded pack]'
     '(-p --prune)'{-p,--prune}'[remove any remote tracking branches that no longer exist remotely]'
-    '(-n --no-tags -t --tags)'{-n,--no-tags}'[disable automatic tag following]'
     '(--no-tags -t --tags)'{-t,--tags}'[fetch remote tags]'
     '(-u --update-head-ok)'{-u,--update-head-ok}'[allow updates of current branch head]'
     '--upload-pack=[specify path to git-upload-pack on remote side]:remote path'
@@ -6633,7 +7181,7 @@ __git_setup_fetch_options () {
     '--submodule-prefix=-[prepend <path> to paths printed in informative messages]:submodule prefix path:_files -/'
     '(-q --quiet -v --verbose --progress)'{-q,--quiet}'[suppress all output]'
     '(-q --quiet -v --verbose)'{-v,--verbose}'[output additional information]'
-    '(-q --quiet)--progress[output progress information]')
+    '(-q --quiet)--progress[force progress reporting]')
 }
 
 (( $+functions[__git_setup_apply_options] )) ||
@@ -6661,7 +7209,7 @@ __git_config_get_regexp () {
   [[ -n $opts[-a] ]] || opts[-a]='.[^.]##'
   [[ $1 == -- ]] && shift
 
-  set -A $2 ${${${(0)"$(_call_program ${3:-$2} "git config -z --get-regexp -- '$1'")"}#${~opts[-b]}}%%${~opts[-a]}$'\n'*}
+  set -A $2 ${${${(0)"$(_call_program ${3:-$2} "git config -z --get-regexp -- ${(q)1}")"}#${~opts[-b]}}%%${~opts[-a]}$'\n'*}
 }
 
 (( $+functions[__git_config_sections] )) ||
@@ -6918,7 +7466,7 @@ __git_sendemail_suppresscc_values () {
 
 (( $+functions[__git_sendmail_smtpserver_values] )) ||
 __git_sendmail_smtpserver_values() {
-  _alternative "smtp hosts:host:_hosts" "sendmail command: :_absolute_command_paths"
+  _alternative "hosts:smtp host:_hosts" "commands: :_absolute_command_paths"
 }
 
 (( $+functions[__git_colors] )) ||
@@ -6942,7 +7490,7 @@ _git() {
   if (( CURRENT > 2 )); then
     local -a aliases
     local -A git_aliases
-    local k v
+    local a k v
     aliases=(${(0)"$(_call_program aliases git config -z --get-regexp '\^alias\.')"})
     for a in ${aliases}; do
         k="${${a/$'\n'*}/alias.}"
@@ -6978,7 +7526,7 @@ _git() {
       '(- :)--version[display version information]' \
       '(- :)--help[display help message]' \
       '-C[run as if git was started in given path]: :_directories' \
-      '-c[pass configuration parameter to command]:parameter' \
+      '*-c[pass configuration parameter to command]: :->configuration' \
       '--exec-path=-[path containing core git-programs]:: :_directories' \
       '(: -)--man-path[print the manpath for the man pages for this version of Git and exit]' \
       '(: -)--info-path[print the path where the info files are installed and exit]' \
@@ -7000,7 +7548,7 @@ _git() {
         ;;
       (option-or-argument)
         curcontext=${curcontext%:*:*}:git-$words[1]:
-
+	(( $+opt_args[--git-dir] )) && local -x GIT_DIR=$opt_args[--git-dir]
 	if ! _call_function ret _git-$words[1]; then
 	  if zstyle -T :completion:$curcontext: use-fallback; then
 	    _default && ret=0
@@ -7009,6 +7557,18 @@ _git() {
 	  fi
         fi
         ;;
+      (configuration)
+        if compset -P 1 '*='; then
+          __git_config_value && ret=0
+        else
+          if compset -S '=*'; then
+            __git_config_option && ret=0 # don't move cursor if we completed just the "foo." in "foo.bar.baz=value"
+            compstate[to_end]=''
+          else
+            __git_config_option -S '=' && ret=0
+          fi
+        fi
+        ;;
     esac
   else
     _call_function ret _$service
@@ -7022,7 +7582,7 @@ declare -gUa _git_third_party_commands
 _git_third_party_commands=()
 
 local file
-for file in ${^fpath}/_git-*~(*~|*.zwc)(.N); do
+for file in ${^fpath}/_git-*~(*~|*.zwc)(-.N); do
   local name=${${file:t}#_git-}
   if (( $+_git_third_party_commands[$name] )); then
     continue
diff --git a/Completion/Unix/Command/_global b/Completion/Unix/Command/_global
index c4714cb05..ffd8c0dce 100644
--- a/Completion/Unix/Command/_global
+++ b/Completion/Unix/Command/_global
@@ -14,7 +14,7 @@ _arguments \
   '(--color)--color=-[color matches]::color:(always auto never)' \
   '(-d --definition)'{-d,--definition}'[print locations of definitions]' \
   '(-e --regexp :)'{-e,--regexp}'[specify pattern]:pattern:_global_tags' \
-  '(--encode-path)--encode-path=-[encode path charcters in hexadecimal representation]:format' \
+  '(--encode-path)--encode-path=-[encode path characters in hexadecimal representation]:format' \
   '(-F --first-match)'{-f,--first-match}'[stop searching if tag is found in current tag file]' \
   '(--from-here)--from-here=-[decide tag type by context]:line_path:' \
   '(-G --basic-regexp :)'{-G,--basic-regexp}'[specify basic regexp to use]:word:_global_tags' \
@@ -23,9 +23,9 @@ _arguments \
   '(-i --ignore-case)'{-i,--ignore-case}'[ignore case in patterns]' \
   '(-L --file-list)'{-L,--file-list}'[obtain files from file in addition to the arguments]:file:_files' \
   '(-l --local)'{-l,--local}'[print just objects which exist under the current directory]' \
-  '(--literal)--literal[use leteral search instead of regexp search]' \
+  '(--literal)--literal[use literal search instead of regexp search]' \
   '(-M --match-case)'{-m,--match-case}'[enable case sensitive search]' \
-  '(--match-part)--match-part=-[speficy how path name completion should match]::part:(first last all)' \
+  '(--match-part)--match-part=-[specify how path name completion should match]::part:(first last all)' \
   '(-n --nofilter)'{-n,--nofilter}'[suppress sort filter and path conversion filter]' \
   '(-O --only-other)'{-O,--only-other}'[search only text files]' \
   '(-o --other)'{-o,--other}'[search in other files, not just source files (with -g)]' \
diff --git a/Completion/Unix/Command/_gpg b/Completion/Unix/Command/_gpg
index fe236d5bf..fe6084f20 100644
--- a/Completion/Unix/Command/_gpg
+++ b/Completion/Unix/Command/_gpg
@@ -62,7 +62,7 @@ fi
   '--desig-revoke[generate a designated revocation certificate]'
   '--export[export all key from all keyrings]'
   '--send-keys[send keys to a keyserver]:key attachment:->public-keyids'
-  '--export-secret-keys:key attahment:->secret-keys'
+  '--export-secret-keys:key attachment:->secret-keys'
   '--export-secret-subkeys:key attachment:->secret-keys'
   '--import[import a gpg key from a file]:_files attachment:_files'
   '--fast-import[import a file without build trustdb]:_files attachment:_files'
diff --git a/Completion/Unix/Command/_gphoto2 b/Completion/Unix/Command/_gphoto2
index 314d83e3a..788c9702f 100644
--- a/Completion/Unix/Command/_gphoto2
+++ b/Completion/Unix/Command/_gphoto2
@@ -1,47 +1,96 @@
 #compdef gphoto2
 
-_arguments -s \
+local curcontext="$curcontext" ret=1
+local -a state line values expl
+typeset -A opt_args
+
+_arguments -s -C \
+  '(-)'{-\?,--help}'[display help information]' \
+  '(-)'{-h,--usage}'[display a short usage message]' \
   '--debug[turn on debugging]' \
+  '--debug-loglevel=[set debug level]:debug level:(error debug data all)' \
+  '--debug-logfile=[name of file to write debug info to]:file:_files' \
   '(-q --quiet)'{-q,--quiet}'[quiet output]' \
-  '(-v --version)'{-v,--version}'[display version and exit]' \
-  '(-h --help)'{-h,--help}'[display a short usage message]' \
-  '--list-cameras[list supported camera models]' \
-  '--list-ports[list supported port devices]' \
+  '--hook-script=[hook script to call after downloads, captures, etc.]:file:_files' \
   '--stdout[send file to stdout]' \
   '--stdout-size[print filesize before data]' \
   '--auto-detect[list auto-detected cameras]' \
-  '--port[specify port device]:port' \
-  '--speed[specify serial transfer speed]:speed' \
-  '--camera[specify camera model]:camera model' \
-  '--filename[specify pattern to save file as]:pattern' \
-  '--usbid[override USB IDs (expert only)]:usbid' \
+  '--show-exif=[show EXIF information of JPEG images]:range' \
+  '--show-info=[show image information, like width, height, and capture time]:range' \
+  '--summary[summary of camera status]' \
+  '--manual[camera driver manual]' \
+  '--about[show information about the camera driver]' \
+  '--storage-info[show storage information]' \
+  '--shell[start the gphoto2 shell]' \
+  '(-)'{-v,--version}'[display version and exit]' \
+  '--list-cameras[list supported camera models]' \
+  '--list-ports[list supported port devices]' \
   '(-a --abilities)'{-a,--abilities}'[display camera abilities]' \
-  '(-f --folder)'{-f,--folder}'[specify camera folder]:folder' \
-  '(-R --recurse --no-recurse)'{-R,--recurse}'[recursion (default for download)]' \
-  '(-R --recurse)--no-recurse[no recursion (default for deletion)]' \
+  '--port=[specify port device]:port:->ports' \
+  '--speed=[specify serial transfer speed]:speed' \
+  '--camera=[specify camera model]:camera model:->models' \
+  '--usbid=[override USB IDs (expert only)]:usbid' \
+  '--list-config[list configuration tree]' \
+  '--list-all-config[dump full configuration tree]' \
+  '--get-config=[get configuration value]:string' \
+  '--set-config=[set configuration value or index in choices]:string' \
+  '--set-config-index=[set configuration value index in choices]:string' \
+  '--set-config-value=[set configuration value]:string' \
+  '--config[start curses configuration menu]' \
+  '--reset[reset device port]' \
+  '--keep[keep images on camera after capturing]' \
+  '--keep-raw[keep the RAW images on the camera with --capture-image-and-download]' \
+  '--no-keep[remove images from camera after capturing]' \
+  '--wait-event=-[wait for event from camera]::count' \
+  '--wait-event-and-download=-[wait for event from camera and download new images]::count' \
+  '--capture-preview[capture a quick preview]' \
+  '--show-preview[capture a quick preview and display using ASCII art]' \
+  '(-B --bulb)'{-B,--bulb=}'[set bulb exposure time]:exposure time (seconds)' \
+  '(-F --frames)'{-F,--frames=}'[set number of frames to capture]:frames [unlimited]' \
+  '(-I --interval)'{-I,--interval=}'[set capture interval in seconds]:interval (seconds)' \
+  '--reset-interval[reset capture interval on signal]' \
+  '--capture-image[capture an image]' \
+  '--trigger-capture[trigger capture of an image]' \
+  '--capture-image-and-download[capture an image and download it]' \
+  '--capture-movie=-[capture a movie]:count or seconds' \
+  '--capture-sound[capture an audio clip]' \
+  '--capture-tethered=-[wait for shutter release on the camera and download]::count' \
   '(-l --list-folders)'{-l,--list-folders}'[list folders in folder]' \
   '(-L --list-files)'{-L,--list-files}'[list files in folder]' \
-  '(-m --mkdir)'{-m,--mkdir}'[create a directory]:directory' \
-  '(-r --rmdir)'{-r,--rmdir}'[remove a directory]:directory' \
-  '(-n --num-files)'{-n,--num-files}'[sisplay number of files]' \
-  '(-p --get-file)'{-p,--get-file}'[get files given in range]:range' \
+  '(-m --mkdir)'{-m,--mkdir=}'[create a directory]:directory' \
+  '(-r --rmdir)'{-r,--rmdir=}'[remove a directory]:directory' \
+  '(-n --num-files)'{-n,--num-files}'[display number of files]' \
+  '(-p --get-file)'{-p,--get-file=}'[get files given in range]:range' \
   '(-P --get-all-files)'{-P,--get-all-files}'[get all files from folder]' \
-  '(-t --get-thumbnail)'{-t,--get-thumbnail}'[get thumbnails given in range]:range' \
+  '(-t --get-thumbnail)'{-t,--get-thumbnail=}'[get thumbnails given in range]:range' \
   '(-T --get-all-thumbnails)'{-T,--get-all-thumbnails}'[get all thumbnails from folder]' \
-  '(-r --get-raw-data)'{-r,--get-raw-data}'[get raw data given in range]:range' \
+  '--get-metadata=[get metadata given in range]:range' \
+  '--get-all-metadata[get all metadata from folder]' \
+  '--upload-metadata=[upload metadata for file]:string' \
+  '--get-raw-data=[get raw data given in range]:range' \
   '--get-all-raw-data[get all raw data from folder]' \
-  '--get-audio-data[get audio data given in range]:range' \
+  '--get-audio-data=[get audio data given in range]:range' \
   '--get-all-audio-data[get all audio data from folder]' \
-  '--delete-file[delete files given in range]:range' \
-  '--delete-all-files[delete all files in folder]' \
-  '(-u --upload-file)'{-u,--upload-file}'[upload a file to camera]:file:_files' \
-  '--capture-preview[capture a quick preview]' \
-  '--capture-image[capture an image]' \
-  '--capture-movie[capture a movie]' \
-  '--capture-sound[capture an audio clip]' \
-  '--show-info[show info about given range]:range' \
-  '--summary[summary of camera status]' \
-  '--manual[camera driver manual]' \
-  '--about[show information about the camera driver]' \
-  '--shell[start the gphoto2 shell]'
+  '(-d --delete-file)'{-d,--delete-file=}'[delete files in given range]:range' \
+  '(-D --delete-all-files)'{-D,--delete-all-files}'[delete all files in folder]' \
+  '(-u --upload-file)'{-u,--upload-file=}'[upload a file to camera]:file:_files' \
+  '--filename=[specify pattern to save file as]:pattern:_date_formats' \
+  '(-f --folder)'{-f,--folder=}'[specify camera folder]:folder [/]' \
+  '(-R --recurse --no-recurse)'{-R,--recurse}'[recursion (default for download)]' \
+  '(-R --recurse)--no-recurse[no recursion (default for deletion)]' \
+  '--new[process new files only]' \
+  '--force-overwrite[overwrite files without asking]' \
+  '--skip-existing[skip files that already exist on local filesystem]' && ret=0
+
+case $state in
+  models)
+    _wanted models expl 'camera model' compadd \
+        ${${${(f)"$(_call_program models $words[1] --list-cameras)"}[3,-1]#*\"}%%\"*} && ret=0
+  ;;
+  ports)
+    values=( ${${${(f)"$(gphoto2 --list-ports)"}[4,-1]/:/\\:}/ ##/:} )
+    _describe -t ports 'port' values
+  ;;
+esac
 
+return ret
diff --git a/Completion/Unix/Command/_graphicsmagick b/Completion/Unix/Command/_graphicsmagick
index 9306acd9c..cc541d891 100644
--- a/Completion/Unix/Command/_graphicsmagick
+++ b/Completion/Unix/Command/_graphicsmagick
@@ -3,7 +3,7 @@
 local state line expl formats curcontext="$curcontext"
 typeset -A opt_args
 
-formats=jpg:jpeg:jp2:j2k:jpc:jpx:jpf:tiff:miff:ras:bmp:cgm:dcx:ps:eps:fig:fits:fpx:gif:mpeg:pbm:pgm:ppm:pcd:pcl:pdf:pcx:png:rad:rgb:rgba:rle:sgi:html:shtml:tga:ttf:uil:xcf:xwd:xbm:xpm:yuv
+formats=jpg:jpeg:jp2:j2k:jpc:jpx:jpf:tif:tiff:miff:ras:bmp:cgm:dcx:ps:eps:fig:fits:fpx:gif:mpeg:pbm:pgm:ppm:pcd:pcl:pdf:pcx:png:rad:rgb:rgba:rle:sgi:html:shtml:tga:ttf:uil:xcf:xwd:xbm:xpm:yuv
 
 if (( $# )); then
   _files "$@" -g "*.(#i)(${~formats//:/|})(-.)"
@@ -360,7 +360,7 @@ case "$words[2]" in
       '*:picture file:_imagemagick' && return
 
     if [[ "$state" = profile ]]; then
-      if compset -P '*:'; then
+      if compset -P 1 '*:'; then
 	_files
       else
 	_wanted prefixes expl 'profile type' compadd icc: iptc:
diff --git a/Completion/Unix/Command/_grep b/Completion/Unix/Command/_grep
index d987c2b1e..5f45ce9a8 100644
--- a/Completion/Unix/Command/_grep
+++ b/Completion/Unix/Command/_grep
@@ -1,7 +1,6 @@
-#compdef grep egrep fgrep bsdgrep zgrep, zegrep, zfgrep -value-,GREP_OPTIONS,-default-
-# Ulrik Haugen 2001
+#compdef grep egrep fgrep bsdgrep zgrep zegrep zfgrep ggrep gegrep gfgrep gzgrep gzegrep gzfgrep -value-,GREP_OPTIONS,-default-
 
-local arguments matchers command
+local arguments matchers command variant
 
 if [[ $service = *GREP_OPT* ]]; then
   compset -q
@@ -9,28 +8,29 @@ if [[ $service = *GREP_OPT* ]]; then
   (( CURRENT++ ))
   command=grep
 else
-  arguments=(
-    '(-e --regexp -f --file)1: :_guard "^--*" pattern'
-    '*:files:_files'
-  )
+  arguments=( '(-e --regexp -f --file)1: :_guard "^-*" pattern' )
+  if [[ $service = z* ]]; then
+    arguments+=( '*:files:_files -g "*.gz(-.)"' )
+  else
+    arguments+=( '*:files:_files' )
+  fi
   command="$words[1]"
 fi
 
-if [[ $service != [ef]grep ]]; then
+if [[ $service != (|g)(|z)[ef]grep ]]; then
   matchers='(--extended-regexp --fixed-strings --basic-regexp --perl-regexp -E -F -G -P)'
   arguments+=(
     $matchers{--extended-regexp,-E}'[use extended regular expression]'
     $matchers{--fixed-strings,-F}'[use literal strings]'
     $matchers{--basic-regexp,-G}'[use basic regular expression]'
-    $matchers{--perl-regexp,-P}'[use perl regular expression]'
   )
 fi
 
-arguments=( $arguments[@]
+arguments+=(
   '(--after-context -A)'{--after-context=,-A+}'[specify lines of trailing context]:lines'
   '(--text -a --binary-files -I)'{--text,-a}'[process binary file as if it were text]'
   '(--before-context -B)'{--before-context=,-B+}'[specify lines of leading context]:lines'
-  '(--context,-C)'{--context=,-C-}'[specify lines of context]:lines'
+  '(--context -C)'{--context=,-C-}'[specify lines of context]:lines'
   '(--color --colour)--'{color,colour}'=-[distinguish matching string]::when:(always never auto)'
   '(--byte-offset -b -c)'{--byte-offset,-b}'[print the byte offset with output lines]'
   '(--text -a -I)--binary-files=[specify type to assume for binary files]:file type:(binary without-match text)'
@@ -45,30 +45,75 @@ arguments=( $arguments[@]
   '--line-buffered[flush output on every line]'
   '(--text -a --binary-files)-I[process binary files as if non-matching]'
   '(--ignore-case -i -y)'{--ignore-case,-i,-y}'[case-insensitive]'
-  '(--files-without-match -L --file-with-matches -l --no-filename -h)'{--files-without-match,-L}"[output non-matching files' names only]"
-  '(--files-with-matches -l --files-without-match -L --no-filename -h)'{--files-with-matches,-l}"[output matching files' names only]"
-  '(--max-count -m)'{--max-count=,-m+}'[stop after specified no of matches]:max number of matches'
+  '(--files-without-match -L --file-with-matches -l --no-filename -h -o --only-matching)'{--files-without-match,-L}"[output non-matching files' names only]"
+  '(--files-with-matches -l --files-without-match -L --no-filename -h -o --only-matching)'{--files-with-matches,-l}"[output matching files' names only]"
+  '(--max-count -m)'{--max-count=,-m+}'[stop after specified no of matches in each file]:max number of matches'
   '(--line-number -n -c)'{--line-number,-n}'[prefix output with line numbers]'
-  '(--only-matching -o)'{--only-matching,-o}'[show only matching part of line]'
+  '(--only-matching -o --files-with-matches -l --files-without-match -L)'{--only-matching,-o}'[show only matching part of line]'
   '(--quiet --silent -q)'{--quiet,--silent,-q}'[suppress normal output]'
-  '(--recursive -r -R -d --directories)'{--recursive,-r,-R}'[recurse subdirectories]'
+  '(--recursive -r --dereference-recursive -R -d --directories)'{--recursive,-r}'[recurse subdirectories]'
   '*--include=[examine files matching specified pattern]:file pattern'
   '*--exclude=[skip files matching specified pattern]:file pattern'
-  '*--exclude-from=[skip files matching pattern in specified file]:file:_files'
   '*--exclude-dir=[skip directories matching specified pattern]:directory pattern'
   '(--no-messages -s)'{--no-messages,-s}'[suppress messages about unreadable]'
   '(--version -V)'{--version,-V}'[display version info]'
   '(--invert-match -v)'{--invert-match,-v}'[select non-matching lines]'
   '(--word-regexp -w --line-regexp -x)'{--word-regexp,-w}'[force pattern to match only whole words]'
   '(--line-regexp -x --word-regexp -w)'{--line-regexp,-x}'[force pattern to match only whole lines]'
-  '(--null -Z --no-filename -h)'{--null,-Z}'[print 0 byte after FILE name]'
-  '--help[display help]'
-  '--mmap[memory map input]'
+  '(-)--help[display help information]'
 )
 
-# remove long options?
-_pick_variant -c "$command" gnu=gnu unix --help ||
-    arguments=( ${arguments:#(|*\)(\*|))--*} )
+_pick_variant -r variant -c "$command" gnu=gnu gpl2=2.5.1 unix --version
+case $variant:$OSTYPE in
+  (gnu:*|gpl2:freebsd*))
+    [[ $service != (|g)(|z)[ef]grep ]] && arguments+=(
+      $matchers{--perl-regexp,-P}'[use perl regular expression]'
+    )
+  ;|
+  (gnu:*|gpl2:(free|net)bsd*))
+    arguments+=(
+      '*--exclude-from=[skip files matching pattern in specified file]:file:_files'
+      '(-z --null-data)'{-z,--null-data}'[input data separated by 0 byte, not newline]'
+    )
+  ;|
+  gpl2:freebsd*)
+    arguments+=(
+      '(--null --no-filename -h)--null[print 0 byte after each filename]'
+    )
+  ;|
+  gpl2:(freebsd|darwin)*)
+    arguments+=(
+      '(-Z --decompress -J --bz2decompress)'{-J,--bz2decompress}"[decompress bzip2'ed input before searching]"
+      '(-Z --decompress -J --bz2decompress)'{-Z,--decompress}"[decompress gzip'ed input before searching]"
+    )
+  ;|
+  (gnu:*|gpl2:netbsd*))
+    arguments+=(
+      '(--null -Z --no-filename -h)'{--null,-Z}'[print 0 byte after each filename]'
+    )
+  ;|
+  gnu:*)
+    arguments+=(
+      '(--no-group-separator)--group-separator=[specify separator between blocks of context]:separator [--]'
+      "(--group-separator)--no-group-separator[don't separate context blocks]"
+      '(-T --initial-tab)'{-T,--initial-tab}'[make tabs line up (if needed)]'
+      '(--recursive -r --dereference-recursive -R -d --directories)'{--dereference-recursive,-R}'[recurse subdirectories, following symlinks]'
+    )
+  ;;
+  gpl2:*) arguments=( ${${arguments:#*\)-r}/\)-r/\)-R} ) ;;
+  *:openbsd*)
+    arguments=(
+      ${(M)arguments:#((#s)|*\))--(context|binary-files|line-buffered)*}
+      ${${arguments:#((#s)|*\))(\*|)-[d-]*}/\)-r/\)-R}
+      "-U[search binary files but don't print them]"
+      '-Z[behave as zgrep]'
+    )
+  ;;
+  *)
+    # remove long options and GNU specific short opts, this is right for solaris
+    arguments=( ${arguments:#((#s)|*\))(\*|)-[aABCdDfGHILmorVy-]*} )
+  ;;
+esac
 
 _arguments -S -s $arguments[@]
 
diff --git a/Completion/Unix/Command/_groff b/Completion/Unix/Command/_groff
index 4f3b8c617..d78d65401 100644
--- a/Completion/Unix/Command/_groff
+++ b/Completion/Unix/Command/_groff
@@ -27,7 +27,7 @@ _arguments \
 	'-I[add search dir for soelim]:directory:_files -/' \
 	'-l[send output to spooler program for printing]' \
 	'*-L[pass arg to spooler program]:spooler argument:' \
-	'-N[do not allow newlines within eqn delimeters]' \
+	"-N[don't allow newlines within eqn delimiters]" \
 	'-p[preprocess with pic]' \
 	'*-P[pass option to postprocessor]:option:' \
         '-R[preprocess with refer]' \
diff --git a/Completion/Unix/Command/_growisofs b/Completion/Unix/Command/_growisofs
index 36b45d5ba..741a7516b 100644
--- a/Completion/Unix/Command/_growisofs
+++ b/Completion/Unix/Command/_growisofs
@@ -116,7 +116,7 @@ _mkisofs_sparc_boot_images () {
 _mkisofs_pathspec () {
   local sep
   if (( $words[(I)-graft-points] )); then
-    if ! compset -P '*[^\\]\='; then
+    if ! compset -P 1 '*[^\\]\='; then
       sep='-qS='
     fi
   fi
@@ -218,7 +218,7 @@ else
     '-check-session[check old session for compliance against current rules]' \
     '-copyright[specify the path and file-name of the copyright file]' \
     '-d[omit trailing period from files that do not have a period]' \
-    '-D[do not use deep directory-realocation]' \
+    "-D[don't use deep directory-reallocation]" \
     '-dir-mode[specify the mode of directories]' \
     '-dvd-video[generate a DVD-Video compliant UDF file-system]' \
     '-f[follow symbolic links when generating the file system]' \
@@ -250,7 +250,7 @@ else
     {-nobak,-no-bak}'[do not include backup files on the ISO9660 file-system]' \
     '-force-rr[do not use the automatic Rock Ridge attribute-recognition for previous sessions]' \
     '-no-rr[do not use use the Rock Ridge attributes from previous sessions]' \
-    '-no-split-symlink-components[do not split the symbolic-link compontents]' \
+    "-no-split-symlink-components[don't split the symbolic-link components]" \
     '-no-split-symlink-fields[do not split the symbolic-link fields]' \
     '-o[output the ISO9660-file-system image to the given file]:ISO9660 image:_files' \
     '-pad[pad the end of the image by 150 sectors]' \
@@ -335,7 +335,7 @@ else
 
     case "$state" in
       (devimg)
-      if compset -P \*=; then
+      if compset -P 1 '*='; then
         _files
       else
         _files -g "*(%,@)"
diff --git a/Completion/Unix/Command/_gs b/Completion/Unix/Command/_gs
index 22f3c789b..98ba14912 100644
--- a/Completion/Unix/Command/_gs
+++ b/Completion/Unix/Command/_gs
@@ -32,7 +32,7 @@ else
     fi
     ;;
   sname)
-    if compset -P '*='; then
+    if compset -P 1 '*='; then
       case "$IPREFIX" in
       *DEVICE\=)
         _wanted devices expl 'ghostscript device' \
diff --git a/Completion/Unix/Command/_gsettings b/Completion/Unix/Command/_gsettings
new file mode 100644
index 000000000..72f015729
--- /dev/null
+++ b/Completion/Unix/Command/_gsettings
@@ -0,0 +1,47 @@
+#compdef gsettings
+
+local curcontext="$curcontext" state line expl ret=1
+local subcmds
+
+_arguments \
+  '(- 1 *)--version[show version information]' \
+  '--schemadir[specify location of schemata]:directory:_directories' \
+  ':command:->subcmds' \
+  '*::args:->subargs' && ret=0
+
+if [[ $state = subargs ]]; then
+  curcontext="${curcontext%:*}-$words[1]:"
+  case $words[1] in
+    help) state=subcmds;;
+    get|range|reset|writable|monitor)
+      _arguments ':schema:->schemata' ':key:->keys'
+    ;;
+    set)
+      _arguments ':schema:->schemata' ':key:->keys' ':value'
+    ;;
+    (list|reset)-(keys|recursively|children)) state=schemata ;;
+    *) _default && ret=0 ;;
+  esac
+fi
+
+case $state in
+  subcmds)
+    subcmds=( ${(L)${${(M)${${(f)"$(_call_program commands $service help)"}[(r)Commands:*,-2]}:#  *}#??}/ ##/:} )
+    _describe -t commands 'command' subcmds -M 'r:?|-=* r:|=*' && ret=0
+    state=''
+  ;;
+  schemata)
+    if compset -P 1 '*:'; then
+      _directories && ret=0
+    else
+      _wanted schemata expl 'schema' compadd -M 'r:|.=* r:|=*' \
+          $(_call_program schemata $service list-schemas) && ret=0
+    fi
+  ;;
+  keys)
+    _wanted keys expl 'key' compadd \
+        $(_call_program keys $service list-keys $words[CURRENT-1]) && ret=0
+  ;;
+esac
+
+return ret
diff --git a/Completion/Unix/Command/_head b/Completion/Unix/Command/_head
index 4f956acdc..75fc1f0a1 100644
--- a/Completion/Unix/Command/_head
+++ b/Completion/Unix/Command/_head
@@ -32,7 +32,7 @@ case $state in
     sign='sign:sign:((-\:"print all but the last specified bytes/lines"'
     sign+=' +\:"print the first specified bytes/lines (default)"))'
     digit='digits:digit:(0 1 2 3 4 5 6 7 8 9)'
-    if compset -P '*[0-9]'; then
+    if compset -P '(-|+|)[0-9]##'; then
       _alternative $mlt $digit && ret=0
     elif [[ -z $PREFIX ]]; then
       _alternative $sign $digit && ret=0
diff --git a/Completion/Unix/Command/_hg b/Completion/Unix/Command/_hg
index 8d31cd377..8eaa457c8 100644
--- a/Completion/Unix/Command/_hg
+++ b/Completion/Unix/Command/_hg
@@ -876,7 +876,7 @@ _hg_cmd_qdiff() {
 
 _hg_cmd_qfold() {
   _arguments -s : $_hg_global_opts $_h_commit_opts \
-  '(--keep,-k)'{-k,--keep}'[keep folded patch files]' \
+  '(--keep -k)'{-k,--keep}'[keep folded patch files]' \
   '*:unapplied patch:_hg_qunapplied'
 }
 
diff --git a/Completion/Unix/Command/_iftop b/Completion/Unix/Command/_iftop
index 41ffb4ea1..05db3fa03 100644
--- a/Completion/Unix/Command/_iftop
+++ b/Completion/Unix/Command/_iftop
@@ -1,9 +1,16 @@
 #compdef iftop
 
 _interfaces () {
-	_wanted interfaces expl 'network interface' \
-		_net_interfaces
-	_values "Pseudo-device that captures on all interfaces" "any"
+  local disp expl sep
+  _description interfaces expl 'network interface'
+  _net_interfaces "$expl[@]"
+  if zstyle -t ":completion:${curcontext}:interfaces" verbose; then
+    zstyle -s ":completion:${curcontext}:interfaces" list-separator sep || sep=--
+    disp=( "any $sep capture on all interfaces" )
+    compadd "$expl[@]" -ld disp any
+  else
+    compadd "$expl[@]" any
+  fi
 }
 
 _arguments \
@@ -14,7 +21,7 @@ _arguments \
   -P'[turn on port display]' \
   -b"[don't display bar graphs of traffic]" \
   -B'[display bandwidth rates in bytes/sec rather than bits/sec]' \
-  -i'[interface]:network interface:_interfaces' \
-  -f'[filter]:BPF filter' \
-  -F'[net/mask]:network/mask' \
-  -c'[config file]:config file:_files'
+  '-i+[interface]:network interface:_interfaces' \
+  '-f+[filter]:BPF filter' \
+  '-F+[net/mask]:network/mask' \
+  '-c+[config file]:config file:_files'
diff --git a/Completion/Unix/Command/_imagemagick b/Completion/Unix/Command/_imagemagick
index 1fc6089c8..c2c9dc478 100644
--- a/Completion/Unix/Command/_imagemagick
+++ b/Completion/Unix/Command/_imagemagick
@@ -12,7 +12,7 @@ typeset -A opt_args
 #
 # and certainly many other things...
 
-formats=(jpg jpeg jp2 j2k jpc jpx jpf tiff miff ras bmp cgm dcx ps eps fig fits fpx gif mpeg pbm pgm ppm pcd pcl pdf pcx png rad rgb rgba rle sgi html shtml tga ttf uil xcf xwd xbm xpm yuv)
+formats=(jpg jpeg jp2 j2k jpc jpx jpf tif tiff miff ras bmp cgm dcx ps eps fig fits fpx gif mpeg pbm pgm ppm pcd pcl pdf pcx png rad rgb rgba rle sgi html shtml tga ttf uil xcf xwd xbm xpm yuv)
 
 if (( $# )); then
   _files "$@" -g "*.(#i)(${(j:|:)formats})(-.)"
@@ -364,7 +364,7 @@ case "$service" in
       '*:picture file:_imagemagick' && return
 
     if [[ "$state" = profile ]]; then
-      if compset -P '*:'; then
+      if compset -P 1 '*:'; then
 	_files
       else
 	_wanted prefixes expl 'profile type' compadd icc: iptc:
diff --git a/Completion/Unix/Command/_initctl b/Completion/Unix/Command/_initctl
index 6505e4298..9d444c6d1 100644
--- a/Completion/Unix/Command/_initctl
+++ b/Completion/Unix/Command/_initctl
@@ -4,7 +4,7 @@
 
 typeset -g -a -U _initctl_events_list _initctl_eventargs_list
 
-# run show-config -e and if possible parse out all events and KEY= argumnts
+# run show-config -e and if possible parse out all events and KEY= arguments
 # otherwise provide some common values
 _initctl_fillarray_events_args ()
 {
@@ -169,7 +169,7 @@ _initctl()
   # define fallback completion function
   local cmd_completion_default=basic
 
-  # depending on which command was used, call different completion funtions
+  # depending on which command was used, call different completion functions
   case $service in
     initctl)
       _arguments "${common_args[@]}" '*::Initctl Commands:_initctl_command'
diff --git a/Completion/Unix/Command/_iostat b/Completion/Unix/Command/_iostat
new file mode 100644
index 000000000..88fc6a103
--- /dev/null
+++ b/Completion/Unix/Command/_iostat
@@ -0,0 +1,132 @@
+#compdef iostat
+
+local -a args
+
+case $OSTYPE:l in
+  *bsd*)
+    args+=(
+      '-c[repeat the display N times]:count'
+      '-C[display CPU statistics]'
+      '-d[display only device statistics]'
+      '-I[display total statistics for a given period, rather than average]'
+      '-M[extract values of the name list from specified file]:core:_files'
+      '-N[extract the name list from the specified file]:system:_files'
+      '-T[display TTY statistics]'
+      '-w[specify the duration of pauses between each display]:duration'
+    )
+    ;|
+  freebsd*)
+    args+=(
+      '-h[top mode]'
+      '-K[display block count in kilobytes, not block size]'
+      '-o[display old-style iostat device statistics]'
+      '-t[specify which type of device to display]: :->devicetype'
+      '-x[show extended disk statistics]'
+      '-z[omit lines for devices with no activity]'
+      '-?[display a usage statement and exit]'
+      '*:drives:( ${${(M)${(f)"$(geom disk list)"}\:#Geom name\:*}#*\: } )'
+    )
+    ;;
+  openbsd*)
+    args+=(
+      '-D[display alternate disk statistics]'
+      '*:drives:( ${${(s.,.)"$(sysctl -n hw.disknames)"}%\:*} )'
+    )
+    ;;
+  netbsd*)
+    args+=(
+      '-D[display alternate disk statistics]'
+      '-x[show extended disk statistics]'
+      '*:drives:( $(sysctl -n hw.disknames) )'
+    )
+    ;;
+  aix*)
+    args=(
+      '(-b -q -Q -f -F)-a[displays the adapter throughput report]'
+      '(-b)-A[displays the legacy asynchronous IO utilization report, and turns off the display of TTY utilization report]'
+      '-b[displays the block I/O device utilization statistics]'
+      '(-b)-d[turns off the display of TTY utilization report or CPU utilization report]'
+      '(-b -f -F)-D[displays the extended tape/drive utilization report]'
+      '(-a -b -D)-f[displays the file system utilization report]'
+      '(-a -b -D)-F[displays the file system utilization report, and turns off other utilization reports]'
+      '(-b)-l[displays the output in long listing mode]'
+      '(-b -t)-m[displays the path utilization report]'
+      '(-b)-p[displays the tape utilization report]'
+      '(-b)-P[displays the POSIX asynchronous IO utilization report]'
+      '(-b)-q[specifies AIO queues and their request counts]'
+      '(-b)-Q[displays a list of all the mounted file systems and the associated queue numbers with their request counts]'
+      '(-b)-R[specifies that the reset of min* and max* values should happen at each interval]'
+      '(-b)-s[specifies the system throughput report]'
+      '(-b)-S[displays the processor statistics that are multiplied by a value of 10]:power'
+      '(-b -m)-t[turns off the display of disk utilization report]'
+      '-T[displays the time stamp]'
+      '(-b)-V[displays valid nonzero statistics]'
+      '(-b)-z[resets the disk input/output statistics]'
+      '(-b)-@[reports I/O activities of a workload partition]:workload:(ALL Global)'
+      '*:drives:_files' # not sure how to enumerate drives on aix
+    )
+    ;;
+  solaris*)
+    args=(
+      '-c[report percentage of time the system spent in user/system mode, dtrace probes and idling]'
+      '-C[report extended disk statistics aggregated by controller id, when used with -x]'
+      '-d[report kilobytes transferred per second, transfers per second and average service time]'
+      '-D[report reads/writes per second and percentage disk utilization]'
+      '-e[display device error summary statistics]'
+      '-E[display all device error statistics]'
+      '-i[display Device ID instead of the Serial No, when used with -E]'
+      '-I[report counts in each interval]'
+      '-l[limit the number of disks included in the report]:number of disks'
+      '-m[report file system mount points]'
+      '-M[display data throughput in MB/sec instead of KB/sec]'
+      '-n[display names in descriptive format]'
+      '-p[report per-partition statistics]'
+      '-P[report per-partition statistics only]'
+      '-r[display data in comma-separated format]'
+      '-s[suppress message related to state changes]'
+      '-t[report the number of characters read and written to terminals per second]'
+      '-T[display a timestamp]:format:(( "u\:internal representation of time" "d\:standard date format" ))'
+      '-X[report statistics for lun.controller, for disks under scsi_vhci(7D) control]'
+      '-x[report extended disk statistics]'
+      '-Y[report statistics for lun.targetport and lun.targetport.controller, for disks under scsi_vhci(7D) control]'
+      '-z[ignore lines where data values are all zeros]'
+      '::device:( ${${${(f)"$(iostat -rx 1 1)"}[3,-1]}%%,*} )'
+    )
+    ;;
+  darwin*)
+    args=(
+      '-C[display CPU statistics]'
+      '-c[number of times to display statistics]'
+      '-d[display only device statistics]'
+      '-l[total statistics for a given time period]'
+      '-K[display block count in kilobytes]'
+      '-n[limit the number of disks included in the report]:number of disks'
+      '-o[display old-style iostat device statistics]'
+      '-T[display TTY statistics]'
+      '-U[display system load averages]'
+      '-w[specify the duration of pauses between each display]:duration'
+      '*::device:_files -W /dev -g "disk*"'
+    )
+    ;;
+  *linux*)
+    args=(
+      '-c[display CPU utilization report]'
+      '-d[display device utilization report]'
+      '-T[only display global statistics for group_name]'
+      '-g[display statistics for a group of devices]:group name'
+      '-h[human readable device utilization report]'
+      '-j[display persistent device name]'
+      '(-m)-k[display statistics in kB/s]'
+      '(-k)-m[display statistics in MB/s]'
+      '-N[display registered device mapper names]'
+      '*::device:_files -W /dev -g "*(-%)"'
+    )
+    ;;
+esac
+
+if (( $#args )); then
+  _arguments -s -w -A '-*' : $args
+  return
+fi
+
+_default
diff --git a/Completion/Unix/Command/_ip b/Completion/Unix/Command/_ip
index 1e3949148..6e1cc3b78 100644
--- a/Completion/Unix/Command/_ip
+++ b/Completion/Unix/Command/_ip
@@ -98,7 +98,7 @@ subcmd_lockmtu=("(" /$'lock\0'/ ":lock:lock:(lock)" "|" ")" $subcmd_number )
 local -a subcmd_nexthop
 _regex_words nexthop 'nexthop route keyword' \
     'via:specify nexthop router:$subcmd_ipaddr' \
-    'dev:sepcify output device:$subcmd_dev' \
+    'dev:specify output device:$subcmd_dev' \
     'weight:specify relative quality of route:$subcmd_number'
 subcmd_nexthop=("$reply[@]" "#")
 
@@ -107,7 +107,7 @@ _regex_words rtprotocol 'route protocol' \
   'redirect:installed from ICMP redirect' \
   'kernel:installed automatically by kernel' \
   'boot:installed during boot sequence' \
-  'static:installed by adminstrator' \
+  'static:installed by administrator' \
   'ra:installed by Router Discovery protocol'
 subcmd_rtprotocol=("$reply[@]")
 
@@ -172,10 +172,10 @@ _regex_words \
   link-set-commands 'link set commands' \
   'dev:specify device:$subcmd_dev' \
   'u*p:change state to up' \
-  'do*wn:change state do down' \
+  'do*wn:change state to down' \
   'ar*p:change ARP flag on device:$subcmd_onoff' \
   'mu*lticast:change MULTICAST flag on device:$subcmd_onoff' \
-  'pr*omisc:set promiscious mode:$subcmd_onoff' \
+  'pr*omisc:set promiscuous mode:$subcmd_onoff' \
   'dy*namic:change DYNAMIC flag on device:$subcmd_onoff' \
   'n*ame:change name of device:$subcmd_string' \
   'txq*ueuelen:specify length of transmit queue:$subcmd_number' \
@@ -285,7 +285,7 @@ local -a neigh_add_cmds
 _regex_words neigh-add-commands "neighbour add command" \
   't*o:add new neighbour IP address:$subcmd_ipaddr' \
   'dev:specify network device:$subcmd_dev' \
-  'l*ladr:specify link layer (MAC) address or null:$subcmd_lladdr' \
+  'l*laddr:specify link layer (MAC) address or null:$subcmd_lladdr' \
   'n*ud:specify neighbour unreachability detection state:$subcmd_nud'
 # to-address without keyword can appear first
 neigh_add_cmds=( "(" $subcmd_ipaddr "|" ")" "$reply[@]" "#")
@@ -490,7 +490,7 @@ maddr_cmds=("$reply[@]")
 # mroute
 #
 local -a mroute_show_cmds
-_regex_words mroute-show-comnands "mroute show command" \
+_regex_words mroute-show-commands "mroute show command" \
   'to:select destination prefix:$subcmd_ipaddr' \
   'iif:select input interface (device):$subcmd_dev' \
   'from:select source prefix:$subcmd_ipaddr'
diff --git a/Completion/Unix/Command/_java b/Completion/Unix/Command/_java
index 2aef15a25..30231c5ee 100644
--- a/Completion/Unix/Command/_java
+++ b/Completion/Unix/Command/_java
@@ -65,13 +65,13 @@ java)
     '-D-[specify a property]:property:->property' \
     \*{-enableassertions,-ea}-::class \
     \*{-disableassertions,-da}-::class \
-    '(-enablesystemassertions,-esa,-disablesystemassertions,-dsa)'{-enablesystemassertions,-esa,-disablesystemassertions,-dsa} \
+    '(-enablesystemassertions -esa -disablesystemassertions -dsa)'{-enablesystemassertions,-esa,-disablesystemassertions,-dsa} \
     '(-verbose:class)-verbose[print class information]' \
     '(-verbose)-verbose\:class[print class information]' \
     '-verbose\:gc[print gc information]' \
     '-verbose\:jni[print JNI information]' \
     '(- 1)-version[print version]' \
-    '-showversion[print version and contrinue]' \
+    '-showversion[print version and continue]' \
     '(- 1)-'{\?,help}'[print help message]' \
     '(- 1)-X-[non-standard java option]:option' \
     '(- 1)-jar[specify a program encapsulated as jar]:jar:_files -g \*.jar\(-.\)' \
@@ -578,7 +578,7 @@ encoding)
   ;;
 
 property)
-  if compset -P '*='; then
+  if compset -P 1 '*='; then
     _default && return
   else
     _message -e property-names 'property name'
diff --git a/Completion/Unix/Command/_joe b/Completion/Unix/Command/_joe
index 91c437ead..592c34a10 100644
--- a/Completion/Unix/Command/_joe
+++ b/Completion/Unix/Command/_joe
@@ -3,7 +3,7 @@
 _arguments \
   '-asis[characters with codes >127 will be displayed non-inverted]' \
   '-backpath[backup file directory]:backup file directory:_files -/' \
-  '-baud[inserts delays for baud rates below 19200]:baud rate:_baudrate' \
+  '-baud[inserts delays for baud rates below 19200]:baud rate:_baudrates' \
   '-beep[beep on command errors or when cursor goes past extremes]' \
   '-columns[sets the number of screen columns]:num of columns' \
   '-csmode[continued search mode]' \
diff --git a/Completion/Unix/Command/_kvno b/Completion/Unix/Command/_kvno
index 782d9e6fc..9664e187b 100644
--- a/Completion/Unix/Command/_kvno
+++ b/Completion/Unix/Command/_kvno
@@ -3,15 +3,17 @@
 local curcontext="$curcontext" state line ret=1
 
 _arguments -C \
-  '(-4)-c[specify credentials cache to use]:cache:_files' \
-  '(-4)-e[specify encryption type]:encryption type' \
+  '-c[specify credentials cache to use]:cache:_files' \
+  '-e[specify encryption type]:encryption type' \
   '-q[suppress printing]' \
   '(- :)-h[display help information]' \
-  '(-c -e)-4[kerberos 4 tickets]' \
+  '-P[acquire credentials for the principal during S4U2Self]' \
+  '-S[specify the service name of the principal]:service' \
+  '-U[specify user for S4U2Self]:user:_users' \
   ':principal:->principal' && ret=0
 
 if [[ $state = principal ]]; then
-  if compset -P host/; then
+  if compset -P '*/'; then
     _hosts && ret=0
   else
     _alternative \
diff --git a/Completion/Unix/Command/_less b/Completion/Unix/Command/_less
index a3ba8f665..9092010f2 100644
--- a/Completion/Unix/Command/_less
+++ b/Completion/Unix/Command/_less
@@ -32,7 +32,8 @@ fi
 
 _arguments -S -s -A "[-+]*"  \
   '(-? --help)'{-\?,--help}'[display summary of less commands]' \
-  '(-a --search-skip-screen)'{-a,--search-skip-screen}'[begin forward searches after last displayed line]' \
+  '(-a --search-skip-screen)'{-a,--search-skip-screen}'[skip current screen in searches]' \
+  '(-A --SEARCH-SKIP-SCREEN)'{-A,--SEARCH-SKIP-SCREEN}"[start searches just after target line]" \
   '(-b --buffers)'{-b+,--buffers=}'[specify amount of buffer space used for each file]:buffer space (kilobytes)' \
   '(-B --auto-buffers)'{-B,--auto-buffers}"[don't automatically allocate buffers for pipes]" \
   '(-C --CLEAR-SCREEN -c --clear-screen)'{-c,--clear-screen}'[repaint screen instead of scrolling]' \
@@ -44,12 +45,14 @@ _arguments -S -s -A "[-+]*"  \
   '(-F --quit-if-one-screen)'{-F,--quit-if-one-screen}'[exit if entire file fits on first screen]' \
   '(-G --HILITE-SEARCH -g --hilite-search)'{-g,--hilite-search}'[highlight only one match for searches]' \
   '(-g --hilite-search -G --HILITE-SEARCH)'{-G,--HILITE-SEARCH}'[disable highlighting of search matches]' \
+  '--old-bot[revert to the old bottom of screen behavior]' \
   '(-h --max-back-scroll)'{-h+,--max-back-scroll=}'[specify backward scroll limit]:backward scroll limit (lines)' \
   '(-I --IGNORE-CASE -i --ignore-case)'{-i,--ignore-case}'[ignore case in searches that lack uppercase]' \
   '(-i --ignore-case -I --IGNORE-CASE)'{-I,--IGNORE-CASE}'[ignore case in all searches]' \
   '(-j --jump-target)'{-j+,--jump-target}'[specify screen position of target lines]:position (line)' \
   '(-J --status-column)'{-J,--status-column}'[display status column on the left]' \
   \*{-k+,--lesskey-file=}'[use specified lesskey file]:lesskey file:_files' \
+  '(-K --quit-on-intr)'{-K,--quit-on-intr}'[exit less in response to ctrl-c]' \
   '(-L --no-lessopen)'{-L,--no-lessopen}'[ignore the LESSOPEN environment variable]' \
   '(-M --LONG-PROMPT -m --long-prompt)'{-m,--long-prompt}'[prompt verbosely]' \
   '(-m --long-prompt -M --LONG-PROMPT)'{-M,--LONG-PROMPT}'[prompt very verbosely]' \
@@ -80,6 +83,8 @@ _arguments -S -s -A "[-+]*"  \
   '(-\" --quotes)'{-\"+,--quotes=}'[change quoting character]:quoting characters' \
   '(-~ --tilde)'{-~,--tilde}"[don't display tildes after end of file]" \
   '(-\# --shift)'{-\#+,--shift=}"[specify amount to move when scrolling horizontally]:number" \
+  '--follow-name[the F command changes file if the input file is renamed]' \
+  '--use-backslash[subsequent options use backslash as escape char]' \
   "$files[@]" && ret=0
 
 
diff --git a/Completion/Unix/Command/_lha b/Completion/Unix/Command/_lha
index c2d5e7d8d..e8d47fcdb 100644
--- a/Completion/Unix/Command/_lha
+++ b/Completion/Unix/Command/_lha
@@ -1,5 +1,7 @@
 #compdef lha
 
+local expl
+
 if (( CURRENT == 2 )); then
     compset -P -
 
diff --git a/Completion/Unix/Command/_libvirt b/Completion/Unix/Command/_libvirt
new file mode 100644
index 000000000..a3ab5a68a
--- /dev/null
+++ b/Completion/Unix/Command/_libvirt
@@ -0,0 +1,238 @@
+#compdef virsh virt-admin virt-host-validate virt-pki-validate virt-xml-validate
+
+local curcontext="$curcontext" state line expl ret=1
+declare -A opt_args
+
+local exargs="-h --help -V -v --version=short --version=long"
+local -a common_opts interact_cmds
+common_opts=(
+  '(- *)'{-h,--help}'[print help information and exit]'
+  '(- *)'{-v,--version=short}'[print short version information and exit]'
+  '(- *)'{-V,--version=long}'[print long version information and exit]'
+  "(-c --connect $exargs)"{-c+,--connect=}'[specify connection URI]:URI:_hosts'
+  "(-d --debug -q --quiet $exargs)"{-d+,--debug=}'[set debug level]:level:(0 1 2 3 4)'
+  "(-l --log $exargs)"{-l+,--log=}'[specify log file]:file:_files'
+  "(-q --quiet -d --debug $exargs)"{-q,--quiet}'[quiet mode]'
+)
+interact_cmds=(cd echo exit quit connect)
+
+typeset -A dom_opts
+dom_opts=(
+  console " "
+  destroy " "
+  edit " "
+  managedsave " "
+  reboot " "
+  reset " "
+  resume --state-paused
+  save " "
+  screenshot " "
+  send-key " "
+  shutdown --state-running
+  start --inactive
+  suspend --state-running
+  ttyconsole " "
+  undefine --inactive
+  vncdisplay " "
+)
+typeset -A iface_opts
+iface_opts=(
+  iface-start --inactive
+)
+typeset -A net_opts
+net_opts=(
+  net-start --inactive
+)
+typeset -A pool_opts
+pool_opts=(
+  pool-start --inactive
+)
+
+case $service in
+  virsh)
+    if (( ! $+_cache_virsh_cmds )); then
+      _cache_virsh_cmds=( ${${${${(f):-"$(_call_program commands virsh help)"}:#*:}/# ##}/ *} )
+      local icmd
+      for icmd in $interact_cmds; do
+        _cache_virsh_cmds[$_cache_virsh_cmds[(i)$icmd]]=()
+      done
+    fi
+    if (( ! $+_cache_virsh_cmd_opts )); then
+      typeset -gA _cache_virsh_cmd_opts
+    fi
+    _arguments -A "-*" -C -S -s -w \
+      "$common_opts[@]" \
+      "(-e --escape $exargs)"{-e+,--escape=}'[set escape sequence for console]:sequence' \
+      "(-k --keepalive-interval $exargs)"{-k+,--keepalive-interval=}'[set keepalive interval]:interval' \
+      "(-K --keepalive-count $exargs)"{-K+,--keepalive-count=}'[set keepalive count]:count' \
+      "(-r --readonly $exargs)"{-r,--readonly}'[connect readonly]' \
+      "(-t --timing $exargs)"{-t,--timing}'[print timing information]' \
+      '1:command:->virsh_cmds' \
+      '*:cmdopt:->virsh_cmd_opts' && return
+      # We accept only virsh command options after the first non-option argument
+      # (i.e., the virsh command itself), this makes it so with the -A "-*" above
+      [[ -z $state ]] && state=virsh_cmd_opts
+  ;;
+  virt-admin)
+    if (( ! $+_cache_virt_admin_cmds )); then
+      _cache_virt_admin_cmds=( ${${${${(f):-"$(_call_program commands virt-admin help)"}:#*:}/# ##}/ *} )
+      local icmd
+      for icmd in $interact_cmds; do
+        _cache_virt_admin_cmds[$_cache_virt_admin_cmds[(i)$icmd]]=()
+      done
+    fi
+    if (( ! $+_cache_virt_admin_cmd_opts )); then
+      typeset -gA _cache_virt_admin_cmd_opts
+    fi
+    _arguments -A "-*" -C -S -s -w \
+      "$common_opts[@]" \
+      '1:command:->virt_admin_cmds' \
+      '*:cmdopt:->virt_admin_cmd_opts' && return
+      # Same as with virsh above
+      [[ -z $state ]] && state=virt_admin_cmd_opts
+  ;;
+  virt-host-validate)
+    _arguments -A "-*" -S \
+      '(- *)'{-h,--help}'[print help information and exit]' \
+      '(- *)'{-v,--version}'[print version information and exit]' \
+      '(- *)'{-q,--quiet}'[quiet mode]' \
+      '1:hv-type:(qemu lxc bhyve)' && return
+  ;;
+  virt-pki-validate)
+    _arguments -A "-*" -S \
+      '(- *)'{-h,--help}'[print help information and exit]' \
+      '(- *)'{-V,--version}'[print version information and exit]' \
+      && return
+  ;;
+  virt-xml-validate)
+    _arguments -A "-*" -S \
+      '(- *)'{-h,--help}'[print help information and exit]' \
+      '(- *)'{-V,--version}'[print version information and exit]' \
+      '1:file:_files -g "*.xml(-.)"' \
+      '2:schema:(domainsnapshot domain network storagepool storagevol nodedev capability nwfilter secret interface)' \
+      && return
+  ;;
+esac
+
+local -a conn_opt
+if [[ -n ${(v)opt_args[(I)-c|--connect]} ]]; then
+  local uri=${(v)opt_args[(I)-c|--connect]}
+  uri=${uri//(#m)\\([\\:])/${MATCH[2]}} # opt_args elements are colon-escaped
+  # For the libvirt remote URI syntax, see:
+  # https://libvirt.org/guide/html/Application_Development_Guide-Architecture-Remote_URIs.html
+  [[ -z ${(Q)uri//([[:alnum:]]|+|:|\/|@|-|\.|\?|=)} ]] && \
+    conn_opt=( -c $uri )
+fi
+
+case $state in
+  virsh_cmds)
+    _wanted commands expl 'virsh command' compadd -a _cache_virsh_cmds && ret=0
+  ;;
+  virsh_cmd_opts)
+    if [[ $words[CURRENT-1] == --(dir|emulatorbin|file|mountpoint|*path|script|source-dev) || $words[CURRENT] == (/*|.*) ]]; then
+      _default
+      return 0
+    fi
+    local cmd word
+    for word in ${words:1}; do
+      [[ -n "${_cache_virsh_cmds[(r)${(b)word}]}" ]] && cmd=$word && break
+    done
+    [[ -z $cmd ]] && return 1
+    local -a values
+    case $words[CURRENT-1] in
+      --domain)
+        values=( $(_call_program domains "noglob virsh $conn_opt list ${dom_opts[$cmd]:-"--all"} --name") )
+        [[ -n $values ]] && _wanted domains expl domain compadd ${=values} && return 0
+        return 1
+      ;;
+      --interface)
+        values=( ${${${${(f):-"$(_call_program interfaces "noglob virsh $conn_opt iface-list ${iface_opts[$cmd]:-"--all"}")"}/ Name*/}:#---*}/  */} )
+        [[ -n $values ]] && _wanted interfaces expl interface compadd ${=values} && return 0
+        return 1
+      ;;
+      --network)
+        values=( $(_call_program networks "noglob virsh $conn_opt net-list ${net_opts[$cmd]:-"--all"} --name") )
+        [[ -n $values ]] && _wanted networks expl network compadd ${=values} && return 0
+        return 1
+      ;;
+      --device)
+        values; values=( $(_call_program devices "noglob virsh $conn_opt nodedev-list") )
+        [[ -n $values ]] && _wanted devices expl device compadd ${=values} && return 0
+        return 1
+      ;;
+      --nwfilter)
+        values=( ${${${${(f):-"$(_call_program nwfilters "noglob virsh $conn_opt nwfilter-list")"}/ UUID*/}:#---*}/  */} )
+        [[ -n $values ]] && _wanted nwfilters expl nwfilter compadd ${=values} && return 0
+        return 1
+      ;;
+      --pool)
+        values=( ${${${${(f):-"$(_call_program pools "noglob virsh $conn_opt pool-list ${pool_opts[$cmd]:-"--all"}")"}/ Name*/}:#---*}/  */} )
+        [[ -n $values ]] && _wanted pools expl pool compadd ${=values} && return 0
+        return 1
+      ;;
+      --secret)
+        values=( ${${${${(f):-"$(_call_program secrets "noglob virsh $conn_opt secret-list")"}/ UUID*/}:#---*}/  */} )
+        [[ -n $values ]] && _wanted secrets expl secret compadd ${=values} && return 0
+        return 1
+      ;;
+      --snapshotname)
+        local dom ; (( ${(k)words[(I)--domain]} > 0 )) && dom=${words[1+${(k)words[(I)--domain]}]}
+        [[ -z $dom ]] && return 1
+        values=( ${${${${(f):-"$(_call_program snapshots "noglob virsh $conn_opt snapshot-list --domain ${(q)dom} 2>/dev/null")"}/ Name*/}:#---*}/  */} )
+        [[ -n $values ]] && _wanted snapshots expl snapshot compadd ${=values} && return 0
+        return 1
+      ;;
+      --vol)
+        local pool ; (( ${(k)words[(I)--pool]} > 0 )) && pool=${words[1+${(k)words[(I)--pool]}]}
+        [[ -z $pool ]] && return 1
+        values=( ${${${${(f):-"$(_call_program volumes "noglob virsh $conn_opt vol-list --pool ${(q)pool} 2>/dev/null")"}/ Name*/}:#---*}/  */} )
+        [[ -n $values ]] && _wanted volumes expl volume compadd ${=values} && return 0
+        return 1
+      ;;
+    esac
+    if [[ $cmd == help ]]; then
+      [[ $words[-1] == -* ]] && _values -w option --command && return 0
+      if [[ $words[-2] == help || $words[-2] == --command ]]; then
+        _wanted commands expl command compadd ${=_cache_virsh_cmds} && return 0
+      fi
+      return 1
+    fi
+    # Allow passing domain without --domain with few of the most used commands
+    if [[ $cmd == (destroy|edit|reboot|reset|start|shutdown) ]]; then
+      if [[ $words[CURRENT-1] == $cmd ]]; then
+        values=( $(_call_program domains "noglob virsh $conn_opt list ${dom_opts[$cmd]:-"--all"} --name") )
+        [[ -n $values ]] && _wanted domains expl domain compadd ${=values} && return 0
+      fi
+    fi
+    [[ -z $_cache_virsh_cmd_opts[$cmd] ]] && \
+      _cache_virsh_cmd_opts[$cmd]=${(M)${${${${=${(f)"$(_call_program options virsh help $cmd 2>&1)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}
+    [[ -n ${=_cache_virsh_cmd_opts[$cmd]} ]] && \
+      _values -w option ${(u)=_cache_virsh_cmd_opts[$cmd]} && ret=0
+  ;;
+  virt_admin_cmds)
+    _wanted commands expl 'virt-admin command' compadd -a _cache_virt_admin_cmds && ret=0
+  ;;
+  virt_admin_cmd_opts)
+    local cmd word
+    for word in ${words:1}; do
+      [[ -n "${_cache_virt_admin_cmds[(r)${(b)word}]}" ]] && cmd=$word && break
+    done
+    [[ -z $cmd ]] && return 1
+    if [[ $words[CURRENT-1] == --server ]]; then
+      _wanted servers expl server compadd ${=${(S)${${(f)$(_call_program -p servers noglob virt-admin ${(Q)conn_opt} srv-list)}##*--- }//[0-9]* }} && return 0
+    fi
+    if [[ $words[CURRENT-1] == --client ]]; then
+      local srv ; (( ${(k)words[(I)--server]} > 0 )) && srv=${words[1+${(k)words[(I)--server]}]}
+      [[ -z $srv ]] && return 1
+      [[ -n ${srv//[[:alnum:]]} ]] && return 1
+      _wanted clients expl client compadd ${=${${(f):-"$(_call_program -p clients noglob virt-admin ${(Q)conn_opt} srv-clients-list --server $srv 2>/dev/null)"}/ [a-z]*}//[^0-9]} && return 0
+    fi
+    [[ -z $_cache_virt_admin_cmd_opts[$cmd] ]] && \
+      _cache_virt_admin_cmd_opts[$cmd]=${(M)${${${${=${(f)"$(_call_program options virt-admin help $cmd 2>&1)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}
+    [[ -n $_cache_virt_admin_cmd_opts[$cmd] ]] && \
+      _values -w option ${(u)=_cache_virt_admin_cmd_opts[$cmd]} && ret=0
+  ;;
+
+esac
+
+return ret
diff --git a/Completion/Unix/Command/_ln b/Completion/Unix/Command/_ln
index c903fee02..efb982aba 100644
--- a/Completion/Unix/Command/_ln
+++ b/Completion/Unix/Command/_ln
@@ -38,6 +38,7 @@ if [[ $variant == gnu ]]; then
     '(-L --logical)'{-L,--logical}'[create hard links to symbolic link references]'
     '(-n --no-dereference)'{-n,--no-dereference}'[treat destination symbolic link to a directory as if it were a normal file]'
     '(-P --physical)'{-P,--physical}'[create hard links directly to symbolic links]'
+    '(-r --relative)'{-r,--relative}'[create symbolic links relative to link location]'
     '(-s --symbolic)'{-s,--symbolic}'[create symbolic links instead of hard links]'
     '(-S --suffix)'{-S,--suffix=}'[override default backup suffix]:suffix'
     '(-t --target-directory)'{-t,--target-directory=}'[specify directory in which to create the links]: :_directories'
diff --git a/Completion/Unix/Command/_locale b/Completion/Unix/Command/_locale
new file mode 100644
index 000000000..59e04a282
--- /dev/null
+++ b/Completion/Unix/Command/_locale
@@ -0,0 +1,84 @@
+#compdef locale
+
+local curcontext="$curcontext" state state_descr line expl ret=1
+typeset -A opt_args; local -a specs aopts
+
+if _pick_variant gnu='(GNU|EGLIBC)' unix --version; then
+
+  local exargs="-? --help --usage -V --version"
+
+  aopts=( -A "-*" -C -S -s )
+  specs=(
+    '(- *)'{-\?,--help}'[display help information]'
+    '(- *)--usage[display a short usage message]'
+    '(- *)'{-V,--version}'[print program version]'
+    - set1
+    "(-a --all-locales $exargs)"{-a,--all-locales}'[list all available locales]'
+    "(-v --verbose $exargs)"{-v,--verbose}'[display additional information]'
+    - set2
+    "(-m --charmaps $exargs)"{-m,--charmaps}'[list all available charmaps]'
+    - set3
+    "(-c --category-name $exargs)"{-c,--category-name}'[print also locale category]'
+    "(-k --keyword-name $exargs)"{-k,--keyword-name}'[print also keyword of each value]'
+    '*:name:->catkey'
+  )
+
+elif [[ $OSTYPE == openbsd* ]]; then
+
+  specs=(
+    '(-m)-a[list all available locales]'
+    '(-a)-m[list all available charmaps]'
+  )
+
+else
+
+  aopts=( -C -A "-*" )
+  specs=(
+    - set1
+    '-a[list all available locales]'
+    - set2
+    '-m[list all available charmaps]'
+    - set3
+    '-c[print also locale category]'
+    '-k[print also keyword of each value]'
+    '*:name:->catkey'
+  )
+fi
+
+_arguments $aopts : $specs && ret=0
+
+if [[ $state == catkey ]]; then
+  typeset -aU cats keys
+
+  case $OSTYPE in
+    *bsd*)
+      # keywords from comparing locale -k list on netbsd and freebsd
+      # the additional keywords freebsd supports will be added via
+      # the reassignment of keys
+      keys+=(
+        charmap decimal_point thousands_sep grouping radixchar thousep int_curr_symbol
+        currency_symbol mon_decimal_point mon_thousands_sep mon_grouping positive_sign
+        negative_sign int_frac_digits frac_digits p_cs_precedes p_sep_by_space n_cs_precedes
+        n_sep_by_space p_sign_posn n_sign_posn int_p_cs_precedes int_p_sep_by_space
+        int_n_cs_precedes int_n_sep_by_space int_p_sign_posn int_n_sign_posn d_t_fmt d_fmt
+        t_fmt am_str pm_str t_fmt_ampm day_1 day_2 day_3 day_4 day_5 day_6 day_7 abday_1
+        abday_2 abday_3 abday_4 abday_5 abday_6 abday_7 mon_1 mon_2 mon_3 mon_4 mon_5 mon_6
+        mon_7 mon_8 mon_9 mon_10 mon_11 mon_12 abmon_1 abmon_2 abmon_3 abmon_4 abmon_5
+        abmon_6 abmon_7 abmon_8 abmon_9 abmon_10 abmon_11 abmon_12 era era_d_fmt era_d_t_fmt
+        era_t_fmt alt_digits yesexpr noexpr yesstr nostr
+      );|
+    (free|net|dragonfly)bsd*) (( words[(I)-k] )) && keys+=(list);;
+    *)
+      cats=( ${${${(f)"$(locale)"}%=*}%(LANG|LANGUAGE|LC_ALL)} )
+    ;;
+  esac
+
+  keys=( $keys ${${(f)"$(locale -k $cats 2>/dev/null)"}%=*} )
+  if [[ $OSTYPE == freebsd* ]] && (( words[(I)list] )); then
+    _message -e values prefix && ret=0
+  else
+    _wanted values expl name compadd "$@" -a - cats keys && ret=0
+  fi
+fi
+
+return ret
diff --git a/Completion/Unix/Command/_localedef b/Completion/Unix/Command/_localedef
new file mode 100644
index 000000000..4d4b4bbe3
--- /dev/null
+++ b/Completion/Unix/Command/_localedef
@@ -0,0 +1,92 @@
+#compdef localedef
+
+local curcontext="$curcontext" state line expl ret=1
+typeset -A opt_args
+
+if _pick_variant gnu='(GNU|EGLIBC)' unix --version; then
+
+  local exargs="-? --help --usage -V --version"
+  _arguments -A "-*" -C -S -s \
+    '(- *)'{-\?,--help}'[display help information]' \
+    '(- *)--usage[display a short usage message]' \
+    '(- *)'{-V,--version}'[print program version]' \
+    "(-A --alias-file $exargs)"{-A+,--alias-file=}'[specify locale alias file]:alias file:_files' \
+    "($exargs)--prefix=[specify path prefix]:prefix:_files" \
+    "(-c --force $exargs)"{-c,--force}'[force write despite of warnings]' \
+    "(-v --verbose $exargs)"{-v,--verbose}'[display additional information]' \
+    "($exargs)--quiet[suppress messages and warnings]" \
+    - set1 \
+    "(-f --charmap $exargs)"{-f+,--charmap=}'[specify locale charmap file]:charmap:->charmap' \
+    "(-i --inputfile $exargs)"{-i+,--inputfile=}'[specify locale definition file]:locale file:_files' \
+    "(-u --repertoire-map $exargs)"{-u+,--repertoire-map=}'[specify repertoire map file]:repertoire map file:_files' \
+    '1:path:_files' \
+    - set2 \
+    "(--list-archive $exargs)--list-archive[list locales in archive]" \
+    - set3 \
+    "(--delete-from-archive $exargs)--delete-from-archive[delete locale from archive]" \
+    '*:locale:->locale' \
+    - set4 \
+    "(--add-to-archive $exargs)--add-to-archive[add locale to archive]" \
+    "(--replace $exargs)--replace[replace locale in archive]" \
+    "(--no-archive $exargs)--no-archive[use subdir not archive]" \
+    '*:compiled path:_files -/' \
+    && return 0
+
+  case "$state" in
+    charmap)
+      if [[ $words[-1] == */* ]]; then
+        _wanted charmaps expl charmap _files && ret=0
+      else
+        typeset -a charmaps
+        charmaps=( ${(f)"$(locale -m)"} )
+        _wanted charmaps expl charmap compadd -a charmaps && ret=0
+      fi
+    ;;
+    locale)
+      typeset -a locales
+      local pref=${opt_args[--prefix]}
+      local p=${pref:+--prefix}
+      locales=( ${(f)"$(localedef --list-archive $p $pref)"} )
+      _wanted locales expl locale compadd -a locales && ret=0
+    ;;
+  esac
+
+  return ret
+
+else
+
+  typeset -a u_opt bsd_opts
+  [[ $OSTYPE != darwin* ]] && u_opt=(
+      '-u+[specify target codeset]:codeset:_files'
+    )
+  [[ $OSTYPE == (freebsd*|dragonfly*) ]] && bsd_opts=(
+      '-D[create BSD-style output]' \
+      '-U[ignore undefined character symbols]' \
+      '-v[verbose debug output]' \
+      '-w+[specify width file]:width file:_files' \
+    )
+
+  _arguments -A "-*" -C \
+    '-c[force write despite of warnings]' \
+    '-f+[specify locale charmap file]:charmap:->charmap' \
+    '-i+[specify locale definition file]:locale file:_files' \
+    $u_opt \
+    $bsd_opts \
+    '1:path:_files' \
+    && return 0
+
+  case "$state" in
+    charmap)
+      if [[ $words[-1] == */* ]]; then
+        _wanted charmaps expl charmap _files && ret=0
+      else
+        typeset -a charmaps
+        charmaps=( ${(f)"$(locale -m)"} )
+        _wanted charmaps expl charmap compadd -a charmaps && ret=0
+      fi
+    ;;
+  esac
+
+  return ret
+
+fi
diff --git a/Completion/Unix/Command/_locate b/Completion/Unix/Command/_locate
index 694f506c3..23305f798 100644
--- a/Completion/Unix/Command/_locate
+++ b/Completion/Unix/Command/_locate
@@ -1,132 +1,96 @@
-#compdef locate mlocate slocate
+#compdef locate mlocate slocate glocate
 
-# Decide if we are using mlocate or slocate.
-local ltype basename=${words[1]:t} input
-# If we can't, use this guess.
-local best_guess=mlocate
+local variant=$service
+local -a args
+[[ $service = locate ]] &&
+  _pick_variant -r variant glocate=findutils mlocate=mlocate slocate=secure $OSTYPE -V
+args=( '(-)'{-V,--version}'[display version information]' )
 
-case $basename in
-  ([ms]locate)
-  ltype=$basename
-  ;;
-
-  (locate)
-  input="$(_call_program locate $words[1] -V 2>&1)"
-  case $input in
-    (*mlocate*)
-    ltype=mlocate
-    ;;
-
-    (*(#i)secure locate*)
-    ltype=slocate
-    ;;
-
-    (*(#i)gnu locate*|*findutils*gnu*)
-    ltype=gnu
-    ;;
-
-    (*"illegal option"*)
-    if [[ $OSTYPE == (freebsd|openbsd|dragonfly|darwin)* ]]; then
-      ltype=bsd
-    else
-      ltype=$best_guess
-    fi
-    ;;
-
-    # guess
-    (*)
-    ltype=$best_guess
-    ;;
-  esac
-  ;;
-
-  (*)
-  # too dangerous to run: guess
-  ltype=$best_guess
-esac
+case $variant in
+  [mg]locate)
+    args+=(
+      '(-A --all)'{-A,--all}'[only print entries that match all patterns]'
+      '(-E --non-existing -e --existing)'{-e,--existing}'[restrict display to existing files]'
+      '(-c --count)'{-c,--count}'[output the number of matching entries]'
+      '(-i --ignore-case)'{-i,--ignore-case}'[ignore case distinctions in patterns]'
+      '(-w --wholename -b --basename)'{-w,--wholename}'[match entire file path (default)]'
+      '(-w --wholename -b --basename)'{-b,--basename}'[match only the basename of files in the database]'
+      '(-P -H --no-follow -L --follow)'{-P,-H,--nofollow}"[don't follow symbolic links]"
+      '(-P -H --no-follow -L --follow)'{-L,--follow}'[follow symbolic links to find existing files (default)]'
+      '(-0 --null)'{-0,--null}'[output separated by NUL characters]'
+      '(-S --statistics)'{-S,--statistics}'[show database statistics]'
+    )
+  ;|
 
-case $ltype in
   (mlocate)
-  # actually, -d can take a colon-separate list
   # -r/--regexp mean no normal arguments, so shouldn't complete
   # -m and --mmap are ignored, so don't bother
   # -s and --stdio likewise
-  _arguments -s -S : \
-    {-b,--basename}'[match only the basename of files in the database]' \
-    {-c,--count}'[output the number of matching entries]' \
-    {-d,--database=}'[use alternative database]:database:_files' \
-    {-e,--existing}'[restrict display to existing files]' \
-    {-L,--follow}'[follow symbolic links to find existing files (default)]' \
-    {-h,--help}'[show help]' \
-    {-i,--ignore-case}'[ignore case distinctions in patterns]' \
-    {-l,-n,--limit=}'[limit search results]:file limit: ' \
-    {-P,-H,--nofollow}'[don'\''t follow symbolic links]' \
-    {-0,--null}'[output separated by NUL characters]' \
-    {-S,--statistics}'[show database statistics]' \
-    {-q,--quiet}'[don'\''t report errors]' \
-    {-r,--regexp=}'[search for given basic regexp]:basic regexp: ' \
-    --regex'[patterns are extended regexps]' \
-    {-V,--version}'[show version]' \
-    {-w,--wholename}'[match entire file path (default)]' \
-    '*:pattern: '
+    args=( -s -S : $args
+      \*{-d,--database=}'[use alternative database]:database:_sequence -s \: _files'
+      '(-)'{-h,--help}'[display help information]'
+      '(-l -n --limit)'{-l,-n,--limit=}'[limit search results]:file limit'
+      '(-q --quiet)'{-q,--quiet}"[don't report errors]"
+      '(:)*'{-r,--regexp=}'[search for given basic regexp]:basic regexp'
+      '--regex[patterns are extended regexps]'
+    )
   ;;
 
   (slocate)
   # -d can take path
   # -e can take a comma-separated list of directories.
   # -f should complete list of file system types like mount
-  _arguments -s -S : \
-    -u'[create slocate database starting at path /]' \
-    -U'[create slocate database starting at given path]:directory:_files -/' \
-    -c'[parse GNU locate updatedb with -u, -U]' \
-    -e'[exclude directories with -u, -U]:directories:_files -/' \
-    -f'[exclude file system types from db with -u, -U]:file system:_file_systems' \
-    -l'[security level]:level:(0 1)' \
-    -q'[quiet mode]' \
-    -n'[limit search results]:file limit: ' \
-    -i'[case insensitive search]' \
-    {-r,--regexp=}'[use basic regular expression]:regexp: ' \
-    {-o,--output=}'[specify database to create]:database:_files' \
-    {-d,--database=}'[specify database to search]:database:_files' \
-    {-h,--help}'[display help]' \
-    {-v,--verbose}'[display files when creating database]' \
-    {-V,--version}'[display version]' \
-    '*:pattern: '
+    args=( -s -S : $args
+      -u'[create slocate database starting at path /]'
+      -U'[create slocate database starting at given path]:directory:_files -/'
+      -c'[parse GNU locate updatedb with -u, -U]'
+      -e'[exclude directories with -u, -U]:directories:_files -/'
+      -f'[exclude file system types from db with -u, -U]:file system:_file_systems'
+      -l'[security level]:level:(0 1)'
+      -q'[quiet mode]'
+      -n'[limit search results]:file limit '
+      -i'[case insensitive search]'
+      {-r,--regexp=}'[use basic regular expression]:regexp'
+      {-o,--output=}'[specify database to create]:database:_files'
+      {-d,--database=}'[specify database to search]:database:_files'
+      '(-)'{-h,--help}'[display help information]'
+      {-v,--verbose}'[display files when creating database]'
+    )
   ;;
 
-  (gnu)
-  _arguments -s : \
-    {-d,--database=}'[use alternative database]:database:_files' \
-    {-e,--existing}'[restrict display to existing files]' \
-    {-E,--non-existing}'[allow display of nonexistent files (default)]' \
-    {-i,--ignore-case}'[ignore case distinctions in patterns]' \
-    {-w,--wholename}'[match entire file path (default)]' \
-    {-b,--basename}'[match only the basename of files in the database]' \
-    {-l,-n,--limit=}'[limit search results]:file limit: ' \
-    {-S,--statistics}'[show database statistics]' \
-    {-0,--null}'[output separated by NUL characters]' \
-    {-c,--count}'[output the number of matching entries]' \
-    {-P,-H,--nofollow}'[don'\''t follow symbolic links]' \
-    {-L,--follow}'[follow symbolic links to find existing files (default)]' \
-    {-A,-all}'[match all arguments instead of at least one]' \
-    {-p,--print}'[include search results with statistics or count]' \
-    {-r,--regex=}'[patterns are regular expressions]:basic regexp: ' \
-    --regextype='[select type of regular expression]' \
-    {-V,--version}'[show version]' \
-    --help'[show help]' \
-    '*:pattern: '
+  (glocate)
+    args=( -s : $args
+      \*{-d,--database=}'[use alternative database]:database:_files'
+      '(-E --non-existing -e --existing)'{-E,--non-existing}'[restrict display to nonexistent files]'
+      '(-l --limit)'{-l,--limit=}'[limit search results]:file limit: '
+      '--max-database-age[specify database age at which warning should be issued]:age (days) [8]'
+      '(-p --print)'{-p,--print}'[include search results with statistics or count]'
+      \*{-r,--regex=}'[patterns are regular expressions]:regexp'
+      --regextype='[select type of regular expression]:regex type [basic]:(findutils-default awk egrep ed emacs gnu-awk grep posix-awk posix-basic posix-egrep posix-extended posix-minimal-basic sed)'
+      '(-)'--help'[display help information]'
+    )
   ;;
 
-  (bsd)
-  _arguments -s -S -A '-*' \
-    '(-S)-0[separate file names by NUL characters]' \
-    '(- *)-S[show database statistics and exit]' \
-    '(-S)-c[output the number of matching file names]' \
-    '(-S)*-d[specify database to search]:database:_files' \
-    '(-S)-i[ignore case distinctions in pattern and database]' \
-    '(-S)-l[limit output to specified number of file names]:file limit: ' \
-    '(-S)-m[use mmap(2) instead of stdio(3) (default)]' \
-    '(-S)-s[use stdio(3) instead of mmap(2)]' \
-    '*:pattern: '
-  ;;
+  (freebsd|openbsd|dragonfly|darwin)*)
+    args=( -s -S -A '-*'
+      '(-S)-c[output the number of matching file names]'
+      '(-S)-i[ignore case distinctions in pattern and database]'
+      '(-S)-l[limit output to specified number of file names]:file limit '
+      '(- *)-S[show database statistics and exit]'
+    )
+  ;|
+  openbsd*)
+    args+=( '(-S)-b[match only the basename of files in the database]' )
+  ;|
+  (freebsd|dragonfly|darwin)*)
+    args+=(
+      '(-S)-0[separate file names by NUL characters]'
+      '(-S)-m[use mmap(2) instead of stdio(3) (default)]'
+      '(-S)-s[use stdio(3) instead of mmap(2)]'
+    )
+  ;|
+  (*) args+=( '(-S)*-d[specify database to search]:database:_files' ) ;;
+
 esac
+
+_arguments $args '*: :_guard "^-*" pattern'
diff --git a/Completion/Unix/Command/_look b/Completion/Unix/Command/_look
index 24a016af4..be8cf8c14 100644
--- a/Completion/Unix/Command/_look
+++ b/Completion/Unix/Command/_look
@@ -1,16 +1,34 @@
 #compdef look
 
-local curcontext="$curcontext" state line expl ret=1
+local curcontext="$curcontext" state line expl args sep='+' ret=1
 typeset -A opt_args
 
-_arguments -C -s \
-  '-t+[termination character]:termination character:' \
-  '-f[case insensitive]' \
-  '-d[dictionary order]' \
-  ':string:->string' \
-  ':dictionary file:_files' && ret=0
+case $OSTYPE in
+  linux*)
+    args=(
+      '(2 -a --alternative)'{-a,--alternative}'[use alternative dictionary file]'
+      '(-d --alphanum)'{-d,--alphanum}'[dictionary order]'
+      '(-f --ignore-case)'{-f,--ignore-case}'[case insensitive]'
+      '(-t --terminate)'{-t+,--terminate=}'[specify termination character]:termination character'
+      '(-)'{-h,--help}'[display help information]'
+      '(-)'{-V,--version}'[display version information]'
+    )
+  ;;
+  solaris*) sep='-' ;&
+  *)
+    args=( -A "-*"
+      "-t${sep}[specify termination character]:termination character"
+      '-f[case insensitive]'
+      '-d[dictionary order]'
+    )
+  ;;
+esac
+
+_arguments -C -s -S $args \
+  '1:string:->string' \
+  '2:dictionary file:_files' && ret=0
 
 [[ -n "$state" && ! -prefix - ]] && _wanted values expl 'word prefix' \
-    compadd - $(_call_program words $words[1] '"$PREFIX"' 2>/dev/null) && return
+    compadd - $(_call_program words $words[1] '"$PREFIX"') && return
 
 return ret
diff --git a/Completion/Unix/Command/_lp b/Completion/Unix/Command/_lp
index 8da84a180..63fbab78a 100644
--- a/Completion/Unix/Command/_lp
+++ b/Completion/Unix/Command/_lp
@@ -44,7 +44,7 @@ _lp_job_options()
 
   # The program specified by the style list-printer-options should list jobs in
   # the same style as lpoptions -l.
-  if compset -P '*='; then
+  if compset -P 1 '*='; then
     # List values for the option
     case ${IPREFIX%=} in
       (media)
diff --git a/Completion/Unix/Command/_ls b/Completion/Unix/Command/_ls
index f2e149453..955b0894d 100644
--- a/Completion/Unix/Command/_ls
+++ b/Completion/Unix/Command/_ls
@@ -1,6 +1,6 @@
 #compdef ls gls
 
-local arguments is_gnu
+local arguments is_gnu datef
 
 if ! _pick_variant gnu=gnu unix --help; then
   arguments=(
@@ -11,10 +11,10 @@ if ! _pick_variant gnu=gnu unix --help; then
     '-R[list subdirectories recursively]'
 
     '(-k)-h[print sizes in human readable form]'
+    '(-h)-k[print sizes in kilobytes]'
 
     '-i[print file inode numbers]'
     '(-l -g -1 -C -m -x)-l[long listing]'
-    '(-l -1 -C -m -x)-g[long listing but without owner information]'
     '(-l -g -C -m -x)-1[single column output]'
     '(-l -g -1 -m -x)-C[list entries in columns sorted vertically]'
     '(-l -g -1 -C -x)-m[comma separated]'
@@ -27,6 +27,7 @@ if ! _pick_variant gnu=gnu unix --help; then
 
     '-r[reverse sort order]'
 
+    '(-t)-S[sort by size]'
     '(-S)-t[sort by modification time]'
 
     '(-p)-F[append file type indicators]'
@@ -34,31 +35,80 @@ if ! _pick_variant gnu=gnu unix --help; then
 
     '-n[numeric uid, gid]'
 
-    '(-B -b -w -q)-b[as -B, but use C escape codes whenever possible]'
     '(-B -b -w -q)-q[hide control chars]'
 
     '*:files:_files'
   )
   if [[ "$OSTYPE" = (netbsd*|dragonfly*|freebsd*|openbsd*|darwin*) ]]; then
     arguments+=(
-      '(-h)-k[print sizes of 1k]'
-      '(-t)-S[sort by size]'
       '-T[show complete time information]'
-      '-o[display file flags]'
-      '-f[output is not sorted]'
-      '(-B -b -w -q)-w[print raw characters]'
+      '(-a -A -r -S -t)-f[output is not sorted]'
+    )
+  fi
+  if [[ $OSTYPE = (netbsd*|dragonfly*|freebsd*|openbsd*) ]]; then
+    arguments+=( '-o[display file flags]' )
+  fi
+  if [[ $OSTYPE = (netbsd*|dragonfly*|freebsd*|darwin*) ]]; then
+    arguments+=(
       '(-B -b -w -q)-B[print octal escapes for control characters]'
+      '(-B -b -w -q)-b[as -B, but use C escape codes whenever possible]'
+      '(-B -b -w -q)-w[print raw characters]'
+      '-W[display whiteouts when scanning directories]'
     )
   fi
-  if [[ "$OSTYPE" = (freebsd*|darwin*) ]]; then
+  if [[ $OSTYPE = (netbsd*|openbsd*|darwin*|solaris*) ]]; then
+    arguments+=(
+      '(-l -1 -C -m -x)-g[long listing but without owner information]'
+    )
+  fi
+  if [[ $OSTYPE = netbsd* ]]; then
+    arguments+=(
+      '-M[output file sizes in comma-separated form]'
+      '-O[output only leaf (non-directory) files]'
+      '-P[print full pathname for each file]'
+      "-X[don't cross mount points when recursing]"
+    )
+  fi
+  if [[ $OSTYPE = (dragonfly*|freebsd*|openbsd*|darwin*) ]]; then
+    arguments+=( '-H[follow symlinks on the command line]' )
+  fi
+  if [[ $OSTYPE = (dragonfly*|freebsd*|darwin*) ]]; then
     arguments+=(
       '-G[enable colorized output]'
-      '-H[follow symlinks on the command line]'
       '-P[do not follow symlinks]'
     )
   fi
+  if [[ $OSTYPE = (dragonfly*|freebsd*) ]]; then
+    arguments+=(
+      '(-A)-I[prevent -A from being automatically set for the super-user]'
+    )
+  fi
+  if [[ $OSTYPE = dragonfly* ]]; then
+    arguments+=( '-y[display FSMID in long listing]' )
+  fi
+  if [[ $OSTYPE = (freebsd*|darwin*) ]]; then
+    arguments+=( '(-c -u)-U[file creation time]' )
+  fi
+  if [[ $OSTYPE = freebsd* ]]; then
+    arguments+=(
+      '-,[print file sizes grouped and separated by thousands]'
+      '-D+[specify format for date]:format: _date_formats'
+      '-y[with -t, sort filenames in the same order as the time]'
+      '-Z[display MAC label]'
+    )
+  fi
+  if [[ $OSTYPE = darwin* ]]; then
+    arguments+=(
+      '-@[display extended attribute keys and sizes in long listing]'
+      '-e[display ACL in long listing]'
+      '(-l -1 -C -m -x)-o[long listing but without group information]'
+      '-O[display file flags]'
+      '-v[print raw characters]'
+    )
+  fi
   if [[ $OSTYPE = solaris* ]]; then
     arguments+=(
+      '(-q)-b[print octal escapes for control characters]'
       '(-l -1 -C -m -x)-o[long listing but without group information]'
       '(-l -t -s -r -a)-f[interpret each argument as a directory]'
       '(-E -l)-e[long listing with full and consistent date/time]'
@@ -70,6 +120,7 @@ if ! _pick_variant gnu=gnu unix --help; then
     )
   fi
 else
+  [[ $PREFIX = *+* ]] && datef='formats:format: _date_formats'
   arguments=(
     '(--all -a -A --almost-all)'{--all,-a}'[list entries starting with .]'
     '(--almost-all -A -a --all)'{--almost-all,-A}'[list all except . and ..]'
@@ -77,61 +128,64 @@ else
     '(--ignore-backups -B)'{--ignore-backups,-B}"[don't list entries ending with ~]"
     '(--directory -d)'{--directory,-d}'[list directory entries instead of contents]'
     '(--dired -D)'{--dired,-D}"[generate output designed for Emacs' dired mode]"
-    '(--ignore,-I)'{--ignore,-I}"[don't list entire matching pattern]:pattern:"
-    '(--dereference -L --dereference-command-line --dereference-command-line-symlink-to-dir)'{--dereference,-L}'[list referenced file for sym link]'
-    '(--dereference -L --dereference-command-line --dereference-command-line-symlink-to-dir)'{--dereference-command-line,--dereference-command-line-symlink-to-dir}
+    '*'{--ignore=,-I+}"[don't list entries matching pattern]:pattern: "
+    '(--dereference -L --dereference-command-line -H --dereference-command-line-symlink-to-dir)'{--dereference,-L}'[list referenced file for sym link]'
+    '(--dereference -L --dereference-command-line -H --dereference-command-line-symlink-to-dir)'{--dereference-command-line,-H}'[follow symlink on the command line]'
+    '(--dereference -L --dereference-command-line -H)'--dereference-command-line-symlink-to-dir
     '(--recursive -R)'{--recursive,-R}'[list subdirectories recursively]'
 
     '(--no-group -G)'{--no-group,-G}'[inhibit display of group information]'
-    '(--human-readable -h -H --si)'{--human-readable,-h}'[print sizes in human readable form]'
-    '(--si -H -h --human-readable)'{--si,-H}'[sizes in human readable form; powers of 1000]'
+    '(--block-size --human-readable -h --si --kilobytes -k)'{--human-readable,-h}'[print sizes in human readable form]'
+    '(--block-size --human-readable -h --si --kilobytes -k)--si[sizes in human readable form; powers of 1000]'
     '(--inode -i)'{--inode,-i}'[print file inode numbers]'
 
     '(--format -l -g -o -1 -C -m -x)-l[long listing]'
     '(--format -l -1 -C -m -x)-g[long listing but without owner information]'
+    --group-directories-first
     '(--format -l --no-group -G -1 -C -m -x)-o[no group, long]'
     '(--format -l -g -o -C -m -x)-1[single column output]'
     '(--format -l -g -o -1 -m -x)-C[list entries in columns sorted vertically]'
     '(--format -l -g -o -1 -C -x)-m[comma separated]'
     '(--format -l -g -o -1 -C -m)-x[sort horizontally]'
-    '(-l -g -o -1 -C -m -x)--format=:format:(verbose long commas horizontal across vertical single-column)'
+    '(-l -g -o -1 -C -m -x)--format=[specify output format]:format:(verbose long commas horizontal across vertical single-column)'
 
     '(--size -s -f)'{--size,-s}'[display size of each file in blocks]'
 
     '(--time -u)-c[status change time]'
     '(--time -c)-u[access time]'
     '(-c -u)--time=[specify time to show]:time:(ctime status use atime access)'
-    '--time-style=[show times using specified style]:time style:(full-iso long-iso iso locale)'
+    '--time-style=[show times using specified style]:style: _alternative "time-styles\:time style\:(full-iso long-iso iso locale)" $datef'
 
     '(-a --all -U -l --format -s --size -t --sort --full-time)-f[unsorted, all, short list]'
-    '(--reverse)'{--reverse,-r}'[reverse sort order]'
+    '(--reverse -r -U -f)'{--reverse,-r}'[reverse sort order]'
 
     '(--sort -t -U -v -X)-S[sort by size]'
     '(--sort -S -U -v -X)-t[sort by modification time]'
     '(--sort -S -t -v -X)-U[unsorted]'
     '(--sort -S -t -U -X)-v[sort by version (filename treated numerically)]'
     '(--sort -S -t -U -v)-X[sort by extension]'
-    '(-S -t -U -v -X)--sort=:sort:(size time none version extension)'
+    '(-S -t -U -v -X)--sort=[specify sort key]:sort key:(size time none version extension)'
 
     '--color=-[control use of color]:color:(never always auto)'
-
+    "*--hide=[like -I, but overridden by -a or -A]:pattern: "
     '(--classify -F --indicator-style -p --file-type)'{--classify,-F}'[append file type indicators]'
-    '(--file-type -p --indicator-style -F --classify)'{--file-type,-p}'[append file type indicators except *]'
-    '(-F --classify -p --file-type)--indicator-style=:indicator style:(none file-type classify)'
+    '(--file-type -p --indicator-style -F --classify)--file-type[append file type indicators except *]'
+    '(--file-type -p --indicator-style -F --classify)-p[append / to directories]'
+    '(-F --classify -p --file-type)--indicator-style=[specify indicator style]:indicator style:(none file-type classify slash)'
 
     '(-f)--full-time[list both full date and full time]'
 
-    '(--kilobytes -k --block-size)'{--kilobytes,-k}'[use block size of 1k]'
-    '(-k --kilobytes)--block-size=[specify block size]:block size (bytes):(1024)'
+    '(--block-size --human-readable -h --si --kilobytes -k)'{--kilobytes,-k}'[use block size of 1k]'
+    '(--human-readable -h --si --kilobytes -k)--block-size=[specify block size]:block size (bytes):(1024)'
 
     '(--numeric-uid-gid -n)'{--numeric-uid-gid,-n}'[numeric uid, gid]'
     '(--tabsize -T)'{--tabsize=,-T+}'[specify tab size]:tab size'
     '(--width -w)'{--width=,-w+}'[specify screen width]:screen width'
 
     '(--quoting-style -b --escape -N --literal -Q --quote-name)'{--escape,-b}'[print octal escapes for control characters]'
-    '(--quoting-style -b --escape -N --literal -Q --quote-name)'{--literal,-N}'[print raw characters]'
+    '(--quoting-style -b --escape -N --literal -Q --quote-name)'{--literal,-N}'[print entry names without quoting]'
     '(--quoting-style -b --escape -N --literal -Q --quote-name)'{--quote-name,-Q}'[quote names]'
-    '(-b --escape -N --literal -Q --quote-name)--quoting-style=:quoting style:(literal shell shell-always c escape clocale locale)'
+    '(-b --escape -N --literal -Q --quote-name)--quoting-style=[specify quoting style]:quoting style:(literal shell shell-always c escape clocale locale)'
 
     '(--hide-control-chars -q --show-control-chars)'{--hide-control-chars,-q}'[hide control chars]'
     '(-q --hide-control-chars)--show-control-chars'
@@ -139,6 +193,11 @@ else
     '(- :)--version[display version information]'
     '*:files:_files'
   )
+  if [[ $OSTYPE = linux* ]]; then
+    arguments+=(
+      '(-Z --context)'{-Z,--context}'[print any security context of each file]'
+    )
+  fi
 fi
 
-_arguments -s $arguments
+_arguments -s -S : $arguments
diff --git a/Completion/Unix/Command/_lsof b/Completion/Unix/Command/_lsof
index c12b9910a..bbb6eab59 100644
--- a/Completion/Unix/Command/_lsof
+++ b/Completion/Unix/Command/_lsof
@@ -1,6 +1,6 @@
 #compdef lsof
 
-local curcontext="$curcontext" state line fields args
+local curcontext="$curcontext" state line expl fields args
 
 case $OSTYPE in
   linux*) args=( '-X[skip reporting of info on network connections]' ) ;;
diff --git a/Completion/Unix/Command/_lzop b/Completion/Unix/Command/_lzop
index 6f09cf47e..7661d117c 100644
--- a/Completion/Unix/Command/_lzop
+++ b/Completion/Unix/Command/_lzop
@@ -69,8 +69,9 @@ case "$state" in
       "F $sep Append a \`*' for executable files"
       "G $sep Inhibit display of group information"
       "Q $sep Enclose file names in double quotes" )
+    # The "Z" on the next line is sentinel to prevent the character class from being empty.
     disp=( ${disp[@]:#[Z$PREFIX]*} )
-    compset -P '[FGQ]*'
+    compset -P '[FGQ]#'
     compadd -d disp - ${disp[@]%% *} && ret=0
   ;;
 esac
diff --git a/Completion/Unix/Command/_make b/Completion/Unix/Command/_make
index c3f3961c9..a2ee9ecac 100644
--- a/Completion/Unix/Command/_make
+++ b/Completion/Unix/Command/_make
@@ -184,9 +184,10 @@ _make() {
       '(-j --jobs)'{-j,--jobs=}'[allow N jobs at once; infinite jobs with no arg]:number of jobs'
       '(-k --keep-going)'{-k,--keep-going}"[keep going when some targets can't be made]"
       '(-l --load-average --max-load)'{-l,--load-average=,--max-load}"[don't start multiple jobs unless load is below N]:load"
-      '(-L --check-symlik-times)'{-L,--check-symlink-times}'[use the latest mtime between symlinks and target]'
+      '(-L --check-symlink-times)'{-L,--check-symlink-times}'[use the latest mtime between symlinks and target]'
       '(-n --just-print --dry-run --recon)'{-n,--just-print,--dry-run,--recon}"[don't actually run any recipe; just print them]"
-      '*'{-o,--old-file=,--assume-old=}"[consider FILE to be very old and don't remake it]:file not to remake:->file"
+      '*'{-o,--old-file=,--assume-old=}"[consider specified file to be old and don't remake it]:file not to remake:->file"
+      '(-O --output-sync)'{-O-,--output-sync=-}'[synchronize output of parallel jobs]::granularity for grouping output:compadd -E 0 none line target recurse'
       '(-p --print-data-base)'{-p,--print-data-base}'[print makes internal database]'
       '(-q --question)'{-q,--question}'[run no recipe; exit status says if up to date]'
       '(-r --no-builtin-rules)'{-r,--no-builtin-rules}'[disable the built-in implicit rules]'
@@ -262,17 +263,20 @@ _make() {
 
     if [[ -n "$file" ]]
     then
-      if [[ $is_gnu == gnu ]] && zstyle -t ":completion:${curcontext}:targets" call-command
+      if [[ $is_gnu == gnu ]] 
       then
-        _make-parseMakefile $PWD < <(_call_program targets "$words[1]" -nsp --no-print-directory -f "$file" .PHONY 2> /dev/null)
+        if zstyle -t ":completion:${curcontext}:targets" call-command; then
+          _make-parseMakefile $PWD < <(_call_program targets "$words[1]" -nsp --no-print-directory -f "$file" .PHONY 2> /dev/null)
+        else
+          _make-parseMakefile $PWD < $file
+        fi
       else
-        case "$OSTYPE" in
-          freebsd*)
-          _make-parseMakefile $PWD < <(_call_program targets "$words[1]" -nsp -f "$file" .PHONY 2> /dev/null)
-    ;;
-    *)
+        if [[ $OSTYPE == (freebsd|dragonfly|netbsd)* || /$words[1] == */bmake* ]]; then
+          TARGETS+=(${=${(f)"$(_call_program targets "$words[1]" -s -f "$file" -V.ALLTARGETS 2> /dev/null)"}})
+          _make-parseMakefile $PWD < <(_call_program targets "$words[1]" -nsdg1Fstdout -f "$file" .PHONY 2> /dev/null)
+        else
           _make-parseMakefile $PWD < $file
-        esac
+        fi
       fi
     fi
 
diff --git a/Completion/Unix/Command/_man b/Completion/Unix/Command/_man
index 0534db753..67810e1dc 100644
--- a/Completion/Unix/Command/_man
+++ b/Completion/Unix/Command/_man
@@ -37,27 +37,43 @@ _man() {
 
   mrd=(${^_manpath/\%L/${LANG:-En_US.ASCII}}/mandb(N))
 
-  # $sect is from the command line, the "3p" in "man 3p memcpy"
+  # $sect is from the command line, the "3p" in "man 3p memcpy".
+  #   It may also be a |-joined (and later in the code "()"-enclosed) list of
+  #   section names.
+  #   TODO: disentangle this to always be an array.
   # $sect_dirname is from the filesystem, the "3" in "/usr/share/man/man3"
   # These are used by _man_pages
   local sect sect_dirname
   if [[ $OSTYPE = solaris* ]]; then
     sect=${${words[(R)-s*]#-s}:-$words[$words[(i)-s]+1]}
+    sect="${sect//,/|}"
   elif [[ -n ${sect:=$words[$words[(i)-S]+1]} || -n ${sect:=$MANSECT} ]]; then
-    if [[ $sect != ${sect::="${sect//:/|}"} ]]; then
-      sect="($sect)"
-    fi
+    sect="${sect//:/|}"
+    sect="${sect//,/|}"
   elif (( CURRENT > 2 )); then
-    sect=$words[2]
+    case $words[2] in
+      (-a) sect='*';;
+      (-*) ;;
+      (*)  sect=$words[2];;
+    esac
   fi
 
-  if [[ $sect = (<->*|1M|l|n) || $sect = \(*\|*\) ]]; then
-    dirs=( $^_manpath/(sman|man|cat)${~sect%%[^0-9]#}/ )
+  if [[ $sect = (<->*|1M|l|n) || $sect = *\|* ]]; then
+    () {
+      local -a sects=( ${(s.|.)sect} )
+      if [[ $sect != (l|n) ]]; then
+        sects=( ${sects%%[^0-9]#} )
+      fi
+      dirs=( $^_manpath/(sman|man|cat)${^sects}*/ )
+    }
+    if [[ $sect == *\|* ]]; then sect="($sect)"; fi
     awk="\$2 == \"$sect\" {print \$1}"
   else
     dirs=( $^_manpath/(sman|man|cat)*/ )
     awk='{print $1}'
   fi
+  # Solaris 11 and on have a man-index directory that doesn't contain manpages
+  dirs=( ${dirs:#*/man-index/} )
   if [[ $OSTYPE = solaris* && ( $words[CURRENT] = -s* || $words[CURRENT-1] == -s ) ]]; then
     [[ $words[CURRENT] = -s* ]] && compset -P '-s'
     sects=( ${(o)${dirs##*(man|cat)}%/} )
@@ -78,6 +94,13 @@ _man() {
       done
       (( ret )) || return 0
     done
+    ## To fall back to other sections' manpages when completing filenames, like
+    ## the 'else' codepath does:
+    #
+    # if (( ret )) && [[ $PREFIX$SUFFIX == */* ]]; then
+    #   sect_dirname=
+    #   _wanted manuals expl 'manual page' _man_pages && return
+    # fi
 
     return 1
   else
@@ -87,7 +110,7 @@ _man() {
 }
 
 _man_pages() {
-  local matcher pages dummy sopt
+  local pages sopt
 
   # What files corresponding to manual pages can end in.
   local suf='.((?|<->*)(|.gz|.bz2|.Z|.lzma))'
@@ -96,22 +119,17 @@ _man_pages() {
     # Easy way to test for versions of man that allow file names.
     # This can't be a normal man page reference.
     # Try to complete by glob first.
-    _path_files -g "*$suf" && return
-    _path_files
-    return
-  fi
-
-  zparseopts -E M+:=matcher
-
-  if (( $#matcher )); then
-    matcher=( ${matcher:#-M} )
-    matcher="$matcher"
-  else
-    matcher=
+    if [[ -n $sect_dirname ]]; then
+      _path_files -g "*.*$sect_dirname*(|.gz|.bz2|.Z|.lzma)" "$expl[@]"
+    else
+      _path_files -g "*$suf" "$expl[@]" && return
+      _path_files "$expl[@]"
+    fi
+    return $?
   fi
 
   pages=( ${(M)dirs:#*$sect_dirname/} )
-  compfiles -p pages '' '' "$matcher" '' dummy "*${(b)sect}*"
+  pages=( ${^pages}/"*$sect${sect:+"*"}" );
   pages=( ${^~pages}(N:t) )
 
   (($#mrd)) && pages[$#pages+1]=($(awk $awk $mrd))
diff --git a/Completion/Unix/Command/_md5sum b/Completion/Unix/Command/_md5sum
index c881a4e6d..073e6beba 100644
--- a/Completion/Unix/Command/_md5sum
+++ b/Completion/Unix/Command/_md5sum
@@ -5,10 +5,11 @@ _arguments -S \
   '(-c --check)'{-c,--check}'[read MD5 sums from the FILEs and check them]' \
   '--tag[create a BSD-style checksum]' \
   '(-t --text)'{-t,--text}'[read in text mode]' \
+  "--ignore-missing[don't fail or report status for missing files]" \
   '(-q --quiet)'{-q,--quiet}"[don't print OK for each successfully verified file]" \
   '--status[no output, status code shows success]' \
   '--strict[exit non-zero for improperly formatted checksum lines]' \
   '(-w --warn)'{-w,--warn}'[warn about improperly formatted checksum lines]' \
-  '--help[display help and exit]' \
-  '--version[output version information and exit]' \
+  '(-)--help[display help and exit]' \
+  '(-)--version[output version information and exit]' \
   '*:files:_files'
diff --git a/Completion/Unix/Command/_mencal b/Completion/Unix/Command/_mencal
index ca56c609d..4286b94ca 100644
--- a/Completion/Unix/Command/_mencal
+++ b/Completion/Unix/Command/_mencal
@@ -10,7 +10,7 @@ _arguments -C \
   '(--quiet -q)'{-q,--quiet}'[no top information]' \
   '(--nocolor -n)'{-n,--nocolor}'[noncolored output]' \
   '(--icolor -i)'{-i,--icolor}'[intersection color]:color:(red green blue yellow violet cyan shiny bold)' \
-  '(-)'{-h,--help}'[display help informaiton]' \
+  '(-)'{-h,--help}'[display help information]' \
   '(-)'{-V,--version}'[print version information]' \
   \*{-c,--config}'[config]:options:->option' && ret=0
 
diff --git a/Completion/Unix/Command/_module b/Completion/Unix/Command/_module
index 060f05b86..2a4dba740 100644
--- a/Completion/Unix/Command/_module
+++ b/Completion/Unix/Command/_module
@@ -41,7 +41,7 @@ _module()
     "purge:unload all loaded modules"
     "refresh:refresh all non-persistent components of loaded modules"
     "whatis:display module information"
-    "appropos:search for a given keyword in modules"
+    "apropos:search for a given keyword in modules"
     "keyword:search for a given keyword in modules"
     "initadd:add or append a module to the user's shell init file"
     "initprepend:add or prepend a module to the user's shell init files"
@@ -85,7 +85,7 @@ _module_available_modules()
 {
   if [[ -n $MODULEPATH ]] && [[ ${+_available_modules} -eq 0 ]]
   then
-    _available_modules=(${$(find ${(e)=MODULEPATH//:/ } -xtype f -print 2>/dev/null | grep -v \\.version | sed -e 's,\('${${(e)=MODULEPATH//:/\/\\\|}%\\\|}'\),,g' -e 's,^/*,,g'):#*\~})
+    _available_modules=(${$(find -L ${(e)=MODULEPATH//:/ } -type f -print 2>/dev/null | grep -v \\.version | sed -e 's,\('${${(e)=MODULEPATH//:/\/\\\|}%\\\|}'\),,g' -e 's,^/*,,g'):#*\~})
   fi
 }
 
@@ -93,14 +93,14 @@ _module_available_modules()
 (( $+functions[_module_help] )) || _module_help()
 {
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 # Completion function for load|add
 (( $+functions[_module_load] )) || _module_load()
 {
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 # Completion function for unload|rm
@@ -114,14 +114,14 @@ _module_available_modules()
 {
   # Actually first argument could be a loaded module
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 # Completion function for display|show
 (( $+functions[_module_display] )) || _module_display()
 {
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 # Completion function for avail
@@ -145,35 +145,35 @@ _module_available_modules()
 (( $+functions[_module_whatis] )) || _module_whatis()
 {
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 # Completion function for initadd
 (( $+functions[_module_initadd] )) || _module_initadd()
 {
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 # Completion function for initprepend
 (( $+functions[_module_initprepend] )) || _module_initprepend()
 {
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 # Completion function for initrm
 (( $+functions[_module_initrm] )) || _module_initrm()
 {
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 # Completion function for initswitch
 (( $+functions[_module_initswitch] )) || _module_initswitch()
 {
   _module_available_modules
-  compadd "$@" -a -- _available_modules
+  _multi_parts / "($_available_modules)"
 }
 
 _module "$@"
diff --git a/Completion/Unix/Command/_mosh b/Completion/Unix/Command/_mosh
index c19f6ebde..431fdbf9e 100644
--- a/Completion/Unix/Command/_mosh
+++ b/Completion/Unix/Command/_mosh
@@ -1,6 +1,7 @@
 #compdef mosh
 
 local curcontext="$curcontext" state line
+local -a _comp_priv_prefix
 
 _arguments -C \
   '(-)--help[display help information]' \
diff --git a/Completion/Unix/Command/_mount b/Completion/Unix/Command/_mount
index a3b58bb87..9a7041dee 100644
--- a/Completion/Unix/Command/_mount
+++ b/Completion/Unix/Command/_mount
@@ -619,7 +619,7 @@ if (( ! $+_fs_any )); then
       'longnames[force Windows 95 long filenames to be visible]'
       'nowin95[completely ignore Windows 95 extended file information]'
     )
-    if [[ "${OSTYPE}" =~ freebsd.* ]]; then
+    if [[ "${OSTYPE}" = freebsd* ]]; then
 	    _fs_msdosfs=( "$_fs_msdos[@]" )
     fi
     ;;
@@ -856,7 +856,7 @@ fsopt)
 devordir)
   local dev_tmp mp_tmp mline
 
-  if compset -P '*:'; then
+  if compset -P 1 '*:'; then
     _wanted exports expl 'exported path' compadd \
 	${${(f)"$(path+=( {/usr,}/sbin(N) ) _call_program exports \
 	showmount -e ${IPREFIX%:} 2>/dev/null)"}[2,-1]%% *} && ret=0
@@ -959,14 +959,20 @@ udevordir)
   esac
 
   local MATCH MBEGIN MEND
-  mp_tmp=("${(@qg::)mp_tmp}")
-  dpath_tmp=( "${(@Mqg::)dev_tmp:#/*}" )
-  dev_tmp=( "${(@qg::)dev_tmp:#/*}" )
+  # The complicated substitution for mount point names is required because
+  # characters in /etc/mtab that might confuse programs reading the names
+  # are encoded as exactly 3 octal digits, like for example \040 for space.
+  # The cleaner-looking ${(g::)mp_tmp} might consume too many digits.
+  # Both mp_tmp and dev_tmp are derived from /etc/mtab or "mount" output.
+  mp_tmp=("${(@)mp_tmp//(#m)\\[0-7](#c3)/${(#)$(( 8#${MATCH[2,-1]} ))}}")
+  dev_tmp=("${(@)dev_tmp//(#m)\\[0-7](#c3)/${(#)$(( 8#${MATCH[2,-1]} ))}}")
+  dpath_tmp=( "${(@M)dev_tmp:#/*}" )
+  dev_tmp=( "${(@)dev_tmp:#/*}" )
 
   _alternative \
     'device-labels:device label:compadd -a dev_tmp' \
-    'device-paths: device path:_canonical_paths -A dpath_tmp -N device-paths device\ path' \
-    'directories:mount point:_canonical_paths -A mp_tmp -N directories mount\ point' && ret=0
+    'device-paths: device path:_canonical_paths -A dpath_tmp -N -M "r:|/=* r:|=*" device-paths device\ path' \
+    'directories:mount point:_canonical_paths -A mp_tmp -N -M "r:|/=* r:|=*" directories mount\ point' && ret=0
   ;;
 labels)
   _wanted labels expl 'disk label' compadd /dev/disk/by-label/*(:t) && ret=0
diff --git a/Completion/Unix/Command/_mpc b/Completion/Unix/Command/_mpc
index 11eab8463..e0c6888b0 100644
--- a/Completion/Unix/Command/_mpc
+++ b/Completion/Unix/Command/_mpc
@@ -131,7 +131,7 @@ _mpc_helper_songnumbers() {
 (( $+functions[_mpc_helper_playlists] )) ||
 _mpc_helper_playlists() {
   local list expl
-  list=($(mpc lsplaylists))
+  list=(${(f)"$(mpc lsplaylists)"})
   _wanted list expl playlist compadd -M $MPC_PLAYLIST_MATCHER $expl -a list
 }
 
diff --git a/Completion/Unix/Command/_mutt b/Completion/Unix/Command/_mutt
index 3d433a0b2..67b974a8d 100644
--- a/Completion/Unix/Command/_mutt
+++ b/Completion/Unix/Command/_mutt
@@ -7,11 +7,12 @@ _arguments -s -S \
   '*-b[specify a BCC recipient]:BCC recipient:_email_addresses -n mutt' \
   '*-c[specify a CC recipient]:CC recipient:_email_addresses -n mutt' \
   '(- :)-D[print the value of all variables]' \
+  '(-x)-E[edit the draft (-H) or include (-i) file]' \
   '-d+[log debugging output to ~/.muttdebug0]:level:(1 2 3 4 5)' \
   '-e+[specify a post-init configuration command]:post-init configuration' \
   '-f+[specify mailbox to load]:mailbox: _mailboxes' \
   '-F+[specify an init file]:init file:_files' \
-  '-h[display help]' \
+  '(- :)-h[display help]' \
   '-H+[specify a draft file for message]:draft file:_files' \
   '-i+[specify file to include in message]:include file:_files' \
   '-m+[specify default mailbox type]:mailbox type:(mbox MMDF MH Maildir)' \
@@ -20,8 +21,8 @@ _arguments -s -S \
   '(- :)-Q+[query a configuration variable]:variable:(${${(f)"$(_call_program variables mutt -D 2>/dev/null)"}%%( is|=)*})' \
   '-R[open in read-only mode]' \
   '-s+[specify a subject]:subject:' \
-  '-v[display mutt version]' \
-  '-x[emulate mailx compose]' \
+  '(- :)-v[display mutt version]' \
+  '(-E)-x[emulate mailx compose]' \
   '-y[start listing mailboxes]' \
   '-z[start only if new messages]' \
   '-Z[open first mailbox with new mail]'
diff --git a/Completion/Unix/Command/_mysql_utils b/Completion/Unix/Command/_mysql_utils
index 6532d0a7b..f1ad97bcd 100644
--- a/Completion/Unix/Command/_mysql_utils
+++ b/Completion/Unix/Command/_mysql_utils
@@ -212,7 +212,7 @@ _mysql_utils() {
     '--defaults-extra-file=[read specified file after the global files]:defaults file:_files'
     '(-S --socket)'{-S+,--socket=}'[specify socket file to use for connection]:server socket file:_files'
     '(-h --host)'{-h+,--host=}'[specify server hostname]:hostname:_mysql_hosts'
-    '(-P,--port)'{-P+,--port=}'[specify port number for connection]:server port:_mysql_ports'
+    '(-P --port)'{-P+,--port=}'[specify port number for connection]:server port:_mysql_ports'
     '(-u --user)'{-u+,--user=}'[specify username for login]:server username:_mysql_users'
     '(-p --password)'{-p-,--password=}'[specify password to use for connection]:server password'
     '(-C --compress)'{-C,--compress}'[use compression in server/client protocol]'
diff --git a/Completion/Unix/Command/_nkf b/Completion/Unix/Command/_nkf
index 4d541274d..04977e467 100644
--- a/Completion/Unix/Command/_nkf
+++ b/Completion/Unix/Command/_nkf
@@ -35,7 +35,7 @@ _arguments -s \
   '(-m)-M-[MIME encode]:mime encode:((\:header B\:base64 Q\:quoted))' \
   '-h-[hirakana<->katakana]:hirakata:((1\:hirakana-\>katakana 2\:katakana-\>hirakana 3\:both))' \
   '-L-[line mode]:line mode:((u\:LF w\:CRLF m\:CR))' \
-  '-I[Convert non ISO-2022-JP charactor to GETA]' \
+  '-I[convert non ISO-2022-JP character to GETA]' \
   '(--cap-input --url-input)'{--cap-input,--url-input}'[Convert hex after \: or \%]' \
   '--overwrite[Overwrite original listed files by filtered result]' \
   '(-v --help)'{-v,--help}'[display help message]' \
diff --git a/Completion/Unix/Command/_nm b/Completion/Unix/Command/_nm
index 73d7508b4..963b43f27 100644
--- a/Completion/Unix/Command/_nm
+++ b/Completion/Unix/Command/_nm
@@ -58,6 +58,7 @@ if _pick_variant -r variant binutils=GNU elftoolchain=elftoolchain elfutils=elfu
 	'--special-syms[include special symbols in the output]'
 	'--synthetic[display synthetic symbols as well]'
 	"--target=[target object format]:targets:(${${(@M)${(f)$(_call_program targets nm --help)}:#*supported targets:*}##*: })"
+	'--with-symbol-versions[display version strings after symbol names]'
       )
     ;;
   esac
diff --git a/Completion/Unix/Command/_nmap b/Completion/Unix/Command/_nmap
index 437e68b7d..b3d3d488a 100644
--- a/Completion/Unix/Command/_nmap
+++ b/Completion/Unix/Command/_nmap
@@ -5,7 +5,7 @@ local curcontext="$curcontext" state line suf ret=1
 _arguments -C \
   '!-sI:zombie host:_hosts' \
   '!-P'{T,S,U}'+:port list' \
-  '*-s-[specify scan type]:scan type:((S\:TCP\ SYN\ scan T\:TCP\ connect\(\)\ scan F\:stealth\ FIN\ scan X\:stealth\ Xmas\ tree\ scan N\:stealth\ null\ scan P\:ping\ scanning U\:UDP\ scan O\:IP\ prototocol\ scan I\:idle\ scan A\:ACK\ scan W\:window\ scan R\:RPC\ scan L\:list\ scan V\:version\ detection))' \
+  '*-s-[specify scan type]:scan type:((S\:TCP\ SYN\ scan T\:TCP\ connect\(\)\ scan F\:stealth\ FIN\ scan X\:stealth\ Xmas\ tree\ scan N\:stealth\ null\ scan P\:ping\ scanning U\:UDP\ scan O\:IP\ protocol\ scan I\:idle\ scan A\:ACK\ scan W\:window\ scan R\:RPC\ scan L\:list\ scan V\:version\ detection))' \
   '-b[specify ftp relay host]:ftp relay host:_hosts' \
   '*-P-[specify probe types and options]:probe type/options:->probe-opts' \
   '-A[enable OS detection and version scanning]' \
@@ -29,7 +29,7 @@ _arguments -C \
   '--data_length[add random data to packets]:data length' \
   '(-R)-n[skip reverse DNS to speed things up]' \
   '(-n)-R[always do reverse DNS on targets]' \
-  '-r[do not ramdomize order in which ports are scanned]' \
+  "-r[don't randomize order in which ports are scanned]" \
   '-ttl[specify IPv4 time to live for sent packets]' \
   '--randomize_hosts[scan hosts in random order]' \
   '-M[specify maximum number of parallel TCP connects]:maximum TCP connects' \
diff --git a/Completion/Unix/Command/_openstack b/Completion/Unix/Command/_openstack
new file mode 100644
index 000000000..fcb704ac8
--- /dev/null
+++ b/Completion/Unix/Command/_openstack
@@ -0,0 +1,192 @@
+#compdef openstack aodh barbican ceilometer cinder cloudkitty designate freezer glance gnocchi heat ironic keystone magnum manila mistral monasca murano neutron nova sahara senlin tacker trove vitrage watcher zun
+
+# https://wiki.openstack.org/wiki/OpenStackClients
+# http://docs.openstack.org/user-guide/common/cli-install-openstack-command-line-clients.html
+
+local curcontext="$curcontext" state line expl ret=1
+
+local -a clnts_compl_new clnts_compl_old clnts_swift_like
+
+#
+# We support three different client categories:
+#  1) Clients with new style complete command where output is like:
+#
+#    cmds='alarm alarm-history capabilities complete help'
+#    cmds_alarm='create delete list show update'
+#    cmds_alarm_history='search show'
+#    cmds_alarm_history_search='-h --help -f --format -c --column --max-width --noindent --quote --query'
+#
+#  2) Clients with old style bash-completion command which does
+#     not separate options and commands:
+#
+#    --tenant_id floatingip-delete bgp-peer-delete --default-prefixlen net-create [...]
+#
+#  3) Swift, slightly different from 2)
+#
+clnts_compl_new=( aodh barbican designate freezer gnocchi openstack vitrage watcher )
+clnts_compl_old=( ceilometer cinder cloudkitty glance heat ironic keystone magnum manila mistral monasca murano neutron nova sahara senlin tacker trove zun )
+clnts_swift_like=( swift )
+
+# Python clients take quite some time to start up and some (openstack(1))
+# even go over the network for completions so we cache things pretty hard
+if (( ! $+_cache_openstack_clnt_opts )); then
+  typeset -gA _cache_openstack_clnt_outputs
+  typeset -gA _cache_openstack_clnt_opts
+  typeset -gA _cache_openstack_clnt_cmds
+  typeset -gA _cache_openstack_clnt_cmds_opts
+  typeset -gA _cache_openstack_clnt_cmds_subcmds
+  typeset -gA _cache_openstack_clnt_cmds_subcmd_opts
+fi
+
+local -a conn_opts
+local opt arg word
+# Only openstack(1) requires parameters to provide completion info
+if [[ $service == openstack && -n ${words[(r)--os-*]} ]]; then
+  if (( ! $+_cache_openstack_conn_opts )); then
+    _cache_openstack_conn_opts=( ${(M)${=${(f)"$($service help 2>/dev/null)"}}:#--os-*} )
+  fi
+  # --os-tenant-id --os-tenant-name are deprecated but still widely used
+  for opt in ${=_cache_openstack_conn_opts} --os-tenant-id --os-tenant-name; do
+    arg=
+    for word in ${words:1}; do
+      [[ $word == $opt ]] && arg=$word && break
+    done
+    [[ -n $arg && -n ${arg##-*} ]] && conn_opts=( $conn_opts $opt $arg )
+  done
+fi
+
+# New style clients
+if [[ -n ${clnts_compl_new[(r)$service]} ]]; then
+  if [[ -z $_cache_openstack_clnt_cmds[$service] ]]; then
+    # Populate caches - clnt_outputs is command raw output used later
+    _cache_openstack_clnt_outputs[$service]=${:-"$($service ${(Q)conn_opts} complete 2>/dev/null)"}
+    _cache_openstack_clnt_opts[$service]=${${${${(M)${${${${=${(f)"$($service help 2>/dev/null)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.}%--os-}
+    _cache_openstack_clnt_cmds[$service]=${${${${_cache_openstack_clnt_outputs[$service]}/* cmds=\'}/\'*}/complete}
+  fi
+  local cmd subcmd
+  # Determine the command
+  for word in ${words:1}; do
+    local s=${_cache_openstack_clnt_cmds[$service]}
+    [[ $s[(wI)$word] -gt 0 ]] && cmd=$word && break
+  done
+  # Populate the subcommand cache
+  if [[ -n $cmd && -z $_cache_openstack_clnt_cmds_subcmds[$service$cmd] ]]; then
+      local t=cmds_${cmd//-/_}
+      _cache_openstack_clnt_cmds_subcmds[$service$cmd]=${${${_cache_openstack_clnt_outputs[$service]}/* $t=\'}/\'*}
+  fi
+  # Determine the subcommand
+  if [[ -n $cmd ]]; then
+    for word in ${words:2}; do
+      local s=${_cache_openstack_clnt_cmds_subcmds[$service$cmd]}
+      [[ $s[(wI)$word] -gt 0 ]] && subcmd=$word && break
+    done
+    # Populate subcommand option cache
+    if [[ -n $subcmd && -z $_cache_openstack_clnt_cmds_subcmd_opts[$service${cmd}--$subcmd] ]]; then
+      local t=cmds_${cmd//-/_}_${subcmd//-/_}
+      _cache_openstack_clnt_cmds_subcmd_opts[$service${cmd}--$subcmd]=${${${_cache_openstack_clnt_outputs[$service]}/* $t=\'}/\'*}
+    fi
+  fi
+  # Special treatment for the help command
+  if [[ $cmd == help ]]; then
+      if [[ $words[CURRENT-1] == $cmd && $words[CURRENT] != -* ]]; then
+        # Offer commands
+        [[ -n $_cache_openstack_clnt_cmds[$service] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0
+      elif [[ $words[CURRENT-2] == $cmd && $words[CURRENT-1] != -* && $words[CURRENT] != -* ]]; then
+        # Offer subcommands
+        local cmd=$words[CURRENT-1]
+        local t=cmds_${cmd//-/_}
+        [[ -z $_cache_openstack_clnt_cmds_subcmds[$service$cmd] ]] && _cache_openstack_clnt_cmds_subcmds[$service$cmd]=${${${_cache_openstack_clnt_outputs[$service]}/* $t=\'}/\'*}
+        [[ -n $_cache_openstack_clnt_cmds_subcmds[$service$cmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_subcmds[$service$cmd]} && ret=0
+      else
+        # Handle help<TAB> properly
+        _values -w option help && ret=0
+      fi
+  # Client options
+  elif [[ -z $cmd && $words[CURRENT] == -* ]]; then
+    _values -w option ${(u)=_cache_openstack_clnt_opts[$service]} && ret=0
+  # Commands
+  elif [[ -z $cmd ]]; then
+    if [[ -z $_cache_openstack_clnt_cmds[$service] ]]; then
+      _message "missing authentication options"
+    else
+      _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0
+    fi
+  # Subcommands
+  elif [[ -z $subcmd ]]; then
+    [[ -n $_cache_openstack_clnt_cmds_subcmds[$service$cmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_subcmds[$service$cmd]} && ret=0
+  # Subcommand options
+  else
+    { ! zstyle -T ":completion:${curcontext}:options" prefix-needed || [[ -prefix - ]] } && \
+      [[ -n $_cache_openstack_clnt_cmds_subcmd_opts[$service${cmd}--$subcmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_subcmd_opts[$service${cmd}--$subcmd]//\:/\\\:} && ret=0
+  fi
+
+# Old style clients
+elif [[ -n ${clnts_compl_old[(r)$service]} ]]; then
+  if [[ -z $_cache_openstack_clnt_cmds[$service] ]]; then
+    # Populate caches
+    _cache_openstack_clnt_opts[$service]=${${${(M)${${${${=${(f)"$($service help 2>/dev/null)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.}
+    _cache_openstack_clnt_cmds[$service]=${${(M)${=${(f)"$($service bash-completion 2>/dev/null)"}}:#[A-Za-z]*}/bash-completion}
+  fi
+  local cmd
+  # Determine the command
+  for word in ${words:1}; do
+    local s=${_cache_openstack_clnt_cmds[$service]}
+    [[ $s[(wI)$word] -gt 0 ]] && cmd=$word && break
+  done
+  # Populate command option cache
+  # Mostly no options for help, prevent consecutive calls with help here
+  if [[ -n $cmd && $cmd != help && -z $_cache_openstack_clnt_cmds_opts[$service$cmd] ]]; then
+    _cache_openstack_clnt_cmds_opts[$service$cmd]=${${${(M)${${${${=${(f)"$($service help $cmd 2>/dev/null)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.}
+  fi
+  # Special treatment for the help command
+  if [[ $cmd == help ]]; then
+      if [[ $words[CURRENT-1] == help && $words[CURRENT] != -* ]]; then
+        _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0
+      else
+        _values -w option help && ret=0
+      fi
+  # Client options
+  elif [[ -z $cmd && $words[CURRENT] == -* ]]; then
+    _values -w option ${(u)=_cache_openstack_clnt_opts[$service]} && ret=0
+  # Commands
+  elif [[ -z $cmd ]]; then
+    _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0
+  # Command options
+  else
+    { ! zstyle -T ":completion:${curcontext}:options" prefix-needed || [[ -prefix - ]] } && \
+      [[ -n $_cache_openstack_clnt_cmds_opts[$service$cmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_opts[$service$cmd]//\:/\\\:} && ret=0
+  fi
+
+# Swift like clients
+elif [[ -n ${clnts_swift_like[(r)$service]} ]]; then
+  if [[ -z $_cache_openstack_clnt_cmds[$service] ]]; then
+    # Populate caches - clnt_outputs is command raw output used later
+    _cache_openstack_clnt_outputs[$service]=${(f)"$($service --help 2>/dev/null)"}
+    _cache_openstack_clnt_opts[$service]=${${${${(M)${${${${=_cache_openstack_clnt_outputs[$service]}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.}/=*}
+    _cache_openstack_clnt_cmds[$service]=${=${(M)${(M)${(f)_cache_openstack_clnt_outputs[$service]}:#    [a-z]*}/ [A-Z]*}}
+  fi
+  local cmd
+  # Determine the command
+  for word in ${words:1}; do
+    local s=${_cache_openstack_clnt_cmds[$service]}
+    [[ $s[(wI)$word] -gt 0 ]] && cmd=$word && break
+  done
+  # Populate command option cache
+  if [[ -n $cmd && -z $_cache_openstack_clnt_cmds_opts[$service$cmd] ]]; then
+    _cache_openstack_clnt_cmds_opts[$service$cmd]=${${${(M)${${${${=${(f)"$($service $cmd --help 2>/dev/null)"}}/\[}/\]}/\;}:#-[-0-9A-Za-z]*}/,}/\.}
+  fi
+  # Client options
+  if [[ -z $cmd && $words[CURRENT] == -* ]]; then
+    _values -w option ${(u)=_cache_openstack_clnt_opts[$service]} && ret=0
+  # Commands
+  elif [[ -z $cmd ]]; then
+    _values -w option ${(u)=_cache_openstack_clnt_cmds[$service]} && ret=0
+  # Command options
+  else
+    { ! zstyle -T ":completion:${curcontext}:options" prefix-needed || [[ -prefix - ]] } && \
+      [[ -n $_cache_openstack_clnt_cmds_opts[$service$cmd] ]] && _values -w option ${(u)=_cache_openstack_clnt_cmds_opts[$service$cmd]//\:/\\\:} && ret=0
+  fi
+
+fi
+
+return ret
diff --git a/Completion/Unix/Command/_paste b/Completion/Unix/Command/_paste
new file mode 100644
index 000000000..6efe8eacb
--- /dev/null
+++ b/Completion/Unix/Command/_paste
@@ -0,0 +1,19 @@
+#compdef paste
+
+local -a args
+local dopt='[specify delimiter list]:delimiter list [tab]'
+local sopt='[paste one file at a time instead of in parallel]'
+
+if _pick_variant gnu=GNU unix --version; then
+  args=(
+    '(-z --zero-terminated)'{-z,--zero-terminated}'[use NUL as line delimiter instead of newline]'
+    "(-d)--delimiters=$dopt"
+    "(-s)--serial$sopt"
+    '(- *)--help[display help information]'
+    '(- *)--version[display version information]'
+  )
+else
+  args=( -A "-?*" )
+fi
+
+_arguments -s $args "(--delimiters)-d+$dopt" "(--serial)-s$sopt" '*:file:_files'
diff --git a/Completion/Unix/Command/_patch b/Completion/Unix/Command/_patch
index c0df00c00..c2725d46b 100644
--- a/Completion/Unix/Command/_patch
+++ b/Completion/Unix/Command/_patch
@@ -9,8 +9,7 @@ if (( ! $+_patch_args )); then
   [[ "$help" = *--[^h]* || "$help" = *\[-c\|-e\|-n\]* ]] && arg=+
 
   optionmap=(
-    '*\[-p\[strip-count\]\]*' '(--strip)-p-[number of path prefix components to strip]:number of path prefix components to strip:'"{$comp_p}"
-    '*( -p NUM[, ]|\[-p num\])*' '(--strip)-p+[number of path prefix components to strip]:number of path prefix components to strip:'"{$comp_p}"
+    '*( -p NUM[, ]|\[-p (num|strip-count)\])*' '(--strip)-p+[number of path prefix components to strip]:number of path prefix components to strip:'"{$comp_p}"
     '*\[--strip\[=strip-count\]\]*' '(-p)--strip=-[number of path prefix components to strip]:number of path prefix components to strip:'"{$comp_p}"
     '* --strip=NUM[, ]*' '(-p)--strip=[number of path prefix components to strip]:number of path prefix components to strip:'"{$comp_p}"
 
@@ -35,8 +34,8 @@ if (( ! $+_patch_args )); then
     '*(\[-[a-zA-Z]#R[a-zA-Z]#\]| -R[, ])*' '(--reverse)-R[reverse mode]'
     '*(\[--reverse\]| --reverse[, ])*' '(-R)--reverse[reverse mode]'
 
-    '*(\[-i patchfile\]| -i PATCHFILE[, ])*' '(--input)-i+[patch file]:patch file:_files'
-    '* --input=PATCHFILE[, ]*' '(-i)--input=[patch file]:patch file:_files'
+    '*(\[-i patchfile\]| -i PATCHFILE[, ])*' '*-i+[specify input patch file]:patch file:_files'
+    '* --input=PATCHFILE[, ]*' '*--input=[specify input patch file]:patch file:_files'
 
     '*(\[-o out-file\]| -o FILE[, ]|\[-o outfile\])*' "(--output)-o${arg}[output file]:output file:_files"
     '*(\[--output=out-file\]| --output=FILE[, ])*' '(-o)--output=[output file]:output file:_files'
@@ -46,6 +45,8 @@ if (( ! $+_patch_args )); then
     '*(\[-D symbol\]| -D NAME[, ]|\[-D define\])*' '(--ifdef)-D+[cpp symbol]:symbol:'
     '*(\[--ifdef=symbol\]| --ifdef=NAME[, ])*' '(-D)--ifdef=[cpp symbol]:symbol:'
 
+    '* --merge*' '(--reject-file --reject-format -r)--merge[merge using conflict markers instead of creating reject files]'
+
     '*(\[-[a-zA-Z]#E[a-zA-Z]#\]| -E[, ])*' '(--remove-empty-files)-E[remove empty files]'
     '*(\[--remove-empty-files\]| --remove-empty-files[, ])*' '(-E)--remove-empty-files[remove empty files]'
 
@@ -62,6 +63,7 @@ if (( ! $+_patch_args )); then
     '* --no-backup-if-mismatch[, ]*' '(--backup-if-mismatch)--no-backup-if-mismatch[back up only if otherwise requested]'
 
     '*(\[-V {numbered,existing,simple}\]| -V STYLE[, ])*' "(--version-control)-V${arg}[backup method]:backup method:(numbered existing simple)"
+    '*\[-V t \| nil \| never\]*' '(-B)-V+[specify backup method]:backup method:((t\:numbered nil\:existing never\:simple))'
     '*(\[--version-control={numbered,existing,simple}\]| --version-control=STYLE[, ])*' '(-V)--version-control=[backup method]:backup method:(numbered existing simple)'
 
     '*(\[-B backup-prefix\]| -B PREFIX[, ])*' "(--prefix)-B${arg}[specify backup prefix]:backup prefix:"
@@ -69,6 +71,7 @@ if (( ! $+_patch_args )); then
     '* -Y PREFIX[, ]*' '(--basename-prefix)-Y+[specify backup basename prefix]:backup basename prefix:'
     '* --basename-prefix=PREFIX[, ]*' '(-Y)--basename-prefix=[specify backup basename prefix]:backup basename prefix:'
     '*\[-b backup-ext\]*'                              "(   -z --suffix)-b${arg}[specify backup suffix]:backup suffix:(.bak)"
+    '*\[-z backup-ext\]*' '(--suffix)-z+[specify backup suffix]:backup suffix [.orig]:(.bak)'
     '* -z SUFFIX[, ]*'                                 '(-b    --suffix)-z+[specify backup suffix]:backup suffix:(.bak)'
     '*(\[--suffix=backup-ext\]| --suffix=SUFFIX[, ])*' '(-b -z         )--suffix=[specify backup suffix]:backup suffix:(.bak)'
 
@@ -90,24 +93,28 @@ if (( ! $+_patch_args )); then
     '*(\[--silent\]|--silent[, ])*'        '(-s --quiet         )--silent[silent mode]'
 
     '* --verbose[, ]*' '--verbose[verbose mode]'
-    '* --dry-run[, ]*' '--dry-run[don'\''t actually change files]'
-    '* --posix[, ]*' '--posix[POSIX mode]'
+
+    '*(\[-[a-zA-Z]#C[a-zA-Z]#\])*' '(--check)-C[only check that the patch would apply cleanly]'
+    '*\[--check\]*' '(-C)--check[only check that the patch would apply cleanly]'
+    '* --dry-run[, ]*' '--dry-run[only check that the patch would apply cleanly]'
+
+    '*--posix*' '--posix[POSIX mode]'
 
     '*(\[-d directory\]| -d DIR[, ]|\[-d dir\])*' '(--directory)-d+[change the working directory]:chdir to:_files -/'
     '*(\[--directory=directory\]| --directory=DIR[, ])*' '(-d)--directory=[change the working directory]:chdir to:_files -/'
 
+    '* --reject-format=*' '--reject-format=[specify format of rejects]:format:(context unified)'
+    '* --read-only=*' '--read-only=[specify how to handle read-only input files]:behaviour [warn]: (ignore warn fail)'
+
     '* --binary[, ]*' '--binary[binary mode]'
 
-    '*(\[-[a-zA-Z]#v[a-zA-Z]#\]| -v[, ])*' '(--version)-v[print version]'
-    '*(\[--version\]| --version[, ])*' '(-v)--version[print version]'
-    '* --help[, ]*' '--help[print help message]'
+    '*(\[-[a-zA-Z]#v[a-zA-Z]#\]| -v[, ])*' '(-)-v[print version]'
+    '*(\[--version\]| --version[, ])*' '(-)--version[print version]'
+    '* --help[, ]*' '(-)--help[print help message]'
 
     '*\[-[a-zA-Z]#S[a-zA-Z]#\]*' '*-S[ignore this patch]'
     '*\[--skip\]*' '*--skip[ignore this patch]'
 
-    '*(\[-[a-zA-Z]#C[a-zA-Z]#\])*' '(--check)-C[check only]'
-    '*\[--check\]*' '(-C)--check[check only]'
-
     '*\[--index-first\]*' '--index-first[take Index: line precedence]'
 
     '* --use-index-line *' '--use-index-line[deal with Index: line]'
diff --git a/Completion/Unix/Command/_patchutils b/Completion/Unix/Command/_patchutils
index 323c0a730..50ea3e4c4 100644
--- a/Completion/Unix/Command/_patchutils
+++ b/Completion/Unix/Command/_patchutils
@@ -43,6 +43,7 @@ case $service in
       '(-F --files)'{-F+,--files=}'[only list files within specified range]:range'
       '--strip=[remove specified number of pathname components before displaying]:components'
       '--addprefix=[insert specified path prefix before displaying path names]:prefix:_directories'
+      '*:diff file:_files'
     )
   ;|
   grepdiff|lsdiff)
@@ -58,7 +59,6 @@ case $service in
       \*{-v,--verbose}'[verbose operation]' 
       '(-H --with-filename -h --no-filename)'{-H,--with-filename}'[print the name of the patch file containing each patch]'
       '!--filter' '!--grep'
-      '*:diff file:_files'
     )
   ;;
   grepdiff|filterdiff)
@@ -71,7 +71,7 @@ case $service in
       '--as-numbered-lines=[display lines of selected hunks]:line numbers:(before after)'
       "--remove-timestamps[don't include timestamps in output]"
     )
-  ;;
+  ;|
   filterdiff)
     args+=(
       '(-X --exclude-from-file)'{-X+,--exclude-from-file=}'[exclude files matching any pattern listed in specified file]:file:_files'
diff --git a/Completion/Unix/Command/_pbm b/Completion/Unix/Command/_pbm
index 747aed3ce..62004f79e 100644
--- a/Completion/Unix/Command/_pbm
+++ b/Completion/Unix/Command/_pbm
@@ -698,7 +698,7 @@ ppmtoacad)
 ppmtobmp)
   _arguments \
     '(-windows)-os2' '(-os2)-windows' \
-    '-bpp[secify bits per pixel for BMP file]:bits per pixel:(1 4 8 24)' \
+    '-bpp[specify bits per pixel for BMP file]:bits per pixel:(1 4 8 24)' \
     ':file:_pbm'
   ;;
 
diff --git a/Completion/Unix/Command/_perforce b/Completion/Unix/Command/_perforce
index db91e11af..3cd99d519 100644
--- a/Completion/Unix/Command/_perforce
+++ b/Completion/Unix/Command/_perforce
@@ -3,7 +3,7 @@
 # Maintainer: Peter Stephenson <pws@csr.com>.
 
 # Increasingly loosely based on _cvs version 1.17.
-# Completions currently based on Perforce release 2010.2.
+# Completions currently based on Perforce release 2016.1.
 
 # Styles, tags and contexts
 # =========================
@@ -460,7 +460,7 @@ _perforce_call_p4() {
   # This is for our own use for parsing, and we need English output,
   # so...
   local +x P4LANGUAGE
-  _call_program $cp_tag p4 "${_perforce_global_options[@]}" "$@"
+  _call_program $cp_tag command p4 "${_perforce_global_options[@]}" "$@"
 }
 
 
@@ -1656,11 +1656,12 @@ _perforce_variables() {
 (( $+functions[_perforce_cmd_add] )) ||
 _perforce_cmd_add() {
   _arguments -s : \
-    '-c+[select by change]:change:_perforce_changes -tc' \
-    '-d[reopen removed file for add (downgrade)]' \
+    '-c[add files to change]:change:_perforce_changes -tc' \
+    '-d[reopen files for add]' \
     '-f[allow filenames with wild cards]' \
-    '-n[display operation without doing it]' \
-    '-t+[set file type]:file type:_perforce_filetypes' \
+    '-I[do not perform ignore checking]' \
+    '-n[preview add]' \
+    '-t[set file type]:file type:_perforce_filetypes' \
     '*:file:_perforce_files -tu'
 }
 
@@ -1682,15 +1683,15 @@ _perforce_cmd_admin() {
       shift words
       (( CURRENT-- ))
       _arguments -s : \
-	'-z[gzip journal file]' \
-	'1::journal file prefix: '
+        '-z[gzip journal file]' \
+        '1::journal file prefix: '
       ;;
 
       (dbstat)
       shift words
       (( CURRENT -- ))
       _arguments -s : \
-	'-s[show sizes]'
+        '-s[show sizes]'
     esac
   fi
 }
@@ -1701,11 +1702,17 @@ _perforce_cmd_annotate() {
   # New in release 2002.2.
   # -c was new in about 2003.2.
   _arguments -s : \
-    '-a[all, show both added and deleted lines]' \
-    '-c[output change numbers instead of revisions]' \
-    '-i[follow branches (integration records)]' \
-    '-I[follow integrations to get change numbers]' \
-    '-q[quiet, suppress one-line file header]' \
+    '-a[include deleted files and lines]' \
+    '-c[output change numbers]' \
+    '-d-[select whitespace option]:whitespace option:((
+b\:ignore\ whitespace\ changes
+w\:ignore\ whitespace
+l\:ignore\ line\ endings))' \
+    '-i[follow branches]' \
+    '-I[follow all integrations]' \
+    '-q[suppress one-line header]' \
+    '-t[display binary files]' \
+    '-u[output user and date]' \
     '*::file:_perforce_files -tR'
 }
 
@@ -1718,11 +1725,12 @@ _perforce_cmd_attribute() {
   # If -f is present, search unopened files, else don't
   [[ ${words[(I)-f]} -eq 0 ]] && limit=" -to"
   _arguments -s : \
-    '-e[value is in hex]' \
-    '-f[set the attribute on a submitted file]' \
-    '-n[set name of attribute]:attribute: ' \
-    '-p[propagate attribute when opened for edit etc.]' \
-    '-v[set value of attribute]:value: ' \
+    '-n[attribute name]:name: ' \
+    '-v[attribute value]:value: ' \
+    '-e[use hex value]' \
+    '-f[set attribute on submitted file]' \
+    '-p[propagate attribute when opened]' \
+    '(-v)-i[read attribute from standard input]' \
     "*::file:_perforce_files$limit"
 }
 
@@ -1730,10 +1738,12 @@ _perforce_cmd_attribute() {
 (( $+functions[_perforce_cmd_branch] )) ||
 _perforce_cmd_branch() {
   _arguments -s : \
-    '(-o)-f[force operation by superuser]' \
-    '(-o -i)-d[delete branch]' \
-    '(-d -i -f)-o[write specification to standard output]' \
-    '(-d -o)-i[read specification from standard input]' \
+    '(-o -S -P)-f[force operation]' \
+    '(-o -i -S -P)-d[delete branch]' \
+    '(-d -i -f)-o[write branch spec to standard output]' \
+    '(-d -o -S -P)-i[read branch spec from standard input]' \
+    '(-f -d -i)-S[expose internally generated mapping]:stream: ' \
+    '(-f -d -i)-P[treat stream as a child of parent stream]:parent stream: ' \
     '(-i)*::branch name:_perforce_branches'
 }
 
@@ -1741,9 +1751,11 @@ _perforce_cmd_branch() {
 (( $+functions[_perforce_cmd_branches] )) ||
 _perforce_cmd_branches() {
   _arguments -s : \
-    '-e[limit by wildcard]:wildcard on branches: ' \
-    '-u+[select by user]:user:_perforce_users' \
-    '-m+[set maximum to show]:max branches: '
+    '(-E)-e[list branches that match pattern]:pattern: ' \
+    '(-e)-E[list branches that match case-insensitive pattern]:case-insensitive pattern: ' \
+    '-u[list branches owned by user]:user:_perforce_users' \
+    '-m[limit output to max branches]:max branches: ' \
+    '-t[display time and date]'
 }
 
 
@@ -1761,14 +1773,18 @@ _perforce_cmd_change() {
     fi
   fi
   _arguments -s : \
-    '(-o)-f[allow force by superuser]' \
-    '-s[joblist includes the fix status]' \
-    '(-o -i)-d[discard newly created pending change]' \
-    '(-d -i -f)-o[output specification to standard output]' \
-    '(-d -o)-i[read specification from standard input]' \
-    '(-d -o)-u[force change of jobs or description by owner]' \
-    "(-i)1::change:_perforce_changes$ctype" \
-    '-t[specify visibility type]:visibility type:(public restricted)'
+    '-f[force update of change]' \
+    '-s[include fix status in job list]' \
+    '(-u -I -o -i -t -U)-d[delete change]' \
+    '(-u -d -o -i -t -U --serverid)-o[write change spec to the standard output]' \
+    '(-O -I -d -o -i -t -U --serverid)-i[read change spec from the standard input]' \
+    '(-s -d -o -i --serverid)-t[set type of change]:type:(public restricted)' \
+    '-U[set user of empty change]:user:_perforce_users' \
+    '-O[change is original number before submit]' \
+    '-I[change is number of Identity field]' \
+    '-u[force update of submitted change]' \
+    '(-s -u -O -I -o -i -t -U)--serverid[specify server]:server ID: ' \
+    "(-i)1::change:_perforce_changes$ctype"
 }
 
 
@@ -1782,13 +1798,15 @@ _perforce_cmd_changelist() {
 _perforce_cmd_changes() {
   _arguments -s : \
     '-i[include integrated changes]' \
-    '-t[output time as well as date]' \
-    '-l[long output, full change text]' \
-    '-L[long output, truncated change text]' \
-    '-c+[select by client]:client:_perforce_clients' \
-    '-m+[most recent N changes]:max changes: ' \
-    '-s+[select by status]:status:(pending shelved submitted)' \
-    '-u+[select by user]:user:_perforce_users' \
+    '-t[display time and date]' \
+    '-l[display full change text]' \
+    '-L[display truncated change text]' \
+    '-f[view restricted changes]' \
+    '-c[display changes submitted by client]:client:_perforce_clients' \
+    '-e[display changes above this change]:change:_perforce_changes' \
+    '-m[limit to max changes]:max changes: ' \
+    '-s[limit output to changes with status]:status:(pending shelved submitted)' \
+    '-u[display changes owned by user]:user:_perforce_users' \
     '*::file:_perforce_files -tR'
 }
 
@@ -1799,14 +1817,33 @@ _perforce_cmd_changelists() {
 }
 
 
+(( $+functions[_perforce_cmd_clean] )) ||
+_perforce_cmd_clean() {
+  _arguments -s : \
+    '-e[clean modified files]' \
+    '-a[clean added files]' \
+    '-d[clean deleted files]' \
+    '-I[do not perform ignore checking]' \
+    '-l[output relative paths]' \
+    '-n[preview clean]' \
+    '*:file:_perforce_files -tu'
+}
+
+
+
 (( $+functions[_perforce_cmd_client] )) ||
 _perforce_cmd_client() {
   _arguments -s : \
-    '(-o)-f[force modification by superuser]' \
-    '-t[use template]:template client:_perforce_clients' \
-    '(-o -i -t)-d[delete client]' \
-    '(-d -i -f)-o[print to standard output]' \
-    '(-d -o -t)-i[read from standard input]' \
+    '-f[force update of client]' \
+    '-Fs[force delete with shelved changes]' \
+    '(-t -o -S -c -s -i)-d[delete client]' \
+    '(-f -d -Fs -s -i --serverid)-o[write client spec to standard output]' \
+    '(-t -d -Fs -i --serverid)-S[create new client dedicated to stream]:stream: ' \
+    '(-d -Fs -o -c -i --serverid)-s[switch client view without opening editor]' \
+    '(-t -d -Fs -o -S -c -s --serverid)-i[read client spec from standard input]' \
+    '-t[use client as template]:client:_perforce_clients' \
+    '(-f -t -d -Fs -s -i --serverid)-c[yield client spec for stream at moment change was recorded]:change:_perforce_changes -ts' \
+    '--serverid[specify server]:server ID: ' \
     '1::file:_perforce_clients'
 }
 
@@ -1814,34 +1851,59 @@ _perforce_cmd_client() {
 (( $+functions[_perforce_cmd_clients] )) ||
 _perforce_cmd_clients() {
   _arguments -s : \
-    '-e[limit by wildcard]:wildcard on clients: ' \
-    '-u+[select by user]:user:_perforce_users' \
-    '-m+[set maximum to show]:max clients: '
+    '-t[display time and date]' \
+    '-u[list clients owned by user]:user:_perforce_users' \
+    '(-E)-e[list clients that match pattern]:pattern: ' \
+    '(-e)-E[list clients that match case-insensitive pattern]:case-insensitive pattern: ' \
+    '-m[limit to max clients]:max clients: ' \
+    '-S[limit output to clients dedicated to stream]:stream: ' \
+    '-U[list unloaded clients]' \
+    '(-s)-a[display all clients]' \
+    '(-a)-s[display clients dedicated to server]:server ID: '
 }
 
 
 (( $+functions[_perforce_cmd_copy] )) ||
 _perforce_cmd_copy() {
-  local range
-  # If -s is present, the first normal argument can't have revRange.
-  [[ ${words[(I)-s]} -eq 0 ]] && range=" -tR"
+  local -a fileargs
+  if [[ ${words[(I)-b*]} -ne 0 ]]; then
+    if [[ ${words[(I)-*s*]} -eq 0 ]]; then
+      # with -b and no -s, all files are to-files (but -s may come later)
+      fileargs=('*::to file:_perforce_files -tR')
+    else
+      # with -b and -s we have one from-file and any number of to-files
+      fileargs=('*::to file:_perforce_files')
+    fi
+  elif [[ ${words[(I)-(S|P)]} -ne 0 ]]; then
+      fileargs=('*::file:_perforce_files -tR')
+  else
+    # with no -b we have one from-file and one to-file
+    fileargs=('1::from file:_perforce_files -tR'
+              '2::to file:_perforce_files')
+  fi
   _arguments -s : \
-    '-b[select branch]:branch:_perforce_branches' \
-    '-c[select change for copy]:change:_perforce_changes -tc' \
-    '-n[no action, dummy run]' \
-    '-r[reverse direction of copy with branch]' \
-    '-s[select source with -b]:source file:_perforce_files -tR' \
-    '-v[leave newly copied files uncopied till sync]' \
-    "1:file:_perforce_files$range" \
-    '*::file:_perforce_files'
+    '-b[use branch view'\''s source and target]:branch:_perforce_branches' \
+    '-s[select source file, use branch view as target]:source file:_perforce_files -tR' \
+    '-r[reverse direction of copy]' \
+    '-c[open files in change]:change:_perforce_changes -tc' \
+    '-f[force creation of extra revisions]' \
+    '-n[preview copy]' \
+    '-m[limit copy to max files]:max files: ' \
+    '-q[suppress normal output messages]' \
+    '-v[do not modify client files]' \
+    '(-b -s)-S[copy from stream to its parent]:stream: ' \
+    '(-b -s)-P[generate branch view using a parent stream]:parent stream: ' \
+    '(-b -s)-F[copy against stream'\''s expected flow]' \
+    $fileargs
 }
 
 (( $+functions[_perforce_cmd_counter] )) ||
 _perforce_cmd_counter() {
   _arguments -s : \
     '-d[delete counter]' \
-    '-f[force setting of internal counter]' \
-    '-i[increment by one atomically]' \
+    '-f[set or delete internal counter]' \
+    '-i[increment counter by 1]' \
+    '-m[allow multiple operations]' \
     '1:counter:_perforce_counters' \
     '(-d -i)2::numeric value:_perforce_counter_values'
 }
@@ -1849,8 +1911,9 @@ _perforce_cmd_counter() {
 
 (( $+functions[_perforce_cmd_counters] )) ||
 _perforce_cmd_counters() {
-  # No arguments
-  _arguments -s :
+  _arguments -s : \
+    '-e[list counters that match pattern]:pattern: ' \
+    '-m[limit to max counters]:max counters: '
 }
 
 
@@ -1884,8 +1947,10 @@ _perforce_cmd_dbstat() {
 (( $+functions[_perforce_cmd_delete] )) ||
 _perforce_cmd_delete() {
   _arguments -s : \
-    '-c[select change for deletion]:change:_perforce_changes -tc' \
-    '-n[show deletions without doing them]' \
+    '-c[delete files for change]:change:_perforce_changes -tc' \
+    '-n[preview delete]' \
+    '-k[perform delete on server]' \
+    '-v[delete unsynced files]' \
     '*::file:_perforce_files'
 }
 
@@ -1893,9 +1958,11 @@ _perforce_cmd_delete() {
 (( $+functions[_perforce_cmd_depot] )) ||
 _perforce_cmd_depot() {
   _arguments -s : \
-    '-d[delete depot]' \
-    '-o[print to stdout]' \
-    '-i[read name from stdin]' \
+    '(-t -o -i)-d[delete depot]' \
+    '(-t -o -i)-f[force delete]' \
+    '(-d -o -i)-t[insert value into type]:type: ' \
+    '(-t -d -i -f)-o[write depot spec to standard output]' \
+    '(-t -d -o -f)-i[read depot spec from standard input]' \
     '(-i)*::depot name:_perforce_depots'
 }
 
@@ -1910,9 +1977,20 @@ _perforce_cmd_depots() {
 (( $+functions[_perforce_cmd_describe] )) ||
 _perforce_cmd_describe() {
   _arguments -s : \
-    '-d-[select diff option]:diff option:((b\:ignore\ blanks c\:context n\:RCS s\:summary u\:unified w\:ignore\ all\ whitespace))' \
-    '-s[short form]' \
-    '-S[show shelved changes]' \
+    '-d-[diff options]:diff options:((
+n\:RCS
+c\:context
+s\:summary
+u\:unified
+b\:ignore\ whitespace\ changes
+w\:ignore\ whitespace
+l\:ignore\ line\ endings))' \
+    '-s[omit diffs]' \
+    '-S[list shelved files]' \
+    '-f[force display of restricted change]' \
+    '-O[change is original number before submit]' \
+    '-I[change is number of Identity field]' \
+    '-m[limit output to max files]:max files: ' \
     '*::change:_perforce_changes'
 }
 
@@ -1920,17 +1998,27 @@ _perforce_cmd_describe() {
 (( $+functions[_perforce_cmd_diff] )) ||
 _perforce_cmd_diff() {
   local limit
-  [[ ${words[(I)-(f|sd|se)]} -eq 0 ]] && limit=" -to"
-  _arguments -s : \
-    '-d-[select diff option]:diff option:((b\:ignore\ blanks c\:context l\:ignore\ line\ endings n\:RCS s\:summary u\:unified w\:ignore\ all\ whitespace))' \
+  [[ ${words[(I)-(f|sd|se|sl)]} -eq 0 ]] && limit=" -to"
+  _arguments -s : \
+    '-d-[diff options]:diff options:((
+n\:RCS
+c\:context
+s\:summary
+u\:unified
+b\:ignore\ whitespace\ changes
+w\:ignore\ whitespace
+l\:ignore\ line\ endings))' \
     '-f[diff every file]' \
-    '-m+[set maximum files to show]:max files: ' \
-    '(-sd -se -sl -sr)-sa[opened files, different or missing]' \
-    '(-sa -se -sl -sr)-sd[unopened files, missing]' \
-    '(-sa -sd -sl -sr)-se[unopened files, different]' \
-    '(-sa -sd -se -sr)-sl[all unopened files with status]' \
-    '(-sa -sd -se -sl)-sr[opened files, same as depot]' \
-    '-t[include non-text files]' \
+    '-m[limit output to max files]:max files: ' \
+    '-Od[limit output to files that differ]' \
+    '-s-[filter options]:filter options:((
+a\:list\ opened\ files\ that\ differ\ from\ depot
+b\:list\ modified\ integrated\ files
+d\:list\ unopened\ missing\ files
+e\:list\ unopened\ files\ that\ differ\ from\ depot
+l\:list\ all\ unopened\ files\ with\ status
+r\:list\ opened\ files\ that\ do\ not\ differ\ from\ depot))' \
+    '-t[diff binary files]' \
     "*::file:_perforce_files$limit"
 }
 
@@ -1938,22 +2026,33 @@ _perforce_cmd_diff() {
 (( $+functions[_perforce_cmd_diff2] )) ||
 _perforce_cmd_diff2() {
   _arguments -s : \
-    '-b[specify branch view]:branch name:_perforce_branches' \
-    '-d-[select diff option]:diff option:((b\:ignore\ blanks c\:context n\:RCS s\:summary u\:unified w\:ignore\ all\ whitespace))' \
-    '-q[only list different files]' \
-    '-t[include non-text files]' \
-    '-u[use patch-friendly output]' \
-    '1::first file:_perforce_files' \
-    '2::second file:_perforce_files'
+    '-b[use branch view'\''s source and target]:branch:_perforce_branches' \
+    '-d-[diff options]:diff options:((
+n\:RCS
+c\:context
+s\:summary
+u\:unified
+b\:ignore\ whitespace\ changes
+w\:ignore\ whitespace
+l\:ignore\ line\ endings))' \
+    '-Od[limit output to files that differ]' \
+    '-q[omit identical files]' \
+    '-t[diff binary files]' \
+    '-u[use GNU diff -u format]' \
+    '(-b)-S[use generated branch view from stream]:stream: ' \
+    '(-b)-P[use generated branch view from parent stream]:parent stream: ' \
+    '1::from file:_perforce_files' \
+    '2::to file:_perforce_files'
 }
 
 
 (( $+functions[_perforce_cmd_dirs] )) ||
 _perforce_cmd_dirs() {
   _arguments -s : \
-    '-C[only dirs on current client]' \
-    '-D[include dirs with deleted files]' \
-    '-H[only dirs on the `have'\'' list]' \
+    '-C[list only directories in current client]' \
+    '-D[include directories with only deleted files]' \
+    '-H[list directories with synced files]' \
+    '-S[limit output to depot directories mapped to stream'\''s client]:stream: ' \
     '*::directory:_perforce_files -td'
 }
 
@@ -1961,10 +2060,10 @@ _perforce_cmd_dirs() {
 (( $+functions[_perforce_cmd_edit] )) ||
 _perforce_cmd_edit() {
   _arguments -s : \
-    '-c[set change for edit]:change:_perforce_changes -tc' \
-    '-k[no resync from server]' \
-    '-n[show files to edit without opening them]' \
-    '-t[set filetype]:filetype:_perforce_filetypes' \
+    '-c[edit files for change]:change:_perforce_changes -tc' \
+    '-t[specify filetype]:filetype:_perforce_filetypes' \
+    '-n[preview edit]' \
+    '-k[edit files on server]' \
     '*::file:_perforce_files'
 }
 
@@ -1986,14 +2085,15 @@ _perforce_cmd_export() {
 (( $+functions[_perforce_cmd_filelog] )) ||
 _perforce_cmd_filelog() {
   _arguments -s : \
-    '-c[select by changelist]:change:_perforce_changes -ts' \
-    '-h[follow branc/copy from records]' \
-    '-i[follow branches]' \
-    '-l[long output, full change text]' \
-    '-L[long output, truncated change text]' \
-    '-m[set maximum number of revisions to show]:max revisions: ' \
-    '-s[short output]' \
-    '-t[include time with date]' \
+    '-c[display files at change]:change:_perforce_changes -ts' \
+    '-i[include inherited file history]' \
+    '-h[display file content history]' \
+    '-t[display time and date]' \
+    '-l[display full change text]' \
+    '-L[display truncated change text]' \
+    '-m[display max number of revisions]:max revisions: ' \
+    '-p[do not follow content of promoted task streams]' \
+    '-s[display shortened form]' \
     '*::file:_perforce_files'
 }
 
@@ -2001,7 +2101,11 @@ _perforce_cmd_filelog() {
 (( $+functions[_perforce_cmd_files] )) ||
 _perforce_cmd_files() {
   _arguments -s : \
-    '-a[display all revisions in given range]' \
+    '-a[display all revisions in range]' \
+    '-A[display files in archive depots]' \
+    '-e[do not display deleted, purged or archived files]' \
+    '-m[limit output to max files]:max files: ' \
+    '-U[display files in unload depot]' \
     '*::file:_perforce_files -tR'
 }
 
@@ -2024,10 +2128,9 @@ _perforce_cmd_fix() {
   fi
 
   _arguments -s : \
-    '-d[delete the fix]' \
-    '-s[set job status]:status:_perforce_statuses' \
-    '1::-c required:(-c)' \
-    '2::change:_perforce_changes' \
+    '-d[delete fix]' \
+    '-s[set status]:status:_perforce_statuses' \
+    '-c[display jobs fixed by change]:change:_perforce_changes -ts' \
     "*::job:_perforce_jobs$job"
 }
 
@@ -2035,10 +2138,10 @@ _perforce_cmd_fix() {
 (( $+functions[_perforce_cmd_fixes] )) ||
 _perforce_cmd_fixes() {
   _arguments -s : \
+    '-j[list fixes for job]:job:_perforce_jobs' \
+    '-c[list fixes for change]:change:_perforce_changes -tR' \
     '-i[include integrated changes]' \
-    '-j[select by job]:job:_perforce_jobs' \
-    '-c[select by change]:change:_perforce_changes' \
-    '-m[set max fixes to show]:max fixes: ' \
+    '-m[limit output to max fixes]:max fixes: ' \
     '*::fixed file:_perforce_files -tR'
 }
 
@@ -2047,8 +2150,12 @@ _perforce_cmd_fixes() {
 _perforce_cmd_flush() {
   _arguments -s : \
     '-f[force resynchronisation]' \
-    '-k[bypass client file update]' \
-    '-n[show operations but don'\''t perform them]' \
+    '-L[use full depot syntax, including revision number]' \
+    '-n[preview flush]' \
+    '-N[preview flush with summary]' \
+    '-q[suppress normal output messages]' \
+    '-r[reopen moved files in new location]' \
+    '-m[limit sync to max files]:max files: ' \
     '*::file:_perforce_files -tR'
 }
 
@@ -2058,26 +2165,46 @@ _perforce_cmd_fstat() {
   local Oattr Aattr
   if [[ ${_perforce_cmd_list[(r)attribute:*]} != '' ]]; then
     # Unsupported feature, try not to show if not present
-    Oattr=' a\:show\ attributes d\:attributes\ digest e\:attributes\ in\ hex'
+    Oattr=' a\:output\ attributes d\:output\ digest e\:output\ values\ in\ hex'
     Aattr='-A[restrict attributes by pattern]:attribute pattern: '
   fi
   _arguments -s : \
-    '-c+[affected since change]:change:_perforce_changes -ts' \
-    '-e+[affected by change]:change:_perforce_changes -ts' \
-    '-C[select mapped files (-Rc)]' \
-    '-F[pick filter for files]:filter:_perforce_fstat_fields -tv' \
-    '-H[select synced files (-Rh)]' \
-    '-W[select opened files (-Ro)]' \
-    '-l[include fileSize, possibly slow (-Ol)]' \
-    '-m[set max files to show]:max files: ' \
-    "-O-[select output type]:output type:((f\:all\ revisions l\:fileSize p\:client\ path\ format r\:pending\ integrations s\:exclude\ local\ path$Oattr))" \
-    '-P[output clientFile in full Perforce syntax (deprecated: use -Op)]' \
-    '-r[show in reverse order]' \
-    '-R-[restrict selected files]:restriction:((c\:mapped\ in\ client h\:synced\ to\ client n\:not\ synced\ to\ head o\:opened r\:resolved s\:shelved u\:unresolved))' \
-    '-s[shorten, no client-related data (deprecated: use -Os)]' \
-    '-S-[changes sort order]:sort criterion:((t\:filetype d\:date r\:head\ revision h\:have\ revision s\:filesize))' \
-    '-T[select output fields]:output field:_perforce_fstat_fields' \
     $Aattr \
+    '-F[list only files satisfying filter]:filter:_perforce_fstat_fields -tv' \
+    '-L[use full depot syntax, including revision number]' \
+    '-T[return specified fields]:output field:_perforce_fstat_fields' \
+    '-m[limits output to max files]:max files: ' \
+    '-r[sort output in reverse order]' \
+    '-c[display files modified by or after change]:change:_perforce_changes -ts' \
+    '-e[list files modified by change]:change:_perforce_changes -ts' \
+    "-O-[output options]:output options:((
+f\:all\ revisions
+l\:fileSize\ and\ digest
+p\:local\ file\ path
+r\:pending\ integration
+s\:exclude\ local\ path
+$Oattr))" \
+    '-R-[restrict files]:file restrictions:((
+c\:mapped\ in\ client
+h\:synced\ to\ client
+n\:opened\ not\ at\ head\ revision
+o\:opened
+r\:resolved
+s\:shelved
+u\:unresolved))' \
+    '-S-[sort order]:sort by:((
+t\:filetype
+d\:date
+r\:head\ revision
+h\:have\ revision
+s\:filesize))' \
+    '-U[display info about unload files in unload depot]' \
+    '-C[limit output to mapped files (-Rc)]' \
+    '-H[limit output to synced files (-Rh)]' \
+    '-W[limit output to opened files (-Ro)]' \
+    '-l[output fileSize and digest (-Ol)]' \
+    '-P[output local file paths (-Op)]' \
+    '-s[exclude local file paths (-Os)]' \
     '*::file:_perforce_files'
 }
 
@@ -2085,22 +2212,21 @@ _perforce_cmd_fstat() {
 (( $+functions[_perforce_cmd_grep] )) ||
 _perforce_cmd_grep() {
   _arguments -s : \
+    '-e[search pattern]:pattern: ' \
     '-a[search all revisions]' \
     '-i[case insensitive match]' \
-    '-n[display matching line]' \
-    '-v[display file name]' \
-    '-F[interpret as fixed string]' \
-    '-G[interpret as regexp (default)]' \
-    '-L[list non-matching file/revisions]' \
-    '-l[list matching file/revisions]' \
-    '-s[suppresses errors on long lines]' \
-    '-t[treat all files as text]' \
-    '-A[]:trailing context lines: ' \
-    '-V[]:leading context lines: ' \
-    '-C[]:context lines: ' \
-    '1:-e required before pattern:(-e)' \
-    '2:pattern: ' \
-    '*::file:_perforce_files'
+    '-n[display matching line number]' \
+    '-v[display files with non-matching lines]' \
+    '-F[interpret pattern as fixed string]' \
+    '-G[interpret pattern as regexp]' \
+    '-L[display non-matching files]' \
+    '-l[display matching files]' \
+    '-s[suppress errors on long lines]' \
+    '-t[search binary files]' \
+    '-A[display N lines of trailing context]:lines: ' \
+    '-B[display N lines of leading context]:lines: ' \
+    '-C[display N lines of output context]:lines: ' \
+    '*::file:_perforce_files -tR'
 }
 
 
@@ -2108,9 +2234,10 @@ _perforce_cmd_grep() {
 _perforce_cmd_group() {
   _arguments -s : \
     '-d[delete group]' \
-    '-o[output to stdout]' \
-    '-i[read from stdin]' \
-    '(-o)-a[allow non-super owner to modify group]' \
+    '-o[write group spec to standard output]' \
+    '-i[read group spec from standard input]' \
+    '(-o -A)-a[allow owner to modify group]' \
+    '(-a -d)-A[allow admin user to add new group]' \
     '1::perforce group:_perforce_groups'
 }
 
@@ -2118,10 +2245,13 @@ _perforce_cmd_group() {
 (( $+functions[_perforce_cmd_groups] )) ||
 _perforce_cmd_groups() {
   _arguments -s : \
-    '-i[show indirect membership by subgroups]' \
-    '-m[set max groups to show]:max groups: ' \
-    '-v[show summary data]' \
-    '1::user or group name:_perforce_users_or_groups'
+    '-i[display indirect membership by subgroups]' \
+    '-m[limit output to max groups]:max groups: ' \
+    '-v[display group data]' \
+    '(-u -o)-g[display group with name]:group:_perforce_groups' \
+    '(-g -o)-u[display all groups for user]:user:_perforce_users' \
+    '(-g -u)-o[display all groups for owner]:owner:_perforce_users' \
+    '(-g -u -o)1::user or group name:_perforce_users_or_groups'
 }
 
 
@@ -2141,7 +2271,7 @@ _perforce_cmd_help() {
     _perforce_help_list=($_perforce_cmd_list)
     _perforce_call_p4 help help | while read -A hline; do
       if [[ $hline[1] = p4 && $hline[2] = help ]]; then
-	_perforce_help_list+=("$hline[3]:${hline[4,-1]}")
+        _perforce_help_list+=("$hline[3]:${hline[4,-1]}")
       fi
     done
     if [[ -z ${_perforce_help_list[(r)undoc:*]} ]]; then
@@ -2155,7 +2285,7 @@ _perforce_cmd_help() {
 (( $+functions[_perforce_cmd_info] )) ||
 _perforce_cmd_info() {
   _arguments -s : \
-    '-s[don'\''t check for unknown users or clients]'
+    '-s[short output]'
 }
 
 
@@ -2165,24 +2295,26 @@ _perforce_cmd_integrate() {
   # If -s is present, the first normal argument can't have revRange.
   [[ ${words[(I)-s]} -eq 0 ]] && range=" -tR"
   _arguments -s : \
-    '-b[select branch]:branch:_perforce_branches' \
-    '-c[select change for integration]:change:_perforce_changes -tc' \
-    '-f[force reintegration]' \
-    '-d[reintegrate deleted files]' \
-    '-D-[specify allowed deletions]:deletion type:((
-t\:rebranch\ on\ deleted\ file
-s\:delete\ modified\ target\ file
-i\:ignore\ readded\ source\ file
-))' \
-    '-h[integrate to revision had on client]' \
-    '-i[integrate if no common file base]' \
-    '-I[same as -i from 2004.2]' \
-    '-n[no action, dummy run]' \
-    '-o[display base file name for subsequent resolve]' \
-    '-r[reverse direction of integration with branch]' \
-    '-s[select source with -b]:source file:_perforce_files -tR' \
-    '-t[propagate type changes]' \
-    '-v[leave newly branched files uncopied till sync]' \
+    '-b[use branch view'\''s source and target]:branch:_perforce_branches' \
+    '(-r)-s[select source file, use branch view as target]:source file:_perforce_files -tR' \
+    '-f[force integration]' \
+    '-O-[output more information]:output options:((
+b\:show\ base\ revision\ for\ merge
+r\:show\ scheduled\ resolves))' \
+    '-R-[specify resolve schedule]:schedule:((
+b\:branch\ resolves
+d\:delete\ resolves
+s\:skip\ cherry-picked\ revisions\ already\ integrated))' \
+    '-Di[retain revisions of deleted files]' \
+    '-h[leave files at revision currently synced]' \
+    '-m[limit integration to max files]:max files: ' \
+    '-n[preview integration]' \
+    '-q[suppress normal output messages]' \
+    '-c[open in change]:change:_perforce_changes -tc' \
+    '-v[do not modify client files]' \
+    '-r[reverse direction of mapping]' \
+    '-S[use generated branch view from stream]:stream: ' \
+    '-P[use generated branch view from parent stream]:parent stream: ' \
     "1:file:_perforce_files$range" \
     '*::file:_perforce_files'
 }
@@ -2196,8 +2328,8 @@ _perforce_cmd_integ() {
 (( $+functions[_perforce_cmd_integrated] )) ||
 _perforce_cmd_integrated() {
   _arguments -s : \
-    '-r[reverse mapping in branch view with -b]' \
-    '-b[select files integrated via branch]:branch:_perforce_branches' \
+    '-r[reverse mapping in branch view]' \
+    '-b[list files integrated from branch view]:branch:_perforce_branches' \
     '*::file:_perforce_files -ti'
 }
 
@@ -2211,34 +2343,51 @@ _perforce_cmd_interchanges() {
   if [[ ${words[(I)-b*]} -ne 0 ]]; then
     if [[ ${words[(I)-*s*]} -eq 0 ]]; then
       # with -b and no -s, all files are to-files (but -s may come later)
-      fileargs=('-s[specify source file]'
-	        '*::to file:_perforce_files -tR')
+      fileargs=('*::to file:_perforce_files -tR')
     else
       # with -b and -s we have one from-file and any number of to-files
-      fileargs=('1::from file:_perforce_files -tR'
-	        '*::to file:_perforce_files')
+      fileargs=('*::to file:_perforce_files')
     fi
+  elif [[ ${words[(I)-(S|P)]} -ne 0 ]]; then
+      fileargs=('*::file:_perforce_files -tR')
   else
     # with no -b we have one from-file and one to-file
     fileargs=('1::from file:_perforce_files -tR'
               '2::to file:_perforce_files')
   fi
   _arguments -s : \
-    '-f[show individual files]' \
-    '-l[long changelist description]' \
-    '-b[select files integrated via branch]:branch:_perforce_branches' \
-    '-r[reverse branch mapping]' \
+    '-f[list files that require integration]' \
+    '-l[display full change text]' \
+    '-t[display time and date]' \
+    '(-S -P)-b[use branch view'\''s source and target]:branch:_perforce_branches' \
+    '(-S -P)-s[select source file, use branch view as target]:source file:_perforce_files -tR' \
+    '-u[limit files submitted by user]:user:_perforce_users' \
+    '-r[reverse mapping direction]' \
+    '-S[use generated branch view from stream]:stream: ' \
+    '-P[use generated branch view from parent stream]:parent stream: ' \
+    '-F[ignore stream'\''s expected flow]' \
     $fileargs
 }
 
 
+(( $+functions[_perforce_cmd_istat] )) ||
+_perforce_cmd_istat() {
+  _arguments -s : \
+    '-a[show status of integration in both directions]' \
+    '-c[assume cache is stale]' \
+    '-r[show status of integration from parent]' \
+    '-s[show cached state without refreshing stale data]' \
+    '1::stream: '
+}
+
+
 (( $+functions[_perforce_cmd_job] )) ||
 _perforce_cmd_job() {
   _arguments -s : \
     '(-d -o -i)-f[force setting of readonly fields]' \
     '(-f -o -i)-d[delete job]' \
-    '(-f -d -i)-o[print to stdout]' \
-    '(-d -o)-i[read from stdin]' \
+    '(-f -d -i)-o[write job spec to standard output]' \
+    '(-d -o)-i[read job spec from standard input]' \
     '(-i)1::job:_perforce_jobs'
 }
 
@@ -2246,12 +2395,12 @@ _perforce_cmd_job() {
 (( $+functions[_perforce_cmd_jobs] )) ||
 _perforce_cmd_jobs() {
   _arguments -s : \
-    '-e[select by jobview]:jobview:_perforce_jobviews' \
-    '-i[included integrated changes]' \
-    '-l[long output, full job descriptions]' \
-    '-r[reverse order of job names]' \
-    '-m[limit to most recent N jobs]:number of most recent jobs: ' \
-    '(-e -i -l -m)-R[rebuild jobs table on upgrade]' \
+    '-e[list jobs matching parameter]::_perforce_jobviews' \
+    '-i[include integrated changes]' \
+    '-l[display full job text]' \
+    '-m[limit output to max jobs]:max jobs: ' \
+    '-r[sort in reverse order]' \
+    '(-e -i -l -m)-R[rebuild jobs table]' \
     '*::file:_perforce_files -tR'
 }
 
@@ -2264,14 +2413,41 @@ _perforce_cmd_jobspec() {
 }
 
 
+(( $+functions[_perforce_cmd_key] )) ||
+_perforce_cmd_key() {
+  local -a keyargs
+  if [[ ${words[(I)-(d|i)]} -ne 0 ]]; then
+    keyargs=('1::name: ')
+  elif [[ ${words[(I)-m]} -ne 0 ]]; then
+    keyargs=('*::name value pairs: ')
+  else
+    keyargs=('1::name: ' '2::value: ')
+  fi
+  _arguments -s : \
+    '(-i -m)-d[delete key]' \
+    '(-d -m)-i[increment key value by 1]' \
+    '(-d -i)-m[allow mulitple operations]' \
+    $keyargs
+}
+
+
+(( $+functions[_perforce_cmd_keys] )) ||
+_perforce_cmd_keys() {
+  _arguments -s : \
+    '-e[list keys that match pattern]:pattern: ' \
+    '-m[limit output to max keys]:max keys: '
+}
+
+
 (( $+functions[_perforce_cmd_label] )) ||
 _perforce_cmd_label() {
   _arguments -s : \
     '-f[force operation]' \
-    '-t+[copy template]:template: ' \
+    '-t[copy view and options from label]:label:_perforce_labels' \
     '(-o -i -t)-d[delete label]' \
-    '(-d -f -i)-o[write to standard output]' \
-    '(-o -d -t)-i[read from standard input]' \
+    '(-d -f -i -g)-o[write label spec to standard output]' \
+    '(-o -d -t)-i[read label spec from standard input]' \
+    '-g[update global label]' \
     '*::label:_perforce_labels'
 }
 
@@ -2279,10 +2455,14 @@ _perforce_cmd_label() {
 (( $+functions[_perforce_cmd_labels] )) ||
 _perforce_cmd_labels() {
   _arguments -s : \
-    '-e[limit by wildcard]:label wildcard: ' \
-    '-m+[set maximum to show]:max labels: ' \
-    '-t[output time as well as date]' \
-    '-u+[select by user]:user:_perforce_users' \
+    '-t[display time and date]' \
+    '-u[list labels owned by user]:user:_perforce_users' \
+    '(-E)-e[list labels that match pattern]:pattern: ' \
+    '(-e)-E[list labels that match case-insensitive pattern]:case-insensitive pattern: ' \
+    '-m[limit output to max labels]:max labels: ' \
+    '(-s)-a[display all labels]' \
+    '(-a)-s[display labels from server]:server ID: ' \
+    '-U[list unloaded labels]' \
     '1::file or revisions which must contain label:_perforce_files -tR'
 }
 
@@ -2290,11 +2470,23 @@ _perforce_cmd_labels() {
 (( $+functions[_perforce_cmd_labelsync] )) ||
 _perforce_cmd_labelsync() {
   _arguments -s : \
+    '-l[specify label]:label:_perforce_labels' \
     '-a[add files to label]' \
     '-d[delete files from label]' \
-    '-n[no effect, dummy run]' \
-    '-l[specify label]:label:_perforce_labels' \
-    '-q[suppress informational messages]' \
+    '-n[preview labelsync]' \
+    '-q[suppress normal output messages]' \
+    '-g[update global label]' \
+    '*::file:_perforce_files -tR'
+}
+
+
+(( $+functions[_perforce_cmd_list] )) ||
+_perforce_cmd_list() {
+  _arguments -s : \
+    '-l[use temporary list name]:list name: ' \
+    '(-C)-d[delete list]' \
+    '-C[limit files to client]' \
+    '-M[forward list to master server]' \
     '*::file:_perforce_files -tR'
 }
 
@@ -2310,7 +2502,8 @@ _perforce_cmd_license() {
 (( $+functions[_perforce_cmd_lock] )) ||
 _perforce_cmd_lock() {
   _arguments -s : \
-    '-c[select by change]:change:_perforce_changes -tc' \
+    '-c[lock files for change]:change:_perforce_changes -tc' \
+    '-g[lock files globally]' \
     '*::file:_perforce_files -to'
 }
 
@@ -2324,8 +2517,8 @@ _perforce_cmd_lockstat() {
 (( $+functions[_perforce_cmd_logger] )) ||
 _perforce_cmd_logger() {
   _arguments -s : \
-    '-c[limit by counter no]:number: ' \
-    '-t[use counter instead of logger]:counter:_perforce_counters'
+    '-c[list events after sequence]:sequence: ' \
+    '-t[list events after counter]:counter:_perforce_counters'
 }
 
 
@@ -2333,9 +2526,11 @@ _perforce_cmd_logger() {
 (( $+functions[_perforce_cmd_login] )) ||
 _perforce_cmd_login() {
   _arguments -s : \
-    '-a[ticket valid on all machines]' \
+    '-a[issue ticket on all host machines]' \
+    '-h[issue ticket on host]:host: ' \
     '-p[display ticket, do not store]' \
-    '-s[show status of ticket]' \
+    '-r[forward login to server]:remote spec: ' \
+    '(-a -p -h)-s[display status of current ticket]' \
     '(-s)1::user:_perforce_users'
 }
 
@@ -2362,6 +2557,27 @@ _perforce_cmd_logtail() {
 }
 
 
+(( $+functions[_perforce_cmd_merge] )) ||
+_perforce_cmd_merge() {
+  local -a fileargs
+  if [[ ${words[(I)--from]} -ne 0 ]]; then
+    fileargs=('1:to file:_perforce_files -tR')
+  else
+    fileargs=('1:from file:_perforce_files -tR'
+              '2:to file:_perforce_files')
+  fi
+  _arguments -s : \
+    '-F[merge against stream'\''s expected flow]' \
+    '-Ob[show base revision for merge]' \
+    '-q[suppress normal output messages]' \
+    '--from[merge from stream other than the parent stream]:stream: ' \
+    '-m[limit merge to max files]:max files: ' \
+    '-n[preview merge]' \
+    '-c[open in change]:change:_perforce_changes -tc' \
+    $fileargs
+}
+
+
 (( $+functions[_perforce_cmd_monitor] )) ||
 _perforce_cmd_monitor() {
   if (( CURRENT > 2 )); then
@@ -2397,25 +2613,25 @@ _perforce_cmd_monitor() {
 (( $+functions[_perforce_cmd_move] )) ||
 _perforce_cmd_move() {
   _arguments -s : \
-    '-c[specify new change list]:change:_perforce_changes -tc' \
-    '-f[force move when already synced]' \
-    '-k[no resync from server]' \
+    '-c[reopen in change]:change:_perforce_changes -tc' \
+    '-f[force move]' \
     '-t[specify new file type]:filetype:_perforce_filetypes' \
-    '-n[show files to move without moving them]' \
-    '1::source file, wildcards allowed:_perforce_files -to' \
-    '2::destination file, wildcards match source:_perforce_files'
+    '-n[preview move]' \
+    '-k[perform move on server]' \
+    '1::from file:_perforce_files -to' \
+    '2::to file:_perforce_files -tu'
 }
 
 
 (( $+functions[_perforce_cmd_obliterate] )) ||
 _perforce_cmd_obliterate() {
     if [[ ${words[(I)-y]} -gt 0 ]]; then
-	_message \
+      _message \
 ": don't complete after -y; run obliterate without, then add the -y"
     else
-	_arguments -s : \
-	    '-y[actually perform the operation]' \
-	    '*::file:_perforce_files -tR'
+      _arguments -s : \
+        '-y[actually perform the operation]' \
+        '*::file:_perforce_files -tR'
     fi
 }
 
@@ -2427,11 +2643,14 @@ _perforce_cmd_opened() {
   # -tp, but currently Perforce doesn't allow that, so -tc is correct.
   # This is true even if -a is also given.
   _arguments -s : \
-    '-a[list for all clients]' \
-    '-c+[select by change]:change:_perforce_changes -tc' \
-    '-C[select by client]:client:_perforce_clients' \
-    '-m[max files to show]:max files: ' \
-    '-u[select by user]:user name:_perforce_users' \
+    '-a[list files for all clients]' \
+    '-c[list files opened in change]:change:_perforce_changes -tc' \
+    '-C[list files open in client]:client:_perforce_clients' \
+    '-u[list files opened by user]:user name:_perforce_users' \
+    '-m[limit output to max files]:max files: ' \
+    '-s[short output]' \
+    '-x[list exclusive files]' \
+    '-g[list files opened on Commit Server]' \
     '*::file:_perforce_files -to'
 }
 
@@ -2458,12 +2677,49 @@ _perforce_cmd_ping() {
 }
 
 
+(( $+functions[_perforce_cmd_populate] )) ||
+_perforce_cmd_populate() {
+  local -a fileargs
+  if [[ ${words[(I)-b*]} -ne 0 ]]; then
+    if [[ ${words[(I)-*s*]} -eq 0 ]]; then
+      # with -b and no -s, all files are to-files (but -s may come later)
+      fileargs=('*::to file:_perforce_files -tR')
+    else
+      # with -b and -s we have one from-file and any number of to-files
+      fileargs=('*::to file:_perforce_files')
+    fi
+  elif [[ ${words[(I)-(S|P)]} -ne 0 ]]; then
+      fileargs=('*::file:_perforce_files -tR')
+  else
+    # with no -b we have one from-file and one to-file
+    fileargs=('1::from file:_perforce_files -tR'
+              '2::to file:_perforce_files')
+  fi
+  _arguments -s : \
+    '(-S -P)-b[use branch view'\''s source and target]:branch:_perforce_branches' \
+    '(-S -P)-s[select source file, use branch view as target]:source file:_perforce_files -tR' \
+    '-r[reverse mapping direction]' \
+    '-S[use generated branch view from stream]:stream: ' \
+    '-P[use generated branch view from parent stream]:parent stream: ' \
+    '-d[description for submitted change]:description: ' \
+    '-f[force deleted files to branch into target]' \
+    '-n[preview populate]' \
+    '-o[display files created by populate]' \
+    '-m[limit max actions]:max actions: ' \
+    $fileargs
+}
+
+
 (( $+functions[_perforce_cmd_print] )) ||
 _perforce_cmd_print() {
   _arguments -s : \
-    '-a[display all revisions in a range]' \
-    '-o[select output file]:output file:_files' \
+    '-a[print all revisions in range]' \
+    '-A[print files in archive depots]' \
+    '-k[suppress keyword expansion]' \
+    '-o[redirect output to file]:file:_files' \
     '-q[suppress header]' \
+    '-m[limit max files]:max files: ' \
+    '-U[print files in unload depot]:unload file:_perforce_files' \
     '*::file:_perforce_files -tR'
 }
 
@@ -2471,23 +2727,31 @@ _perforce_cmd_print() {
 (( $+functions[_perforce_cmd_protect] )) ||
 _perforce_cmd_protect() {
   _arguments -s : \
-    '-o[write spec to stdout]' \
-    '-i[read spec from stdin]'
+    '-o[write protection table to standard output]' \
+    '-i[read protection table from standard input]'
 }
 
 
 (( $+functions[_perforce_cmd_protects] )) ||
 _perforce_cmd_protects() {
   _arguments -s : \
-    '(-g -u)-a[show for all users]' \
-    '(-a -u)-g[select by group]:perforce group:_perforce_groups' \
-    '(-a -g)-u[select by user]:perforce user:_perforce_users' \
-    '-h[limit to host]:host:_perforce_hosts' \
-    '-m[single word summary]' \
+    '(-g -u)-a[display protection lines for all users]' \
+    '(-a -u)-g[display protection lines for group]:perforce group:_perforce_groups' \
+    '(-a -g)-u[display protection lines for user]:perforce user:_perforce_users' \
+    '-h[display protection lines for host]:host:_perforce_hosts' \
+    '-m[report single word summary]' \
     '*:file:_perforce_files'
 }
 
 
+(( $+functions[_perforce_cmd_prune] )) ||
+_perforce_cmd_prune() {
+  _arguments -s : \
+    '-y[execute prune]' \
+    '-S[stream to prune]:stream: '
+}
+
+
 (( $+functions[_perforce_cmd_pull] )) ||
 _perforce_cmd_pull() {
   _arguments -s : \
@@ -2497,6 +2761,37 @@ _perforce_cmd_pull() {
     '-J[specify prefix for journal file]:journal file prefix: '
 }
 
+
+(( $+functions[_perforce_cmd_reconcile] )) ||
+_perforce_cmd_reconcile() {
+  _arguments -s : \
+    '-n[preview reconcile]' \
+    '-c[open files for change]:change:_perforce_changes -tc' \
+    '-e[open modified files for edit]' \
+    '-a[open new files for add]' \
+    '-d[open removed files for delete]' \
+    '-f[reformat filenames with wildcard characters]' \
+    '-I[do not perform ignore checking]' \
+    '-l[output relative paths]' \
+    '-m[check file modification times]' \
+    '-w[force client files to be updated to match depot]' \
+    '-k[reconcile have list with client]' \
+    '*:file:_perforce_files -tu'
+}
+
+
+(( $+functions[_perforce_cmd_rec] )) ||
+_perforce_cmd_rec() {
+  _perforce_cmd_reconcile "$@"
+}
+
+
+(( $+functions[_perforce_cmd_rename] )) ||
+_perforce_cmd_rename() {
+  _perforce_cmd_move "$@"
+}
+
+
 (( $+functions[_perforce_cmd_reopen] )) ||
 _perforce_cmd_reopen() {
   # Assume user doesn't want to reopen to same changelist.
@@ -2508,8 +2803,8 @@ _perforce_cmd_reopen() {
   fi
 
   _arguments -s : \
-    '-c+[select change to reopen on]:change:_perforce_changes -tc' \
-    '-t+[set file type]:file type:_perforce_filetypes' \
+    '-c[reopen files for change]:change:_perforce_changes -tc' \
+    '-t[specify new file type]:filetype:_perforce_filetypes' \
     '*::file:_perforce_files -to'
 }
 
@@ -2533,13 +2828,32 @@ _perforce_cmd_replicate() {
 (( $+functions[_perforce_cmd_resolve] )) ||
 _perforce_cmd_resolve() {
   _arguments -s : \
-    '-a-[select automatic merge type]:automation type:((f\:force\ acceptance m\:skip\ conflicts s\:safe t\:use\ theirs y\:use\ yours))' \
-    '-d-[select diff option]:diff option:((b\:ignore\ blanks w\:ignore\ all\ whitespace))' \
-    '-f[force re-resolution]' \
-    '-n[no action, just list]' \
+    '-A-[limit resolve attempts]:resolve attempts:((
+a\:resolve\ attributes
+b\:resolve\ file\ branching
+c\:resolve\ file\ content\ changes
+d\:resolve\ file\ deletions
+m\:resolve\ moved\ and\ renamed\ files
+t\:resolve\ filetype\ changes
+Q\:resolve\ charset\ changes
+))' \
+    '-a-[set automatic resolve]:resolve:((
+s\:skip\ files\ that\ need\ merging
+m\:skip\ files\ with\ conflicts
+f\:accept\ merged\ files\ with\ conflicts
+t\:use\ theirs
+y\:use\ yours))' \
+    '-d-[control whitespace merging]:whitespace option:((
+b\:ignore\ whitespace\ changes
+w\:ignore\ whitespace\ altogether
+l\:ignores\ line\ endings))' \
+    '-f[re-resolve files]' \
+    '-n[preview resolve]' \
+    '-N[preview resolve with summary]' \
     '-o[display base file name and revision for merge]' \
-    '-t[force textual merge on binary files]' \
-    '-v[verbose, mark all changes]' \
+    '-t[force textual merge]' \
+    '-v[insert markers for all changes]' \
+    '-c[limit resolve to change]:change:_perforce_changes -tc' \
     '*::file:_perforce_files -to'
 }
 
@@ -2555,10 +2869,12 @@ _perforce_cmd_resolved() {
 (( $+functions[_perforce_cmd_revert] )) ||
 _perforce_cmd_revert() {
   _arguments -s : \
-    '-a[revert unaltered files]' \
-    '-c[limit reversions to change]:change:_perforce_changes -tc' \
-    '-k[bypass client refresh]' \
-    '-n[no action, show effect only]' \
+    '-a[revert open unchanged files]' \
+    '-n[preview revert]' \
+    '-k[mark files as reverted on server]' \
+    '-w[delete new files]' \
+    '-c[revert files opened in change]:change:_perforce_changes -tc' \
+    '-C[specify client]:client:_perforce_clients' \
     '*::file:_perforce_files -to'
 }
 
@@ -2566,15 +2882,16 @@ _perforce_cmd_revert() {
 (( $+functions[_perforce_cmd_review] )) ||
 _perforce_cmd_review() {
   _arguments -s : \
-    '-c[select change for counter]:change:_perforce_changes -ts' \
-    '-t[limit change number by counter]:counter:_perforce_counters'
+    '-c[specify change]:change:_perforce_changes -ts' \
+    '-t[specify counter]:counter:_perforce_counters'
 }
 
 
 (( $+functions[_perforce_cmd_reviews] )) ||
 _perforce_cmd_reviews() {
   _arguments -s : \
-    '-c[show users by change]:change:_perforce_changes -ts' \
+    '-c[limit files submitted in change]:change:_perforce_changes -ts' \
+    '-C[limit files opened in client]:client:_perforce_clients' \
     '*::file:_perforce_files'
 }
 
@@ -2583,8 +2900,9 @@ _perforce_cmd_reviews() {
 _perforce_cmd_set() {
   # Only works under Windoze but maybe we are on Cygwin.
   _arguments -s : \
+    '-q[remove origin]' \
     '-s[set for whole system]' \
-    '-S[set for specified service]:service: ' \
+    '-S[specify service]:service: ' \
     "*::environment variable:_perforce_variables"
 }
 
@@ -2592,26 +2910,80 @@ _perforce_cmd_set() {
 (( $+functions[_perforce_cmd_shelve] )) ||
 _perforce_cmd_shelve() {
   _arguments -s : \
-    '(-i)-c[specify changelist if not default]:change:_perforce_changes -tc' \
-    '(-i -r)-d[delete shelved files]' \
-    '(-r)-f[force by admin user or force to overwrite]' \
-    '(-c)-i[read from standard input]' \
-    '(-d)-r[replace shelved files in changelist]' \
+    '-i[read change spec from standard input]' \
+    '(-i)-c[shelve files in change]:change:_perforce_changes -tc' \
+    '-f[overwrite existing shelved files]' \
+    '-r[replace shelved files in change]' \
+    '-a[handle unchanged files]:option:(submitunchanged leaveunchanged)' \
+    '(-p -a -i -r)-d[delete shelved files]' \
+    '-p[promote shelved change to commit server]' \
     '(-i -r)*::file:_perforce_files -to'
 }
 
 
+(( $+functions[_perforce_cmd_status] )) ||
+_perforce_cmd_status() {
+  _arguments -s : \
+    '-c[list files in change]:change:_perforce_changes -tc' \
+    '-A[list all new, modified, and removed files]' \
+    '-e[list modified files]' \
+    '-a[list new files]' \
+    '-d[list removed files]' \
+    '-f[reformat filenames with wildcard characters]' \
+    '-s[summarize output for new files]' \
+    '-I[do not perform ignore checking]' \
+    '-m[check file modification times]' \
+    '-k[reconcile have list with client]' \
+    '*:file:_perforce_files -tuo'
+}
+
+
 (( $+functions[_perforce_cmd_sizes] )) ||
 _perforce_cmd_sizes() {
   _arguments -s : \
-    '-a[show for all revisions]' \
-    '-b[set blocksize]:blocksize in bytes: ' \
+    '-a[list all revisions in range]' \
+    '-b[specify blocksize]:blocksize in bytes: ' \
+    '(-H)-h[print sizes in human-readable form (GiB)]' \
+    '(-h)-H[print sizes in human-readable form (GB)]' \
+    '-m[limit max files]:max files: ' \
     '-s[sum the file sizes]' \
-    '-S[show sizes of shelved files]' \
+    '-S[display sizes for shelved files]' \
+    '-z[omit lazy copies]' \
+    '(-z -S)-A[display files in archive depots]' \
+    '-U[display sizes for unload files]' \
     '*:file:_perforce_files -tR'
 }
 
 
+# TODO Add more logic for subcommands
+#p4 stream edit
+#p4 stream resolve [-a<flag>] [-n] [-o]
+#p4 stream revert
+(( $+functions[_perforce_cmd_stream] )) ||
+_perforce_cmd_stream() {
+  _arguments -s : \
+    '(-o -v)-d[delete stream]' \
+    '(-f)-o[write stream spec to standard output]' \
+    '(-o -v)-P[insert value into parent field]:parent stream: ' \
+    '(-o -v)-t[insert value into type field]:type: ' \
+    '(-o -v)-i[read stream spec from standard input]' \
+    '(-o -v)-f[force modification]' \
+    '(-f)-v[expose client view]' \
+    '1:stream name: '
+}
+
+
+(( $+functions[_perforce_cmd_streams] )) ||
+_perforce_cmd_streams() {
+  _arguments -s : \
+    '-F[limit files to pattern]:file pattern: ' \
+    '-T[limit fields to list]:field list: ' \
+    '-m[limit max streams]:max streams: ' \
+    '-U[list unloaded task streams]' \
+    '*:stream path: '
+}
+
+
 (( $+functions[_perforce_cmd_spec] )) ||
 _perforce_cmd_spec() {
   _arguments -s : \
@@ -2623,26 +2995,40 @@ label spec trigger typemap user)"
 }
 
 
+# TODO Figure out how --parallel will work
+#p4 submit -i [-r -s -f option] --parallel=threads=N[,batch=N][,min=N]
 (( $+functions[_perforce_cmd_submit] )) ||
 _perforce_cmd_submit() {
   _arguments -s : \
-    '-r[files open for add or edit remain open]' \
-    '-s[include fix status in list]' \
+    '(-s -d -e -i)-c[submit change]:change:_perforce_changes -tc' \
+    '(-r -s -f -d -c -i --noretransfer)-e[submit shelved change]:change:_perforce_changes -tS' \
+    '(-s -c -e -i --noretransfer)-d[specify description]:description: ' \
+    '(-d -c -e --noretransfer)-i[read change spec from standard input]' \
     '-f[override submit option]:submit option:_perforce_submit_options' \
-    '(-s -i)-c[submit specific change]:change:_perforce_changes -tc' \
-    '(-s -c)-d[specify description on command line]:description: ' \
-    '(-c)-i[read change spec from stdin]' \
+    '-r[reopen submitted files]' \
+    '(-d -c)-s[include fix status in list]' \
+    '--parallel[parallel file transfer options]:parallel options: ' \
+    '--noretransfer[do not re-transfer submitted files]:no re-transfer?:(0 1)' \
     '*::file:_perforce_files -to -tr'
 }
 
 
+# TODO Figure out how --parallel will work
+#--parallel=threads=N[,batch=N][,batchsize=N][,min=N][,minsize=N]
 (( $+functions[_perforce_cmd_sync] )) ||
 _perforce_cmd_sync() {
   _arguments -s : \
     '-f[force resynchronisation]' \
-    '-n[show operations but don'\''t perform them]' \
-    '-k[bypass client file update]' \
-    '-q[suppress informational messages]' \
+    '-L[use full depot syntax]' \
+    '-n[preview sync]' \
+    '-N[preview sync with summary]' \
+    '(-s -p)-k[update server without syncing files]' \
+    '(-f -k -r -s)-p[sync client without updating server]' \
+    '-q[suppress normal output messages]' \
+    '(-s -p)-r[reopen moved files in new location]' \
+    '(-f -k -r -p)-s[do not clobber modified files]' \
+    '-m[limit max files to sync]:max files: ' \
+    '--parallel[parallel file transfer options]:parallel options: ' \
     '*::file:_perforce_files -tR'
 }
 
@@ -2651,7 +3037,9 @@ _perforce_cmd_sync() {
 _perforce_cmd_tag() {
   _arguments -s : \
     '-d[delete association between label and files]' \
-    '-n[show what files would be tagged]' \
+    '-n[preview tag]' \
+    '-g[update global label]' \
+    '-U[create label with autoreload option]' \
     '-l[specify label]:label:_perforce_labels' \
     '*::file:_perforce_files -tR'
 }
@@ -2683,8 +3071,10 @@ _perforce_cmd_typemap() {
 (( $+functions[_perforce_cmd_unlock] )) ||
 _perforce_cmd_unlock() {
   _arguments -s : \
-    '-c[non-default change to unlock]:change:_perforce_changes -tc' \
-    '-f[allow superuser to unlock any file]' \
+    '-s[unlock files from shelved change]:change:_perforce_changes -tS' \
+    '-c[unlock files from change]:change:_perforce_changes -tc' \
+    '-x[unlock exclusive files]' \
+    '-f[unlock files owned by other users]' \
     '*::file:_perforce_files'
 }
 
@@ -2692,21 +3082,37 @@ _perforce_cmd_unlock() {
 (( $+functions[_perforce_cmd_unshelve] )) ||
 _perforce_cmd_unshelve() {
   _arguments -s : \
-    '-s[specify shelving change]:change:_perforce_changes -tS' \
-    '-c[specify change for unshelve]:change:_perforce_changes -tc' \
+    '-s[unshelve files from change]:change:_perforce_changes -tS' \
+    '-c[unshelve files to change]:change:_perforce_changes -tc' \
     '-f[force clobbering of writeable files]' \
     '-n[preview unshelve]' \
+    '-b[use branch view for unshelve]:branch:_perforce_branches' \
+    '-S[use generated branch view from stream]:stream: ' \
+    '-P[use generated branch view from parent stream]:parent stream: ' \
     '*::file, pattern allowed:_perforce_files'
 }
 
 
+(( $+functions[_perforce_cmd_update] )) ||
+_perforce_cmd_update() {
+  _arguments -s : \
+    '-f[force resynchronisation]' \
+    '-L[use full depot syntax]' \
+    '-n[preview update]' \
+    '-N[preview update with summary]' \
+    '-q[suppress normal output messages]' \
+    '-m[limit max files to update]:max files: ' \
+    '*::file:_perforce_files -tR'
+}
+
+
 (( $+functions[_perforce_cmd_user] )) ||
 _perforce_cmd_user() {
   _arguments -s : \
-    '(-o)-f[force edit by superuser]' \
     '(-o -i)-d[delete user]' \
-    '(-o -d)-i[read form from stdin]' \
-    '(-f -i -d)-o[write form to stdout]' \
+    '(-f -i -d)-o[write user spec to standard output]' \
+    '(-o -d)-i[read user spec from standard input]' \
+    '(-o)-f[force edit of user]' \
     '(-i)1::username:_perforce_users'
 }
 
@@ -2714,7 +3120,11 @@ _perforce_cmd_user() {
 (( $+functions[_perforce_cmd_users] )) ||
 _perforce_cmd_users() {
   _arguments -s : \
-    '-m[set max users to show]:max users: ' \
+    '-m[limit output to max users]:max users: ' \
+    '-a[output service and operator users]' \
+    '-l[long output]' \
+    '-r[list only replica users]' \
+    '-c[list only central server users]' \
     '*::username:_perforce_users'
 }
 
diff --git a/Completion/Unix/Command/_perl b/Completion/Unix/Command/_perl
index 52559b800..0914264fe 100644
--- a/Completion/Unix/Command/_perl
+++ b/Completion/Unix/Command/_perl
@@ -56,7 +56,7 @@ _perl_normal() {
 _perl_m_opt () {
   compset -P '-'
 
-  if compset -P '*='; then
+  if compset -P 1 '*='; then
     _message -e module-arguments 'module arguments, comma separated'
   else
     _perl_modules -S= -q
diff --git a/Completion/Unix/Command/_pgrep b/Completion/Unix/Command/_pgrep
index 0b7d23d4d..714bf095b 100644
--- a/Completion/Unix/Command/_pgrep
+++ b/Completion/Unix/Command/_pgrep
@@ -28,6 +28,7 @@ arguments=('-P[parent process id]:parent process id:->ppid'
      '-q[do not write anything to standard output]'
      '-S[search also in system processes]'
      '-v[negate matching]'
+     '-w[show thread ids instead of pids]'
      '-x[match exactly]'
      '-z[match only in zones]:zone:_zones')
 
@@ -41,7 +42,7 @@ fi
 local optchars
 case "$OSTYPE" in
   linux*)
-    optchars="cflvxdnoPgsuUGt"
+    optchars="cflvxdnoPgsuUGtw"
     ;;
   freebsd*)
     optchars="LSafilnoqvxFGMNPUdgjstu"
diff --git a/Completion/Unix/Command/_php b/Completion/Unix/Command/_php
index 0e840032f..d03f3395e 100644
--- a/Completion/Unix/Command/_php
+++ b/Completion/Unix/Command/_php
@@ -50,7 +50,7 @@ case $state in
     local -a directives suf
     local code='foreach (ini_get_all() as $k => $v) { echo "$k\n"; }'
     directives=( $(_call_program directives $words[1] -r ${(q)code} 2>/dev/null) )
-    if compset -P '*='; then
+    if compset -P 1 '*='; then
       _default && return 0
     else
       compset -S '=*' || suf=( -qS '=' )
diff --git a/Completion/Unix/Command/_picocom b/Completion/Unix/Command/_picocom
index c9d3be0e0..4b8b3ea2e 100644
--- a/Completion/Unix/Command/_picocom
+++ b/Completion/Unix/Command/_picocom
@@ -32,7 +32,7 @@ function _picocom_escape () {
 function _picocom () {
     local -a args
 
-    args=( '(--baud -b)'{--baud,-b}'[define baud-rate to set the terminal to]:baud rate:_baudrate'
+    args=( '(--baud -b)'{--baud,-b}'[define baud-rate to set the terminal to]:baud rate:_baudrates'
            '(--flow -f)'{--flow,-f}'[define type of flow control to use]:flow control:_picocom_flowcontrol'
            '(--parity -p)'{--parity,-p}'[define type of parity to use]:parity mode:_picocom_paritymode'
            '(--databits -d)'{--databits,-d}'[define the number of databits per word]:data bits:_picocom_databits'
diff --git a/Completion/Unix/Command/_pkg-config b/Completion/Unix/Command/_pkg-config
index e44b36897..43773967e 100644
--- a/Completion/Unix/Command/_pkg-config
+++ b/Completion/Unix/Command/_pkg-config
@@ -1,14 +1,17 @@
 #compdef pkg-config
 
-local arguments packages curcontext="$curcontext" state line ret=1
+local arguments packages curcontext="$curcontext" state line expl ret=1
 declare -A opt_args
 
+# Up-to-date as of pkg-config 0.29-4 (debian package) man page synopsis
 arguments=(
       "--modversion[print the version information of a given package]"
+      "--version[print version information of pkg-config itself]"
       "--atleast-pkgconfig-version=[require given version of pkg-config]:minimum version"
       "(- *)"{--help,-\?}"[display a help message]"
       "(- *)--usage[display brief usage message]"
       "--print-errors[cause errors to be printed]"
+      "--short-errors[print short error messages]"
       "--silence-errors[prevent the printing of errors]"
       "--errors-to-stdout[print errors to stdout rather than stderr]"
       "--cflags[print the preprocessor and compiler flags]"
@@ -19,25 +22,45 @@ arguments=(
       "--libs-only-L[print the -L and -R parts of \"--libs\"]"
       "--libs-only-l[print the -l part of \"--libs\"]"
       "--libs-only-other[output other libs]"
+      "--validate[syntax check a .pc file]"
       "--list-all[list all known packages]"
-      "--variable=[return the value of the specified variable]:variable"
+      "--variable=[return the value of the specified variable]:variable:->variable"
       "--define-variable=[set the global value for a variable]:name value pair"
+      "--print-variables[list all variables defined in the package]"
       "--uninstalled[return success if any \"-uninstalled\" packages are being used]"
       "--exists[test whether the package exists or not]"
       "--atleast-version=[test whether the version is at least that of the specified value]:least value"
       "--exact-version=[test whether the version is exactly that of the specified value]:exact value"
       "--max-version=[test whether the version is no greater than some specific value]:max version"
+      "--print-provides[list all modules the package provides]"
+      "--print-requires[list all modules the package requires]"
+      "--print-requires-private[list all modules the package requires for static linking (see --static)]"
 #      "--msvc-syntax[output linker flags in a form compatible with MSVC++ (Windows only)]"
 #      "--dont-define-prefix[disables automatic overiding of the variable \"prefix\" (Windows only)]"
 #      "--prefix-variable=[set the name of the variable \"prefix\" (Windows only)]:prefix value"
       "*: :->packages"
 )
 
-_arguments -C $arguments && ret=0
+_arguments -C -S : $arguments && ret=0
 
-if [[ -n $state ]] ; then
-  packages=( ${${(f)"$(_call_program packages pkg-config --list-all)"}%% *} )
-  _wanted packages expl 'package' compadd -a - packages && ret=0
-fi
+case $state in
+  (packages)
+    packages=( ${${(f)"$(_call_program packages pkg-config --list-all)"}%% *} )
+    _alternative \
+      'packages:package:compadd -a - packages' \
+      'files:package file:_files -g "*.pc(-.)"' \
+      && ret=0
+  ;;
+
+  (variable)
+    if [[ $line[1] != '-' ]]; then
+      local -a variables=( ${${(f)"$(_call_program variables "pkg-config --print-variables -- ${(q)line[1]}")"}} )
+      _wanted variables expl 'variable' compadd -a - variables && ret=0
+    else
+      _message "variable"
+    fi
+    ;;
+
+esac
 
 return ret
diff --git a/Completion/Unix/Command/_postfix b/Completion/Unix/Command/_postfix
index 0ced6c24a..006c950e3 100644
--- a/Completion/Unix/Command/_postfix
+++ b/Completion/Unix/Command/_postfix
@@ -1,20 +1,163 @@
-#compdef postsuper
+#compdef postconf postqueue postsuper
+
+# Last updated from postfix 3.1.0.
+
+local context state state_descr line
+typeset -A opt_args
+integer NORMARG
 
 _postfix_queue_id() {
-compadd ${${(M)${(f)"$(postqueue -p)"}:#(#s)([0-9A-F]##)*}/(#s)(#b)([0-9A-F]##)*/$match[1]}
+  local -a lines=( ${(f)"$(_call_program mailq 'mailq')"} )
+
+  # $enable_long_queue_ids = no
+  compadd "$@" -- ${${(M)lines:#(#s)([0-9A-F]##([*!]|) )*}/(#s)(#b)([0-9A-F]##)*/$match[1]}
+
+  # $enable_long_queue_ids = yes
+  compadd "$@" -- ${${${(M)lines:#(#s)[0-9bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ](#c10)z*}%% *}%[*!]}
+}
+
+# The first argument must be either 'd' or 'n', to complete parameters in
+# `postconf -d -H` or `postconf -n -H` output, respectively.
+_postfix_main_cf_parameter() {
+  local -a expl
+  local kind
+
+  kind=$1; shift
+  case $kind in
+    (d)
+      # Note for the future: if $mail_version >= 3.1, we can pass -H instead of
+      # stripping the = signs by hand.
+      #
+      # don't bother to add -c in this case: the defaults don't depend on the config dir.
+      _wanted parameters expl 'main.cf parameter' compadd "$@" -- \
+        ${${(f)"$(_call_program postconf_-d "${words[1]} -$kind")"}%% =*}
+      ;;
+    (n)
+      # Show the values too.
+      local -a kv=( ${${(f)"$(_call_program postconf_-n "${words[1]} ${opt_args[-c]+"-c ${opt_args[-c]}"} -$kind")"}/ = /:} )
+      _describe -t parameters 'main.cf parameter' kv
+      ;;
+    (*)
+      return 1 # can't happen due to the guard above
+      ;;
+  esac
+}
+
+_postfix_main_cf_parameter_and_value() {
+  # Note: be careful not to accidentally run 'postconf foo=bar' here.
+  #
+  # The '-P 1' syntax chooses the shortest match.  If the '1' were removed,
+  # completing «postconf foo=bar=<TAB>» would change main.cf.  So, don't remove
+  # it.
+  if compset -P 1 '*='; then
+    local value="`_call_program postconf-get-value-at-dir "${words[1]} ${opt_args[-c]+"-c ${opt_args[-c]}"} -h -- ${(q)IPREFIX%=}"`"
+    [[ -n $value ]] && compadd "$@" -- $value
+  else
+    _postfix_main_cf_parameter d -S=
+  fi
 }
 
 case $service in
 	(postsuper)
-	_arguments -C \
+	_arguments -C -s : \
 	'-p[purge old tempfiles]' \
 	'-s[structure check and repair]' \
-	'-v[verbose]' \
+	'*-v[verbose]' \
 	'-c[configdir]:config dir:_files -/' \
 	'-d[delete]:queue id:_postfix_queue_id' \
 	'-h[hold]:queue id:_postfix_queue_id' \
 	'-H[release]:queue id:_postfix_queue_id' \
-	'-r[requeue]:queue id:_postfix_queue_id' \
+	'*-r[requeue]:queue id, or "ALL":_postfix_queue_id' \
 	'1:queue:(hold incoming active deferred)'
 	;;
+        (postqueue)
+        _arguments -C -s : \
+          '*-v[enable verbose logging]' \
+          '-c[configdir]:config dir:_files -/' \
+          '(-f -i -j -p -s)-f[flush the queue]' \
+          '(-f -i -j -p -s)-i[immediately deliver one message]:queue id:_postfix_queue_id' \
+          '(-f -i -j -p -s)-j[print the queue in json]' \
+          '(-f -i -j -p -s)-p[print the queue in traditional format]' \
+          '(-f -i -j -p -s)-s[immediately deliver messages to specified site]:site:_hosts' 
+        ;;
+        (postconf)
+          local -a file_ops=(-b -t -a -A -l -m -T)
+          local -a modes=(-F -M -P $file_ops -p)
+          local -a only_for_p=(-C -d -h -n)
+          local -a only_for_asterisk_dot_cf=(-e -f -o -x)
+          local -a args=(
+              # global
+              '-c[configdir]:config dir:_files -/' \
+              '*-v[enable verbose logging]'
+
+              # mode selection
+              "($modes $only_for_p                              -X -#)"'-F[operate on master.cf entry fields]'
+              "($modes $only_for_p                           -H      )"'-M[operate on master.cf services entries]'
+              "($modes $only_for_p                                 -#)"'-P[operate on master.cf parameter settings]'
+              "($modes $only_for_p $only_for_asterisk_dot_cf -H -X -#)"'-b[display DSN text, expanded]'
+              "($modes $only_for_p $only_for_asterisk_dot_cf -H -X -#)"'-t[display DSN text, unexpanded]'
+              "($modes $only_for_p $only_for_asterisk_dot_cf -H -X -#)"'-a[list available SASL server plug-ins]'
+              "($modes $only_for_p $only_for_asterisk_dot_cf -H -X -#)"'-A[list available SASL client plug-ins]'
+              "($modes $only_for_p $only_for_asterisk_dot_cf -H -X -#)"'-l[list supported mailbox locking methods]'
+              "($modes $only_for_p $only_for_asterisk_dot_cf -H -X -#)"'-m[list supported lookup table types]'
+              "($modes                                               )"'-p[(default) print main.cf settings]'
+              "($modes $only_for_p $only_for_asterisk_dot_cf -H -X -#)"'-T[print TLS information]:mode:((
+                           compile-version\:"OpenSSL compile-time version"
+                           run-version\:"OpenSSL run-time version"
+                           public-key-algorithms\:"supported public-key algorithms"
+                           ))'
+
+              # other options; comments indicate modes:
+              # -p only
+              '-C[display parameters from the specified class]:parameter class:(builtin service user all)'
+              '-d[print default values]'
+              '-h[print value only]'
+              '-n[show parameters changed in main.cf]'
+
+              # all except $file_ops:
+              '-e[change parameter values]'
+              '-f[fold long output lines]'
+              '-o[set parameter value for this operation]: :_postfix_main_cf_parameter_and_value'
+              '-x[expand '\''$name'\'' in parameter values]'
+
+              # -p -F -P only
+              '-H[show parameter name only]'
+              # -p -M -P only
+              '-X[remove parameters from main.cf/master.cf]'
+              # -p -M only
+              '-#[comment out parameters in main.cf/master.cf]'
+
+              # $state
+              '*: :->positional'
+          )
+          _arguments -C -s -S -n : "$args[@]"
+
+          case $state in
+            (positional)
+              # Simulate the default
+              if [[ -z $opt_args[(i)${(j.|.)modes}] ]]; then
+                opt_args[-p]=""
+              fi
+              if [[ -n $opt_args[(i)(-b|-t)] ]]; then
+                local expl
+                if (( CURRENT == NORMARG )); then
+                  _wanted files expl 'template file, or "" for default' _files
+                else
+                  _nothing
+                fi
+              elif [[ -n $opt_args[(i)${(j.|.)file_ops}] ]]; then
+                _nothing
+              elif (( $+opt_args[-p] )); then
+                if (( $+opt_args[-e] )); then
+                  _postfix_main_cf_parameter_and_value
+                elif [[ -n $opt_args[(i)(-X|-[#])] ]]; then
+                  _postfix_main_cf_parameter n
+                else
+                  _postfix_main_cf_parameter d
+                fi
+              else # one of the master.cf modes: -M -F -P
+                _message "arguments for $opt_args[(i)${(j.|.)modes}] mode"
+              fi
+          esac
+        ;;
 esac
diff --git a/Completion/Unix/Command/_prove b/Completion/Unix/Command/_prove
index 1f21423e6..17b48a54d 100644
--- a/Completion/Unix/Command/_prove
+++ b/Completion/Unix/Command/_prove
@@ -7,7 +7,7 @@
 _arguments \
   '(- *)'{-h,--help}'[display help and exit]' \
   '(- *)'{-H,--man}'[display longer help and exit]' \
-  '(- *)--version[display version and exit]' \
+  '(- *)'{-V,--version}'[display version and exit]' \
   '(--quiet -q -Q --QUIET)'{-v,--verbose}'[print all test lines]' \
   {-l,--lib}'[add lib to path]' \
   {-b,--blib}'[add blib to path]' \
diff --git a/Completion/Unix/Command/_rake b/Completion/Unix/Command/_rake
index 7fed949ab..8814edaa5 100644
--- a/Completion/Unix/Command/_rake
+++ b/Completion/Unix/Command/_rake
@@ -22,7 +22,7 @@ _arguments -C -s -S \
   \*{--require,-r}'[require specified module before executing rakefile]:library:->library' \
   '(- *)--rules[trace the rules resolution]' \
   '(--quiet -q --silent -s --verbose -v)'{--silent,-s}"[like --quiet, but also suppresses the 'in directory' announcement]" \
-  '(--system,-g)'{--system,-g}'[using system wide (global) rakefiles (usually '~/.rake/*.rake')]' \
+  '(--system -g)'{--system,-g}'[using system wide (global) rakefiles (usually '~/.rake/*.rake')]' \
   '(- *)'{--tasks,-T}'[display the tasks (matching the specified pattern) with descriptions, then exit]:pattern::' \
   '(--trace -t)'{--trace,-t}'[turn on invoke/execute tracing, enable full backtrace]' \
   '(--quiet -q --silent -s --verbose -v)'{--verbose,-v}'[log message to standard output (default)]' \
diff --git a/Completion/Unix/Command/_rar b/Completion/Unix/Command/_rar
index e2081f6e7..906e236fd 100644
--- a/Completion/Unix/Command/_rar
+++ b/Completion/Unix/Command/_rar
@@ -22,7 +22,7 @@ common=(
   '-ow[save or restore file owner and group]'
   '-p+:password'
   '-p\-[do not query password]'
-  '-r[recurse subdirectorie]'
+  '-r[recurse subdirectories]'
   '-ta+[process files modified after a date]:date (YYYYMMDDHHMMSS)'
   '-tb+[process files modified before a date]:date (YYYYMMDDHHMMSS)'
   '-tn+[process files newer than a specified time]:time'
diff --git a/Completion/Unix/Command/_readelf b/Completion/Unix/Command/_readelf
index a474a8dc4..46da00cc4 100644
--- a/Completion/Unix/Command/_readelf
+++ b/Completion/Unix/Command/_readelf
@@ -34,6 +34,7 @@ case $variant in
       '(-g --section-groups)'{-g,--section-groups}'[show section groups]'
       '(-t --section-details)'{-t,--section-details}'[show section details]'
       '(-e --headers)'{-e,--headers}'[show file, program and sections headers]'
+      '(-s --syms --symbols)'{-s,--syms,--symbols}'[show symbol table]'
       '(-u --unwind)'{-u,--unwind}'[show unwind info (if present)]'
       '(-D --use-dynamic)'{-D,--use-dynamic}'[use dynamic section info when showing symbols]'
     )
@@ -51,6 +52,9 @@ case $variant in
       '--elf-section[used specified section as ELF input data]::section'
       '(-e --exception)'{-e,--exception}'[show sections for exception handling]'
       '(-N --numeric-addresses)'{-N,--numeric-addresses}"[don't find symbol names for addresses in DWARF data]"
+      '(-z --decompress)'{-z,--decompress}'[show compression information; decompress before dumping data]'
+      '(--symbols)-s[show symbol table]'
+      '(-s)--symbols=-[show symbol table]::section:(.dynsym .symtab)'
     )
   ;;
 esac
diff --git a/Completion/Unix/Command/_rlogin b/Completion/Unix/Command/_rlogin
index a04c6d068..685e4e50b 100644
--- a/Completion/Unix/Command/_rlogin
+++ b/Completion/Unix/Command/_rlogin
@@ -12,6 +12,7 @@ _rlogin () {
   rsh|remsh)
     local context state line ret=1
     typeset -A opt_args
+    local -a _comp_priv_prefix
 
     _arguments -s \
       '-n[ignore stdin]' \
@@ -37,9 +38,9 @@ _rlogin () {
       '*:files:->files' && ret=0
 
     if [[ -n "$state" ]]; then
-      if compset -P '*:'; then
+      if compset -P 1 '*:'; then
 	_remote_files -- rsh && ret=0
-      elif compset -P '*@'; then
+      elif compset -P 1 '*@'; then
         _wanted hosts expl host _rlogin_hosts -S: && ret=0
       else
         _alternative \
diff --git a/Completion/Unix/Command/_rm b/Completion/Unix/Command/_rm
index 4d0dbdb3f..6d728b157 100644
--- a/Completion/Unix/Command/_rm
+++ b/Completion/Unix/Command/_rm
@@ -22,16 +22,24 @@ if _pick_variant gnu=gnu unix --help; then
     '(- *)--version[output version information and exit]'
   )
 else
-  args=(${args:#*--(force|recursive)\[*})
+  args=(${args:#*)--*\[*})
   case $OSTYPE in
-    freebsd*)
+    dragonfly*|freebsd*|netbsd*|openbsd*)
       args+=(
         '-d[remove directories as well]'
-	'(-i)-I[prompt when removing many files]'
-	'-P[overwrite files before deleting them]'
-	'-v[explain what is being done]'
-	'-W[attempt to undelete named files]'
-	"-x[don't cross file systems when removing a hierarchy]"
+        '-P[overwrite files before deleting them]'
+      )
+    ;|
+    dragonfly*|freebsd*|netbsd*)
+      args+=(
+        '-v[explain what is being done]'
+        '-W[attempt to undelete named files]'
+        "-x[don't cross file systems when removing a hierarchy]"
+      )
+    ;|
+    dragonfly*|freebsd*)
+      args+=(
+        '(-i)-I[prompt when removing many files]'
       )
     ;;
   esac
diff --git a/Completion/Unix/Command/_rrdtool b/Completion/Unix/Command/_rrdtool
index 9d097bd77..96bdaf0db 100644
--- a/Completion/Unix/Command/_rrdtool
+++ b/Completion/Unix/Command/_rrdtool
@@ -1,23 +1,25 @@
 #compdef rrdtool
 
-_arguments \
+local curcontext="$curcontext" state line expl ret=1
+
+_arguments -C \
   ':rrdtool command:(create update updatev graph dump restore
                    last lastupdate first help info fetch tune
 		   resize xport)' \
-  '*::subcmd:->subcmd' && return 0
+  '*:: :->subcmds' && ret=0
 
+curcontext="${curcontext%:*}-$words[1]:"
 case "$state" in
-    (subcmd)
-
-  case "$words[1]" in
+  (subcmds)
+    case "$words[1]" in
       (help)
-      	_wanted -V 'subcommands' expl 'subcommand' compadd \
-	create update updatev graph dump restore last lastupdate \
-	first help info fetch tune resize xport
-	;;
+	_wanted -V 'subcommands' expl 'subcommand' compadd \
+	  create update updatev graph dump restore last lastupdate \
+	  first help info fetch tune resize xport
+      ;;
       (*)
-    	_files
-    	;;
-  esac
+        _files
+      ;;
+    esac
   ;;
 esac
diff --git a/Completion/Unix/Command/_rsync b/Completion/Unix/Command/_rsync
index 79d8243e1..f79ec1dfe 100644
--- a/Completion/Unix/Command/_rsync
+++ b/Completion/Unix/Command/_rsync
@@ -66,6 +66,20 @@ fi
 
 }
 
+_rsync_info() {
+  local opts
+  opts=( ${${(M)${(f)"$(_call_program values $words[1] --info=help)"}:#*Mention*}/ ##Me/[me} )
+  (( $#opts )) && opts=( '(ALL NONE HELP)'${^opts}\] )
+  _values -s , 'info options' $opts ALL NONE HELP
+}
+
+_rsync_debug() {
+  local opts
+  opts=( ${${(M)${(f)"$(_call_program values $words[1] --debug=help)"}:#*Debug*}/ ##De/[de} )
+  (( $#opts )) && opts=( '(ALL NONE HELP)'${^opts}\] )
+  _values -s , 'debug options' $opts ALL NONE HELP
+}
+
 _rsync_files() {
   _alternative "files:file:_files" "remote-files:remote file:_rsync_remote_files"
 }
@@ -78,6 +92,8 @@ _rsync() {
     '--outbuf=[set output buffering]:buffering:(none line block)' \
     '--port=[specify alternate port number]:port:(873)' \
     '--address=[bind to the specified address]:bind address:_bind_addresses' \
+    '--log-file-format=[log updates using specified format]:format' \
+    '--log-file=[log what rsync is doing to the specified file]:file:_files' \
     '(-T --temp-dir)'{-T,--temp-dir=}'[create temporary files in specified directory]:directory:_directories' \
     '--sockopts=[specify custom TCP options]' \
     '(-4 -6 --ipv4 --ipv6)'{-4,--ipv4}'[prefer IPv4]' \
@@ -87,6 +103,7 @@ _rsync() {
     '--config=[specify alternate rsyncd.conf file]:file:_files' \
     '--daemon[run as an rsync daemon]' \
     '--detach[detach from the parent]' \
+    '(-M --dparam)'{-M,--dparam=}'[override global daemon config parameter]:config parameter' \
     '--no-detach[do not detach from the parent]' \
    - client \
     '(-)--help[display help information]' \
@@ -205,15 +222,13 @@ _rsync() {
     '(-i --itemize-changes)'{-i,--itemize-changes}'[output a change-summary for all updates]' \
     '--log-format=[deprecated version of --out-format]' \
     '--out-format=[output updates using specified format]:format' \
-    '--log-file-format=[log updates using specified format]:format' \
-    '--log-file=[log what rsync is doing to the specified file]:file:_files' \
     '--password-file=[read daemon-access password from file]:file:_files' \
     '--list-only[list the files instead of copying them]' \
     '(--only-write-batch)--write-batch=[write a batched update to the specified file]:file:_files' \
     '(--write-batch)--only-write-batch=[like --write-batch but w/o updating destination]:file:_files' \
     '--protocol=[force an older protocol version to be used]:number' \
-    '--info=[fine-grained informational verbosity]:comma-separated list' \
-    '--debug=[fine-grained debug verbosity]:comma-separated list' \
+    '--info=[fine-grained informational verbosity]:info option:_rsync_info' \
+    '--debug=[fine-grained debug verbosity]:debug option:_rsync_debug' \
     '--msgs2stderr[special output handling for debugging]' \
     '--munge-links[munge symlinks to make them safer, but unusable]' \
     '--ignore-missing-args[ignore missing source args without error]' \
diff --git a/Completion/Unix/Command/_ruby b/Completion/Unix/Command/_ruby
index 49a1170ef..bb0558fde 100644
--- a/Completion/Unix/Command/_ruby
+++ b/Completion/Unix/Command/_ruby
@@ -35,11 +35,12 @@ opts=(
   '(-n)-p[assume loop like -n but print line also like sed]'
   '-s[enable some switch parsing for switches after script name]'
   '-S[look for the script using PATH environment variable]'
-  '-T-[turn on tainting checks]:taint level:((0\:strings\ from\ streams/environment/ARGV\ are\ tainted 1\:no\ dangerous\ operation\ by\ tainted\ value 2\:process/file\ operations\ prohibited 3\:all\ generated\ objects\ are\ tainted 4\:no\ global\ \(non-tainted\)\ variable\ modification/no\ direct\ output))'
+  '-T-[turn on tainting checks]::taint level [1]:((0\:strings\ from\ streams/environment/ARGV\ are\ tainted 1\:no\ dangerous\ operation\ by\ tainted\ value 2\:process/file\ operations\ prohibited 3\:all\ generated\ objects\ are\ tainted 4\:no\ global\ \(non-tainted\)\ variable\ modification/no\ direct\ output))'
   '(-v --verbose)'{-v,--verbose}'[print version number, then turn on verbose mode]'
   '-x-[strip off text before #!ruby line and perhaps cd to directory]:directory:_files -/'
   '(1 * -)--copyright[print the copyright]'
-  --{en,dis}able-{gems,rubyopt,all}
+  --{en,dis}'able=[enable or disable features]:feature:(gems did_you_mean rubyopt frozen_string_literal all)'
+  \!--{en,dis}able-{gems,rubyopt,all}
   --{external,internal}'-encoding=:charset:->charsets'
   '!'{-y,--yydebug}
   '!--dump=:target:(version copyright usage yydebug syntax parsetree parsetree_with_comment insns)'
@@ -113,7 +114,7 @@ case "$state" in
     charsets=( $(_call_program charsets $RUBY -e 'puts\ Encoding.list' 2>/dev/null) )
     # could also add Encoding.aliases.map(&:first) for aliases
     desc='charset'
-    if [[ $curcontext = *option-E-1 ]]; then
+    if [[ $curcontext = *option-(E|-encoding)-1 ]]; then
       if compset -P '*:'; then
 	desc='internal charset'
       else
diff --git a/Completion/Unix/Command/_screen b/Completion/Unix/Command/_screen
index f4d2ef943..ebc8ba155 100644
--- a/Completion/Unix/Command/_screen
+++ b/Completion/Unix/Command/_screen
@@ -99,7 +99,7 @@ if [[ -n $state ]]; then
       if (( CURRENT == 1 )) && [[ $PREFIX == /dev/* ]]; then
 	  _path_files -g '*(%)'
       elif (( CURRENT == 2 )) && [[ ${words[1]} == /dev/* ]]; then
-	  _baudrate
+	  _baudrates
       elif (( CURRENT > 2 )) && [[ ${words[1]} == /dev/* ]]; then
 	  _message "no more parameters"
       else
diff --git a/Completion/Unix/Command/_script b/Completion/Unix/Command/_script
new file mode 100644
index 000000000..7f682eaa2
--- /dev/null
+++ b/Completion/Unix/Command/_script
@@ -0,0 +1,71 @@
+#compdef script scriptreplay
+
+local args hlp="-h --help -V --version"
+
+if [[ $service = scriptreplay ]]; then
+  _arguments -S -s \
+    "(1 -t --timing $hlp)"{-t+,--timing=}'[specify file containing timing output]:timing file:_files' \
+    "(2 -s --typescript $hlp)"{-s+,--typescript=}'[specify file containing terminal output]:typescript file:_files' \
+    "(3 -d --divisor $hlp)"{-d+,--divisor=}'[speed up replay]:factor' \
+    "(-m --maxdelay $hlp)"{-m+,--maxdelay=}'[set maximum delay between updates]:delay (seconds)' \
+    '(- *)'{-h,--help}'[display help information]' \
+    '(- *)'{-V,--version}'[display version information]' \
+    "(-t --timing $hlp):timing file:_files" \
+    "(-s --typescript $hlp):typescript file:_files" \
+    "(-d --divisor $hlp): :_guard '[0-9.]#' 'timing divisor'"
+  return
+fi
+
+case $OSTYPE in
+  linux*)
+    args=( -S
+      "(-a --append $hlp)"{-a,--append}'[append output]'
+      "(-c --command $hlp)"{-c,--command=}'[run specified command instead of a shell]:command:_cmdstring'
+      "(-e --return $hlp)"{-e,--return}'[return exit status of the child process]'
+      "(-f --flush $hlp)"{-f,--flush}'[flush output after each write]'
+      "($hlp)--force[use output file even when it is a link]"
+      "(-q --quiet $hlp)"{-q,--quiet}'[be quiet]'
+      "(-t --timing $hlp)"{-t-,--timing=-}'[output timing data]::timing file:_files'
+      '(- 1)'{-h,--help}'[display help information]'
+      '(- 1)'{-V,--version}'[display version information]'
+    )
+  ;;
+  darwin*|dragonfly*|netbsd*|freebsd*)
+    args=(
+      '-q[be quiet: suppress display of starting and ending lines]'
+    )
+  ;|
+  netbsd*|freebsd*)
+    args+=(
+      '(-a -r -k)-d[suppress sleeps when playing back a session]'
+      '(-a -r -k -t)-p[play back a recorded session]'
+      '(-d -p)-r[record a session with input, output and timing data]'
+    )
+  ;|
+  netbsd*)
+    args+=(
+      '-f[flush output after each write]'
+      '-c[run specified command instead of a shell]:command:_cmdstring'
+    )
+  ;|
+  freebsd*)
+    args+=(
+      '-f[use filemon(4)]'
+    )
+  ;|
+  darwin*|dragonfly*|freebsd*)
+    args+=(
+      '-t+[specify interval of data flushing]:interval (seconds)'
+      '-k[log keys sent to the program as well as output]'
+      '*:::arguments: _normal'
+    )
+  ;|
+  *)
+    args+=(
+      '(-p -d)-a[append output]'
+    )
+  ;;
+esac
+
+_arguments -s $args \
+  "($hlp):typescript file:_files"
diff --git a/Completion/Unix/Command/_sed b/Completion/Unix/Command/_sed
index cc7a9631d..222798b8a 100644
--- a/Completion/Unix/Command/_sed
+++ b/Completion/Unix/Command/_sed
@@ -23,11 +23,13 @@ elif _pick_variant gnu=GNU unix --version; then
     '(-i --in-place)'{-i-,--in-place=-}$inplace
     '(-l --line-length)'{-l,--line-length=-}'[specify line-wrap length for the l command]'
     '(-r)--posix[disable GNU extensions]'
-    '(-r --regexp-extended)'{-r,--regexp-extended}$extended
+    '(-E -r --regexp-extended)'{-E,-r,--regexp-extended}$extended
     '(-s --separate)'{-s,--separate}'[consider files separately instead of as a combined stream]'
+    '--sandbox[block commands that can affect the system (r/w/W/e)]'
     '(-u --unbuffered)'{-u,--unbuffered}'[disable data buffering]'
+    '(-z --null-data)'{-z,--null-data}'[separate lines by NUL characters]'
     '(- 1 :)--help[print program usage]'
-    '(- 1 :)'{-V,--version}'[print program version]'
+    '(- 1 :)--version[print program version]'
   )
 else
   args=( "${(@)args:#(|\(*\))(|\*)--*}" )
diff --git a/Completion/Unix/Command/_service b/Completion/Unix/Command/_service
index e99ad556f..50e8607bf 100644
--- a/Completion/Unix/Command/_service
+++ b/Completion/Unix/Command/_service
@@ -5,27 +5,34 @@
 # _sub_command happy
 
 # we are interested in init service only
-local ctx="${curcontext}argument-1:"
+local args ctx="${curcontext}argument-1:"
 zstyle -T  ":completion:${ctx}" tag-order && \
   zstyle ":completion:${ctx}" tag-order init
 
-
-if [[ $OSTYPE = freebsd* ]]; then
-  _arguments -s \
-    '(-)-e[show services that are enabled]' \
-    '(-)-l[list all scripts in /etc/rc.d and the local startup directory]' \
-    '(-)-r[show the results of boot time rcorder]' \
-    '(-)-v[verbose]' \
-    ':service name:_services' \
-    '*::service argument:_init_d'
-else
-  _arguments -s \
-    '(-d --debug)'{-d,--debug}'[turn debugging on]' \
-    '(- :)'{-h,--help}'[print usage]' \
-    '(- :)'{-v,--version}'[print version]' \
-    '(-)'{-f,--full-restart}'[restart service]' \
-    '(- :)'{-R,--full-restart-all}'[restart all services]' \
-    '(- :)'{-s,--status-all}'[print status of all services]' \
-    ':service name:_services' \
-    '*::service argument: _init_d'
-fi
+case $OSTYPE in
+  freebsd*|dragonfly*)
+    args=(
+      '(-)-r[show the results of boot time rcorder]'
+      '(-)-R[restart all enabled local services]'
+    )
+  ;&
+  netbsd*)
+    _arguments -s $args \
+      '(-)-e[show services that are enabled]' \
+      '(-)-l[list all scripts in /etc/rc.d and the local startup directory]' \
+      '(-e -R)-v[verbose]' \
+      ':service name:_services' \
+      '*::service argument:_init_d'
+  ;;
+  *)
+    _arguments -s \
+      '(-d --debug)'{-d,--debug}'[turn debugging on]' \
+      '(- :)'{-h,--help}'[print help information]' \
+      '(- :)'{-v,--version}'[print version information]' \
+      '(-)'{-f,--full-restart}'[restart service]' \
+      '(- :)'{-R,--full-restart-all}'[restart all services]' \
+      '(- :)'{-s,--status-all}'[print status of all services]' \
+      ':service name:_services' \
+      '*::service argument: _init_d'
+  ;;
+esac
diff --git a/Completion/Unix/Command/_sisu b/Completion/Unix/Command/_sisu
index 6ca2abfaa..0250581cf 100644
--- a/Completion/Unix/Command/_sisu
+++ b/Completion/Unix/Command/_sisu
@@ -23,7 +23,7 @@ _arguments -s -C -M 'r:|[_-]=* r:|=*' \
   '(--convert --to -C)-I[texinfo output, not maintained]' \
   '(--convert --to -C)-L[print license info]' \
   '(--convert --to -C)-M[maintenance mode, retain intermediate processing files]' \
-  '(--convert --to -C)-m[create intermediate markup file, metaverse, assumed for most output instuctions]' \
+  '(--convert --to -C)-m[create intermediate markup file, metaverse, assumed for most output instructions]' \
   '(--convert --to -C)-N[document content certificate, output document digests]' \
   '(--convert --to -C)-n[skip intermediate markup, skip -m]' \
   '(--convert --to -C)-o[Open Document text format output]' \
diff --git a/Completion/Unix/Command/_sort b/Completion/Unix/Command/_sort
index 1ad57f442..91e9132ad 100644
--- a/Completion/Unix/Command/_sort
+++ b/Completion/Unix/Command/_sort
@@ -4,8 +4,8 @@ local args variant
 local ordering='(-d --dictionary-order -g --general-numeric-sort -M --month-sort -h --human-numeric-sort -n --numeric-sort --sort -V --version-sort --help --version)'
 
 args=(
-  '(-c --check -C)-c[check whether input is sorted; do not sort]'
-  '(-m --merge)'{-m,--merge}'[merge already sorted files; do not sort]'
+  "(-c --check -C)-c[check whether input is sorted; don't sort]"
+  '(-m --merge)'{-m,--merge}"[merge already sorted files; don't sort]"
   '(-o --output)'{-o+,--output=}'[write result to file instead of standard output]:output file:_files'
   \*{-T+,--temporary-directory=}'[specify directory for temporary files]:directory:_directories'
   '(-u --unique)'{-u,--unique}'[with -c, check for strict ordering; without -c, output only the first of an equal run]'
@@ -26,15 +26,19 @@ case $variant in
       '(-s --stable)'{-s,--stable}'[preserve original order of lines with the same key]'
     )
   ;|
+  openbsd*|freebsd*|gnu|solaris2.<11->)
+    args+=(
+      "(-c --check -C)-C[check whether input is sorted silently; don't sort]"
+    )
+  ;|
   openbsd*|freebsd*|gnu)
     args+=(
-      '(-c --check -C)-C[check whether input is sorted; do not sort]'
       '(-z --zero-terminated)'{-z,--zero-terminated}'[end lines with 0 byte, not newline]'
     )
   ;|
   freebsd*|gnu)
     args+=(
-      '(-c --check -C)--check=-[check whether input is sorted; do not sort]::bad line handling:(diagnose-first silent quiet)'
+      "(-c --check -C)--check=-[check whether input is sorted; don't sort]::bad line handling:(diagnose-first silent quiet)"
       "$ordering"{-g,--general-numeric-sort}'[compare according to general numeric value]'
       "$ordering"{-M,--month-sort}"[compare (unknown) < 'JAN' < ... < 'DEC']"
       "$ordering"{-h,--human-numeric-sort}'[compare human readable numbers (e.g., 2K 1G)]'
@@ -46,7 +50,7 @@ case $variant in
       '--batch-size=[maximum inputs to merge]:number'
       '--compress-program=[specify program to compress temporary files with]:program:(gzip bzip2 lzop xz)'
       '--debug[annotate the of the line used to sort]'
-      '--files0-from=[read input files from file]:file:_files'
+      '(*)--files0-from=[read input files from file]:file:_files'
       '(-S --buffer-size)'{-S+,--buffer-size=}'[specify size for main memory buffer]:size'
       '(- *)--help[display help and exit]'
       '(- *)--version[output version information and exit]'
diff --git a/Completion/Unix/Command/_sqsh b/Completion/Unix/Command/_sqsh
index f41ab5bf8..5caf7f981 100644
--- a/Completion/Unix/Command/_sqsh
+++ b/Completion/Unix/Command/_sqsh
@@ -17,7 +17,7 @@ _sybase_server() {
 _arguments : \
     '-A[adjust TDS packet size (512)]:packet size (bytes):(512 1024 1536 2048)' \
     '-B[turn off file buffering on startup]' \
-    '-C[send sql statment to server]:sql' \
+    '-C[send sql statement to server]:sql' \
     '-D[change database context on startup]:database' \
     '-E[replace default editor (vi)]:editor' \
     '-H[set the client hostname]:reported hostname' \
diff --git a/Completion/Unix/Command/_ssh b/Completion/Unix/Command/_ssh
index 1f8f62cac..28d2c38e7 100644
--- a/Completion/Unix/Command/_ssh
+++ b/Completion/Unix/Command/_ssh
@@ -1,12 +1,10 @@
 #compdef ssh slogin=ssh scp ssh-add ssh-agent ssh-keygen sftp ssh-copy-id
 
-# Completions currently based on OpenSSH 7.0 (released on 2015-08-11).
-#
-# TODO: update ssh-keygen (not based on 5.9)
 # TODO: sshd, ssh-keyscan, ssh-keysign
 
 _ssh () {
-  local curcontext="$curcontext" state line expl common tmp cmds suf ret=1
+  local curcontext="$curcontext" state line expl suf ret=1
+  local args common tmp p1 file cmn cmds sdesc
   typeset -A opt_args
 
   common=(
@@ -44,6 +42,7 @@ _ssh () {
       '-g[allow remote hosts to connect to local forwarded ports]' \
       '-G[output configuration and exit]' \
       '-I+[specify smartcard device]:device:_files' \
+      '-J+[connect via a jump host]: :->userhost' \
       '-K[enable GSSAPI-based authentication and forwarding]' \
       '-k[disable forwarding of GSSAPI credentials]' \
       '*-L[specify local port forwarding]:local port forwarding:->forward' \
@@ -84,11 +83,12 @@ _ssh () {
       '-c[identity is subject to confirmation via SSH_ASKPASS]' \
       '-D[delete all identities]' \
       '-d[remove identity]' \
-      '-e[remove keys provided by the PKCS#11 shared library]:library:' \
+      '-E[specify hash algorithm for fingerprints]:algorithm:(md5 sha256)' \
+      '-e[remove keys provided by the PKCS#11 shared library]:library:_files -g "*.(so|dylib)(|.<->)(-.)"' \
       '-k[load plain private keys only and skip certificates]' \
       '-L[lists public key parameters of all identities in the agent]'\
       '-l[list all identities]' \
-      '-s[add keys provided by the PKCS#11 shared library]:library:' \
+      '-s[add keys provided by the PKCS#11 shared library]:library:_files -g "*.(so|dylib)(|.<->)(-.)"' \
       '-t[set maximum lifetime for identity]:maximum lifetime (in seconds or time format):' \
       '-X[unlock the agent]' \
       '-x[lock the agent with a password]' \
@@ -107,32 +107,83 @@ _ssh () {
     return
     ;;
   ssh-keygen)
-    cmds=( -p -i -e -y -c -l -B -D -U )
-    _arguments -s \
-      '-q[silence ssh-keygen]' \
-      "($cmds -P)-b[specify number of bits in key]:bits in key" \
-      "($cmds -P)-t[specify the type of the key to create]:key type:(rsa1 rsa dsa ecdsa ed25519)" \
-      "(${cmds#-p })-N[provide new passphrase]:new passphrase" \
-      "($cmds -b -t)-C[provide new comment]:new comment" \
-      '(-D)-f[key file]:key file:_files' \
-      '('${(j. .)cmds:#-[pc]}' -t -b)-P[provide old passphrase]:old passphrase' \
-      "($cmds -q -b -t -C)-p[change passphrase of private key file]" \
-      "($cmds -q -b -t -N -C -P)-i[import key to OpenSSH format]" \
-      "($cmds -q -b -t -N -C -P)-e[export key to SECSH file format]" \
-      "($cmds -q -b -t -N -C -P)-y[get public key from private key]" \
-      "($cmds -q -b -t -N)-c[change comment in private and public key files]" \
-      "($cmds -q -b -t -N -C -P)-l[show fingerprint of key file]" \
-      "($cmds -q -b -t -N -C -P)-B[show the bubblebabble digest of key]" \
-      "($cmds -q -b -t -N -C -P -f)-D[download key stored in smartcard reader]:reader" \
-      "($cmds -q -b -t -N -C -P)-U[upload key to smartcard reader]:reader"
+    # options can be in any order but use ! to limit those shown for the first argument
+    (( CURRENT == 2 )) && p1='!'
+    args=( '!-z:number' )
+    sdesc='certify keys with CA key'
+    (( $+words[(r)-s] )) && args=( '-z[specify serial number]:serial number' )
+    (( $+words[(r)-[ku]] )) && args=( '-z[specify version number]:version number' ) &&
+        sdesc='specify CA public key file'
+    file=key
+    (( $+words[(r)-[HR]] )) && file=known_hosts
+    (( $+words[(r)-T] )) && file=input
+    if (( $+words[(r)-[kQ]] )); then
+      file=krl
+      args+=( '*:file:_files' )
+    fi
+    cmds=( -p -i -e -y -c -l -B -D -H -R -r -G -T -s -L -A -k -Q ) # basic commands
+    cmn=( -b -P -N -C -m -v ) # options common to many basic commands (except -f which is common to most)
+    cms=( -E -q -t -g -M -S -a -J -j -K -W -I -h -n -O -V -u ) # options specific to one basic command
+    _arguments -s $args \
+      "(${${(@)cmds:#-G}} -P -m ${${(@)cms:#-[MS]}})-b[specify number of bits in key]:bits in key" \
+      "$p1(${${(@)cmds:#-[pc]}} -b -C $cms)-P[provide old passphrase]:old passphrase" \
+      "(${${(@)cmds:#-p}} -m -v ${${(@)cms:#-[qt]}})-N[provide new passphrase]:new passphrase" \
+      "(${${(@)cmds:#-c}} -m -v $cms)-C[provide new comment]:new comment" \
+      "(-D -G -M -S -I -h -n -O -V -A)-f[$file file]:$file file:_files" \
+      "$p1(${${(@)cmds:#-[ie]}})-m[specify conversion format]:format:(PEM PKCS7 RFC4716)" \
+      "(${${(@)cmds:#-[lGT]}} ${${(@)cmn:#-[bv]}} -f)*-v[verbose mode]" \
+      - '(commands)' \
+      "(-b -P -C -v)-p[change passphrase of private key file]" \
+      '(-b -P -N -C -v)-i[import key to OpenSSH format]' \
+      '(-b -P -N -C -v)-e[export key to SECSH file format]' \
+      "($cmn)-y[get public key from private key]" \
+      '(-b -N -m -v)-c[change comment in private and public key files]' \
+      "($cmn)-B[show the bubblebabble digest of key]" \
+      "(-)-D[download key stored in smartcard reader]:reader" \
+      "($cmn)-H[hash names in known_hosts file]" \
+      "($cmn)-R[remove host from known_hosts file]:host:_ssh_hosts" \
+      "($cmn)-L[print the contents of a certificate]" \
+      "(-)-A[generate host keys for all key types]" \
+      "($cmn)-Q[test whether keys have been revoked in a KRL]" \
+      - finger \
+      "($cmn)-l[show fingerprint of key file]" \
+      "$p1($cmn)-E[specify hash algorithm for displayed fingerprints]:hash algorithim:(md5 sha256)" \
+      - create \
+      '(-P -m)-q[silence ssh-keygen]' \
+      "(-P -m)-t[specify the type of the key to create]:key type:(rsa1 rsa dsa ecdsa ed25519)" \
+      - dns \
+      "($cmn)-r[print DNS resource record]:hostname:_hosts" \
+      "$p1($cmn)-g[use generic DNS format]" \
+      - primes \
+      "(-P -N -C -m -f)-G[generate candidates for DH-GEX moduli]" \
+      "$p1(-P -N -C -m -f)-M[specify amount of memory to use for generating DH-GEX moduli]:memory (MB)" \
+      "$p1(-P -N -C -m -f)-S[specify start point]:start point (hex)" \
+      - screen \
+      "(${${(@)cmn:#-v}})-T[screen candidates for DH-GEX moduli]:output file:_files" \
+      "${p1}(${${(@)cmn:#-v}})-a[specify number of rounds]:rounds" \
+      "${p1}(${${(@)cmn:#-v}})-J[exit after screening specified number of lines]" \
+      "${p1}(${${(@)cmn:#-v}})-j[start screening at the specified line number]:line number" \
+      "${p1}(${${(@)cmn:#-v}})-K[write the last line processed to file]:file:_files" \
+      "${p1}(${${(@)cmn:#-v}})-W[specify desired generator]:generator" \
+      - certify \
+      "($cmn)-s[$sdesc]:CA key:_files" \
+      "$p1($cmn -f -u)-I[specify key identifier to include in certificate]:key id" \
+      "$p1($cmn -f -u)-h[generate host certificate instead of a user certificate]" \
+      "$p1($cmn -f -u)-n[specify user/host principal names to include in certificate]:principals" \
+      "$p1($cmn -f -u)-O[specify a certificate option]:option" \
+      "$p1($cmn -f -u)-V[specify certificate validity interval]:interval" \
+      "($cmn -I -h -n -O -V)-k[generate a KRL file]" \
+      "$p1($cmn -I -h -n -O -V)-u[update a KRL]"
     return
     ;;
   sftp)
     _arguments -C -s \
-      '-B+[specify buffer size]:buffer size in bytes (default\: 32768):' \
+      '-a[attempt to continue interrupted transfers]' \
+      '-B+[specify buffer size]:buffer size (bytes) [32768]' \
       '-b+[specify batch file to read]:batch file:_files' \
-      '-D[connect directly to a local sftp server]:sftp server path:' \
-      '-R[specify number of outstanding requests]:number of requests (default\: 64):' \
+      '-D[connect directly to a local sftp server]:sftp server path' \
+      '-f[request that files be flushed immediately after transfer]' \
+      '-R[specify number of outstanding requests]:number of requests [64]' \
       '-s[SSH2 subsystem or path to sftp server on the remote host]' \
       '1:file:->rfile' '*:file:->file' "$common[@]" "$common_transfer[@]" && ret=0
     ;;
@@ -149,7 +200,7 @@ _ssh () {
 
     case "$lstate" in
     option)
-      if compset -P '*='; then
+      if compset -P 1 '*='; then
         case "${IPREFIX#-o}" in
           (#i)(ciphers|macs|kexalgorithms|hostkeyalgorithms|pubkeyacceptedkeytypes|hostbasedkeytypes)=)
           if ! compset -P +; then
@@ -315,7 +366,7 @@ _ssh () {
           ;;
         (#i)pkcs11provider=*)
           _description files expl 'PKCS#11 shared library'
-          _files -g '*.so' "$expl[@]" && ret=0
+          _files -g '*.(so|dylib)(|.<->)(-.)' "$expl[@]" && ret=0
           ;;
         (#i)port=*)
           _message -e 'port number on remote host'
@@ -331,10 +382,7 @@ _ssh () {
               '2' && ret=0
           ;;
         (#i)proxycommand=*)
-          compset -q
-          shift 1 words
-          (( CURRENT-- ))
-          _normal && ret=0
+          _cmdstring && ret=0
           ;;
         (#i)rekeylimit=*)
           _message -e 'maximum number of bytes transmitted before renegotiating session key'
@@ -398,6 +446,7 @@ _ssh () {
         # old options are after the empty "\"-line
         _wanted values expl 'configure file option' \
             compadd -M 'm:{a-z}={A-Z}' -q -S '=' - \
+	        AddKeysToAgent \
                 AddressFamily \
                 BatchMode \
                 BindAddress \
@@ -406,6 +455,7 @@ _ssh () {
                 CanonicalizeHostname \
                 CanonicalizeMaxDots \
                 CanonicalizePermittedCNAMEs \
+		CertificateFile \
                 ChallengeResponseAuthentication \
                 CheckHostIP \
                 Cipher \
@@ -440,6 +490,7 @@ _ssh () {
                 HostKeyAlias \
                 HostName \
                 IdentitiesOnly \
+		IdentityAgent \
                 IdentityFile \
                 IgnoreUnknown \
                 IPQoS \
@@ -459,6 +510,7 @@ _ssh () {
                 PreferredAuthentications \
                 Protocol \
                 ProxyCommand \
+		ProxyJump \
                 ProxyUseFdpass \
                 PubkeyAcceptedKeyTypes \
                 PubkeyAuthentication \
@@ -553,6 +605,7 @@ _ssh () {
           hmac-sha2-256-96 hmac-sha2-512 hmac-sha2-512-96 && ret=0
       ;;
     command)
+      local -a _comp_priv_prefix
       shift 1 words
       (( CURRENT-- ))
       _normal
@@ -575,9 +628,9 @@ _ssh () {
       fi
       ;;
     file)
-      if compset -P '[^./][^/]#:'; then
+      if compset -P 1 '[^./][^/]#:'; then
         _remote_files -- ssh ${(kv)~opt_args[(I)-[FP1246]]/-P/-p} && ret=0
-      elif compset -P '*@'; then
+      elif compset -P 1 '*@'; then
         suf=( -S '' )
         compset -S ':*' || suf=( -r: -S: )
         _wanted hosts expl 'remote host name' _ssh_hosts $suf && ret=0
@@ -589,9 +642,9 @@ _ssh () {
       fi
       ;;
     rfile)
-      if compset -P '*:'; then
+      if compset -P 1 '*:'; then
         _remote_files -- ssh && ret=0
-      elif compset -P '*@'; then
+      elif compset -P 1 '*@'; then
         _wanted hosts expl host _ssh_hosts -r: -S: && ret=0
       else
         _alternative \
@@ -627,17 +680,23 @@ _ssh_hosts () {
     config="$HOME/.ssh/config"
   fi
   if [[ -r $config ]]; then
-    local key hosts host
-    while IFS=$'=\t ' read -r key hosts; do
-      if [[ "$key" == (#i)host ]]; then
-         for host in ${(z)hosts}; do
-            case $host in
-            (*[*?]*) ;;
-            (*) config_hosts+=("$host") ;;
-            esac
-         done
-      fi
-    done < "$config"
+    local key line host
+    local -a lines=("${(@f)$(<"$config")}") 2>/dev/null
+    while (($#lines)); do
+      IFS=$'=\t ' read -r key line <<<"${lines[1]}"
+      case "$key" in
+      ((#i)include)
+        lines[1]=("${(@f)$(cd $HOME/.ssh; cat ${(z)~line})}") 2>/dev/null;;
+      ((#i)host(|name))
+        for host in ${(z)line}; do
+          case $host in
+          (*[*?]*) ;;
+          (*) config_hosts+=("$host") ;;
+          esac
+        done ;&
+      (*) shift lines;;
+      esac
+    done
     if (( ${#config_hosts} )); then
       _wanted hosts expl 'remote host name' \
         compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" $config_hosts
diff --git a/Completion/Unix/Command/_stgit b/Completion/Unix/Command/_stgit
index f313f651a..e31af460a 100644
--- a/Completion/Unix/Command/_stgit
+++ b/Completion/Unix/Command/_stgit
@@ -4,7 +4,7 @@ typeset -a subcmds
 
 subcmds=( ${${${(M)${(f)"$(stg help 2> /dev/null)"}## *}#  }/#(#b)([^[:space:]]##)[[:space:]]##(*)/$match[1]:$match[2]} )
 
-local curcontext="$curcontext"
+local curcontext="$curcontext" expl
 local subcmd
 local ret=1
 
@@ -18,17 +18,17 @@ else
 
   case $subcmd in
     (push)
-      _wanted -V "unapplied patches" expl "patch" \
+      _wanted -V unapplied-patches expl "patch" \
        	compadd ${${(M)${(f)"$(stg series 2> /dev/null)"}##- *}#- } \
 		&& ret=0
     ;;
     (pop)
-      _wanted -V "applied patches" expl "patch" \
+      _wanted -V applied-patches expl "patch" \
 	compadd ${${(M)${(f)"$(stg series 2> /dev/null)"}##[+>] *}#[+>] } \
 		&& ret=0
     ;;
-    (edit|files|goto|rename|log|float|delete|sink|mail|sync|show|pick|hide)
-      _wanted -V "patches" expl "patch" \
+    (edit|files|goto|rename|log|float|delete|sink|mail|sync|show|pick|hide|squash)
+      _wanted -V patches expl "patch" \
 	compadd $(stg series --noprefix 2> /dev/null) \
 		&& ret=0
     ;;
@@ -36,7 +36,7 @@ else
       last_word="$words[$CURRENT-1]"
       refresh_patch_options=( -p --patch )
       if [[ -n ${refresh_patch_options[(r)$last_word]} ]]; then
-	_wanted -V "applied patches" expl "patch" \
+	_wanted -V applied-patches expl "patch" \
 	  compadd ${${(M)${(f)"$(stg series 2> /dev/null)"}##[+>] *}#[+>] } \
 		  && ret=0
       else
diff --git a/Completion/Unix/Command/_strip b/Completion/Unix/Command/_strip
index 726d87c2b..f244b0ace 100644
--- a/Completion/Unix/Command/_strip
+++ b/Completion/Unix/Command/_strip
@@ -16,11 +16,12 @@ if _pick_variant gnu=GNU solaris --version; then
   fi
   args=(
     '(-F --target)'{-F+,--target=}'[object code format to use]:bfd name:->bfdnames'
-    '--help[display usage information and exit]'
-    '--info[display list of architectures and object formats]'
+    '(-)--help[display usage information]'
+    '(-)--info[display list of architectures and object formats]'
     '(-I --input-target)'{-I+,--input-target=}'[object code format of input]:bfd name:->bfdnames'
     '(-O --output-target)'{-I+,--output-target=}'[object code format of output]:bfd name:->bfdnames'
     '*'{-R+,--remove-section=}'[remove given sections]:section name'
+    '--remove-relocations=[remove relocations from specified section]:section'
     '(-s --strip-all)'{-s,--strip-all}'[remove all symbols]'
     '(-g -S -d --strip-debug)'{-g,-S,-d,--strip-debug}'[remove debugging symbols]'
     '--strip-unneeded[remove symbols not needed for relocation processing]'
@@ -33,7 +34,7 @@ if _pick_variant gnu=GNU solaris --version; then
     '(-X --discard-locals)'{-X,--discard-locals}'[remove compiler-generated local symbols]'
     '--keep-file-symbols[retain symbols specifying source file names]'
     '--only-keep-debug[remove everything except debugging information]'
-    '(-V --version)'{-V,--version}'[display version information and exit]'
+    '(-)'{-V,--version}'[display version information and exit]'
     '(-v --verbose)'{-v,--verbose}'[list all object files modified or members of archives]')
 else
   args=(
diff --git a/Completion/Unix/Command/_su b/Completion/Unix/Command/_su
index 057a41371..900905632 100644
--- a/Completion/Unix/Command/_su
+++ b/Completion/Unix/Command/_su
@@ -2,79 +2,86 @@
 
 local -A opt_args
 local -a args context state line expl
-local shell=${words[(i)(-s|--shell=*)]} first='1:user name:_users'
-local usr=root
+local first='(-)${norm}:user name:_users'
+integer norm=1 strip
+local shell usr
 
-if _pick_variant gnu="Free Software Foundation" unix --version; then
-  args=(
-    '(--command)-c[pass command to shell]:command string:->command'
-    '(-c)--command=-[pass command to shell]:command string:->command'
-    '-f[pass -f to shell (csh)]'
-    '(--login)-l[use a login shell]'
-    '(-l)--login[use a login shell]'
-    '(-p --preserve-environment)-m[do not reset environment]'
-    '(-m --preserve-environment)-p[do not reset environment]'
-    '(-m -p)--preserve-environment[do not reset environment]'
-    '(--shell)-s[run the specified shell]:shell:->shell'
-    '(-s)--shell=-[run the specified shell]:shell:->shell'
-  )
-else
-  args=(
-    '-l[use a login shell]'
-    '-s[run the specified shell]:shell:->shell'
-  )
-  case $OSTYPE in
-  freebsd*)
-    args=(
+(( $words[(i)-(l|-login)] < CURRENT )) || args=( '-[use a login shell]' )
+case $OSTYPE in
+  linux*)
+    args=( -S $args
+      '(-c --command --session-command *)'{-c,--command=}'[pass command to shell]:command string:_cmdstring'
+      "(-c --command *)--session-command=[pass command to shell and don't create a new session]:command string:_cmdstring"
+      '(--fast -f)'{-f,--fast}'[pass -f to shell]'
+      '(-l --login -m -p --preserve-environment)'{-l,--login}'[use a login shell]'
+      '(-l --login -m -p --preserve-environment)'{-m,-p,--preserve-environment}"[don't reset environment]"
+      '(-s --shell)'{-s,--shell=}'[run the specified shell]:shell:->shells'
+      '(-)--help[display help information]'
+      '(-)--version[display version information]'
+    )
+    (( EUID )) || args+=(
+      '(-g --group)'{-g,--group=}'[specify primary group]:group:_groups'
+      \*{-G,--supp-group=}'[specify supplemental group]:group:_groups'
+    )
+    first="(--help --version)${first#???}"
+  ;;
+  *bsd*|darwin*|dragonfly*)
+    args+=(
       '-c[use settings from specified login class]:class'
       '-f[if the invoked shell is csh, prevent it from reading .cshrc]'
-      '-l[use a login shell]'
-      '-m[do not reset environment]'
-      '-s[set the MAC label]'
+      '(-m)-l[use a login shell]'
+      "(-l)-m[don't reset environment]"
+    )
+  ;|
+  freebsd*) args+=( '-s[set the MAC label]' ) ;;
+  openbsd*)
+    args+=(
+      '(-K)-a[specify authentication type]:authentication type'
+      '(-a)-K[shorthand for -a passwd]'
+      '-s[run the specified shell]:shell:->shells'
+      '-L[loop until login succeeds]'
     )
   ;;
-  *) args+=( '-c[pass command to shell]:command string:->command' ) ;;
-  esac
-fi
+  netbsd*)
+    args+=(
+      '-d[use a login shell but retain current directory]'
+      "-K[don't use Kerberos]"
+    )
+  ;;
+esac
 
-if [[ $#words -ge 2 && $words[2] != -* && CURRENT -ne 2 ]]; then
-    usr=$words[2]
-    first=
+if (( $words[(i)-] < CURRENT )); then
+  args=( ${args:#*-(-login|l|)\[*} '1:-' )
+  norm=2
 fi
 
-[[ $words[shell] == -s ]] && ((shell++))
+_arguments $args ${(e)first} "*:shell arguments:= ->rest" && return
 
-if [[ CURRENT -ne shell && -n ${words[shell]} ]]; then
-    shell=${words[shell]#*=}
+usr=${line[norm]/--/root}
+if (( $#opt_args[(i)-(s|-shell)] )); then
+  shell=${(v)opt_args[(i)-(s|-shell)]}
+elif (( ${+commands[getent]} )); then
+  shell="${$(_call_program shells getent passwd $usr)##*:}"
 else
-    shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}"
+  shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}"
 fi
 
-[[ -z $first ]] && compset -n 2
-
-_arguments : $args[@] $first "*:${shell:t} arguments:->rest" && return
-
 case $state in
-    (command)
-        compset -q
-        _normal
-        return
-        ;;
-    (shell)
-        _wanted -C $context shells expl shell compadd ${(f)^"$(</etc/shells)"}(N)
-        return
-        ;;
-    (rest)
-        if [[ -z $shell || $shell = */(nologin|false) ]]; then
-            _arguments "-s[run the specified shell, $usr has no shell]" ||
-                _message "-s option required, $usr has no shell"
-            compstate[insert]=
-        else
-            # Something wrong here: doubles the file listing sometimes
-            _dispatch ${service}:${context} $shell $shell:t -default-
-            return
-        fi
-        ;;
+  shells)
+    _wanted -C $context shells expl shell compadd ${(f)^"$(</etc/shells)"}(N)
+    return
+  ;;
+  rest)
+    if [[ -z $shell || $shell = */(nologin|false) ]]; then
+      _message "-s option required, $usr has no shell"
+    else
+      (( strip = $#words - $#line + norm ))
+      (( CURRENT -= strip - 1 ))
+      words[2,strip]=()
+      _dispatch ${service}:${context} $shell $shell:t -default-
+      return
+    fi
+  ;;
 esac
 
 return 1
diff --git a/Completion/Unix/Command/_subversion b/Completion/Unix/Command/_subversion
index 3cc9e8a0b..640c88950 100644
--- a/Completion/Unix/Command/_subversion
+++ b/Completion/Unix/Command/_subversion
@@ -65,30 +65,33 @@ _svn () {
 	    ${=${${${(M)${(f)"$(_comp_locale; _call_program options svn help $cmd)"#(*Valid options:|(#e))}:#* :*}%% #:*}/ (arg|ARG)/:arg:}/(#b)(-##)([[:alpha:]]##) \[--([a-z-]##)\](:arg:)#/(--$match[3])$match[1]$match[2]$match[4] ($match[1]$match[2])--$match[3]$match[4]}
 	  )
           while (( idx=$args[(I)*--accept:arg:] )); do
-            args[(I)*--accept:arg:]=( --accept':automatic conflict resolution action:((working\:working base\:base '"`for i j in p postpone mc mine-conflict tc theirs-conflict mf mine-full tf theirs-full e edit l launch; do print -rn $i\\\\:$j $j\\\\:$j ""; done `"'))' )
+            args[(I)*--accept:arg:]=( --accept'=:automatic conflict resolution action:((working\:working base\:base '"`for i j in p postpone mc mine-conflict tc theirs-conflict mf mine-full tf theirs-full e edit l launch; do print -rn $i\\\\:$j $j\\\\:$j ""; done `"'))' )
           done
           while (( idx=$args[(I)*--c(l|hangelist):arg:] )); do
-            args[(I)*--c(l|hangelist):arg:]=( \*{--cl,--changelist}':change list:_svn_changelists' )
+            args[(I)*--c(l|hangelist):arg:]=( \*{--cl,--changelist}'=:change list:_svn_changelists' )
           done
           while (( idx=$args[(I)*--config-dir:arg:] )); do
-            args[(I)*--config-dir:arg:]=( --config-dir':config dir:_directories' )
+            args[(I)*--config-dir:arg:]=( --config-dir'=:config dir:_directories' )
           done
           while (( idx=$args[(I)*--depth:arg:] )); do
-            args[(I)*--depth:arg:]=( --depth':operation depth (how far to recurse):(empty files immediates infinity)' )
+            args[(I)*--depth:arg:]=( --depth'=:operation depth (how far to recurse):(empty files immediates infinity)' )
           done
           while (( idx=$args[(I)*(-F|--file):arg:] )); do
-            args[(I)*(-F|--file):arg:]=( '(-F --file)'{-F,--file}':log message file:_files' )
+            args[(I)*(-F|--file):arg:]=( '(-F --file)'{-F+,--file=}':log message file:_files' )
           done
           while (( idx=$args[(I)*--set-depth:arg:] )); do
-            args[(I)*--set-depth:arg:]=( --set-depth'[make working copy deeper or shallower]:new depth:(exclude empty files immediates infinity)' )
+            args[(I)*--set-depth:arg:]=( --set-depth'=[make working copy deeper or shallower]:new depth:(exclude empty files immediates infinity)' )
           done
           while (( idx=$args[(I)*--trust-server-cert-failures:arg:] )); do
-            args[(I)*--trust-server-cert-failures:arg:]=( --trust-server-cert-failures':failures:_values -s , "certificate failures to ignore" "unknown-ca[unknown authority]" "cn-mismatch[hostname mismatch]" "expired[certificate expired]" "not-yet-valid[certificate not yet valid]" "other[all other failures]"' )
+            args[(I)*--trust-server-cert-failures:arg:]=( --trust-server-cert-failures'=:failures:_values -s , "certificate failures to ignore" "unknown-ca[unknown authority]" "cn-mismatch[hostname mismatch]" "expired[certificate expired]" "not-yet-valid[certificate not yet valid]" "other[all other failures]"' )
           done
           while (( idx=$args[(I)*--show-item:arg:] )); do
             # (q) to quote the parentheses in the value
-            args[(I)*--show-item:arg:]=( --show-item':item key:(('"`for i j in ${(kv)show_item_keys}; do print -rn - $i\\\\:"${(q)j}" ""; done`"'))' )
+            args[(I)*--show-item:arg:]=( --show-item'=:item key:(('"`for i j in ${(kv)show_item_keys}; do print -rn - $i\\\\:"${(q)j}" ""; done`"'))' )
           done
+          # All other options get {-x+,--long-x=}
+          args=( ${args/(#b)(--[A-Za-z0-9-]##):arg:/$match[1]=:arg:} )
+          args=( ${args/(#b)([^=]):arg:/$match[1]+:arg:} )
 	  _store_cache svn-${cmd}-args args
 	fi
 
@@ -132,7 +135,7 @@ _svn () {
             )
           ;;
           (mergeinfo)
-            args[(r)--show-revs:arg:]=( '--show-revs=:revisions:(merged eligible)' )
+            args[(r)--show-revs=:arg:]=( '--show-revs=:revisions:(merged eligible)' )
           ;;
 	  (propget|propedit|propdel)
 	    args+=(
@@ -183,6 +186,9 @@ _svn () {
 
 _svnadmin () {
   local curcontext="$curcontext" state line ret=1
+  integer NORMARG
+  local context state_descr
+  typeset -A opt_args
 
   _arguments -C \
     '(-)--help[print help information]' \
@@ -212,13 +218,53 @@ _svnadmin () {
         args=(
           ${=${${${(M)${(f)"$(_comp_locale; _call_program options svnadmin help $cmd)"#(*Valid options:|(#e))}:#* :*}%% #:*}/ (arg|ARG)/:arg:}/(#b)-([[:alpha:]]) \[--([a-z-]##)\](:arg:)#/(--$match[2])-$match[1]$match[3] (-$match[1])--$match[2]$match[3]}
         )
+        # All options get {-x+,--long-x=}
+        args=( ${args/(#b)(--[A-Za-z0-9-]##):arg:/$match[1]=:arg:} )
+        args=( ${args/(#b)([^=]):arg:/$match[1]+:arg:} )
         if [[ $usage == *REPOS_PATH* ]]; then
-          args+=( ":path:_files -/" )
+          args+=( ":repository path:_files -/" )
+          case $cmd in
+            (freeze)
+              args+=( "*:arguments:->normal" )
+              ;;
+            (hotcopy)
+              args+=( ":new repository:_files -/" )
+              ;;
+            (setlog)
+              args+=( ": :_files" )
+              ;;
+            (setrevprop)
+              args+=( ":property name" ":property value file:_files" )
+              ;;
+            (delrevprop)
+              args+=( ":property name" )
+              ;;
+          esac
         elif [[ $cmd = help ]]; then
           args+=( "*:subcommand:_svnadmin_commands" )
         fi
 
-        _arguments "$args[@]" && ret=0
+        _arguments -n -s -S : "$args[@]" && ret=0
+
+        case $state in
+          # Test cases:
+          #   svnadmin freeze . rsync --<TAB> offers --file
+          #   svnadmin freeze -- . rsync -<TAB> offers rsync's options
+          #
+          # Note: the NORMARG calculations here include one positional argument
+          # (the '.') before the command.
+          (normal)
+            if (( ${words[(i)--]} < CURRENT )); then
+              words[1,NORMARG]=()
+              (( CURRENT -= NORMARG ))
+              _normal && ret=0
+            elif (( NORMARG+1 == CURRENT )); then
+              # ### don't allow --options in this case
+              # TODO: this should just use '_normal -F "(-*)"', but _normal ignores its arguments.
+              _command_names -e && ret=0
+            fi
+            ;;
+        esac
       else
         _message "unknown svnadmin command: $words[1]"
       fi
diff --git a/Completion/Unix/Command/_sudo b/Completion/Unix/Command/_sudo
index 63ac37f62..aa7a1a498 100644
--- a/Completion/Unix/Command/_sudo
+++ b/Completion/Unix/Command/_sudo
@@ -2,8 +2,9 @@
 
 setopt localoptions extended_glob
 
-local environ e
+local environ e cmd
 local -a args
+local -a _comp_priv_prefix
 
 zstyle -a ":completion:${curcontext}:" environ environ
 
@@ -39,6 +40,7 @@ args=(
 if [[ $service = sudoedit ]] || (( $words[(i)-e] < $words[(i)^(*sudo|-[^-]*)] ))  ; then
   args=( -A "-*" $args '!(-V --version -h --help)-e' '*:file:_files' )
 else
+  cmd="$words[1]"
   args+=(
     '(-e --edit 1 *)'{-e,--edit}'[edit files instead of running a command]' \
     '(-s --shell)'{-s,--shell}'[run shell as the target user; a command may also be specified]' \
@@ -48,7 +50,7 @@ else
     '(-H --set-home -i --login -s --shell -e --edit)'{-H,--set-home}"[set HOME variable to target user's home dir]" \
     '(-P --preserve-groups -i -login -s --shell -e --edit)'{-P,--preserve-groups}"[preserve group vector instead of setting to target's]" \
     '(-)1:command: _command_names -e'
-    '*::arguments: _normal'
+    '*::arguments:{ _comp_priv_prefix=( $cmd -n ${(kv)opt_args[(I)(-[ugHEP]|--(user|group|set-home|preserve-env|preserve-groups))]} ) ; _normal }'
   )
 fi
 
diff --git a/Completion/Unix/Command/_surfraw b/Completion/Unix/Command/_surfraw
index 0307555a9..d9df4170d 100644
--- a/Completion/Unix/Command/_surfraw
+++ b/Completion/Unix/Command/_surfraw
@@ -118,7 +118,7 @@ case $state in
       deblists)
         _arguments $args \
           '-shelp[go to search help page]' \
-          '-results=-[specifiy number of results to return]:number' \
+          '-results=-[specify number of results to return]:number' \
           '-dates=-[quarters to search]:date' \
           '-case[use case sensitive search]' \
           '-errors=-[specify errors allowed]:errors:(0 1 2 best)' \
diff --git a/Completion/Unix/Command/_swaks b/Completion/Unix/Command/_swaks
new file mode 100644
index 000000000..a0ffb53ad
--- /dev/null
+++ b/Completion/Unix/Command/_swaks
@@ -0,0 +1,40 @@
+#compdef swaks
+
+_arguments \
+  '(-s --server -p --port)'{-s+,--server=}'[target host[:port\]]:host[\:port]:_hosts' \
+  '(-p --port)'{-p+,--port=}'[target port number]:port number:(25 465 587)' \
+  '--copy-routing[derive target host:port from email address domain part]:email address domain part' \
+  '(-t --to)'{-t+,--to=}':envelope recipient(s):_sequence _email_addresses -c' \
+  '(-f --from)'{-f+,--from=}':envelope sender:_email_addresses -c' \
+  '(--ehlo --lhlo -h --helo)'{-h+,--ehlo,--helo,--lhlo}':HELO string:_hosts' \
+  '(-q --quit-after)'{-q+,--quit-after=}'[stop transaction early]:stop point:((
+      CONNECT\:banner BANNER\:banner
+      FIRST-HELO\:first\ HELO FIRST-EHLO\:first\ HELO
+      XCLIENT\:XCLIENT
+      TLS\:TLS\ negotiation
+      HELO\:second\ HELO EHLO\:second\ HELO
+      AUTH\:authentication
+      MAIL\:MAIL\ FROM FROM\:MAIL\ FROM
+      RCPT\:RCPT\ TO TO\:RCPT\ TO
+      ))' \
+  '--protocol=:protocol variant:((
+      SMTP\:HELO\ 25
+      SSMTP\:EHLO\ 465
+      SSMTPA\:EHLO\ 465\ authenticated
+      SMTPS\:HELO\ 465
+      ESMTP\:EHLO\ 25
+      ESMTPA\:EHLO\ 25\ authenticated
+      ESMTPS\:EHLO\ STARTTLS\ 25
+      ESMTPSA\:EHLO\ STARTTLS\ 25\ authenticated
+      ))' \
+  '-tls[TLS required]' \
+  '(-tlsos --tls-optional-strict)'{-tlsos,--tls-optional-strict}'[TLS iff offered by target]' \
+  '(-tlsc --tls-on-connect)'{-tlsc,--tls-on-connect}'[TLS on connect (port 465)]' \
+  '(-tlsp --tls-protocol)'{-tlsp,--tls-protocol=}':TLS protocol:(sslv2 sslv3 tlsv1 tlsv1_1 tlsv1_2)' \
+  '-tls-cipher:OpenSSL cipher string: ' \
+  '--tls-verify[verify TLS certificates]' \
+  '--tls-ca-path=:OpenSSL CAfile or CAdir:_files' \
+  '--tls-get-peer-cert=-:file to write (omit for STDOUT)' \
+  '(-d --data)'{-d+,--data=}'[specify DATA payload]:filename (or string with tokens):_files' \
+  '*'{-ah,--add-header=}'[add headers]:<Header>\: Value' \
+  '*'{-h,--header=}'[replace headers]:<Header>\: Value'
diff --git a/Completion/Unix/Command/_swift b/Completion/Unix/Command/_swift
new file mode 100644
index 000000000..6776f0dea
--- /dev/null
+++ b/Completion/Unix/Command/_swift
@@ -0,0 +1,123 @@
+#compdef swift swiftc
+
+# swift(1) and swiftc(1) are part of the Swift programming language.
+# https://swift.org/
+
+local -a common_options swiftc_mode_options swiftc_additional_options
+local -A swiftc_modes
+
+common_options=(
+  '-assert-config[specify the assert_configuration replacement]:config:(Debug Release Unchecked DisableReplacement)'
+  '*-D[marks a conditional compilation flag as true]:flag:'
+  '*-framework[specifies a framework which should be linked against]:framework:'
+  '*-F[add directory to framework search path]:path:_files -/'
+  '(-gnone)-gdwarf-types[emit full DWARF type info]'
+  '(-gnone)-gline-tables-only[emit minimal debug info for backtraces only]'
+  '(-gdwarf-types -gline-tables-only -g)-gnone[do not emit debug info]'
+  '(-gnone)-g[emit debug info]'
+  '(- : *)-help[display available options]'
+  '-index-store-path[store indexing data to the specified path]:directory:_files -/'
+  '*-I[add directory to the import search path]:path:_files -/'
+  '-j[number of commands to execute in parallel]:count:'
+  '*-L[add directory to library link search path]:path:_files -/'
+  '*-l-[specifies a library which should be linked against]:library:'
+  '-module-cache-path[specifies the Clang module cache path]:path:_files -/'
+  '-module-link-name[library to link against when using this module]:name:'
+  '-module-name[name of the module to build]:name:'
+  '-nostdimport[do not search the standard library import path for modules]'
+  '-num-threads[enable multi-threading and specify number of threads]:count:'
+  '(-Ounchecked -O)-Onone[compile without any optimization]'
+  '(-Onone)-Ounchecked[compile with optimizations and remove runtime safety checks]'
+  '(-Onone)-O[compile with optimizations]'
+  '-sdk[compile against SDK]:sdk:_files -/'
+  '-static-stdlib[statically link the Swift standard library]'
+  '-suppress-warnings[suppress all warnings]'
+  '-target-cpu[generate code for a particular CPU variant]:cpu'
+  '-target[generate code for the given target]:target'
+  '-use-ld=-[specifies the linker to be used]:linker:_files -/'
+  '(- : *)-version[print version information and exit]'
+  '-v[show commands to run and use verbose output]'
+  '-warnings-as-errors[treat warnings as errors]'
+  '*-Xcc[pass argument to the C/C++/Objective-C compiler]:arg:'
+  '*-Xlinker[specifies an option which should be passed to the linker]:option:'
+)
+
+swiftc_modes=(
+  -dump-ast        'parse and type-check input file(s) and dump AST(s)'
+  -dump-parse      'parse input file(s) and dump AST(s)'
+  -dump-type-refinement-contexts
+                   'type-check input file(s) and dump type refinement contexts(s)'
+  -emit-assembly   'emit assembly file(s) (-S)'
+  -emit-bc         'emit LLVM BC file(s)'
+  -emit-executable 'emit a linked executable'
+  -emit-ir         'emit LLVM IR file(s)'
+  -emit-library    'emit a linked library'
+  -emit-object     'emit object file(s) (-c)'
+  -emit-sibgen     'emit serialized AST + raw SIL file(s)'
+  -emit-sib        'emit serialized AST + canonical SIL file(s)'
+  -emit-silgen     'emit raw SIL file(s)'
+  -emit-sil        'emit canonical SIL file(s)'
+  -parse           'parse input file(s)'
+  -print-ast       'parse and type-check input file(s) and pretty print AST(s)'
+)
+local mode
+for mode in ${(k)swiftc_modes}; do
+  # Mode options are mutually exclusive
+  swiftc_mode_options+=("(${(k)swiftc_modes})${mode}[$swiftc_modes[$mode]]")
+done
+
+swiftc_additional_options=(
+  '-application-extension[restrict code to those available for App Extensions]'
+  '-embed-bitcode-marker[embed placeholder LLVM IR data as a marker]'
+  '-embed-bitcode[embed LLVM IR bitcode as data]'
+  '-emit-dependencies[emit basic Make-compatible dependencies files]'
+  '-emit-module-path[emit an importable module to the specified path]:path:_files -/'
+  '-emit-module[emit an importable module]'
+  '-emit-objc-header-path[emit an Objective-C header file to the specified path]:path:_files -/'
+  '-emit-objc-header[emit an Objective-C header file]'
+  '-fixit-all[apply all fixits from diagnostics without any filtering]'
+  '-fixit-code[get compiler fixits as code edits]'
+  '-import-underlying-module[implicitly imports the Objective-C half of a module]'
+  '-output-file-map[a file which specifies the location of outputs]:path:_files'
+  '-o[write output to specified file]:path:_files'
+  '-parse-as-library[parse the input file(s) as libraries, not scripts]'
+  '-parse-sil[parse the input file as SIL code, not Swift source]'
+  '-parseable-output[emit textual output in a parseable format]'
+  '-profile-coverage-mapping[generate coverage data for use with profiled execution counts]'
+  '-profile-generate[generate instrumented code to collect execution counts]'
+  '-sanitize-coverage=-[specify the type of coverage instrumentation for Sanitizers and additional options separated by commas]:type:'
+  '*-sanitize=-[turn on runtime checks for erroneous behavior]:check:'
+  '-save-temps[save intermediate compilation results]'
+  '-serialize-diagnostics[serialize diagnostics in a binary format]'
+  '-tools-directory[look for external executables (ld, clang, binutils) in the specified directory]:directory:_files -/'
+  '-whole-module-optimization[optimize input files together instead of individually]'
+)
+
+case "$words[1]" in
+  swift)
+    # The name swift conflicts with the command with the same name from the
+    # OpenStack project. We delegate completion to _openstack if swift(1) is
+    # detected to be from OpenStack.
+    local variant
+    _pick_variant -r variant openstack=OpenStack swiftlang='Swift compiler' unknown --help
+    case $variant in
+      openstack)
+        _openstack "$@"
+        ;;
+      swiftlang)
+        _arguments \
+            "$common_options[@]" \
+            '*:input:_files'
+        ;;
+      *)
+        _default "$@"
+    esac
+    ;;
+  swiftc)
+    _arguments \
+        "$swiftc_mode_options[@]" \
+        "$common_options[@]" \
+        "$swiftc_additional_options[@]" \
+        '*:input:_files'
+    ;;
+esac
diff --git a/Completion/Unix/Command/_sysctl b/Completion/Unix/Command/_sysctl
index 9d9e8b968..c5bb26eb0 100644
--- a/Completion/Unix/Command/_sysctl
+++ b/Completion/Unix/Command/_sysctl
@@ -1,21 +1,39 @@
 #compdef sysctl
 
+local -a args
+
 case $OSTYPE in
-  *freebsd<5->.*|freebsd4.[4-9]*)
+  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*)
+    args+=( "-i[silently exit if variable doesn't exist]" )
+  ;|
+  freebsd*)
     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*)
+  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/_tail b/Completion/Unix/Command/_tail
index fbe30f13a..4e6422621 100644
--- a/Completion/Unix/Command/_tail
+++ b/Completion/Unix/Command/_tail
@@ -56,7 +56,7 @@ case $state in
     sign='signs:sign:((+\:"start at the specified byte/line"'
     sign+=' -\:"output the last specified bytes/lines (default)"))'
     digit='digits:digit:(0 1 2 3 4 5 6 7 8 9)'
-    if compset -P '*[0-9]'; then
+    if compset -P '(-|+|)[0-9]##'; then
       _alternative $mlt $digit && ret=0
     elif [[ -z $PREFIX ]]; then
       _alternative $sign $digit && ret=0
diff --git a/Completion/Unix/Command/_tcpdump b/Completion/Unix/Command/_tcpdump
index edc6c7306..2c1d82226 100644
--- a/Completion/Unix/Command/_tcpdump
+++ b/Completion/Unix/Command/_tcpdump
@@ -2,33 +2,70 @@
 
 typeset -A opt_args
 
-_interfaces () {
-	_wanted interfaces expl 'network interface' \
-		_net_interfaces
-	_values "Pseudo-device that captures on all interfaces" "any"
+_interfaces() {
+  local disp expl sep
+  _description interfaces expl 'network interface'
+  _net_interfaces "$expl[@]"
+  if zstyle -t ":completion:${curcontext}:interfaces" verbose; then
+    zstyle -s ":completion:${curcontext}:interfaces" list-separator sep || sep=--
+    disp=( "any $sep capture on all interfaces" )
+    compadd "$expl[@]" -ld disp any
+  else
+    compadd "$expl[@]" any
+  fi
 }
 
 _esp_secrets () {
-	_values -S : 'ESP algorithm' \
-		'des-cbc:secret' \
-		'3des-cbc:secret' \
-		'blowfish-cbc:secret' \
-		'rc3-cbc:secret' \
-		'cast128-cbc:secret' \
-		none
+  if [[ $OSTYPE = openbsd* ]]; then
+    _values -S : 'ESP algorithm' \
+      aes128:secret \
+      aes128-hmac96:secret \
+      blowfish:secret \
+      blowfish-hmac96:secret \
+      cast:secret \
+      cast-hmac96:secret \
+      des3:secret \
+      des3-hmac96:secret \
+      des:secret \
+      des-hmac96:secret
+  else
+    _values -S : 'ESP algorithm' \
+      'des-cbc:secret' \
+      '3des-cbc:secret' \
+      'blowfish-cbc:secret' \
+      'rc3-cbc:secret' \
+      'cast128-cbc:secret' \
+      none
+  fi
 }
 
 _packet_types () {
-	_values 'Packets type' \
-		'aodv[Ad-hoc On-demand Distance Vector protocol]' \
-		'cnfp[Cisco NetFlow protocol]' \
-		'rpc[Remote Procedure Call]' \
-		'rtp[Real-Time  Applications  protocol]' \
-		'rtcp[Real-Time Applications control protocol]' \
-		'snmp[Simple Network Management Protocol]' \
-		'tftp[Trivial File Transfer Protocol]' \
-		'vat[Visual Audio Tool]' \
-		'wb[distributed White Board]'
+  types=(
+    'cnfp[Cisco NetFlow protocol]'
+    'rpc[Remote Procedure Call]'
+    'rtp[Real-Time Applications protocol]'
+    'rtcp[Real-Time Applications control protocol]'
+    'vat[Visual Audio Tool]'
+    'wb[distributed White Board]'
+  )
+  if [[ $OSTYPE = openbsd* ]]; then
+    types+=(
+      'sack[RFC 2018 TCP Selective Acknowledgements Options]'
+      'vrrp[Virtual Router Redundancy Protocol]'
+      'tcp[Transmission Control Protocol]'
+    )
+  else
+    types+=(
+      'aodv[Ad-hoc On-demand Distance Vector protocol]'
+      'carp[Common Address Redundancy Protocol]'
+      'radius[RADIUS]'
+      'snmp[Simple Network Management Protocol]'
+      'tftp[Trivial File Transfer Protocol]'
+      'vxlan[Virtual eXtensible Local Area Network]'
+      'zmtpl[ZeroMQ Message Transport Protocol]'
+    )
+  fi
+  _values 'Packets type' $types
 }
 
 _data_link_types () {
@@ -45,48 +82,81 @@ _data_link_types () {
 _bpf_filter () {
 }
 
-_arguments \
-  '()-A[print each packet in ASCII]' \
-  -c'[exit after receiving specified number of packets]:number of packets' \
-  -C'[specify output file size in MB (10e6 bytes)]:output file size' \
-  '(-ddd)-d[dump the compiled packet-matching code in a human readable form]' \
-  '(-ddd)-dd[dump packet-matching code as a C program fragment]' \
-  '(-d -dd)-ddd[dump packet-matching code as decimal numbers (preceded with a count)]' \
-  '(-A -c -C -d -dd -ddd -e -E -f -F -i -l -L -m -M -n -N -O -p -q -R -r -S -s -T -t -tt -ttt -tttt -u -U -v -vv -vvv -w -W -x -xx -X -XX -y -Z *)'-D'[print the list of the network interfaces available on the system]' \
-  -e'[print the link-level header on each dump line]' \
-  -E"[decrypting IPsec ESP packets]:spi@ipaddr::algo\:secret:_esp_secrets" \
-  -f"[print 'foreign' IPv4 addresses numerically]" \
-  -F'[input file for the filter expression]:filter expression file:_files' \
-  -i'[interface]:interface:_interfaces' \
-  -l'[make stdout line buffered]' \
-  '(-A -c -C -d -dd -ddd -e -E -f -F -l -D -m -M -n -N -O -p -q -R -r -S -s -T -t -tt -ttt -tttt -u -U -v -vv -vvv -w -W -x -xx -X -XX -y -Z *)'-L'[list the known data link types for the interface]' \
-  '*-m[load SMI MIB module definitions]:SMI MIB module definitions:_files' \
-  -M'[shared secret for validating the digests in TCP segments with the TCP-MD5 option]:secret' \
-  -n"[don't convert addresses to names]" \
-  -N"[don't print domain name qualification of host names]" \
-  -O"[don't run the packet-matching code optimizer]" \
-  -p"[don't put the interface into promiscuous mode]" \
-  -q'[quick (quiet?) output]' \
-  -R'[assume ESP/AH packets to be based on old specification (RFC1825 to RFC1829)]' \
-  -r'[read packets from file]:input file:_files' \
-  -S'[print absolute TCP sequence numbers]' \
-  -s'[specify number of bytes of data to snarf from each packet]:number of bytes to snap' \
-  -T'[interpret captured packets as specified type]:packet type:_packet_types' \
-  "(-tttt)-t[don't print a timestamp on each dump line]" \
-  '(-ttt -tttt)-tt[print an unformatted timestamp on each dump line]' \
-  '(-tt -tttt)-ttt[print a delta (in micro-seconds) between current and previous line on each dump line]' \
-  '(-t -tt -ttt)-tttt[print a timestamp in default format proceeded by date on each dump line]' \
-  -u'[print undecoded NFS handles]' \
-  -U'[make output packet-buffered when saving to file (-w)]' \
-  '(-vvv)-v[slightly more verbose output]' \
-  '(-vvv)-vv[more verbose output]' \
-  '(-v -vv)-vvv[most verbose output]' \
-  -w'[write the raw packets to file]:output file:_files' \
-  -W'[limit the number of created files (-C)]:number of files' \
-  -x'[print each packet (minus its link level header) in hex]' \
-  '(-x)-xx[print each packet, including its link level header, in hex]' \
-  -X'[print each packet (minus its link level header) in hex and ASCII]' \
-  '(-X)-XX[print each packet, including its link level header, in hex and ASCII]' \
-  -y'[set the data link type to use while capturing packets]:data link type:_data_link_types' \
-  -Z'[drops privileges (if root) and changes user ID (along with primary group)]:user:_users' \
+args=(
+  '-A[print each packet in ASCII]'
+  '-c[exit after receiving specified number of packets]:number of packets'
+  '(-ddd)-d[dump the compiled packet-matching code in a human readable form]'
+  '(-ddd)-dd[dump packet-matching code as a C program fragment]'
+  '(-d -dd)-ddd[dump packet-matching code as decimal numbers (preceded with a count)]'
+  "-E[decrypting IPsec ESP packets]:spi@ipaddr::algo\:secret:_esp_secrets"
+  '-e[print the link-level header on each dump line]'
+  '-F[input file for the filter expression]:filter expression file:_files'
+  "-f[print 'foreign' IPv4 addresses numerically]"
+  '-l[make stdout line buffered]'
+  "-N[don't print domain name qualification of host names]"
+  "-n[don't convert addresses to names]"
+  "-O[don't run the packet-matching code optimizer]"
+  "-p[don't put the interface into promiscuous mode]"
+  '-q[quick (quiet?) output]'
+  '-r[read packets from file]:input file:_files'
+  '-S[print absolute TCP sequence numbers]'
+  '-s[specify number of bytes of data to snarf from each packet]:number of bytes to snap'
+  '-T[interpret captured packets as specified type]:packet type:_packet_types'
+  "(-tt -ttt -tttt -ttttt)-t[don't print a timestamp on each dump line]"
+  '(-t -ttt -tttt -ttttt)-tt[print an unformatted timestamp on each dump line]'
+  '(-vv -vvv)-v[slightly more verbose output]'
+  '(-v -vvv)-vv[more verbose output]'
+  '-w[write the raw packets to file]:output file:_files'
+  '-X[print each packet (minus its link level header) in hex and ASCII]'
+  '-x[print each packet (minus its link level header) in hex]'
+  '-y[set the data link type to use while capturing packets]:data link type:_data_link_types'
   '*:BPF filter:_bpf_filter'
+)
+
+if [[ $OSTYPE = openbsd* ]]; then
+  args+=(
+    '(-n)-a[attempt to convert network and broadcast addresses to names]'
+    '-D[select packet flowing in specified direction]:direction:(in out)'
+    '-I[print the interface on each dump line]'
+    '-o[print a guess of the possible operating system(s)]'
+    '(-t -tt -tttt -ttttt)-ttt[print day and month in timestamp]'
+    '(-t -tt -ttt -ttttt)-tttt[print timestamp difference between packets]'
+    '(-t -tt -ttt -tttt)-ttttt[print timestamp difference since the first packet]'
+  )
+else
+  args+=(
+    '-B[specify the capture buffer size in KiB]:capture buffer size'
+    '-b[print the AS number in BGP packets in ASDOT notation]'
+    '-C[specify output file size in MB (10e6 bytes)]:output file size'
+    '(-* *)'-D'[print the list of the network interfaces available on the system]'
+    '-G[specify the interval to rotate the dump file in seconds]:dump file rotate seconds'
+    '-H[attempt to detect 802.11s draft mesh headers]'
+    '(-* *)-h[print version strings and a usage message]'
+    '-I[put the interface in monitor mode]'
+    '(-* *)-J[list the supported timestamp types]'
+    '-j[set the timestamp type]:timestamp type'
+    "-K[don't attempt to verify checksums]"
+    '*-m[load SMI MIB module definitions]:SMI MIB module definitions:_files'
+    '-M[shared secret for validating the digests in TCP segments with the TCP-MD5 option]:secret'
+    '-R[assume ESP/AH packets to be based on old specification (RFC1825 to RFC1829)]'
+    '(-t -tt -tttt)-ttt[print a delta (in micro-seconds) between current and previous line on each dump line]'
+    '(-t -tt -ttt)-tttt[print a timestamp in default format proceeded by date on each dump line]'
+    '(-t -tt -ttt -tttt)-ttttt[print a delta (micro-second resolution) since the first line on each dump line]'
+    '-U[make output packet-buffered when saving to file (-w)]'
+    '-u[print undecoded NFS handles]'
+    '-V[Read a list of filenames from file]:file:_files'
+    '(-v -vv)-vvv[most verbose output]'
+    '-W[limit the number of created files (-C)]:number of files'
+    '(-X)-XX[print each packet, including its link level header, in hex and ASCII]'
+    '(-x)-xx[print each packet, including its link level header, in hex]'
+    '-Z[drops privileges (if root) and changes user ID (along with primary group)]:user:_users'
+    '-z[command to run after file rotation]:command:_command_names'
+  )
+fi
+
+_arguments : \
+  '-i[interface]:interface:_interfaces' \
+  - optL \
+  '-L[list the known data link types for the interface]' \
+  - default \
+  $args
diff --git a/Completion/Unix/Command/_texinfo b/Completion/Unix/Command/_texinfo
index 12d964e3f..57e13bdc2 100644
--- a/Completion/Unix/Command/_texinfo
+++ b/Completion/Unix/Command/_texinfo
@@ -1,29 +1,65 @@
-#compdef info tkinfo install-info makeinfo texi2dvi texindex
+#compdef info tkinfo install-info makeinfo texi2any texi2dvi pdftexi2dvi texi2pdf texindex
 
-local curcontext="$curcontext" state line ret=1
-local -A opt_args
-local -a info
+_info_nodes_caching_policy() {
+  local dir oldp
+  for dir in $^infopath/usr/share/info}/dir(.N); do
+    # rebuild if any dir file is newer than cache
+    [[ $dir -nt $1 ]] && return
+  done
+  # and if we didn't find a dir file, rebuild if cache older than a month
+  if [[ -z $dir ]]; then
+    oldp=( "$1"(mM+1) )
+    (( $#oldp )) && return
+  fi
+  return 1
+}
+
+_info_retrieve_nodes() {
+  # expects $cmd, $hash and $infopath to be set
+  local update_policy
+  zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+  if [[ -z "$update_policy" ]]; then
+    zstyle ":completion:${curcontext}:" cache-policy \
+      _info_nodes_caching_policy
+  fi
+
+  if _cache_invalid info-nodes-$hash || ! _retrieve_cache info-nodes-$hash; then
+    set -A _cache_info_nodes_$hash \
+      ${${${${(f)"$(INFOPATH="${(j.:.)infopath}" _call_program info-nodes $cmd -k '')"}%%\" --*}#??}/\)/:}
+    _store_cache info-nodes-$hash _cache_info_nodes_$hash
+  fi
+}
+
+local curcontext="$curcontext" state line cmd ret=1
+local -A opt_args infodirs
 
 case $service in
   info)
-    info=( _call_program info ${words[1]} )
+    cmd=${words[1]}
     _arguments -C -s \
-      '(: -)--apropos=[look up string in indices]:search string: ' \
-      '(-f --file)'{\*-d,\*--directory=}'[add directory to infopath]:info dir:_files -/' \
+      '(-a --all)'{-a,--all}'[use all matching manuals]' \
+      '(: -)'{-k+,--apropos=}'[look up string in indices]:search string: ' \
+      \*{-d+,--directory=}'[add directory to infopath]:info dir:_files -/' \
       '--dribble=[record keystrokes]:file with keystrokes:_files' \
-      '(-f --file -d --directory)'{-f,--file=}'[info file to show]:info file:_files -g "*.info(|.gz|.bz2)(-.)"' \
+      '(-f --file 1)'{-f+,--file=}'[specify Info manual to visit]:info manual:->infofiles' \
       '(: - -h --help)'{-h,--help}'[display usage]' \
       '(-o --output -O)--index-search=[go directly to node if found]:search string: ' \
-      '(--index-search -o --output -O)'{-o,--output=}'[dump selected nodes to filename]:filename:_files -g "*(-.)"' \
-      '(-R --raw-escapes)'{-R,--raw-escapes}'[do not remove ANSI escapes from man pages]' \
+      '(--index-search -o --output -O)'{-o+,--output=}'[dump selected nodes to filename]:filename:_files -g "*(-.)"' \
+      '(-n --node)'{-n+,--node=}'[specify nodes in first visited Info file]:node:->nodes' \
+      '--no-raw-escapes[output escapes as literal text]' \
       '--restore=[read keystrokes from file]:filename:_files -g "*(-.)"' \
       '(--index-search -o --output -O --show-options --usage)'{-O,--show-options,--usage}'[go to command-line options node]' \
+      '--strict-node-location[(for debugging) use Info file pointers as-is]' \
       '--subnodes[recursively output menu items]' \
+      \*{-v,--variable}'[assign to Info variable]:variable' \
       '--vi-keys[use Vi-like key bindings]' \
       '(: -)--version[display version information]' \
-      '(--apropos -h --help -O --output --version)*::menu item:->item' && ret=0
+      '(-w --where --location)'{-w,--where,--location}'[print physical location of Info file]' \
+      '(-x --debug)'{-x+,--debug=}'[set debugging level]:number' \
+      '1:menu item:->infomanuals' \
+      '2:node:->nodes' && ret=0
 
-    info=( $info {(kv)opt_args[(I)(-d|--directory|-f|--file)]} )
+    infodirs=( "${(@Qkv)opt_args[(I)(-d|--directory)]}" )
   ;;
   install-info)
     if _pick_variant debian=Debian gnu --version; then
@@ -41,131 +77,216 @@ case $service in
         '--description=[specify description for menu entry]:description' \
         '--menuentry=[specify the menu entry for dir file]:menu entry' \
         '--keep-old=[inhibit replacement of existing entries/removal of empty sections]' \
-        '--test[do not update dir file]' \
+        "--test[don't update dir file]" \
         '--debug[enable debugging]' \
         '*:info file:_files -g "*.info(-.)"'
 	return
     else
       _arguments \
+	'--add-once[add only to first matching section]' \
+	'--align=[specify minimum indentation for description]:indentation' \
+	'--calign=[specify minimum indentation for continuation lines of description]:indentation' \
+        '--debug[report what is being done]' \
         '(--delete --remove)'{--delete,--remove}'[delete existing entries]' \
+        '--description=[specify description for menu entry]:description' \
         '(2)--dir-file=[specify dir file]:dir file:_files -g "dir(-.)"' \
+	'(--test --dry-run)'{--dry-run,--test}"[don't update dir file]" \
         \*{--entry,--info}'[specify directory entry to add]:text' \
+	'--defsection=[like --section, but only use text if no sections present in info file]:text' \
+	{--maxwidth,--max-width}'=[specify maximum width of dir file]:width' \
         '(- 1 2)--help[display help information]' \
         '(1)--info-file=[specify info file to install in the directory]:info file:_files -g "*.info(-.)"' \
         '(2)--info-dir=[specify directory containing dir file]:info directory:_files -/' \
+        '--keep-old=[inhibit replacement of existing entries/removal of empty sections]' \
+	'(--name --menuentry)'{--name,--menuentry}'=[specify the menu entry for dir file]:menu entry' \
+	"--no-indent[don't format new entries in the DIR file]"
         '--quiet[suppress warnings]' \
-        '(--delete --remove)--section=[put new entries in specified section]' \
+	'--regex=[specify sections for file entries using a regex]:regex' \
+        '(--delete --remove)--section=[put new entries in specified section]:section' \
+        '--silent[no output except errors]' \
         '(- 1 2)--version[display version information]' \
         '1:info file:_files -g "*.info(-.)"' \
         '2:dir file:_files -g "dir(-.)"'
 	return
     fi
   ;;
-  makeinfo)
+  makeinfo|texi2any)
     _arguments -s \
-      '--error-limit=[specify number of errors to quit after]:number' \
+      '--error-limit=[specify number of errors to quit after]:number [100]' \
+      '--document-language=[specify locale to use in translating Texinfo keywords]:locale [C]:_locales' \
       '--force[preserve output even if errors]' \
       '(* -)--help[display help]' \
       '--no-validate[suppress node cross-reference validation]' \
       '--no-warn[suppress warnings]' \
-      '--reference-limit=[warn about at most specified number of references]:number' \
+      '--conf-dir=[specify additional directory for configuration files]:directory:_directories' \
+      '--init-file=[specify initialisation file]:file:_files' \
+      \*{-c+,--set-customization-variable=}'[set customization variable]:variable' \
       '(-v --verbose)'{-v,--verbose}'[explain what is being done]' \
       '(* -)--version[display version info]' \
-      '(--html --xml)--docbook[output in DocBook format]' \
-      '(--docbook --xml)--html[output in HTML format]' \
+      '(--html --xml --plaintext)--docbook[output in DocBook XML format]' \
+      '(--docbook --xml --plaintext)--html[output in HTML format]' \
       '--no-headers[suppress node separators and menus]' \
-      '(--docbook --html)--xml[output in XML (TexinfoML) format]' \
+      '(--docbook --html --plaintext)--xml[output in XML (TexinfoML) format]' \
+      '(--docbook --html --xml)--plaintext[output in plain text format]' \
+      '--dvi[output in dvi format]' \
+      '--dvipdf[output in pdf format]' \
+      '--ps[output in ps format]' \
+      '--pdf[output in pdf format]' \
       '(-E --macro-expand)'{-E,--macro-expand}'[output macro-expanded source to specified file]:file:_files' \
       '(--docbook --xml)--no-split[suppress splitting of output]' \
-      '--number-sections[output chapter and section numbers]' \
+      '--no-number-sections[output chapter and section numbers]' \
       '(-o --output=)'{-o,--output}'[specify output file]:output file:_files' \
-      '(--docbook --html --xml)--enable-encoding[output special characters]' \
+      '(--docbook --html --xml)--disable-encoding[output special characters]' \
       '(--docbook --html --xml)--fill-column=[specify width to break lines at]:width' \
       '(--docbook --html --xml)--footnote-style=[specify style for output of footnotes]:((separate\:in\ own\ node end\:at\ end\ of\ node))' \
       '(--docbook --html --xml)--paragraph-indent=[specify spaces to indent paragraphs by]' \
-      '(--docbook --html --xml)--split-size=[split Info files at specified size]:size' \
-      '--commands-in-node-names[allow @ commands in node names]' \
+      '(--docbook --html --xml)--split-size=[split Info files at specified size]:size [300000]' \
+      '(--docbook --xml --plaintext)--css-include=[specify file in include in HTML <style> output]:file:_files' \
+      '(--docbook --xml --plaintext)--css-ref=[generate reference to a CSS file]:URL:_urls' \
+      '(--docbook --xml --plaintext)--internal-links=[produce list of internal links in a file]:file:_files' \
+      '(--docbook --xml --plaintext)--split=[split output at specified boundary]:split boundary:(chapter section node)' \
+      '(--docbook --xml --plaintext)--transliterate-file-names[produce file names in ASCII transliteration]' \
+      '(--docbook --xml --plaintext)--node-files[produce redirection files for nodes]' \
+      '-Xopt=[specify option to texi2dvi]:options' \
       '-D[define variable]:variable' \
       '-I[specify directory to append to @include search path]:directory:_files -/' \
       '-P[specify directory to prepend to @include search path]:directory:_files -/' \
       '-U[undefine variable]:variable' \
+      '(--docbook --no-ifdocbook)--ifdocbook[process @ifdocbook and @docbook even when not generating Docbook]' \
       '(--html --no-ifhtml)--ifhtml[process @ifhtml and @html when not generating HTML]' \
       '(--no-ifinfo)--ifinfo[process @ifinfo even when not generating Info]' \
+      '(--plaintext --no-ifplaintext)--ifplaintext[process @ifplaintext even when not generating plain text]' \
       '(--no-iftex)--iftex[process @iftex and @tex text]' \
-      '(--no-ifplaintext)--ifplaintext[process @ifplaintext even when not generating plain text]' \
-      '(--ifhtml)--no-ifhtml[do not process @ifhtml and @html text]' \
-      '(--ifinfo)--no-ifinfo[do not process @ifinfo text]' \
-      '(--ifplaintext)--no-ifplaintext[do not process @ifplaintext text]' \
-      '(--iftex)--no-iftex[do not process @iftex and @tex text]' \
+      '(--xml --no-ifxml)--ifxml[process @ifxml and @xml]' \
+      "(--ifdocbook --html --xml --plaintext)--no-ifdocbook[don't process @ifdocbook and @docbook text]" \
+      "(--ifhtml --docbook --xml --plaintext)--no-ifhtml[don't process @ifhtml and @html text]" \
+      "(--ifinfo --docbook --html --xml --plaintext)--no-ifinfo[don't process @ifinfo text]" \
+      "(--ifplaintext --docbook --html --xml)--no-ifplaintext[don't process @ifplaintext text]" \
+      "(--iftex --docbook --html --xml --plaintext)--no-iftex[don't process @iftex and @tex text]" \
+      "(--ifxml --docbook --html --xml --plaintext)--no-ifxml[don't process @ifxml and @xml text]" \
       '*:texinfo file:_texi'
       return
   ;;
-  texi2dvi)
+  (pdf|)texi2(dvi|pdf))
     _arguments -s \
       '(-b --batch)'{-b,--batch}'[no interaction]' \
-      '(-c --clean)'{-c,--clean}'[remove all auxiliary files]' \
       '(-D --debug)'{-D,--debug}'[turn on shell debugging (set -x)]' \
       '(- *)'{-h,--help}'[display help information]' \
       '(-o --output)'{-o,--output=}'[specify output file]:output file:_files' \
       '(-q -s --quiet --silent -V --verbose)'{-q,-s,--silent,--quiet}'[no output except errors]' \
       '(-q -s --quiet --silent -V --verbose)'{-V,--verbose}'[report on what is done]' \
       '(- *)'{-v,--version}'[display version information]' \
+      "--max-iterations=[don't process files more than specified times]:iterations [7]" \
+      '--mostly-clean[remove the auxiliary files and directories]' \
       '-@[use @input instead of \input; for preloaded Texinfo]' \
-      '(-e --expand)'{-e,--expand}'[force macro expansion using makeinfo]' \
+      '(-p --pdf --dvipdf --html --info --ps --text)--dvi[output a DVI file]' \
+      '(-p --pdf --dvi --html --info --ps --text)--dvipdf[output a PDF file via DVI]' \
+      '(-p --pdf --dvi --dvipdf --info --ps --text)--html[output an HTML file]' \
+      '(-p --pdf --dvi --dvipdf --html --ps --text)--info[output an Info file]' \
+      '(-p --pdf --dvi --dvipdf --html --info --ps --text)'{-p,--pdf}'[use pdftex or pdflatex for processing]' \
+      '(-p --pdf --dvi --dvipdf --html --info --text)--ps[output a PostScript file]' \
+      '(-p --pdf --dvi --dvipdf --html --info --ps)--text[output a plain text file]' \
+      '(-e -E --expand)'{-e,-E,--expand}'[force macro expansion using makeinfo]' \
       '-I[specify search dir for texinfo files]:directory:_files -/' \
       '(-l --language)'{-l,--language}'[specify language of input file]:language:(LaTeX Texinfo)' \
-      '(-p --pdf)'{-p,--pdf}'[use pdftex or pdflatex for processing]' \
-      \*{-t,--texinfo}'[specify command to insert after @setfilename]:command' \
+      "--no-line-error[don't pass --file-line-error to TeX]" \
+      '--shell-escape[pass --shell-escape to TeX]' \
+      '--src-specials[pass --src-specials to TeX]' \
+      \*{-t,--command,--texinfo}'[specify command to insert after @setfilename]:command' \
+      '--translate-file=[use given charset translation file for TeX]:file:_files' \
+      '(--tidy -c --clean)--build=[specify build mode]:build mode:(local tidy clean)' \
+      '(--tidy -c --clean --build)--tidy[same as --build=tidy]' \
+      '(--tidy -c --clean --build)'{--tidy,-c,--clean}'[same as --build=clean]' \
+      '--build-dir=[specify build directory]:directory:_directories' \
       '*:file:_texi'
       return
   ;;
   texindex)
-    _arguments \
+    _arguments -S \
       '(* -)--help[display help]' \
       '(* -)--version[display version info]' \
-      '(--no-keep)--keep[keep temporary files around after processing]' \
-      '(--keep)--no-keep[do not keep temporary files (default)]' \
-      '(-o --output)'{-o,--output=}'[specify output file]:file:_files' \
       '*:texinfo file:_texi'
       return
   ;;
   tkinfo)
+    cmd=$commands[info]
     _x_arguments -C \
+      '(-)--help' \
       '-+'{headers,buttons,balloons,scrollthrough,pagesep,showdir} \
       '-linklook:menu display:(color font underline)' \
       '-highlight:link display:(color inverse underline)' \
       '-searchlook:search match display:(color inverse underline)' \
       '-iconic' \
       '-dir:info path:_dir_list' \
-      '-file:info file:_files -g "*.info(|.gz|.bz2)(-.)"' \
-      '-node:info node:->item' \
-      '*::menu items:->item' && ret=0
-    info=( _call_program info info ${(kv)opt_args[(I)-file]/-file/-f} )
+      '-file:info file:->infofiles' \
+      '-node:info node:->nodes' \
+      '*::menu items:->infomanuals' && ret=0
+    info=( info ${(kv)opt_args[(I)-file]/-file/-f} )
   ;;
 esac
 
-case $state in
-  item )
-    local -a items tags expl infopath
-    (( $#INFOPATH )) && infopath=( -W ${s/:/INFOPATH} )
+if [[ -n $state ]]; then
+  local chr cache file q
+  local -a expl suf tags
+  local -i36 hash=5381
+  local -aU infopath=( /usr/share/info ${commands[info]:h:h}/share/info ${(s.:.)INFOPATH} $infodirs )
+  infopath=( $^infopath(N) )
+  # run simple hash function on infopath
+  for chr in "${(s..)infopath}"; do
+    (( hash += (hash << 5) + ##$chr ))
+  done
+  typeset +i -l hash=${hash#*\#}
+  cache=_cache_info_nodes_$hash
+  typeset -gHU $cache
+
+  if [[ $state = infomanuals ]]; then
+    [[ -z $compstate[quote] ]] && q='\\'
+    if compset -P "${q}\("; then
+      if [[ -prefix *\) ]]; then
+	file="${PREFIX%%\)*}"
+	compset -P 1 '*\)'
+	state=nodes
+      else
+	compset -S "${q}\)*" || suf=( -S "${q[1]})" )
+	state=infofiles
+      fi
+    fi
+  fi
 
-    tags=(items)
-    if [[ $CURRENT -eq 1 ]]; then
-	tags+=files
+  [[ -z $file ]] && file=${opt_args[-f]:-$line[1]}
+  if [[ $state = info* ]]; then
+    local -aU files=( $^infopath/*.info(|.gz|.bz2)(-.:t:s/.gz//:s/.bz2//:r) )
+    local items
+    if (( ! $#files )); then
+      _info_retrieve_nodes
+      files=( ${(P)cache%%:*} )
+    fi
+    items=( ${${${(M)${(f)"$(_call_program menu-items info -o-)"}:#(#s)\* *: \(*}#??}%%\)*} )
+    files+=( ${items##*\(} )
+    tags=( info-files )
+    if [[ $state != infofiles ]]; then
+      tags+=( menu-items )
+      items=( ${items%:*} )
+    fi
+  elif [[ $state = nodes ]]; then
+    tags=( menu-items )
+    if [[ -n $file ]]; then
+      _info_retrieve_nodes
+      nodes=( ${(@PM)cache:#${file}:*} )
+      tags+=( info-nodes )
     fi
+    items=( ${${${(M)${(f)"$(_call_program menu-items info -o- $file)"}:#(#s)\* *::*}%%::*}#??} )
+  fi
 
-    _tags $tags
-    while _tags; do
-	if _requested files expl 'info file'; then
-	    _files "$expl[@]" $infopath -g '*.info(-.)' && ret=0
-	fi
-	if _requested items; then
-	    items=(${${(M)${${(f)"$(${info} --output - ${words[1,CURRENT-1]} 2>/dev/null)"}[1,(r)[[:space:]]#--- The Detailed Node Listing ---[[:space:]]#]}:#\* *~\* Menu:*}:/(#b)\*[[:space:]]##([^:]##):(#B)( \(?##\)[^.]#.|(:|))[[:space:]]#(#b)(*)[[:space:]]#/$match[1]${match[2]:+:}$match[2]})
+  _tags $tags
 
-	    _describe -t items "menu item" items && ret=0
-	fi
-    done
-  ;;
-esac
+  while _tags; do
+    _requested info-files expl 'info file' compadd $suf -M 'm:{a-zA-Z}={A-Za-z}' -a files && ret=0
+    _requested menu-items expl 'menu item' compadd -M 'm:{a-zA-Z}={A-Za-z}' -a items && ret=0
+    _requested info-nodes expl 'node' compadd -M 'm:{a-zA-Z}={A-Za-z}' ${nodes#*:} && ret=0
+
+    (( ret )) || break
+  done
+fi
 
 return ret
diff --git a/Completion/Unix/Command/_tin b/Completion/Unix/Command/_tin
index c63ccd9e6..61d203d1f 100644
--- a/Completion/Unix/Command/_tin
+++ b/Completion/Unix/Command/_tin
@@ -3,6 +3,8 @@
 local newshosts expl state line curcontext="$curcontext" ret=1
 
 _arguments -C -s \
+  '(-6)-4[force connecting via IPv4]' \
+  '(-4)-6[force connecting via IPv6]' \
   '-a[toggle color flag]' \
   '-A[force authentication on connect]' \
   '-c[mark all news as read in subscribed groups]' \
diff --git a/Completion/Unix/Command/_tmux b/Completion/Unix/Command/_tmux
index 93b5c7faa..0917da604 100644
--- a/Completion/Unix/Command/_tmux
+++ b/Completion/Unix/Command/_tmux
@@ -51,7 +51,7 @@
 
 # Global variables; setup the first time _tmux is called.
 # For $_tmux_commands[] generation, see the very end of this file.
-typeset -ga _tmux_commands _tmux_aliases
+typeset -ga _tmux_commands=() _tmux_aliases=()
 typeset -gA _tmux_aliasmap
 
 _tmux_aliasmap=(
@@ -147,970 +147,775 @@ _tmux_aliasmap=(
 
 # --- Sub-command functions ---
 # These *must* be called _tmux-*(); The description generation relies on
-# them being names that way. *No* other functions may match that pattern.
+# them being named that way. *No* other functions may match that pattern.
 # Other utility functions should be named __tmux-*() (see below).
 #
 # Another thing, the description generation needs, is handling of
 # $tmux_describe: If that parameter is non-empty, the sub-command function
 # should only print a description of the sub-command it handles and return
-# immidiately after doing so.
+# immediately after doing so.
 #
 # To add support for a new sub-command, you only have to add a new
 # _tmux-<foo>() function below (preferably alphabetically sorted), that
 # behaves like described above; and add a alias->command pair in the
-# _tmux_aliasmap associative array above (if the comand in fact has an
+# _tmux_aliasmap associative array above (if the command in fact has an
 # alias). The rest should just work[tm].
 
-function _tmux-attach-session() {
-    [[ -n ${tmux_describe} ]] && print "Attach or switch to a session" && return
-    local -a args
+_tmux-attach-session() {
+  [[ -n ${tmux_describe} ]] && print "attach or switch to a session" && return
+
+  _arguments -s \
+    '-c+[specify working directory for the session]:directory:_directories' \
+    '-d[detach other clients attached to target session]' \
+    '-r[put the client into read-only mode]' \
+    '-t+[specify target session]:target session:__tmux-sessions' \
+    "-E[don't apply update-environment option]"
+}
+
+_tmux-bind-key() {
+  [[ -n ${tmux_describe} ]] && print "bind a key to a command" && return
+  _arguments -s -A "-*" \
+    '-c[bind to command mode instead of normal mode]' \
+    '-n[make the binding work without the need for the prefix key]' \
+    '-r[the key may repeat]' \
+    '-t+[specify mode table for the binding]:mode table:__tmux-mode-tables' \
+    '-R+[specify repeat count]:repeat count' \
+    '-T+[specify key table for the binding]:key table' \
+    '1:key' \
+    '*:::template:_tmux'
+}
+
+_tmux-break-pane() {
+  [[ -n ${tmux_describe} ]] && print "break a pane from an existing into a new window" && return
+  _arguments -s \
+    "-d[don't make the new window become the active one]" \
+    '-F+[specify output format]:format:__tmux-format__tmux-format' \
+    '-P[print information of new window after it has been created]' \
+    '-s+[specify source pane]:pane:__tmux-panes' \
+    '-t+[specify destination window]:pane:__tmux-panes'
+}
+
+_tmux-capture-pane() {
+  [[ -n ${tmux_describe} ]] && print "capture the contents of a pane to a buffer" && return
+  _arguments -s \
+    '-a[use alternate screen]' \
+    '(-p)-b+[choose target buffer]:target buffer:__tmux-buffers' \
+    '-C[escape non-printable characters as octal \\ooo]' \
+    '-e[include escape sequences for attributes etc]' \
+    '-E[specify last line to capture]:line number (- means last line)' \
+    '-J[join wrapped lines and preserve trailing space]' \
+    '-q[ignore errors when trying to access alternate screen]' \
+    '(-b)-p[print data to stdout]' \
+    '-P[only capture beginnings of as-yet incomplete escape sequences]' \
+    '-S[specify start line to capture]:first line (- means start of scrollback)' \
+    '-t+[choose source pane]:source pane:__tmux-panes'
+}
+
+_tmux-choose-buffer() {
+  [[ -n ${tmux_describe} ]] && print "put a window into buffer choice mode" && return
+  _arguments -s \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-t+[specify target window]:session:__tmux-windows' \
+    '*:::template:_tmux'
+}
+
+_tmux-choose-client() {
+  [[ -n ${tmux_describe} ]] && print "put a window into client choice mode" && return
+  _arguments -s \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-t+[specify target window]:session:__tmux-windows' \
+    '*:::template:_tmux'
+}
+
+_tmux-choose-session() {
+  [[ -n ${tmux_describe} ]] && print "put a window into session choice mode" && return
+  _arguments -s \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-t+[specify target window]:session:__tmux-windows' \
+    '*:::template:_tmux'
+}
+
+_tmux-choose-tree() {
+  [[ -n ${tmux_describe} ]] && print "put a window into tree choice mode" && return
+  _arguments -s \
+    '-b+[override default session command]:session-command' \
+    '-c+[override default window command]:window-command' \
+    '-S+[specify session format]:session-format:__tmux-formats' \
+    '-s[choose among sessions]' \
+    '-t+[specify target window]:session:__tmux-windows' \
+    '-u[show generated tree uncollapsed at startup]' \
+    '-W+[specify window format]:window-format:__tmux-formats' \
+    '-w[choose among windows]' \
+    '*:::template:_tmux'
+}
+
+_tmux-choose-window() {
+  [[ -n ${tmux_describe} ]] && print "put a window into window choice mode" && return
+  _arguments -s \
+    '-F=[specify output format]:format:__tmux-format' \
+    '-t+[specify target window]:session:__tmux-windows' \
+    '*:::template:_tmux'
+}
+
+_tmux-clear-history() {
+  [[ -n ${tmux_describe} ]] && print "remove and clear history for a pane" && return
+  _arguments '-t+[specify target pane]:pane:__tmux-panes'
+}
+
+_tmux-clock-mode() {
+  [[ -n ${tmux_describe} ]] && print "enter clock mode" && return
+  _arguments '-t+[specify target pane]:pane:__tmux-panes'
+}
+
+_tmux-command-prompt() {
+  [[ -n ${tmux_describe} ]] && print "open the tmux command prompt in a client" && return
+  _arguments -s \
+    '-I+[specify list of initial inputs]:initial-text (comma-separated list)' \
+    '-p+[specify list of prompts]:prompts (comma-separated list)' \
+    '-t+[specify target client]:client:__tmux-clients' \
+    '*:::template:_tmux'
+}
+
+_tmux-confirm-before() {
+  [[ -n ${tmux_describe} ]] && print "run a command but ask for confirmation before" && return
+  _arguments -s \
+    '-p+[specify prompt]:prompt string' \
+    '-t+[specify target client]:client:__tmux-clients' \
+    '*:::command:_tmux'
+}
+
+_tmux-copy-mode() {
+  [[ -n ${tmux_describe} ]] && print "enter copy mode" && return
+  _arguments -s \
+    '-t+[specify target pane]:pane:__tmux-panes' \
+    '-u[scroll up one page]' \
+    '-M[begin a mouse drag]'
+}
+
+_tmux-delete-buffer() {
+  [[ -n ${tmux_describe} ]] && print "delete a paste buffer" && return
+  _arguments '-b+[specify target buffer name]:buffer:__tmux-buffers'
+}
+
+_tmux-detach-client() {
+  [[ -n ${tmux_describe} ]] && print "detach a client from the server" && return
+  _arguments -s \
+    '-a[kill all clients except for the named by -t]' \
+    '-P[send SIGHUP to parent process]' \
+    '-s+[specify target session and kill its clients]:session:__tmux-sessions' \
+    '-t+[specify target client]:client:__tmux-clients'
+}
 
-    args=(
-        '-c[specify working directory for the session]:directory:_path_files -g "*(-/)"'
-        '-d[detach other clients attached to target session]'
-        '-r[put the client into read-only mode]'
-        '-t[choose a target session]:target session:__tmux-sessions'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-bind-key() {
-    [[ -n ${tmux_describe} ]] && print "Bind a key to a command" && return
-    local curcontext="${curcontext}" state
-    local -a args
-
-    args=(
-        '-c[bind to command mode instead of normal mode]'
-        '-n[make the binding work without the need for the prefix key]'
-        '-r[the key may repeat]'
-        '-t[choose a key table for the binding]:key tables:__tmux-key-tables'
-        '1: :->key'
-        '*:: :->command_and_args'
-    )
-    _arguments -C : ${args} && return
-
-    if [[ ${state} == 'key' ]]; then
-        _message "key"
-    else
-        # quite cool, that this works. :-)
-        _tmux
-    fi
-}
-
-function _tmux-break-pane() {
-    [[ -n ${tmux_describe} ]] && print "Break a pane from an existing into a new window" && return
-    local -a args
-    args=(
-        '-d[do not make the new window become the active one]'
-        '-F[specify format of output]:format:__tmux-format__tmux-format'
-        '-P[print information of new window after it has been created]'
-        '-t[choose a target pane]:panes:__tmux-panes'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-capture-pane() {
-    [[ -n ${tmux_describe} ]] && print "Capture the contents of a pane to a buffer" && return
-    local -a args
-    args=(
-        '-a[use alternate screen]'
-        '-b[choose target buffer]:target buffer:__tmux-buffers'
-        '-C[escape non-printable characters as octal \\ooo]'
-        '-e[include escape sequences for attributes etc]'
-        '-E[specify last line to capture. - means last line of pane]'
-        '-J[join wrapped lines and preserver trailing space]'
-        '-q[ignore errors when trying to access alternate screen]'
-        '-p[print data to stdout]'
-        '-P[only capture that is the beginning of an as-yet incomplete esc seq]'
-        '-S[specify start line to capture. - means first line of scrollback]'
-        '-t[choose source pane]:source pane:__tmux-panes'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-choose-buffer() {
-    [[ -n ${tmux_describe} ]] && print "Put a window into buffer choice mode" && return
-    local -a args
-    args=(
-        '-F[specify format of output]:format:__tmux-format'
-        '-t[choose a target window]:sessions:__tmux-windows'
-        '*:: :->tmpl'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-choose-client() {
-    [[ -n ${tmux_describe} ]] && print "Put a window into client choice mode" && return
-    local -a args
-    args=(
-        '-F[specify format of output]:format:__tmux-format'
-        '-t[choose a target window]:sessions:__tmux-windows'
-        '*:: :->tmpl'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-choose-session() {
-    [[ -n ${tmux_describe} ]] && print "Put a window into session choice mode" && return
-    local -a args
-    args=(
-        '-F[specify format of output]:format:__tmux-format'
-        '-t[choose a target window]:sessions:__tmux-windows'
-        '*:: :->tmpl'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-choose-tree() {
-    [[ -n ${tmux_describe} ]] && print "Put a window into tree choice mode" && return
-    local -a args
-    args=(
-        '-b[override default session command]:session-command:'
-        '-c[override default window command]:window-command:'
-        '-S[specify session format]:session-format:__tmux-formats'
-        '-s[choose among sessions]'
-        '-t[choose a target window]:sessions:__tmux-windows'
-        '-u[show generated tree uncollapsed at startup]'
-        '-W[specify window format]:window-format:__tmux-formats'
-        '-w[choose among windows]'
-        '*:: :->tmpl'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-choose-window() {
-    [[ -n ${tmux_describe} ]] && print "Put a window into window choice mode" && return
-    local -a args
-    args=(
-        '-F[specify format of output]:format:__tmux-format'
-        '-t[choose a target window]:sessions:__tmux-windows'
-        '*:: :->tmpl'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-clear-history() {
-    [[ -n ${tmux_describe} ]] && print "Remove and clear history for a pane" && return
-    local -a args
-    args=('-t[choose a target pane]:panes:__tmux-panes')
-    _arguments : ${args}
-}
-
-function _tmux-clock-mode() {
-    [[ -n ${tmux_describe} ]] && print "Enter clock mode" && return
-    local -a args
-    args=('-t[choose a target pane]:panes:__tmux-panes')
-    _arguments : ${args}
-}
-
-function _tmux-command-prompt() {
-    [[ -n ${tmux_describe} ]] && print "Open the tmux command prompt in a client" && return
-    local state
-    local -a args
-    args=(
-        '-I[comma separated list of initial inputs]:initial-text:->ilist'
-        '-p[list of prompts]:prompts:->plist'
-        '-t[choose a target client]:clients:__tmux-clients'
-        '*:: :->tmpl'
-    )
-    _arguments -C : ${args} && return
-    if [[ ${state} == 'plist' ]]; then
-        _message "comma seperated list of prompts"
-        return
-    elif [[ ${state} == 'ilist' ]]; then
-        _message "comma seperated list of initial text"
-        return
-    fi
-    __tmux-lastarg ${state} 'tmpl' 1 "command template"
-}
-
-function _tmux-confirm-before() {
-    [[ -n ${tmux_describe} ]] && print "Run a command but ask for confirmation before" && return
-    local state
-    local -a args
-    args=(
-        '-p[specify prompt]:prompt:->prompt'
-        '-t[choose a target client]:clients:__tmux-clients'
-        '*:: :->command_and_args'
-    )
-    _arguments -C : ${args} && return
-    if [[ ${state} == 'prompt' ]]; then
-        _message 'prompt string'
-        return
-    fi
-    __tmux-lastarg ${state} 'command_and_args' 1 "command string"
-}
-
-function _tmux-copy-mode() {
-    [[ -n ${tmux_describe} ]] && print "Enter copy mode" && return
-    local -a args
-    args=(
-        '-t[choose a target pane]:panes:__tmux-panes'
-        '-u[scroll up one page]'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-delete-buffer() {
-    [[ -n ${tmux_describe} ]] && print "Delete a paste buffer" && return
-    local -a args
-    args=('-b[choose a target buffer index]:buffers:__tmux-buffers')
-    _arguments : ${args} && return
-}
-
-function _tmux-detach-client() {
-    [[ -n ${tmux_describe} ]] && print "Detach a client from the server" && return
-    local -a args
-    args=(
-        '-a[kill all clients except for the named by -t]'
-        '-P[send SIGHUP to parent process]'
-        '-s[choose a target session and kill its clients]:sessions:__tmux-sessions'
-        '-t[choose a target client]:clients:__tmux-clients'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-display-message() {
-    [[ -n ${tmux_describe} ]] && print "Display a message in the status line" && return
-    local -a args
-    args=(
-        '-c[choose a target client]:clients:__tmux-clients'
-        '-p[print message to stdout]'
-        '-t[choose a target client]:clients:__tmux-clients'
-        '*:: :->msg'
-    )
-    _arguments : ${args} && return
-    __tmux-lastarg ${state} 'msg' 1 "message"
-}
-
-function _tmux-display-panes() {
-    [[ -n ${tmux_describe} ]] && print "Display an indicator for each visible pane" && return
-    local -a args
-    args=('-t[choose a target client]:clients:__tmux-clients')
-    _arguments : ${args}
-}
-
-function _tmux-find-window() {
-    [[ -n ${tmux_describe} ]] && print "Search for a pattern in windows" && return
-    local curcontext="${curcontext}" state
-    local -a args
-    args=(
-        '-C[match visible contents]'
-        '-F[specify format of output]:format:__tmux-format'
-        '-N[match window name]'
-        '-T[match window title]'
-        '-t[choose a target window]:windows:__tmux-windows'
-        '*:: :->pattern'
-    )
-    _arguments : ${args} && return
-    __tmux-lastarg ${state} 'pattern' 1 "window search pattern"
-}
-
-function _tmux-has-session() {
-    [[ -n ${tmux_describe} ]] && print "Check and report if a session exists on the server" && return
-    local -a args
-    args=('-t[choose a target session]:sessions:__tmux-sessions')
-    _arguments : ${args}
-}
-
-function _tmux-if-shell() {
-    [[ -n ${tmux_describe} ]] && print "Execute a tmux command if a shell-command succeeded" && return
-    local -a args
-    args=(
-        '-b[run shell command in background]'
-        '-F[do not execute shell command but use it as a string-value]'
-        '1:shell command:'
-        '2:tmux command:'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-join-pane() {
-    [[ -n ${tmux_describe} ]] && print "Split a pane and move an existing one into the new space" && return
-    local -a args
-    args=(
-        '-b[join source pane left of or above target pane]'
-        '-d[do not make the new window become the active one]'
-        '-h[split horizontally]'
-        '-v[split vertically]'
-        '-l[define new pane'\''s size]: :_guard "[0-9]#" "numeric value"'
-        '-p[define new pane'\''s size in percent]: :_guard "[0-9]#" "numeric value"'
-        '-s[choose source pane]:window:__tmux-panes'
-        '-t[choose target pane]:window:__tmux-panes'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-kill-pane() {
-    [[ -n ${tmux_describe} ]] && print "Destroy a given pane" && return
-    local -a args
-    args=(
-        '-a[kill all panes except the one specified by -t]'
-        '-t[choose a target pane]:panes:__tmux-panes'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-kill-server() {
-    [[ -n ${tmux_describe} ]] && print "Kill clients, sessions and server" && return
-    __tmux-nothing-else
-}
-
-function _tmux-kill-session() {
-    [[ -n ${tmux_describe} ]] && print "Destroy a given session" && return
-    local -a args
-    args=(
-        '-a[kill all session except the one specified by -t]'
-        '-t[choose a target session]:sessions:__tmux-sessions'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-kill-window() {
-    [[ -n ${tmux_describe} ]] && print "Destroy a given window" && return
-    local -a args
-    args=(
-        '-a[kill all windows except the one specified by -t]'
-        '-t[choose a target window]:windows:__tmux-windows'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-last-pane() {
-    [[ -n ${tmux_describe} ]] && print "Select the previously selected pane" && return
-    local -a args
-    args=(
-        '-d[disable input to the pane]'
-        '-e[enable input to the pane]'
-        '-t[choose a session]:sessions:__tmux-sessions'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-last-window() {
-    [[ -n ${tmux_describe} ]] && print "Select the previously selected window" && return
-    local -a args
-    args=('-t[choose a session]:sessions:__tmux-sessions')
-    _arguments : ${args} && return
-}
-
-function _tmux-link-window() {
-    [[ -n ${tmux_describe} ]] && print "Link a window to another" && return
-    local -a args
-    args=(
-        '-d[do not make the new window become the active one]'
-        '-k[kill the target window if it exists]'
-        '-s[choose source window]:window:__tmux-windows'
-        '-t[choose destination window]:window:__tmux-windows'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-list-buffers() {
-    [[ -n ${tmux_describe} ]] && print "List paste buffers of a session" && return
-    local -a args
-    args=('-F[specify format of output]:format:__tmux-format')
-    _arguments : ${args} && return
-}
-
-function _tmux-list-clients() {
-    [[ -n ${tmux_describe} ]] && print "List clients attached to server" && return
-    local -a args
-    args=(
-        '-F[specify format of output]:format:__tmux-format'
-        '-t[choose a session]:sessions:__tmux-sessions'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-list-commands() {
-    [[ -n ${tmux_describe} ]] && print "List supported sub-commands" && return
-    __tmux-nothing-else
-}
-
-function _tmux-list-keys() {
-    [[ -n ${tmux_describe} ]] && print "List all key-bindings" && return
-    local -a args
-    args=('-t[choose a key table]:key table:__tmux-key-tables')
-    _arguments : ${args} && return
-}
-
-function _tmux-list-panes() {
-    [[ -n ${tmux_describe} ]] && print "List panes of a window" && return
-    local -a args
-    args=(
-        '-a[list all panes the server possesses]'
-        '-F[specify format of output]:format:__tmux-format'
-        '-s[if specified, -t chooses a session]'
-        # TODO: Use __tmux-windows or __tmux-sessions depending on -s.
-        '-t[choose a window]:windows:__tmux-windows'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-list-sessions() {
-    [[ -n ${tmux_describe} ]] && print "List sessions managed by server" && return
-    local -a args
-    args=('-F[specify format of output]:format:__tmux-format')
-    _arguments : ${args} && return
-}
-
-function _tmux-list-windows() {
-    [[ -n ${tmux_describe} ]] && print "List windows of a session" && return
-    local -a args
-    args=(
-        '-a[list all windows the tmux server possesses]'
-        '-F[specify format of output]:format:__tmux-format'
-        '-t[choose a session]:sessions:__tmux-sessions'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-load-buffer() {
-    [[ -n ${tmux_describe} ]] && print "Load a file into a paste buffer" && return
-    local -a args
-
-    args=(
-        '-b[choose a target buffer index]:panes:__tmux-buffers'
-        '1:file name:_files -g "*(-.)"'
-    )
-    _arguments : ${args} && return
+_tmux-display-message() {
+  [[ -n ${tmux_describe} ]] && print "display a message in the status line" && return
+  _arguments -s -S \
+    '-c+[specify target client]:client:__tmux-clients' \
+    '-p[print message to stdout]' \
+    '-t+[specify target client]:client:__tmux-clients' \
+    '-F+[specify output format]:format:__tmux-format' \
+    ':message'
 }
 
-function _tmux-lock-client() {
-    [[ -n ${tmux_describe} ]] && print "Lock a client" && return
-    local -a args
-    args=('-t[choose a client]:clients:__tmux-clients')
-    _arguments : ${args} && return
+_tmux-display-panes() {
+  [[ -n ${tmux_describe} ]] && print "display an indicator for each visible pane" && return
+  _arguments '-t+[specify target client]:client:__tmux-clients'
 }
 
-function _tmux-lock-server() {
-    [[ -n ${tmux_describe} ]] && print "Lock all clients attached to the server" && return
-    __tmux-nothing-else
+_tmux-find-window() {
+  [[ -n ${tmux_describe} ]] && print "search for a pattern in windows" && return
+  _arguments -s \
+    '-C[match visible contents]' \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-N[match window name]' \
+    '-T[match window title]' \
+    '-t+[specify target window]:window:__tmux-windows' \
+    ':window search pattern'
 }
 
-function _tmux-lock-session() {
-    [[ -n ${tmux_describe} ]] && print "Lock all clients attached to a session" && return
-    local -a args
-    args=('-t[choose a session]:sessions:__tmux-sessions')
-    _arguments : ${args} && return
-}
-
-function _tmux-move-pane() {
-    [[ -n ${tmux_describe} ]] && print "Move a pane into a new space" && return
-    local -a args
-    args=(
-        '-b[join source pane left of or above target pane]'
-        '-d[do not make the new window become the active one]'
-        '-h[split horizontally]'
-        '-v[split vertically]'
-        '-l[define new pane'\''s size]: :_guard "[0-9]#" "numeric value"'
-        '-p[define new pane'\''s size in percent]: :_guard "[0-9]#" "numeric value"'
-        '-s[choose source pane]:window:__tmux-panes'
-        '-t[choose target pane]:window:__tmux-panes'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-move-window() {
-    [[ -n ${tmux_describe} ]] && print "Move a window to another" && return
-    local -a args
-    args=(
-        '-d[do not make the new window become the active one]'
-        '-k[kill the target window if it exists]'
-        '-s[choose source window]:window:__tmux-windows'
-        '-r[renumber windows in session in sequential order]'
-        '-t[choose destination window]:window:__tmux-windows'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-new-session() {
-    [[ -n ${tmux_describe} ]] && print "Create a new session" && return
-    local -a args
-    args=(
-        '-A[attach to existing session if it already exists]'
-        '-c[specify working directory for the session]:directory:_path_files -g "*(-/)"'
-        '-d[do not attach new session to current terminal]'
-        '-D[in case of -A behave like attach-session'\''s -d]'
-        '-F[specify format of output]:format:__tmux-format'
-        '-n[name the initial window]:window name'
-        '-P[print information about new session after it is created]'
-        '-s[name the session]:session name:__tmux-sessions'
-        '-t[specify target session]:sessions:__tmux-sessions'
-        '-x[specify width]:width:_guard "[0-9]#" "numeric value"'
-        '-y[specify height]:height:_guard "[0-9]#" "numeric value"'
-        '*:: :_cmdstring'
-    )
-    _arguments -s : ${args}
-}
-
-function _tmux-new-window() {
-    [[ -n ${tmux_describe} ]] && print "Create a new window" && return
-    local -a args
-    args=(
-        '-a[insert new window at next free index from -t]'
-        '-c[specify working directory for the session]:directory:_path_files -g "*(-/)"'
-        '-d[do not make the new window become the active one]'
-        '-F[specify format of output]:format:__tmux-format'
-        '-k[destroy it if the specified window exists]'
-        '-n[specify a window name]:window name:'
-        '-P[print information about new window after it is created]'
-        '-t[specify target window]:windows:__tmux-windows'
-        '*:: :_cmdstring'
-    )
-    _arguments : ${args}
+_tmux-has-session() {
+  [[ -n ${tmux_describe} ]] && print "check and report if a session exists on the server" && return
+  _arguments '-t+[specify target session]:session:__tmux-sessions'
 }
 
-function _tmux-next-layout() {
-    [[ -n ${tmux_describe} ]] && print "Move a window to the next layout" && return
-    local -a args
-    args=('-t[choose target window]:window:__tmux-windows')
-    _arguments : ${args}
+_tmux-if-shell() {
+  [[ -n ${tmux_describe} ]] && print "execute a tmux command if a shell-command succeeded" && return
+  local curcontext="$curcontext" state line ret=1
+  _arguments -C -s \
+    '-b[run shell command in background]' \
+    "-F[don't execute shell command but use it as a string-value]" \
+    '-t+[specify target pane]:pane:__tmux-panes' \
+    '1:shell command:_cmdstring' \
+    '2:tmux command (success):->tmuxcmd' \
+    '3:tmux command (failure):->tmuxcmd' && ret=0
+  if [[ -n $state ]]; then
+    compset -q
+    _tmux && ret=0
+  fi
 }
 
-function _tmux-next-window() {
-    [[ -n ${tmux_describe} ]] && print "Move to the next window in a session" && return
-    local -a args
-    args=(
-        '-a[move to the next window with an alert]'
-        '-t[choose target session]:session:__tmux-sessions'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-paste-buffer() {
-    [[ -n ${tmux_describe} ]] && print "Insert a paste buffer into the window" && return
-    local -a args
-    args=(
-        '-b[choose buffer]:source buffer:__tmux-buffers'
-        '-d[remove buffer from stack after pasting]'
-        '-p[use bracketed paste mode if the application requested it]'
-        '-r[do not replace LF with CR when pasting]'
-        '-s[specify separator]:separator:'
-        '-t[choose target window]:window:__tmux-windows'
-    )
-    _arguments : ${args}
+_tmux-join-pane() {
+  [[ -n ${tmux_describe} ]] && print "split a pane and move an existing one into the new space" && return
+  _arguments -s \
+    '-b[join source pane left of or above target pane]' \
+    "-d[don't make the new window become the active one]" \
+    '-h[split horizontally]' \
+    '-v[split vertically]' \
+    "-l+[define new pane's size]: :_guard '[0-9]#' 'numeric value'" \
+    "-p+[define new pane's size in percent]: :_guard '[0-9]#' 'numeric value'" \
+    '-s+[specify source pane]:pane:__tmux-panes' \
+    '-t+[specify target pane]:pane:__tmux-panes'
 }
 
-function _tmux-pipe-pane() {
-    [[ -n ${tmux_describe} ]] && print "Pipe output from a pane to a shell command" && return
-    local state
-    args=(
-        '-o[only open a pipe if none is currently opened]'
-        '-t[choose target pane]:pane:__tmux-panes'
-        '*:: :->cmd'
-    )
-    _arguments : ${args} && return
-    __tmux-lastarg ${state} 'cmd' 1 "command string"
+_tmux-kill-pane() {
+  [[ -n ${tmux_describe} ]] && print "destroy a given pane" && return
+  _arguments -s \
+    '-a[kill all panes except the one specified by -t]' \
+    '-t+[specify target pane]:pane:__tmux-panes'
 }
 
-function _tmux-previous-layout() {
-    [[ -n ${tmux_describe} ]] && print "Move a window to the previous layout" && return
-    local -a args
-    args=('-t[choose target window]:window:__tmux-windows')
-    _arguments : ${args}
+_tmux-kill-server() {
+  [[ -n ${tmux_describe} ]] && print "kill clients, sessions and server" && return
+  __tmux-nothing-else
 }
 
-function _tmux-previous-window() {
-    [[ -n ${tmux_describe} ]] && print "Move to the previous window in a session" && return
-    local -a args
-    args=(
-        '-a[move to the previous window with an alert]'
-        '-t[choose target session]:session:__tmux-sessions'
-    )
-    _arguments : ${args}
+_tmux-kill-session() {
+  [[ -n ${tmux_describe} ]] && print "destroy a given session" && return
+  _arguments -s \
+    '-a[kill all session except the one specified by -t]' \
+    '-t+[specify target session]:session:__tmux-sessions' \
+    '-C[clear alerts (bell, activity, silence) in all windows linked to the session]'
 }
 
-function _tmux-refresh-client() {
-    [[ -n ${tmux_describe} ]] && print "Refresh a client" && return
-    local -a args
-    args=(
-        '-S[Only update the client'\''s status bar]'
-        '-t[choose target client]:client:__tmux-clients'
-    )
-    _arguments : ${args}
+_tmux-kill-window() {
+  [[ -n ${tmux_describe} ]] && print "destroy a given window" && return
+  _arguments -s \
+    '-a[kill all windows except the one specified by -t]' \
+    '-t+[specify target window]:window:__tmux-windows'
 }
 
-function _tmux-rename-session() {
-    [[ -n ${tmux_describe} ]] && print "Rename a session" && return
-    local state
-    args=(
-        '-t[choose target session]:session:__tmux-sessions'
-        '*:: :->name'
-    )
-    _arguments : ${args} && return
-    __tmux-lastarg ${state} 'name' 1 "new session name"
+_tmux-last-pane() {
+  [[ -n ${tmux_describe} ]] && print "select the previously selected pane" && return
+  _arguments -s \
+    '-d[disable input to the pane]' \
+    '-e[enable input to the pane]' \
+    '-t+[specify session]:session:__tmux-sessions'
 }
 
-function _tmux-rename-window() {
-    [[ -n ${tmux_describe} ]] && print "Rename a window" && return
-    local state
-    args=(
-        '-t[choose target window]:window:__tmux-windows'
-        '*:: :->name'
-    )
-    _arguments : ${args} && return
-    __tmux-lastarg ${state} 'name' 1 "new window name"
-}
-
-function _tmux-resize-pane() {
-    [[ -n ${tmux_describe} ]] && print "Resize a pane" && return
-    args=(
-        '-D[resize downward]'
-        '-L[resize to the left]'
-        '-R[resize to the right]'
-        '-U[resize upward]'
-        '-t[choose target pane]:pane:__tmux-panes'
-        '-x[specify width]:width:_guard "[0-9]#" "numeric value"'
-        '-y[specify height]:height:_guard "[0-9]#" "numeric value"'
-        '-Z[toggle zoom of pane]'
-        '1::adjustment (defaults to one):_guard "[0-9]#" "numeric value"'
-    )
-    _arguments : ${args}
+_tmux-last-window() {
+  [[ -n ${tmux_describe} ]] && print "select the previously selected window" && return
+  _arguments '-t+[specify session]:session:__tmux-sessions'
 }
 
-function _tmux-respawn-pane() {
-    [[ -n ${tmux_describe} ]] && print "Reuse a pane in which a command has exited" && return
-    local -a args
-    args=(
-        '-k[kill window if it is in use]'
-        '-t[choose target pane]:window:__tmux-pane'
-        '*::command:_cmdstring'
-    )
-    _arguments : ${args}
+_tmux-link-window() {
+  [[ -n ${tmux_describe} ]] && print "link a window to another" && return
+  _arguments -s \
+    "-d[don't make the new window become the active one]" \
+    '-k[kill the target window if it exists]' \
+    '-s+[specify source window]:window:__tmux-windows' \
+    '-t+[specify destination window]:window:__tmux-windows'
 }
 
-function _tmux-respawn-window() {
-    [[ -n ${tmux_describe} ]] && print "Reuse a window in which a command has exited" && return
-    local -a args
-    args=(
-        '-k[kill window if it is in use]'
-        '-t[choose target window]:window:__tmux-windows'
-        '*::command:_cmdstring'
-    )
-    _arguments : ${args}
+_tmux-list-buffers() {
+  [[ -n ${tmux_describe} ]] && print "list paste buffers of a session" && return
+  _arguments '-F+[specify output format]:format:__tmux-format' 
 }
 
-function _tmux-rotate-window() {
-    [[ -n ${tmux_describe} ]] && print "Rotate positions of panes in a window" && return
-    local -a args
-    args=(
-        '-D[rotate downward]'
-        '-U[rotate upward]'
-        '-t[choose target window]:window:__tmux-windows'
-    )
-    _arguments : ${args}
+_tmux-list-clients() {
+  [[ -n ${tmux_describe} ]] && print "list clients attached to server" && return
+  _arguments -s \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-t+[specify session]:session:__tmux-sessions'
+}
+
+_tmux-list-commands() {
+  [[ -n ${tmux_describe} ]] && print "list supported sub-commands" && return
+  _arguments '-F+[specify format]:format'
 }
-
-function _tmux-run-shell() {
-    [[ -n ${tmux_describe} ]] && print "Execute a command without creating a new window" && return
-    local -a args
-    args=(
-        '-b[run shell command in background]'
-        '-t[choose target pane]:pane:__tmux-panes'
-        '*::command:_cmdstring'
-    )
-    _arguments : ${args}
+
+_tmux-list-keys() {
+  [[ -n ${tmux_describe} ]] && print "list all key-bindings" && return
+  _arguments -s \
+    '-t+[specify mode table]:mode table:__tmux-mode-tables' \
+    '-T+[specify key table]:key table'
+}
+
+_tmux-list-panes() {
+  [[ -n ${tmux_describe} ]] && print "list panes of a window" && return
+  local -a args
+  if (( ${+words[(r)-*s*]} )); then
+    args=( '-t+[specify target session]:session:__tmux-sessions' )
+  else
+    args=( '-t+[specify target window]:window:__tmux-windows' )
+  fi
+  _arguments -s $args \
+    '-a[list all panes the server possesses]' \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-s[if specified, -t chooses a session]'
 }
-
-function _tmux-save-buffer() {
-    [[ -n ${tmux_describe} ]] && print "Save a paste buffer to a file" && return
-    local -a args
-
-    args=(
-        '-a[append to rather than overwriting file]'
-        '-b[choose a target buffer index]:buffer:__tmux-buffers'
-    )
-    _arguments : ${args} && return
+
+_tmux-list-sessions() {
+  [[ -n ${tmux_describe} ]] && print "list sessions managed by server" && return
+  _arguments '-F+[specify output format]:format:__tmux-format'
 }
 
-function _tmux-select-layout() {
-    [[ -n ${tmux_describe} ]] && print "Choose a layout for a window" && return
-    args=(
-        '-n[behave like next-layout]'
-        '-p[behave like previous-layout]'
-        '-t[choose a target window]:target window:__tmux-windows'
-        '*::layout name:__tmux-layouts'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-select-pane() {
-    [[ -n ${tmux_describe} ]] && print "Make a pane the active one in the window" && return
-    local -a args
-    args=(
-        '-D[Move to the pane down of this]'
-        '-d[disable input to the pane]'
-        '-e[enable input to the pane]'
-        '-l[behave like last-pane]'
-        '-L[Move to the pane left of this]'
-        '-R[Move to the pane right of this]'
-        '-U[Move to the pane above this]'
-        '-t[choose a target pane]:panes:__tmux-panes'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-select-window() {
-    [[ -n ${tmux_describe} ]] && print "Select a window" && return
-    local -a args
-    args=(
-        '-l[behave like last-window]'
-        '-n[behave like next-window]'
-        '-p[behave like previous-window]'
-        '-T[if selected window is the current behave like last-window]'
-        '-t[choose a target window]:windows:__tmux-windows'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-send-keys() {
-    [[ -n ${tmux_describe} ]] && print "Send key(s) to a window" && return
-    local curcontext="${curcontext}" state
-    local -a args
-    args=(
-        '-l[disable key name lookup and send data literally]'
-        '-R[reset terminal state]'
-        '-t[choose a target pane]:panes:__tmux-panes'
-        '*:: :->key'
-    )
-    _arguments : ${args} && return
-    __tmux-lastarg ${state} 'key' 1 "key"
+_tmux-list-windows() {
+  [[ -n ${tmux_describe} ]] && print "list windows of a session" && return
+  _arguments -s \
+    '-a[list all windows the tmux server possesses]' \
+    '-F[specify output format]:format:__tmux-format' \
+    '-t+[specify session]:session:__tmux-sessions'
 }
 
-function _tmux-send-prefix() {
-    [[ -n ${tmux_describe} ]] && print "Send the prefix key to a window" && return
-    local -a args
-    args=(
-        '-2[send secondary prefix key]'
-        '-t[choose a target pane]:panes:__tmux-panes'
-    )
-    _arguments : ${args}
+_tmux-load-buffer() {
+  [[ -n ${tmux_describe} ]] && print "load a file into a paste buffer" && return
+  _arguments -A "-*" -S \
+    '-b+[specify target buffer name]:buffer:__tmux-buffers' \
+    '1:file:_files'
 }
 
-function _tmux-server-info() {
-    [[ -n ${tmux_describe} ]] && print "Show server information" && return
-    __tmux-nothing-else
+_tmux-lock-client() {
+  [[ -n ${tmux_describe} ]] && print "lock a client" && return
+  _arguments '-t+[specify client]:client:__tmux-clients'
 }
 
-function _tmux-set-buffer() {
-    [[ -n ${tmux_describe} ]] && print "Set contents of a paster buffer" && return
-    local state
-    local -a args
-    args=(
-        '-a[append to rather than overwriting target buffer]'
-        '-b[choose a target buffer index]:panes:__tmux-buffer'
-        '-n[specify new buffer name]:buffer-name:'
-        '*:: :->data'
-    )
-    _arguments : ${args} && return
-    __tmux-lastarg ${state} 'data' 1 "data"
-}
-
-function _tmux-set-environment() {
-    [[ -n ${tmux_describe} ]] && print "(Un)Set an environment variable" && return
-    local state
-    local -a args
-    args=(
-        '-g[modify global environment]'
-        '-r[remove variable before starting new processes]'
-        '-u[unset a variable]'
-        '-t[choose a target session]:target session:__tmux-sessions'
-        '*:: :->name_or_value'
-    )
-    _arguments -C : ${args}
-
-    case ${state} in
-        name_or_value)
-            if (( CURRENT == 1 )); then
-                _message 'name'
-            elif (( CURRENT == 2 )); then
-                _message 'value'
-            else
-                __tmux-nothing-else
-            fi
-            ;;
-    esac
+_tmux-lock-server() {
+  [[ -n ${tmux_describe} ]] && print "lock all clients attached to the server" && return
+  __tmux-nothing-else
 }
 
-function _tmux-set-option() {
-    [[ -n ${tmux_describe} ]] && print "Set a session option" && return
-    local mode
-    local -a args
-    args=(
-        '-a[append to string options]'
-        '-g[set a global session option]'
-        '-u[unset a non-global option]'
-        '-w[change window (not session) options]'
-        '-s[change server (not session) options]'
-        '-t[choose a target session]:target session:__tmux-sessions'
-        '*:: :->name_or_value'
-    )
-    if __tmux-got-option-already -w; then
-        mode=window
-    elif __tmux-got-option-already -s; then
-        mode=server
-    else
-        mode=session
-    fi
-    _arguments -C : ${args}
-    __tmux-options-complete ${mode} ${state}
-}
-
-function _tmux-set-window-option() {
-    [[ -n ${tmux_describe} ]] && print "Set a window option" && return
-    local -a args
-    args=(
-        '-a[append to string options]'
-        '-g[set a global window option]'
-        '-u[unset a non-global option]'
-        '-t[choose a target window]:target window:__tmux-windows'
-        '*:: :->name_or_value'
-    )
-    _arguments -C : ${args}
-    __tmux-options-complete window ${state}
+_tmux-lock-session() {
+  [[ -n ${tmux_describe} ]] && print "lock all clients attached to a session" && return
+  _arguments '-t+[specify session]:session:__tmux-sessions'
 }
 
-function _tmux-show-buffer() {
-    [[ -n ${tmux_describe} ]] && print "Display the contents of a paste buffer" && return
-    local -a args
-    args=('-b[choose a target buffer index]:panes:->buffer')
-    _arguments : ${args} && return
+_tmux-move-pane() {
+  [[ -n ${tmux_describe} ]] && print "move a pane into a new space" && return
+  _arguments -s \
+    '-b[join source pane left of or above target pane]' \
+    "-d[don't make the new window become the active one]" \
+    '-h[split horizontally]' \
+    '-v[split vertically]' \
+    "-l+[define new pane's size]:numeric value" \
+    "-p+[define new pane's size in percent]:numeric value" \
+    '-s+[specify source pane]:pane:__tmux-panes' \
+    '-t+[specify target pane]:pane:__tmux-panes'
 }
 
-function _tmux-show-environment() {
-    [[ -n ${tmux_describe} ]] && print "Display the environment" && return
-    local -a args
-    args=(
-        '-g[show global environment]'
-        '-t[choose a target session]:target session:__tmux-sessions'
-    )
-    _arguments : ${args}
+_tmux-move-window() {
+  [[ -n ${tmux_describe} ]] && print "move a window to another" && return
+  _arguments -s \
+    "-d[don't make the new window become the active one]" \
+    '-k[kill the target window if it exists]' \
+    '-s+[specify source window]:window:__tmux-windows' \
+    '-r[renumber windows in session in sequential order]' \
+    '-t+[specify destination window]:window:__tmux-windows'
 }
 
-function _tmux-show-messages() {
-    [[ -n ${tmux_describe} ]] && print "Show client"\'"s message log" && return
-    local -a args
-    args=(
-        '-I[show debugging information about the tmux server]'
-        '-J[show debugging information about running jobs]'
-        '-T[show debugging information about involved terminals]'
-        '-t[choose target client]:client:__tmux-clients'
-    )
-    _arguments : ${args}
-}
+_tmux-new-session() {
+  [[ -n ${tmux_describe} ]] && print "create a new session" && return
+  _arguments -s -A "-*" -S \
+    '-A[attach to existing session if it already exists]' \
+    '-c+[specify working directory for the session]:directory:_directories' \
+    "-d[don't attach new session to current terminal]" \
+    "-D[in case of -A behave like attach-session's -d]" \
+    "-E[don't apply update-environment option]" \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-n+[specify initial window name]:window name' \
+    '-P[print information about new session after it is created]' \
+    '-s+[name the session]:session name:__tmux-sessions' \
+    '-t+[specify target session]:session:__tmux-sessions' \
+    '-x[specify width]:width' \
+    '-y[specify height]:height' \
+    '*:: :_cmdstring'
+}
+
+_tmux-new-window() {
+  [[ -n ${tmux_describe} ]] && print "create a new window" && return
+  _arguments -s -A "-*" -S \
+    '-a[insert new window at next free index from -t]' \
+    '-c+[specify working directory for the session]:directory:_directories' \
+    "-d[don't make the new window become the active one]" \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-k[destroy it if the specified window exists]' \
+    '-n+[specify a window name]:window name' \
+    '-P[print information about new window after it is created]' \
+    '-t+[specify target window]:window:__tmux-windows' \
+    '*:: :_cmdstring'
+}
+
+_tmux-next-layout() {
+  [[ -n ${tmux_describe} ]] && print "move a window to the next layout" && return
+  _arguments '-t+[specify target window]:window:__tmux-windows'
+}
+
+_tmux-next-window() {
+  [[ -n ${tmux_describe} ]] && print "move to the next window in a session" && return
+  _arguments -s \
+    '-a[move to the next window with an alert]' \
+    '-t+[specify target session]:session:__tmux-sessions'
+}
+
+_tmux-paste-buffer() {
+  [[ -n ${tmux_describe} ]] && print "insert a paste buffer into the window" && return
+  _arguments -s \
+    '-b+[specify buffer]:source buffer:__tmux-buffers' \
+    '-d[remove buffer from stack after pasting]' \
+    '-p[use bracketed paste mode if the application requested it]' \
+    "-r[don't replace LF with CR when pasting]" \
+    '-s+[specify separator]:separator' \
+    '-t+[specify target window]:window:__tmux-windows'
+}
+
+_tmux-pipe-pane() {
+  [[ -n ${tmux_describe} ]] && print "pipe output from a pane to a shell command" && return
+  _arguments -s -A "-*" -S \
+    '-o[only open a pipe if none is currently opened]' \
+    '-t+[specify target pane]:pane:__tmux-panes' \
+    ':shell command:_cmdstring'
+}
+
+_tmux-previous-layout() {
+  [[ -n ${tmux_describe} ]] && print "move a window to the previous layout" && return
+  _arguments '-t+[specify target window]:window:__tmux-windows'
+}
+
+_tmux-previous-window() {
+  [[ -n ${tmux_describe} ]] && print "move to the previous window in a session" && return
+  _arguments -s \
+    '-a[move to the previous window with an alert]' \
+    '-t+[specify target session]:session:__tmux-sessions'
+}
+
+_tmux-refresh-client() {
+  [[ -n ${tmux_describe} ]] && print "refresh a client" && return
+  _arguments -s \
+    "-S[only update the client's status bar]" \
+    '-t+[specify target client]:client:__tmux-clients' \
+    '-C+:size'
+}
+
+_tmux-rename-session() {
+  [[ -n ${tmux_describe} ]] && print "rename a session" && return
+  _arguments -s -A "-*" -S \
+    '-t+[specify target session]:session:__tmux-sessions' \
+    ':new session name'
+}
+
+_tmux-rename-window() {
+  [[ -n ${tmux_describe} ]] && print "rename a window" && return
+  _arguments -s -A "-*" -S \
+    '-t+[specify target window]:window:__tmux-windows' \
+    ':new window name'
+}
+
+_tmux-resize-pane() {
+  [[ -n ${tmux_describe} ]] && print "resize a pane" && return
+  _arguments -s -A "-*" -S \
+    '-D[resize downward]' \
+    '-L[resize to the left]' \
+    '-M[begin mouse resizing]' \
+    '-R[resize to the right]' \
+    '-U[resize upward]' \
+    '-t+[specify target pane]:pane:__tmux-panes' \
+    '-x+[specify width]:width' \
+    '-y+[specify height]:height' \
+    '-Z[toggle zoom of pane]' \
+    ':adjustment'
+}
+
+_tmux-respawn-pane() {
+  [[ -n ${tmux_describe} ]] && print "reuse a pane in which a command has exited" && return
+  _arguments -s -A "-*" -S \
+    '-k[kill window if it is in use]' \
+    '-t+[specify target pane]:pane:__tmux-pane' \
+    ':command:_cmdstring'
+}
+
+_tmux-respawn-window() {
+  [[ -n ${tmux_describe} ]] && print "reuse a window in which a command has exited" && return
+  _arguments -s -A "-*" -S \
+    '-k[kill window if it is in use]' \
+    '-t+[specify target window]:window:__tmux-windows' \
+    ':command:_cmdstring'
+}
+
+_tmux-rotate-window() {
+  [[ -n ${tmux_describe} ]] && print "rotate positions of panes in a window" && return
+  _arguments -s \
+    '-D[rotate downward]' \
+    '-U[rotate upward]' \
+    '-t+[specify target window]:window:__tmux-windows'
+}
+
+_tmux-run-shell() {
+  [[ -n ${tmux_describe} ]] && print "execute a command without creating a new window" && return
+  _arguments -s -A "-*" -S \
+    '-b[run shell command in background]' \
+    '-t+[specify target pane]:pane:__tmux-panes' \
+    ':command:_cmdstring'
+}
+
+_tmux-save-buffer() {
+  [[ -n ${tmux_describe} ]] && print "save a paste buffer to a file" && return
+  _arguments -s \
+    '-a[append to rather than overwriting file]' \
+    '-b+[specify a target buffer index]:buffer:__tmux-buffers'
+}
+
+_tmux-select-layout() {
+  [[ -n ${tmux_describe} ]] && print "choose a layout for a window" && return
+  _arguments -s -A "-*" -S \
+    '-n[behave like next-layout]' \
+    '-o[revert to previous layout]' \
+    '-p[behave like previous-layout]' \
+    '-t+[specify a target window]:target window:__tmux-windows' \
+    ':layout:(even-horizontal even-vertical main-horizontal main-vertical tiled)'
+}
+
+_tmux-select-pane() {
+  [[ -n ${tmux_describe} ]] && print "make a pane the active one in the window" && return
+  _arguments -s \
+    '-D[move to the pane below target]' \
+    '-d[disable input to the pane]' \
+    '-e[enable input to the pane]' \
+    '-g[show current pane style]' \
+    '-l[behave like last-pane]' \
+    '-L[move to the pane left of target]' \
+    '-M[clear marked pane]' \
+    '-m[set marked pane]' \
+    '-R[move to the pane right of target]' \
+    '-U[move to the pane above target]' \
+    '-P+[set pane style]:style:__tmux-style' \
+    '-t+[specify target pane]:pane:__tmux-panes'
+}
+
+_tmux-select-window() {
+  [[ -n ${tmux_describe} ]] && print "select a window" && return
+  _arguments -s \
+    '-l[behave like last-window]' \
+    '-n[behave like next-window]' \
+    '-p[behave like previous-window]' \
+    '-T[if selected window is the current behave like last-window]' \
+    '-t+[specify target window]:window:__tmux-windows'
+}
+
+_tmux-send-keys() {
+  [[ -n ${tmux_describe} ]] && print "send key(s) to a window" && return
+  _arguments -s -A "-*" -S \
+    '-l[disable key name lookup and send data literally]' \
+    '-R[reset terminal state]' \
+    '-M[pass through a mouse event]' \
+    '-t+[specify target pane]:pane:__tmux-panes' \
+    '*:key'
+}
+
+_tmux-send-prefix() {
+  [[ -n ${tmux_describe} ]] && print "send the prefix key to a window" && return
+  _arguments -s \
+    '-2[send secondary prefix key]' \
+    '-t+[specify target pane]:pane:__tmux-panes'
+}
+
+_tmux-server-info() {
+  [[ -n ${tmux_describe} ]] && print "show server information" && return
+  __tmux-nothing-else
+}
+
+_tmux-set-buffer() {
+  [[ -n ${tmux_describe} ]] && print "set contents of a paster buffer" && return
+  _arguments -s -A "-*" -S \
+    '-a[append to rather than overwriting target buffer]' \
+    '-b+[specify target buffer index]:pane:__tmux-buffers' \
+    '-n+[specify new buffer name]:buffer-name' \
+    ':data'
+}
+
+_tmux-set-environment() {
+  [[ -n ${tmux_describe} ]] && print "(un)set an environment variable" && return
+  _arguments -s -A "-*" -S \
+    '-g[modify global environment]' \
+    '-r[remove variable before starting new processes]' \
+    '-u[unset a variable]' \
+    '-t[specify target session]:target session:__tmux-sessions' \
+    ':name' ':value'
+}
+
+_tmux-set-option() {
+  [[ -n ${tmux_describe} ]] && print "set a session option" && return
+  local mode=session
+  local curcontext="$curcontext" state line ret=1
+  typeset -A opt_args
+  _arguments -C -s \
+    '-a[append to string options]' \
+    '-g[set a global session option]' \
+    '-o[prevent setting of an option that is already set]' \
+    '-q[suppress errors about unknown or ambiguous options]' \
+    '-u[unset a non-global option]' \
+    '-w[change window (not session) options]' \
+    '-s[change server (not session) options]' \
+    '-t+[specify target session]:target session:__tmux-sessions' \
+    '*:: :->name_or_value' && ret=0
+
+  if (( ${+opt_args[-w]} )); then
+    mode=window
+  elif (( ${+opt_args[-s]} )); then
+    mode=server
+  fi
+  __tmux-options-complete ${mode} ${state} && ret=0
+  return ret
+}
+
+_tmux-set-window-option() {
+  [[ -n ${tmux_describe} ]] && print "set a window option" && return
+  local curcontext="$curcontext" state line ret=1
+  typeset -A opt_args
+  _arguments -C -s \
+    '-a[append to string options]' \
+    '-g[set a global window option]' \
+    '-o[prevent setting of an option that is already set]' \
+    '-q[suppress errors about unknown or ambiguous options]' \
+    '-u[unset a non-global option]' \
+    '-t+[specify target window]:target window:__tmux-windows' \
+    '*:: :->name_or_value' && ret=0
+  __tmux-options-complete window ${state} && ret=0
+  return ret
+}
+
+_tmux-set-hook() {
+  [[ -n ${tmux_describe} ]] && print "set a hook to a command" && return
+  _arguments -s \
+    '-g[add hook to global list]' \
+    '-t+[specify target session]:session:__tmux-sessions'
+    ':command'
+}
+
+_tmux-show-hooks() {
+  [[ -n ${tmux_describe} ]] && print "show the global list of hooks" && return
+  _arguments -s -S -A "-*" \
+    '-g[show global list of hooks]' \
+    '-t+[specify target session]:session:__tmux-sessions' \
+    ':hook name:(alert-activity alert-bell alert-silence client-attached client-detached client-resized pane-died pane-exited)' \
+}
+
+_tmux-show-buffer() {
+  [[ -n ${tmux_describe} ]] && print "display the contents of a paste buffer" && return
+  _arguments '-b[specify target buffer index]:pane:->buffer'
+}
+
+_tmux-show-environment() {
+  [[ -n ${tmux_describe} ]] && print "display the environment" && return
+  _arguments -s \
+    '-g[show global environment]' \
+    '-s[format output as Bourne shell commands]' \
+    '-t+[specify target session]:target session:__tmux-sessions'
+}
+
+_tmux-show-messages() {
+  [[ -n ${tmux_describe} ]] && print "show client's message log" && return
+  _arguments -s \
+    '-J[show debugging information about running jobs]' \
+    '-T[show debugging information about involved terminals]' \
+    '-t+[specify target client]:client:__tmux-clients'
+}
+
+_tmux-show-options() {
+  [[ -n ${tmux_describe} ]] && print "show session options" && return
+  _arguments -s \
+    '-g[show global options]' \
+    '-q[suppress errors about unknown or ambiguous options]' \
+    '-s[show server options]' \
+    '-v[show only the option value, not the name]' \
+    '-w[show window options]' \
+    '-t+[specify target session]:target session:__tmux-sessions'
+}
+
+_tmux-show-window-options() {
+  [[ -n ${tmux_describe} ]] && print "show window options" && return
+  _arguments -s \
+    '-g[show global options]' \
+    '-v[show only the option value, not the name]' \
+    '-t+[specify target window]:target window:__tmux-windows'
+}
+
+_tmux-source-file() {
+  [[ -n ${tmux_describe} ]] && print "execute tmux commands from a file" && return
+  _arguments \
+    "-q[don't report error if path doesn't exist]" \
+    '*:path:_directories'
+}
+
+_tmux-split-window() {
+  [[ -n ${tmux_describe} ]] && print "splits a pane into two" && return
+  _arguments -s \
+    '-b[create new pane left of or above target pane]' \
+    "-d[don't make the new window become the active one]" \
+    '-F+[specify output format]:format:__tmux-format' \
+    '-h[split horizontally]' \
+    '-v[split vertically]' \
+    "-l[define new pane's size]:size" \
+    "-p[define new pane's size in percent]:size (percentage)" \
+    '-t+[specify target pane]:pane:__tmux-panes' \
+    ':command:_cmdstring'
+  # Yes, __tmux-panes is correct here. The behaviour was changed
+  # in recent tmux versions and makes more sense. Except that
+  # changing the command's name might annoy users. So it stays like
+  # this.
+}
+
+_tmux-start-server() {
+  [[ -n ${tmux_describe} ]] && print "start a tmux server" && return
+  __tmux-nothing-else
+}
+
+_tmux-suspend-client() {
+  [[ -n ${tmux_describe} ]] && print "suspend a client" && return
+  _arguments '-t+[specify destination client]:client:__tmux-clients'
+}
+
+_tmux-swap-pane() {
+  [[ -n ${tmux_describe} ]] && print "swap two panes" && return
+  _arguments -s \
+    '-D[move pane down]' \
+    '-U[move pane up]' \
+    "-d[don't change the active pane]" \
+    '-s+[specify source pane]:pane:__tmux-panes' \
+    '-t+[specify destination pane]:pane:__tmux-panes'
+}
+
+_tmux-swap-window() {
+  [[ -n ${tmux_describe} ]] && print "swap two windows" && return
+  _arguments -s \
+    "-d[don't make the new window become the active one]" \
+    '-s+[specify source window]:window:__tmux-windows' \
+    '-t+[specify destination window]:window:__tmux-windows'
+}
+
+_tmux-switch-client() {
+  [[ -n ${tmux_describe} ]] && print "switch the client to another session" && return
+  _arguments -s \
+    '-c+[specify a target client]:client:__tmux-clients' \
+    "-E[don't apply update-environment option]" \
+    '-l[move client to last session]' \
+    '-n[move client to next session]' \
+    '-p[move client to previous session]' \
+    '-r[toggle read-only flag of client]' \
+    '-t+[specify target window]:window:__tmux-windows'
+}
+
+_tmux-unbind-key() {
+  [[ -n ${tmux_describe} ]] && print "unbind a key" && return
+  local curcontext="$curcontext" state line keytable
+  local -a ow
+
+  ow=( "${words[@]}" )
+  _arguments -C -s \
+    '-a[remove all key bindings]' \
+    '-c[kill the window if it is only in one session]' \
+    '-n[remove a non-prefix binding]' \
+    '-t+[specify mode table]:mode table:__tmux-mode-tables' \
+    '-T[specify key table]:key table' \
+    '*:: :->boundkeys'
 
-function _tmux-show-options() {
-    [[ -n ${tmux_describe} ]] && print "Show session options" && return
-    local -a args
-    args=(
-        '-g[show global options]'
-        '-t[choose a target session]:target session:__tmux-sessions'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-show-window-options() {
-    [[ -n ${tmux_describe} ]] && print "Show window options" && return
-    local -a args
-    args=(
-        '-g[show global options]'
-        '-t[choose a target window]:target window:__tmux-windows'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-source-file() {
-    [[ -n ${tmux_describe} ]] && print "Execute tmux commands from a file" && return
-    _files -g "*(-.)"
-}
-
-function _tmux-split-window() {
-    [[ -n ${tmux_describe} ]] && print "Splits a pane into two" && return
-    local -a args
-    args=(
-        '-b[create new pane left of or above target pane]'
-        '-d[do not make the new window become the active one]'
-        '-F[specify format of output]:format:__tmux-format'
-        '-h[split horizontally]'
-        '-v[split vertically]'
-        '-l[define new pane'\''s size]: :_guard "[0-9]#" "numeric value"'
-        '-p[define new pane'\''s size in percent]: :_guard "[0-9]#" "numeric value"'
-        # Yes, __tmux-panes is correct here. The behaviour was changed
-        # in recent tmux versions and makes more sense. Except that
-        # changing the command's name might annoy users. So it stays like
-        # this.
-        '-t[choose target pane]:window:__tmux-panes'
-        '*:: :_cmdstring'
-    )
-    _arguments : ${args} && return
-}
-
-function _tmux-start-server() {
-    [[ -n ${tmux_describe} ]] && print "Start a tmux server" && return
-    __tmux-nothing-else
-}
-
-function _tmux-suspend-client() {
-    [[ -n ${tmux_describe} ]] && print "Suspend a client" && return
-    local -a args
-    args=('-t[choose destination client]:client:__tmux-clients')
-    _arguments : ${args}
-}
-
-function _tmux-swap-pane() {
-    [[ -n ${tmux_describe} ]] && print "Swap two panes" && return
-    local -a args
-    args=(
-        '-D[move pane down]'
-        '-U[move pane up]'
-        '-d[do not change the active pane]'
-        '-s[choose source pane]:pane:__tmux-panes'
-        '-t[choose destination pane]:pane:__tmux-panes'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-swap-window() {
-    [[ -n ${tmux_describe} ]] && print "Swap two windows" && return
-    local -a args
-    args=(
-        '-d[do not make the new window become the active one]'
-        '-s[choose source window]:window:__tmux-windows'
-        '-t[choose destination window]:window:__tmux-windows'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-switch-client() {
-    [[ -n ${tmux_describe} ]] && print "Switch the client to another session" && return
-    local -a args
-    args=(
-        '-c[choose a target client]:client:__tmux-clients'
-        '-l[move client to last session]'
-        '-n[move client to next session]'
-        '-p[move client to previous session]'
-        '-r[toggle read-only flag of client]'
-        '-t[choose a target window]:window:__tmux-windows'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-unbind-key() {
-    [[ -n ${tmux_describe} ]] && print "Unbind a key" && return
-    local state keytable
-    local -a args ow
-
-    ow=( "${words[@]}" )
-    args=(
-        '-a[Remove all key bindings]'
-        '-c[kill the window if it is only in one session]'
-        '-n[remove a non-prefix binding]'
-        '-t[choose a key table]:key table:__tmux-key-tables'
-        '*:: :->boundkeys'
-    )
-    _arguments : ${args} && return
     [[ ${state} != 'boundkeys' ]] && return
     keytable="$(__tmux-get-optarg -t "${ow[@]}")"
     if [[ -n ${keytable} ]]; then
@@ -1120,39 +925,31 @@ function _tmux-unbind-key() {
     __tmux-bound-keys
 }
 
-function _tmux-unlink-window() {
-    [[ -n ${tmux_describe} ]] && print "Unlink a window" && return
-    local -a args
-    args=(
-        '-k[kill the window if it is only in one session]'
-        '-t[choose a target window]:target window:__tmux-windows'
-    )
-    _arguments : ${args}
-}
-
-function _tmux-wait-for() {
-    [[ -n ${tmux_describe} ]] && print "Wait for an event or trigger it" && return
-    local state
-    local -a args
-    args=(
-        '-L[lock the named channel]'
-        '-S[send signal to channel]'
-        '-U[unlock the named channel]'
-        '*:: :->channel'
-    )
-    _arguments : ${args} && return
-    __tmux-lastarg ${state} 'channel' 1 "event channel"
+_tmux-unlink-window() {
+  [[ -n ${tmux_describe} ]] && print "unlink a window" && return
+  _arguments -s \
+    '-k[kill the window if it is only in one session]' \
+    '-t+[specify target window]:target window:__tmux-windows'
+}
+
+_tmux-wait-for() {
+  [[ -n ${tmux_describe} ]] && print "wait for an event or trigger it" && return
+  _arguments -s \
+    '-L[lock the named channel]' \
+    '-S[send signal to channel]' \
+    '-U[unlock the named channel]' \
+    ':event channel'
 }
 
 # --- Utility functions ---
-# They should be called __tmux-*() and kept seperate from the
+# They should be called __tmux-*() and kept separate from the
 # sub-command functions.
 
 function __tmux-attributes() {
     local -a attr already
     attr=( default bright bold dim underscore blink reverse hidden italics )
     compset -P '*,'
-    already=(${(s<,>)IPREFIX})
+    already=( ${(s<,>)IPREFIX} )
     _describe -t tmux-attribute 'tmux attribute' attr -S, -F already -q
 }
 
@@ -1213,37 +1010,14 @@ function __tmux-get-optarg() {
     done
 }
 
-function __tmux-got-option-already() {
-    [[ -n ${(M)words:#$1} ]] && return 0
-    return 1
+__tmux-mode-tables() {
+  local expl
+  _description mode-tables expl 'mode table'
+  compadd "$@" "$expl[@]" vi-edit emacs-edit vi-choice emacs-choice vi-copy emacs-copy
 }
 
-function __tmux-key-tables() {
-    local expl
-    local -a tables
-    tables=( vi-edit emacs-edit vi-choice emacs-choice vi-copy emacs-copy )
-    _wanted keytable expl 'key tables' compadd ${expl} -- ${tables}
-}
-
-function __tmux-lastarg() {
-    local got_state="$1" want_state="$2" pos="$3" msg="$4"
-
-    if [[ ${want_state} == ${got_state} ]] && (( CURRENT == ${pos} )); then
-        _message ${msg}
-    else
-        __tmux-nothing-else
-    fi
-}
-
-function __tmux-layouts() {
-    local expl
-    local -a layouts
-    layouts=( even-horizontal even-vertical main-horizontal main-vertical )
-    _wanted layout expl 'layouts' compadd ${expl} -- ${layouts}
-}
-
-function __tmux-nothing-else() {
-    _message "no further arguments"
+__tmux-nothing-else() {
+  _message "no further arguments"
 }
 
 function __tmux-option-guard() {
@@ -1273,12 +1047,10 @@ function __tmux-option-guard() {
             'message-command-style:__tmux-style'
             'message-style:__tmux-style'
             'mouse:DESC:on off'
-            'mouse-utf8:DESC:on off'
             'prefix:MSG:primary prefix key'
             'prefix2:MSG:secondary prefix key'
             'renumber-windows:DESC:on off'
             'repeat-time:'${int_guard}
-            'set-remain-on-exit:DESC:on off'
             'set-titles:DESC:on off'
             'set-titles-string:MSG:title format string'
             'status:DESC:on off'
@@ -1293,7 +1065,6 @@ function __tmux-option-guard() {
             'status-right-length:'${int_guard}
             'status-right-style:__tmux-style'
             'status-style:__tmux-style'
-            'status-utf8:DESC:on off'
             'update-environment:MSG:string listing env. variables'
             'visual-activity:DESC:on off'
             'visual-bell:DESC:on off'
@@ -1334,10 +1105,11 @@ function __tmux-option-guard() {
             'other-pane-width:'${int_guard}
             'pane-active-border-style:__tmux-style'
             'pane-base-index:'${int_guard}
+            'pane-border-format:MSG:pane border status string'
+            'pane-border-status:DESC:off top bottom'
             'pane-border-style:__tmux-style'
             'remain-on-exit:DESC:on off'
             'synchronize-panes:DESC:on off'
-            'utf8:DESC:on off'
             'window-active-style:__tmux-style'
             'window-status-activity-style:__tmux-style'
             'window-status-bell-style:__tmux-style'
@@ -1348,7 +1120,7 @@ function __tmux-option-guard() {
             'window-status-separator:MSG:separator string'
             'window-status-style:__tmux-style'
             'window-style:__tmux-style'
-            'wrap-seach:DESC:on off'
+            'wrap-search:DESC:on off'
             'xterm-keys:DESC:on off'
         )
     fi
@@ -1391,17 +1163,16 @@ function __tmux-session-options() {
         'display-panes-time:time (in msecs) of display-panes output'
         'display-time:time (in msecs) messages are displayed'
         'history-limit:number of copy-mode lines per window'
+        'key-table:default key table'
         'lock-after-time:lock sessions after N seconds'
         'lock-command:command to run for locking a client'
         'message-command-style:status line message command style'
         'message-style:status line message style'
         'mouse:enable mouse support'
-        'mouse-utf8:request utf8 mouse support'
         'prefix:primary prefix key'
         'prefix2:secondary prefix key'
         'renumber-windows:renumber windows if a window is closed'
         'repeat-time:time for multiple commands without prefix-key presses'
-        'set-remain-on-exit:set remain-on-exit window option'
         'set-titles:try to set xterm window titles'
         'set-titles-string:format used by set-titles'
         'status:show or hide the status bar'
@@ -1416,8 +1187,7 @@ function __tmux-session-options() {
         'status-right-length:maximum length of the right part of the status bar'
         'status-right-style:style of right part of status line'
         'status-style:style status line'
-        'status-utf8:assume UTF-8 sequences to appear in status bar'
-        'update-environment:list of variables to be copied to a session'\''s environment'
+        "update-environment:list of variables to be copied to a session's environment"
         'visual-activity:display status line messages upon activity'
         'visual-bell:use visual bell instead of audible'
         'visual-silence:print a message if monitor-silence is on'
@@ -1485,7 +1255,6 @@ function __tmux-server-options() {
 }
 
 function __tmux-sessions() {
-    local expl
     local -a sessions
     sessions=( ${${(f)"$(command tmux 2> /dev/null list-sessions)"}/:[ $'\t']##/:} )
     _describe -t sessions 'sessions' sessions "$@"
@@ -1495,7 +1264,7 @@ function __tmux-socket-name() {
     local expl sdir
     local curcontext="${curcontext}"
     local -a socks
-    zstyle -s ":completion:${curcontext}:sockets" socketdir sdir || sdir="/tmp/tmux-${UID}"
+    zstyle -s ":completion:${curcontext}:sockets" socketdir sdir || sdir="${TMUX_TMPDIR:-/tmp}/tmux-${UID}"
     socks=(${sdir}/*(=:t))
     _wanted socket expl 'socket name' compadd ${expl} -- ${socks}
 }
@@ -1526,10 +1295,11 @@ function __tmux-window-options() {
         'other-pane-width:width of other panes'
         'pane-active-border-style:style of border of active pane'
         'pane-base-index:integer at which to start indexing panes'
+        'pane-border-format:set pane border format string'
+        'pane-border-status:turn border status off or set its position'
         'pane-border-style:style of border pane'
-        'remain-on-exit:do not destroy windows after the program exits'
+        "remain-on-exit:don't destroy windows after the program exits"
         'synchronize-panes:send input to all panes of a window'
-        'utf8:assume UTF-8 sequences to appear in a window'
         'window-active-style:style of active window'
         'window-status-activity-style:style of status bar activity tag'
         'window-status-bell-style:style of status bar bell tag'
@@ -1564,65 +1334,58 @@ function __tmux-windows() {
 }
 
 # And here is the actual _tmux(), that puts it all together:
-function _tmux() {
-    local curcontext="${curcontext}"
-    local mode state ret=1
-    local -a args
-    local tmuxcommand
-    local tmux_describe=
-
-    args=(
-        '-2[force using 256 colours]'
-        '-8[force using 88 colours]'
-        '-c[execute a shell command]:command name:_command_names'
-        '-C[start tmux in control mode. -CC disables echo]'
-        '-f[specify configuration file]:tmux config file:_files -g "*(-.)"'
-        '-l[behave like a login shell]'
-        '-L[specify socket name]:socket name:__tmux-socket-name'
-        '-S[specify socket path]:server socket:_path_files -g "*(=,/)"'
-        '-u[force using UTF-8]'
-        '-v[request verbose logging]'
-        '-V[report tmux version]'
-        '*:: :->subcommand_or_options'
-    )
-    _arguments -C -s -w : ${args} && ret=0
-
-    if [[ ${state} == "subcommand_or_options" ]]; then
-        if (( CURRENT == 1 )) ; then
-            zstyle -s ":completion:${curcontext}:subcommands" mode mode || mode='both'
-            if [[ ${mode} == 'commands' ]]; then
-                _describe -t subcommands 'tmux commands' _tmux_commands && ret=0
-            elif [[ ${mode} == 'aliases' ]]; then
-                _describe -t subcommands 'tmux aliases' _tmux_aliases && ret=0
-            else
-                _describe -t subcommands 'tmux commands and aliases' _tmux_commands -- _tmux_aliases && ret=0
-            fi
-        else
-            if (( ${+commands[tmux]} == 0 )); then
-                _message '`tmux'\'' not found in $path; sub-cmd completions disabled.'
-                return
-            fi
-            tmuxcommand="${words[1]}"
-            if [[ -n ${_tmux_aliasmap[$tmuxcommand]} ]] ; then
-                tmuxcommand="${_tmux_aliasmap[$tmuxcommand]}"
-            fi
-            if ! (( ${+functions[_tmux-$tmuxcommand]} )); then
-              local low high
-              low=$_tmux_commands[(i)$tmuxcommand*]
-              high=$_tmux_commands[(I)$tmuxcommand*]
-              if (( low == high )); then
-                tmuxcommand=${_tmux_commands[low]%%:*}
-              elif (( low < high )); then
-                _message -e "Ambiguous command $tmuxcommand"
-              else
-                _message -e "Subcommand $tmuxcommand not known"
-              fi
-            fi
-            curcontext="${curcontext%:*:*}:tmux-${tmuxcommand}:"
-            _call_function ret _tmux-${tmuxcommand}
-        fi
+_tmux() {
+  local curcontext="${curcontext}" state line ret=1
+  local mode
+  local tmuxcommand
+  local tmux_describe
+
+  _arguments -C -s -w \
+    '-2[force using 256 colours]' \
+    '-c[execute a shell command]:command name:_command_names' \
+    '-C[start tmux in control mode. -CC disables echo]' \
+    '-f[specify configuration file]:tmux config file:_files -g "*(-.)"' \
+    '-l[behave like a login shell]' \
+    '-L[specify socket name]:socket name:__tmux-socket-name' \
+    '-S[specify socket path]:server socket:_path_files -g "*(=,/)"' \
+    '-u[force using UTF-8]' \
+    '-v[request verbose logging]' \
+    '-V[report tmux version]' \
+    '*:: :->subcommand_or_options' && ret=0
+
+  [[ -z $state ]] && return ret
+
+  if (( CURRENT == 1 )); then
+    zstyle -s ":completion:${curcontext}:subcommands" mode mode || mode='both'
+    if [[ ${mode} == 'commands' ]]; then
+      _describe -t subcommands 'tmux commands' _tmux_commands && ret=0
+    elif [[ ${mode} == 'aliases' ]]; then
+      _describe -t subcommands 'tmux aliases' _tmux_aliases && ret=0
+    else
+      _describe -t subcommands 'tmux commands and aliases' _tmux_commands -- _tmux_aliases && ret=0
+    fi
+  else
+    tmuxcommand="${words[1]}"
+    if [[ -n ${_tmux_aliasmap[$tmuxcommand]} ]] ; then
+      tmuxcommand="${_tmux_aliasmap[$tmuxcommand]}"
+    fi
+    if ! (( ${+functions[_tmux-$tmuxcommand]} )); then
+      local low high
+      low=$_tmux_commands[(i)$tmuxcommand*]
+      high=$_tmux_commands[(I)$tmuxcommand*]
+      if (( low == high )); then
+	tmuxcommand=${_tmux_commands[low]%%:*}
+      elif (( low < high )); then
+	_message "ambiguous command $tmuxcommand"
+      else
+	_message "subcommand $tmuxcommand not known"
+	_normal && ret=0
+      fi
     fi
-    return ret
+    curcontext="${curcontext%:*}-${tmuxcommand}:"
+    _call_function ret _tmux-${tmuxcommand}
+  fi
+  return ret
 }
 
 # description generation follows; only done on 1st _tmux call.
@@ -1631,12 +1394,12 @@ local -A rev
 local tmux_describe
 tmux_describe='yes, please'
 for f in ${(k)_tmux_aliasmap} ; do
-    rev+=( ${_tmux_aliasmap[$f]} $f )
+  rev+=( ${_tmux_aliasmap[$f]} $f )
 done
 for f in ${(M)${(k)functions}:#_tmux-*} ; do
-    desc="$($f)"
-    _tmux_commands+=( "${f#_tmux-}${desc:+:$desc}" )
-    [[ -n ${rev[${f#_tmux-}]} ]] && _tmux_aliases+=( "${rev[${f#_tmux-}]}${desc:+:$desc}" )
+  desc="$($f)"
+  _tmux_commands+=( "${f#_tmux-}${desc:+:$desc}" )
+  [[ -n ${rev[${f#_tmux-}]} ]] && _tmux_aliases+=( "${rev[${f#_tmux-}]}${desc:+:$desc}" )
 done
 
 _tmux "$@"
diff --git a/Completion/Unix/Command/_top b/Completion/Unix/Command/_top
index 10c0e3481..8f81e9526 100644
--- a/Completion/Unix/Command/_top
+++ b/Completion/Unix/Command/_top
@@ -1,12 +1,16 @@
 #compdef top
 
-local specs fields
+local curcontext="$curcontext" state state_descr line ret=1
+local -A opt_args
+local -a specs fields order opts
+
+opts=( -s -w -C )
 
 case $OSTYPE in
   *linux*)
     fields=(
       '%CPU:CPU usage' '%MEM:memory usage (res)' 'CGROUPS:control groups'
-      'CODE:code size' 'COMMAND:Commane name/line' 'DATA:data + stack size'
+      'CODE:code size' 'COMMAND:Command name/line' 'DATA:data + stack size'
       'ENVIRON:environment variables' 'Flags:task flags' 'GID:group id'
       'GROUP:group name' 'NI:nice value' 'P:last used CPU (SMP)'
       'PGRP:process group id' 'PID:process id' 'PPID:parent pid' 'PR:priority'
@@ -24,78 +28,147 @@ case $OSTYPE in
       'nsUTS:UTS namespace' 'vMj:major page fault count delta'
       'vMn:minor page fault count delta'
     )
+    order=( '+:descending (default)' '-:ascending' )
     specs=(
-      '(-v -h)-'{h,v}'[show version and usage]'
+      '(-)-'{h,v}'[show version and usage]'
       '-b[batch mode]'
       '-c[command line/program name toggle]'
-      '-d[delay time interval]:interval'
+      '-d+[delay time interval]:interval'
       '-H[threads mode operation]'
       '-i[idle process toggle]'
-      '-n[number of iterations]:number of iterations'
-      '-o[override sort field]:fieldname:(( $fields ))'
+      '-n+[number of iterations]:number of iterations'
+      '-o+[override sort field]:fieldname:->sortkey'
       '-O[output field names]'
-      '*-p[monitor pids]: :_pids'
+      '*-p+[monitor pids]: :_sequence -s , _pids'
       '-s[secure mode operation]'
       '-S[cumulative time toggle]'
-      '(-U)-u[effective user filter mode]: :_users'
-      '(-u)-U[user filter mode]: :_users'
-      '-w[output width override]:number'
+      '(-U)-u+[effective user filter mode]: :_users'
+      '(-u)-U+[user filter mode]: :_users'
+      '-w+[output width override]::number'
     );;
-  freebsd*)
+  freebsd*|openbsd*)
+    fields=( cpu size res time pri pid )
     specs=(
-      '-C[CPU display mode]'
-      '-S[show system processes]'
-      '-a[display command names via argv]'
       '-b[batch mode]'
+      '-d+[show only specified number of displays then exit]:count:'
       '-H[display individual threads]'
-      '-i[interactive mode]'
       '-I[do not display idle processes]'
+      '-i[interactive mode]'
+      '-n[non-interactive mode (identical to batch mode)]'
+      '-o+[sort process display by the specified field]:field:( $fields )'
+      '-q[renice top to -20]'
+      '-S[show system processes]'
+      '-s+[specify delay interval]:seconds:'
+      '-u[do not translate uid to name]'
+      '1: :_guard "^-*" "number of processes to display"'
+    );|
+  freebsd*)
+    fields+=( threads total read write fault vcsw ivcsw jid )
+    specs+=(
+      '-C[CPU display mode]'
+      '-a[display command names via argv]'
       '-j[display the jail ID]'
       '-t[do not display the top process]'
-      '-m+[statistic type]:type:(( cpu\:default io ))'
-      '-n[non-interactive mode]'
+      '-m+[specify statistic type]:type:(( cpu\:default io ))'
       '-P[per-cpu CPU usage statistics]'
-      '-q[renice top to -20]'
-      '-u[do not translate uid to name]'
-      '-v[write version number]'
-      '-z[no not display system idle process]'
-      '-d+[number of iterations]:count:'
-      '-s+[set delay interval]:interval:'
-      '-o+[sort process display by field]:field:(
-        cpu size res time pri threads total read 
-        write fault vcsw ivcsw jid pid
-      )'
-      '-J+[show processes owned by jail]:jail:_jails -0'
-      '-U+[show processes owned by username]: :_users'
-      '1: : _message "top number of processes"'
+      '(1 -)-v[write version number and exit]'
+      '-z[do not display system idle process]'
+      '-J+[show processes owned by the specified jail]:jail:_jails -0'
+      '-U+[show processes owned by the specified username]: :_users'
     );;
   openbsd*)
-    specs=(
+    fields+=( command )
+    specs+=(
       '-1[combine CPU statistic into one line]'
-      '-b[batch mode]'
-      '-C[show command arguments as well and process name]'
-      '-d[number of iterations]:number of iterations'
-      '-g[filter processes by string]:string'
-      '-H[display process threads]'
-      '-I[do not display idle processes]'
-      '-i[interactive mode]'
-      '-n[non-interactive mode]'
-      '-o[sort display by field]:field:(
-        cpu size res time pri pid command
-      )'
-      '-p[filter by pid]: :_pids'
-      '-q[renice top to -20]'
-      '-S[show system processes]'
-      '-s[delay time interval]:interval'
-      '-U[filter processes by user]: :_users -M "L\:|-="'
-      '-u[do not map uid to usernames]'
-      '1: : _message "top number of processes"'
+      '-C[show command arguments as well as process name]'
+      '-g+[filter processes by the specified string]:string'
+      '-p+[filter by the specified pid]: :_pids'
+      '-U+[filter processes by the specified user]: :_users -M "L\:|-="'
+    );;
+  darwin*)
+    local -a modes
+    opts=( -C )   # no option stacking
+    modes=(
+      'a:count events cumulatively'
+      'd:count events relative to the previous sample'
+      'e:count events using absolute counters'
+      'n:non-event mode (default)'
+    )
+    fields=(
+      'pid:process id'
+      'command:command name'
+      'cpu:CPU usage'
+      'cpu_me:CPU time charged to me by other processes'
+      'cpu_others:CPU time charged to other processes by me'
+      'csw:number of context switches'
+      'time:execution time'
+      {threads,th}':number of threads'
+      {ports,prt}':number of Mach ports'
+      {mregion,mreg,reg}':number of memory regions'
+      'mem:internal memory size'
+      'rprvt:resident private address space size'
+      'purg:purgeable memory size'
+      'vsize:total memory size'
+      'vprvt:private address space size'
+      'kprvt:private kernel memory size'
+      'kshrd:shared kernel memory size'
+      'pgrp:process group id'
+      'ppid:parent process id'
+      {state,pstate}':process state'
+      'uid:user id'
+      {wq,'#wq',workqueue}':workqueue total/running'
+      {faults,fault}':number of page faults'
+      {cow,cow_faults}':copy-on-write faults'
+      {user,username}':username'
+      'msgsent:total number of Mach messages sent'
+      'msgrecv:total number of Mach messages received'
+      'sysbsd:total BSD syscalls'
+      'sysmach:total Mach syscalls'
+      'pageins:total pageins'
+      'boosts:number of boosts held by the process'
+    )
+    order=( '-:descending (default)' '+:ascending' )
+    specs=(
+      '-a[count events cumulatively]'
+      '-c[set event counting mode]:mode:(( $modes ))'
+      '-d[count events relative to the previous sample]'
+      '-e[count events using absolute counters]'
+      '-F[do not calculate statistics on shared libraries]'
+      '-f[calculate statistics on shared libraries]'
+      '(-)-h[print usage information and exit]'
+      '-i+[specify interval between samples for -f option]:interval'
+      '-l+[logging mode. output specified number of samples periodically]:number of samples'
+      '-ncols[output specified number of columns in logging mode]:number of columns'
+      '-n+[only display up to the specified number of processes]:number of processes:'
+      '-O+[specify the secondary sort key]:key:->sortkey'
+      '-o+[specify the primary sort key]:key:->sortkey'
+      '-R[do not traverse and report memory object map for each process]'
+      '-r[traverse and report memory object map for each process]'
+      '-S[display global statistics for swap and purgeable memory]'
+      '-s[set the delay between update]:number of seconds'
+      '-stats[only display the specified fields]:list of fields:->fieldlist'
+      '*-pid[only display the specified process]:pid:_pids'
+      {-user,-U+}'[only display processes owned by the specified user]:user:_users'
+      '-u[same as -o cpu -O time]'
     );;
 esac
 
-if (( $#specs )); then
-  _arguments -s -w : "$specs[@]"
+if (( $#specs == 0 )); then
+  _default
   return
 fi
 
-_normal
+_arguments $opts : "$specs[@]" && ret=0
+
+case $state in
+  (sortkey)
+    compset -P '(+|-)' && order=()
+    _alternative 'sort-orders:sort order:(( $order ))' \
+	'sort-keys:sort key:(( $fields ))' && ret=0
+    ;;
+  (fieldlist)
+    _sequence -s , _describe -t fields 'field' fields && ret=0
+    ;;
+esac
+
+return ret
diff --git a/Completion/Unix/Command/_touch b/Completion/Unix/Command/_touch
new file mode 100644
index 000000000..9b9144756
--- /dev/null
+++ b/Completion/Unix/Command/_touch
@@ -0,0 +1,45 @@
+#compdef touch gtouch
+
+local args variant
+_pick_variant -r variant gnu=GNU $OSTYPE --version
+
+args=(
+  '-a[change access time (atime)]'
+  '-m[change modification time (mtime)]'
+  '(-r -d --date --reference 1)-t+[use specified time]:time ([[CC]YY]MMDDhhmm[.SS])'
+)
+case $variant in
+  gnu)
+    args+=(
+      '(-c --no-create)'{-c,--no-create}"[don't create file if it doesn't exist]"
+      '(-h --no-dereference)'{-h,--no-dereference}'[act on symbolic links themselves]'
+      '(-t -d --date -r --reference)'{-r+,--reference=}'[use corresponding times from specified reference file]:file:_files'
+      '(-t -d --date -r --reference)'{-d+,--date=}'[use specified date/time]:date/time'
+      '*--time=[change specified time]:time:(atime access use mtime modify)'
+      '(-)--help[display help information]'
+      '(-)--version[display version information]'
+    )
+  ;;
+  darwin*|dragonfly*|freebsd*)
+    args+=(
+      '(-c 1)-A+[adjust time stamps by relative value]:time delta ([[-][hh]mm]SS)'
+    )
+  ;|
+  darwin*|dragonfly*|freebsd*|netbsd*)
+    args+=( '-h[act on symbolic links themselves]' )
+  ;|
+  dragonfly*|freebsd*|openbsd*|solaris*)
+    args+=( '(-r -t 1)-d+[use specified date/time]:date/time' )
+  ;|
+  darwin*|dragonfly*|freebsd*|netbsd*|solaris*)
+    args+=( '1:: :_guard "[0-9]#" "timespec (MMDDhhmm[YY])"' )
+  ;|
+  *) # not GNU
+    args=( -A "-*" $args
+      "(-A)-c[don't create file if it doesn't exist]"
+      '(-t -d 1)-r+[use corresponding times from specified reference file]:file:_files'
+    )
+  ;;
+esac
+
+_arguments -s -S $args '*:file:_files'
diff --git a/Completion/Unix/Command/_tree b/Completion/Unix/Command/_tree
index d759409b5..4fd9aed44 100644
--- a/Completion/Unix/Command/_tree
+++ b/Completion/Unix/Command/_tree
@@ -1,51 +1,54 @@
 #compdef tree
 
-# Completions for tree, version 1.5.3
-# Tree is available at
-# http://mama.indstate.edu/users/ice/tree/
-
-typeset -a opts
-
-opts=(
-'--help[verbose usage listing]'
-'--version[version of tree]'
-'-a[show all files, including hidden ones]'
-'-d[list directories only]'
-'-f[print full path prefix for each file]'
-'-i[do not print indentation lines]'
-'-l[follow symlinks that point to directories]'
-'-x[stay on current filesystem]'
-'-P[list only files matching a pattern]:pattern:'
-'-I[do not list files matching a pattern]:pattern:'
-'--noreport[do not print file and directory report at end]'
-'-p[print file type and permissions, like ls -l]'
-'-s[print size of each file in bytes]'
-'-h[print human readable file size]'
-'-u[print username]'
-'-g[print group name]'
-'-D[print date of last modification]'
-'--inodes[print inode numbers]'
-'--device[print device number to which file or directory belongs]'
-'-F[append descriptive character to end, like ls -F]'
-'-q[print non-printable characters as question mark, not caret]'
-'-N[print non-printable characters as is, not as caret]'
-'-v[sort the output as version]'
-'-r[sort output in reverse alphabetic order]'
-'-t[sort output by last modification time instead of alphabetically]'
-'--dirsfirst[list directories before files]'
-'-n[turn colorization off always, over-ridden by the -C option]'
-'-C[turn colorization on always]'
-'-A[turn on ANSI line graphics hack when printing indentation lines]'
-'-S[turn on ASCII line graphics]'
-'-L[max display depth of tree]:level:'
-'--filelimit[do not descend directories with more than number of entries]:number:'
-'-R[recursively cross down the tree and execute tree again]'
-'-H[turn on HTML output]'
-'-T[title for HTML output]'
-'--charset[character set for HTML and for line drawing]:charset:'
-'--nolinks[turn off hyperlinks in HTML output]'
-'-o[send output to file]:filename:_files'
-'*:directory:_files -/'
-)
-
-_arguments $opts
+_arguments -s -S \
+  '-a[show all files, including hidden ones]' \
+  '-d[list directories only]' \
+  '-l[follow symlinks that point to directories]' \
+  '-f[print full path prefix for each file]' \
+  '-x[stay on current filesystem]' \
+  '-L[specify max tree depth to descend]:level' \
+  '-R[recursively cross down the tree and execute tree again]' \
+  '-P[only list files matching a pattern]:pattern:_files' \
+  "-I[don't list files matching a pattern]:pattern:_files" \
+  '--ignore-case[ignore case when pattern matching]' \
+  '--matchdirs[include directory names in -P pattern matching]' \
+  '--noreport[omit file and directory report at end]' \
+  '--charset=[character set for HTML and for line drawing]:charset' \
+  "--filelimit=[don't descend directories with more than specified number of entries]:entries" \
+  '--timefmt=[use specified time format]:format:_date_formats' \
+  '-o[output to specified file]:file:_files' \
+  '--du[print directory sizes]' \
+  '--prune[exclude empty directories from the output]' \
+  '(-N)-q[print non-printable characters as question mark, not caret]' \
+  '(-q)-N[print non-printable characters as is, not as caret]' \
+  '-Q[quote filenames with double quotes]' \
+  '-p[print file type and permissions, like ls -l]' \
+  '-u[print file owner]' \
+  '-g[print file group]' \
+  '(-h --si)-s[print size of each file in bytes]' \
+  '(-s --si)-h[print human readable file size]' \
+  '(-s -h)--si[print human readable file size in SI units (powers of 1000)]' \
+  '-D[print last modification date or change time (with -c)]' \
+  '-F[append descriptive character to end, like ls -F]' \
+  '--inodes[print inode numbers]' \
+  '--device[print device number to which file or directory belongs]' \
+  '(--sort -t -c -U)-v[sort the output as version]' \
+  '(-v --sort -c -U)-t[sort output by modification time]' \
+  '(-v --sort -t -U)-c[sort output by change time]' \
+  '(-v --sort -t -c -r --dirsfirst)-U[leave files unsorted]' \
+  '(-U)-r[sort in reversed order]' \
+  '(-v -t -c -U)--sort[sort in specified order]:order:(name version size mtime ctime)' \
+  '(-U)--dirsfirst[list directories before files]' \
+  "-i[don't print indentation lines]" \
+  '(-S -X)-A[use ANSI line graphics hack when printing indentation lines]' \
+  '(-A -X)-S[use console (CP437) line graphics]' \
+  '(-C)-n[turn colorization off always, over-ridden by the -C option]' \
+  '(-n)-C[turn colorization on always]' \
+  '(-A -S -n -C -J -H -T --nolinks)-X[XML output]' \
+  '(-A -S -n -C -X -H -T --nolinks)-J[JSON output]' \
+  '(-n -C -X)-H[turn on HTML output]:base HREF' \
+  '(-n -C -X)-T[title for HTML output]:title' \
+  '(-n -C -X)--nolinks[turn off hyperlinks in HTML output]' \
+  '(-)--version[version of tree]' \
+  '(-)--help[verbose usage listing]' \
+  '*:directory:_files -/'
diff --git a/Completion/Unix/Command/_truss b/Completion/Unix/Command/_truss
new file mode 100644
index 000000000..656c94244
--- /dev/null
+++ b/Completion/Unix/Command/_truss
@@ -0,0 +1,76 @@
+#compdef truss
+
+local curcontext="$curcontext" state line expl ret=1
+typeset -A opt_args
+local args faults
+
+args=(
+  '(-c)-a[show argument strings with exec system call]'
+  '(-a -d -D -e -E -l -r -v -w -x)-c[count traced system calls, signals etc]'
+  '(-c)-d[include timestamps in output]'
+  '(-c)-D[include delta timestamps in output]'
+  '(-c)-e[show environment strings with exec system call]'
+  '-f[follow child processes created after a fork]'
+  '-o+[specify trace output file]:output file:_files'
+)
+
+case $OSTYPE in
+  aix*|solaris*)
+    args+=(
+      '(-c)-E[include delta timestamps of time spent within the system call]'
+      "-i[don't display interruptible sleeping system calls]"
+      '(-c)-l[include LWP id in each line of output]'
+      '-m+[specify machine faults to trace]: :->faults'
+      '(-c)-r+[show full contents of the I/O buffer for each read()]:file descriptor'
+      '-s+[specify signals to trace]:signal:_sequence _signals -M "B\:!="'
+      '-S+[specify signals at which process should be stopped and abandoned]:signal:_sequence _signals -M "B\:!="'
+      '-t+[specify system calls to trace or exclude]:system call:_sequence _sys_calls -a -M "B\:!="'
+      '-T+[specify system calls at which process should be stopped and abandoned]:system call:_sequence _sys_calls -a -M "B\:!="'
+      '*-u+[user-level function call tracing]: :->userfuncs'
+      '-U+[specify user-level functions at which process should be stopped and abandoned]: :->userfuncs'
+      '(-c)-v+[enable verbose output of structures for specified system calls]:system call:_sequence _sys_calls -a -M "B\:!="'
+      '(-c)-w+[show full contents of the I/O buffer for each write()]:file descriptor'
+      '(-c)-x+[enable raw output of structures for specified system calls]:system call:_sequence _sys_calls -a'
+      '-p[trace specified existing processes]'
+    )
+  ;;
+  dragonfly*|freebsd*)
+    args+=(
+      '-s+[specify the maximum string size to print]:maximum string size [32]'
+      "(-c)-S[don't report signals received by the process]"
+      '(*)-p[trace specified existing processes]:pid:_pids'
+    )
+  ;;
+esac
+
+_arguments -C -s : $args \
+  '*::arguments:->args' && ret=0
+
+case $state in
+  faults)
+    faults=( all ${${${(M)${(f)"$(</usr/include/sys/fault.h)"}:#?define[[:blank:]]##FLT*}#*[[:blank:]]FLT}%%[[:blank:]]*} ) 2>/dev/null
+    _sequence _wanted faults expl fault compadd - -M 'B:!=' -M 'B:[Ff][Ll][Tt]=' -M 'm:{a-z}={A-Z}' -a faults && ret=0
+  ;;
+  args)
+    if [[ $OSTYPE = solaris* ]] && (( $+opt_args[-p] )); then
+      _pids && ret=0
+    elif (( CURRENT == 1 )); then
+      _command_names -e && ret=0
+    else
+      _normal && ret=0
+    fi
+  ;;
+  userfuncs)
+    if [[ -prefix *: ]]; then
+      _message -e functions function
+    else
+      compset -P '*,'
+      compset -S '[,:]*'
+      _description -x libs expl lib
+      compadd "$expl[@]" -S '' lib && ret=0
+      compadd "$expl[@]" -qS, a.out && ret=0
+    fi
+  ;;
+esac
+
+return ret
diff --git a/Completion/Unix/Command/_uniq b/Completion/Unix/Command/_uniq
index 1cf12357b..6973cb312 100644
--- a/Completion/Unix/Command/_uniq
+++ b/Completion/Unix/Command/_uniq
@@ -5,8 +5,10 @@ local args
 args=(
   '(-c --count)'{-c,--count}'[prefix lines by the number of occurrences]'
   '(-d --repeated)'{-d,--repeated}'[only print duplicate lines]'
-  '(-D --all-repeated)'{-D,--all-repeated=}'[print all duplicate lines]:delimit method:(none prepend separate)'
+  '(--all-repeated)-D-[print all duplicate lines]'
+  '(-D)--all-repeated=-[print all duplicate lines]::delimit method [none]:(none prepend separate)'
   '(-f --skip-fields)'{-f,--skip-fields=}'[avoid comparing initial fields]:number of fields'
+  '--group=-[show all items]::group separation [separate]:(separate prepend append both)'
   '(-i --ignore-case)'{-i,--ignore-case}'[ignore differences in case when comparing]'
   '(-s --skip-chars)'{-s,--skip-chars=}'[avoid comparing initial characters]:number of characters'
   '(-t --separator)'{-t,--separator=}'[specify field delimiter]:separator'
diff --git a/Completion/Unix/Command/_units b/Completion/Unix/Command/_units
index 7fcb07894..bea77ae67 100644
--- a/Completion/Unix/Command/_units
+++ b/Completion/Unix/Command/_units
@@ -1,6 +1,6 @@
 #compdef units
 
-local curcontext="$curcontext" state line
+local curcontext="$curcontext" state line expl
 integer ret=1
 typeset -A opt_args
 
@@ -13,12 +13,12 @@ typeset -A opt_args
 _arguments -C -s -S \
   '(-c --check --check-verbose)'{-c,--check}'[check units are reducible]' \
   '(-c --check)--check-verbose[verbosely check units are reducible]' \
-  '(-o --output-format)'{-o,--output-format}'[specify output format]:printf formt: ' \
+  '(-o --output-format)'{-o,--output-format}'[specify output format]:printf format' \
   '(-f --file)'{-f,--file}'[specify file with units]:units file:_files' \
   '(-m --minus)'{-m,--minus}'[- is subtraction]' \
   '(-p --product)'{-p,--product}'[binary - is product]' \
   '(-q --quiet --silent)'{-q,--quiet,--silent}'[suppress prompts and statistics]' \
-  '(-s --strict)'{-s,--strict}'[suppress conversion to reciprocals units]' \
+  '(-s --strict)'{-s,--strict}'[suppress conversion to reciprocal units]' \
   '(-t --terse)'{-t,--terse}'[make conversion output briefer]' \
   '(-v --verbose)'{-v,--verbose}'[make output more verbose]' \
   '(- *)'{-h,--help}'[show help information and exit]' \
diff --git a/Completion/Unix/Command/_user_admin b/Completion/Unix/Command/_user_admin
index 3653308a1..7eeec7e9b 100644
--- a/Completion/Unix/Command/_user_admin
+++ b/Completion/Unix/Command/_user_admin
@@ -1,69 +1,171 @@
 #compdef useradd usermod groupadd groupmod
 
-local args shells home=${${words[(r)-D]:+b}:-d} sun redhat
+local -a args shells logindefs
+local defex
 
-[[ -e /etc/redhat-release || -e /etc/mandrake-release ]]
-redhat=$?
-
-if [[ $service = user* ]]; then
-  if [[ -r /etc/shells ]]; then
-    shells=( ${${(f)"$(</etc/shells)"}:#\#*} )
-  else
-    shells=( ${(M)commands:#*/(|[abckz]|tc|ba)sh} )
-  fi
-
-  args=(
-    '(-D)-c+[comment]:comment'
-    "(-D)-${home}+[home directory]:home directory:_directories -W /"
-    '(-D)-e+[specify expiration date]:expiration date (YYYY-MM-DD)'
-    '(-D)-f+[specify inactive days]:inactive days'
-    '(-D)-g+[initial group]:initial group:_groups'
-    '(-D)-G+[supplementary groups]:supplementary group:_groups -S,'
-    "(-D)-s+[shell]:shell:( $shells /bin/false )"
-    '(-D -M)-m[create home directory]'
-    '(-D)-u[uid]:uid'
-    '(-D)-o[allow non unique uid]'
-  )
-  [[ $OSTYPE = linux* ]] && args+=(
-      '(-D -U -L)-p+[specify encrypted password]:encrypted password' )
-
-  if [[ $service = useradd ]]; then
-    (( redhat )) || args+=(
-      "(-D -k -m)-M[don't create home]"
-      '(-D)-r[create system account]'
-      "(-D)-n[don't create mirrored user]"
+# this handles solaris, netbsd, openbsd and linux
+case ${service%???}:${(M)service%???}:$OSTYPE in
+  user:*)
+    if [[ -r /etc/shells ]]; then
+      shells=( ${${(f)"$(</etc/shells)"}:#\#*} )
+    else
+      shells=( ${(M)commands:#*/(|[abckz]|tc|ba)sh} )
+    fi
+    args+=(
+      '(-D -c --commend)'{-c+,--comment=}'[comment]:comment'
+      '(-D -d --home -b --base-dir)'{-d+,--home=}"[specify home directory]:home directory:_directories -W /"
+      '(-D -e --expiredate)'{-e+,--expiredate}'[specify expiration date]:expiration date (YYYY-MM-DD)'
+      '(-D -f --inactive)'{-f+,--inactive=}'[specify inactive days]:inactive days'
+      '(-D -g --gid)'{-g+,--gid=}'[specify primary group]:initial group:_groups'
+      '(-D -G --groups)'{-G+,--groups=}'[specify supplementary groups]:supplementary group:_sequence _groups'
+      '(-D -s --shell)'{-s+,--shell=}"[shell]:shell:( $shells /bin/false )"
+      '(-D -u --uid)'{-u+,--uid=}'[specify uid]:uid'
+      '(-D -o --non-unique)'{-o,--non-unique}'[allow non unique uid]'
     )
-    [[ $OSTYPE = linux* ]] || sun=" -s"
+  ;|
+  user:add:*)
+    [[ $OSTYPE = linux* ]] && defex=" -k -K -M -p -r -R -Z"
+    [[ $OSTYPE = (net|open)bsd* ]] && defex=" -p -v"
     args+=(
-      "(-c -G -m -k -M -p -u -o -n -r$sun)-D[modify or display defaults]"
-      '(-D -M)-k[skeleton home directory]:skeleton directory:_directories -W /'
+      "(-c -d -G -m -l -N -u -U -o -n -S$defex)"{-D,--defaults}'[show or modify defaults]'
+      '(-D -M -k --skel)'{-k,--skel}'[skeleton home directory]:skeleton directory:_directories -W /'
+      '(-D -M -m --create-home)'{-m,--create-home}'[create home directory]'
       ':username'
     )
-  else
-    (( redhat )) || args=( $args[@]
-	"(-U -p)-L[lock user's password]"
-	"(-L -p)-U[unlock user's password]"
+  ;|
+  user:add:linux*)
+    logindefs=( # see login.defs(5)
+      CREATE_HOME GID_MAX GID_MIN MAIL_DIR MAX_MEMBERS_PER_GROUP
+      PASS_MAX_DAYS PASS_MIN_DAYS PASS_WARN_AGE SUB_GID_COUNT SUB_GID_MAX
+      SUB_GID_MIN SUB_UID_COUNT SUB_UID_MAX SUB_UID_MIN SYS_GID_MAX
+      SYS_GID_MIN SYS_UID_MAX SYS_UID_MIN UID_MAX UID_MIN UMASK
+    )
+    args+=(
+      '(-l --no-log-init)'{-l,--no-log-init}"[don't add user to lastlog and faillog databases]"
+      '(-m --create-home -M --no-create-home)'{-M,--no-create-home}"[don't create user's home directory, regardless of /etc/login.defs]"
+      '(-N --no-user-group -U --user-group)'{-N,--no-user-group}"[don't create a group with the same name as the user]"
+      '(-N --no-user-group -U --user-group)'{-U,--user-group}"[create a group with the same name as the user]"
+    )
+  ;|
+  user:add:(^solaris2.<-10>))
+    args+=(
+      '(-b --base-dir -d --home-dir)'{-b,--base-dir=}'[specify base directory for new home directory]:directory:_directories'
+    )
+  ;|
+  user:*:(net|open)bsd*)
+    args+=(
+      '-L[specify login class]:login class'
+      '-p+[specify encrypted password]:encrypted password'
+    )
+  ;|
+  user:add:(net|open)bsd*)
+    args+=( '-r[specify UID range]:low.high' )
+  ;|
+  user:add:netbsd*)
+    args+=( '-M[specify home directory permissions]:permissions (octal)' )
+  ;|
+  user:mod:netbsd*)
+    args+=( '-C[lock or unlock account]:locked:(yes no)' )
+  ;|
+  user:*:netbsd*)
+    args+=(
+      '-F[force password change on first login]'
+      '-S[allow samba usernames with a trailing dollar]'
+    )
+  ;|
+  user:mod:openbsd*)
+    args+=(
+      '(-G)-S+[set supplementary groups]:supplementary group:_sequence _groups'
+      "(-U)-Z[lock the account by adding \'-\' to password and shell]"
+      '(-Z)-U[unlock the account]'
+    )
+  ;|
+  *:*:(net|open)bsd*)
+    args+=( '-v[verbose mode - explain commands as they are executed]' )
+  ;|
+  *:*:solaris2.<11->)
+    args+=( '-S[specify repository]:repository:(files ldap)' )
+  ;|
+  user:*:solaris2.<11->)
+    args+=(
+      '-A[specify authorizations]:authorization'
+      \*{-K,--key=}'[set user attributes]:user attribute'
+      '-P[specify execution profiles]:profile'
+      '-R[specify roles]:role'
+      '-p[specify projects]:project'
     )
-    [[ $OSTYPE = openbsd* ]] || args+=('-a[append groups]')
+  ;|
+  user:mod:solaris2.<11->)
     args+=(
-      '-l[specify new user name]:new username'
+      '-q[specify host or netgroup to qualify extended attributes]:host or netgroup:_hosts'
+    )
+  ;|
+  user:mod:linux*)
+    args+=(
+      '(-a --append)'{-a,--append}'[add user to supplementary groups without removing from other groups]'
+      \*{-v,--add-sub-uids}'[add a range of subordinate uids]:uids (first-last)'
+      \*{-V,--del-sub-uids}'[remove a range of subordinate uids]:uids (first-last)'
+      \*{-w,--add-sub-gids}'[add a range of subordinate gids]:gids (first-last)'
+      \*{-W,--del-sub-gids}'[remove a range of subordinate gids]:gids (first-last)'
+    )
+  ;|
+  user:mod:*)
+    args+=(
+      '(-l --no-log-init)'{-l,--no-log-init}'[specify new user name]:new username'
+      '(-m --move-home)'{-m,--move-home}'[move home directory contents to new location]'
       ':username:_users'
     )
-  fi
-else
-  args=( '-g+[gid]:gid' '-o[allow non unique gid]' )
-  if [[ $service = groupadd ]]; then
-    args+=( ':group name' )
-    (( redhat )) || args=( $args[@]
-      '-r[create system group]'
-      '-f[force]'
+  ;|
+  user:*:linux*)
+    args+=(
+      '(-U --unlock --lock -L -p)'{-L,--lock}"[lock user's password]"
+      '(-U --unlock --lock -L -p)'{-U,--unlock}"[unlock user's password]"
+      '(-Z --selinux-user)'{-Z,--selinux-user}"[specify SELinux user for the user's login]:user"
+    )
+  ;|
+  group:*)
+    args+=(
+      '(-g --gid)'{-g+,--gid=}'[specify gid]:gid'
+      '(-o --non-unique)'{-o,--non-unique}'[allow non unique gid]'
     )
-  else
+  ;|
+  group:add:linux*)
+    logindefs=( GID_MAX GID_MIN MAX_MEMBERS_PER_GROUP SYS_GID_MAX SYS_GID_MIN )
+    args+=(
+      '(-r --system)'{-r,--system}'[create a system account]'
+      '(-f --force)'{-f,--force}'[exit successfully if group already exists; cancel -g if GID in use]'
+    )
+  ;|
+  group:*:solaris2.<11->)
+    args+=( '-U[add users to the group]:user:_sequence _users' )
+  ;|
+  *:add:linux*)
+    args+=(
+      \*{-K,--key=}'[override /etc/login.defs defaults]:key: _values 'key' ${^logindefs}\:value'
+    )
+  ;|
+  group:add:netbsd*)
+    args+=( '-r[specify GID range]:low.high' )
+  ;|
+  *:*:linux*)
+    args+=(
+      '(-R --root)'{-R,--root=}'[specify directory to chroot into]:directory:_directories'
+      '(-D -U -L -p --password)'{-p+,--password=}'[specify encrypted password]:encrypted password'
+      '(-)'{-h,--help}'[display help information]'
+    )
+  ;|
+  group:add:*)
+    args+=( ':group name' )
+  ;|
+  group:mod:*)
     args+=(
-      '-n[specify new group name]:new group name'
+      '(-n --new-name)'{-n,--new-name}'[specify new group name]:new group name'
       ':group:_groups'
     )
-  fi
-fi
+  ;|
+  ^*:linux*)
+    args=( ${(R)args:#(|\*)(|\(*\))--*} )    # remove long options
+  ;|
+esac
 
 _arguments -A "-*" -s $args[@]
diff --git a/Completion/Unix/Command/_vim b/Completion/Unix/Command/_vim
index dbc946cb1..9fd2d63e8 100644
--- a/Completion/Unix/Command/_vim
+++ b/Completion/Unix/Command/_vim
@@ -13,7 +13,7 @@ _vim_files () {
   esac
 }
 
-local curcontext="$curcontext" state line expl
+local curcontext="$curcontext" state line expl ret=1
 typeset -A opt_args
 
 local arguments
@@ -30,16 +30,7 @@ arguments=(
   '-C[start in compatible mode]'
   '-N[start in incompatible mode]'
   '(--nofork -f)'{--nofork,-f}'[do not detach the GUI version from the shell]'
-  '-V-[verbosity level]::verbosity:((0\:"do not display any messages"
-                                     1\:"display when viminfo file is read or written"
-                                     2\:"display sourced files"
-                                     5\:"display every searched tag-file"
-                                     8\:"display files that trigger autocommands"
-                                     9\:"display every triggered autocommand (default)"
-                                    12\:"display every executed function"
-                                    13\:"report every thrown, caught, finished, or discarded exception"
-                                    14\:"display anything pending in a \:finally clause"
-                                    15\:"display every executed ex-command"))'
+  '-V-[verbosity level]::verbosity [10]:->verbosity'
   '-D[debugging mode]'
   '-n[no swap file (memory only)]'
   '-nb[start as NetBean server]'
@@ -48,8 +39,9 @@ arguments=(
   '(-A    -F)-H[start in Hebrew mode]'
   '(-A -H   )-F[start in Farsi mode]'
   '-T[set terminal type]:::_terminals'
+  '--not-a-term[skip warning for input/output not being a terminal]'
   '-u[use given vimrc file instead of default .vimrc]::rc file:_files'
-  '--noplugin[do not load plugin scripts]'
+  "--noplugin[don't load plugin scripts]"
   '-o-[number of windows to open (default: one for each file)]::window count: '
   '-O-[number of windows to vertically split open (default is one for each file)]::window count: '
   '-p-[number of tabs to open (default: one for each file)]::tab count: '
@@ -77,7 +69,7 @@ arguments=(
   '--servername[name of vim server to send to or name of server to become]:server name:->server'
   '--startuptime[write startup timing messages to given file]:log file:_files'
   '--socketid[run GVIM in another window]'
-  '-i[use given viminfo file instead of default .viminfo]:viminfo file:_files'
+  '-i[use specified viminfo file]:viminfo file [~/.viminfo]:_files'
   '(- *)'{-h,--help}'[print help and exit]'
   '(- *)--version[print version information and exit]'
   '(* -q)-t[edit file where tag is defined]:tag:_complete_tag'
@@ -98,12 +90,33 @@ arguments=(
   '-U[use given gvimrc file instead of default .gvimrc]::rc file:_files'
 )
 
-_arguments -C -S $arguments && return
+_arguments -C -S $arguments && ret=0
 
 if [[ "$state" = server ]]; then
   local -a servers
   servers=( ${(f)"$(_call_program servers $words[1] --serverlist 2>/dev/null)"} )
-  _wanted servers expl server compadd -M 'm:{a-z}={A-Z}' -a servers && return
+  _wanted servers expl server compadd -M 'm:{a-z}={A-Z}' -a servers && ret=0
+elif [[ $state = verbosity ]]; then
+  _tags numbers files
+  while _tags; do
+    _requested numbers && _describe 'verbosity [10]' "(
+      0:don\'t' display any messages'
+      1:'display when viminfo file is read or written'
+      2:'display sourced files'
+      5:'display every searched tag-file'
+      8:'display files that trigger autocommands'
+      9:'display every triggered autocommand'
+      12:'display every executed function'
+      13:'report every thrown, caught, finished, or discarded exception'
+      14:'display anything pending in a :finally clause'
+      15:'display every executed ex-command'
+    )" && ret=0
+    if _requested files expl 'file for verbose output'; then
+      compset -P '[0-9]#'
+      _files "$expl[@]" && ret=0
+    fi
+    (( ret )) || break
+  done
 fi
 
-return 1
+return ret
diff --git a/Completion/Unix/Command/_vmstat b/Completion/Unix/Command/_vmstat
index 02fa6be64..7082cbbd5 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/_w3m b/Completion/Unix/Command/_w3m
index 9569368a5..6e83a6781 100644
--- a/Completion/Unix/Command/_w3m
+++ b/Completion/Unix/Command/_w3m
@@ -90,7 +90,7 @@ case "$state" in
   option)
     local -a options
     options=( ${${(M)${(f)"$(_call_program options $words[1] -show-option 2>/dev/null)"}:#    -o *}/(#b)    -o (*)=[^ ]#[[:blank:]]##(*)/$match[1]:${match[2]:l}} )
-    if compset -P '*='; then
+    if compset -P 1 '*='; then
       _message -e values 'value'
     else
       compset -S '=*' || suf=( -S '=' )
@@ -98,7 +98,7 @@ case "$state" in
     fi
   ;;
   pauth)
-    if compset -P '*:'; then
+    if compset -P 1 '*:'; then
       _message -e passwords 'password'
     else
       compset -S ':*' || suf=( -S ':' )
diff --git a/Completion/Unix/Command/_wget b/Completion/Unix/Command/_wget
index b6feab581..8a9cc871a 100644
--- a/Completion/Unix/Command/_wget
+++ b/Completion/Unix/Command/_wget
@@ -32,7 +32,7 @@ _arguments -C -s \
   '(--timeout -T)--dns-timeout=[set the DNS lookup timeout]:DNS lookup timeout (seconds)' \
   '(--timeout -T)--connect-timeout=[set the connect timeout]:connect timeout (seconds)' \
   '(--timeout -T)--read-timeout=[set the read timeout]:read timeout (seconds)' \
-  '(--wait,-w)'{--wait=,-w+}'[specify wait between retrievals]:time (seconds)' \
+  '(--wait -w)'{--wait=,-w+}'[specify wait between retrievals]:time (seconds)' \
   '(--random-wait)--waitretry=:time (seconds)' \
   '(--waitretry)--random-wait[random wait time between retrievals]' \
   '(--proxy -Y --no-proxy)'{--proxy=,-Y+}'[explicitly turn on proxy]' \
@@ -127,7 +127,6 @@ _arguments -C -s \
   '--trust-server-names' \
   '(--exclude-directories -X)'{--exclude-directories=,-X+}'[exclude directories]:excluded directories' \
   '(-np --no-parent)'{-np,--no-parent}"[don't ascend to parent directory]" \
-  '--no-host-lookup' \
   '--no-verbose' \
   '--no-clobber' \
   '--no-directories' \
diff --git a/Completion/Unix/Command/_wiggle b/Completion/Unix/Command/_wiggle
index ec71fdcb9..0a2f0c0cb 100644
--- a/Completion/Unix/Command/_wiggle
+++ b/Completion/Unix/Command/_wiggle
@@ -9,7 +9,7 @@ _arguments \
   '(-w --words -l --lines)'{-w,--words}'[make operations and display word based]' \
   '(-l --lines -w --words)'{-l,--lines}'[make operations and display line based]' \
   '(-p --patch)'{-p,--patch}'[treat last named file as a patch]' \
-  '(-r --replace)'{-r,--replace}'[replace orginal file with merged output]' \
+  '(-r --replace)'{-r,--replace}'[replace original file with merged output]' \
   '(-R --reverse -x --extract)'{-R,--reverse}'[swap the files or revert changes]' \
   '(-2 -3 -m --merge)-1[select branch]' \
   '(-1 -3 -m --merge)-2[select branch]' \
diff --git a/Completion/Unix/Command/_xargs b/Completion/Unix/Command/_xargs
index d8c0a0ec2..8b543341d 100644
--- a/Completion/Unix/Command/_xargs
+++ b/Completion/Unix/Command/_xargs
@@ -47,6 +47,7 @@ case $variant in
       '(-0 --null -d --delimiter)'{-0,--null}'[expect NUL characters as input separators]'
       '(-d --delimiter -0 --null)'{-d+,--delimiter=}'[specify delimiter of input items]:delimiter'
       '(-l -L --max-lines -n --max-args -s --max-chars)--max-lines=-[call program for every number of lines]::number of input lines'
+      '--process-slot-var=[set environment variable to unique value in child processes]:variable:_parameters -g "*export*"'
       '(-r --no-run-if-empty)'{-r,--no-run-if-empty}"[don't run command in absence of input]"
       '(- *)--help[show help information]'
       '(- *)--version[show version information]'
diff --git a/Completion/Unix/Command/_xmlsoft b/Completion/Unix/Command/_xmlsoft
index 67ba6c001..7b4b0b03d 100644
--- a/Completion/Unix/Command/_xmlsoft
+++ b/Completion/Unix/Command/_xmlsoft
@@ -1,7 +1,7 @@
 #compdef xsltproc xmllint -value-,XML_CATALOG_FILES,-default-
 
-# xmllint: using libxml version 20707
-# xsltproc: using libxml 20707, libxslt 10126 and libexslt 815
+# xmllint: using libxml version 20904
+# xsltproc: using libxml 20904, libxslt 10129 and libexslt 817
 
 local -a encoding
 
@@ -38,7 +38,9 @@ case $service in
       '--nodtdattr[do not default attributes from the DTD]' \
       '--noout[do not dump the result]' \
       '--maxdepth[increase the maximum depth]:depth' \
+      '--maxvars[increase the maximum variables]:variables' \
       '--maxparserdepth[increase the maximum parser depth]:depth' \
+      '--seed-rand[initialise random number generator]:seed' \
       '--html[input document is an HTML file]' \
       '--encoding[the input document character encoding]:encoding:(${encoding[@]})' \
       '*--param[pass a parameter,value pair]:name::value (xpath expression)' \
@@ -87,6 +89,7 @@ case $service in
       '--xmlout[use the XML serializer when using --html]' \
       '--nodefdtd[do not default HTML doctype]' \
       '--push[use the push mode of the parser]' \
+      '--pushsmall[use the push mode of the parser using tiny increments]' \
       '--memory[parse from memory]' \
       '--maxmem[limit memory allocation]:bytes' \
       '--nowarning[do not emit warnings from parser/validator]' \
diff --git a/Completion/Unix/Command/_xxd b/Completion/Unix/Command/_xxd
index 1a822553c..1b1613a64 100644
--- a/Completion/Unix/Command/_xxd
+++ b/Completion/Unix/Command/_xxd
@@ -22,21 +22,23 @@ local arguments
 
 arguments=(
   # output options
-  '(-b -bits            -i -include -p -postscript -plain -ps -r -reverse -u -uppercase)'{-b,-bits}'[output in binary digits, rather than hex]'
-  '(         -E -EBCDIC -i -include -p -postscript -plain -ps -r -reverse              )'{-E,-EBCDIC}'[print human-readable part in EBCDIC rather than ASCII]'
-  '(-b -bits -E -EBCDIC -i -include -p -postscript -plain -ps -r -reverse              )'{-i,-include}'[output in C include file style]'
-  '(-b -bits -E -EBCDIC -i -include -p -postscript -plain -ps                          )'{-p,-postscript,-plain,-ps}'[read or write a plain hexdump (no line numbers or ASCII rendering)]'
+  '(-b -bits            -i -include -p -postscript -plain -ps -r -revert -u -uppercase)'{-b,-bits}'[output in binary digits, rather than hex]'
+  '(         -E -EBCDIC -i -include -p -postscript -plain -ps -r -revert              )'{-E,-EBCDIC}'[print human-readable part in EBCDIC rather than ASCII]'
+  '(-i -include -p -postscript -plain -ps -r -revert)'{-e,-endian}'[little-endian dump]'
+  '(-b -bits -E -EBCDIC -i -include -p -postscript -plain -ps -r -revert              )'{-i,-include}'[output in C include file style]'
+  '(-b -bits -E -EBCDIC -i -include -p -postscript -plain -ps                         )'{-p,-postscript,-plain,-ps}'[read or write a plain hexdump (no line numbers or ASCII rendering)]'
 
-  '(-b -bits -E -EBCDIC -i -include                           -r -reverse -u -uppercase)'{-r,-reverse}'[reverse mode\: read a hex dump and output binary data]'
-  '(-b -bits                                                  -r -reverse -u -uppercase)'{-u,-uppercase}'[output upper-case hex digits]'
+  '(-b -bits -E -EBCDIC -i -include                           -r -revert -u -uppercase)'{-r,-revert}'[reverse mode\: read a hex dump and output binary data]'
+  '(-b -bits                                                  -r -revert -u -uppercase)'{-u,-uppercase}'[output upper-case hex digits]'
 
-  {-h,-help}'[display usage message]'
-  {-v,-version}'[show program version]'
+  '(- :)'{-h,-help}'[display usage message]'
+  '(- :)'{-v,-version}'[show program version]'
   '*'{-a,-autoskip}"[a single '*' replaces runs of NUL (toggleable)]"
 
   {-c+,-cols}'[specify number of octets per line]: :_guard "[0-9a-fA-Fx]#" "number of octets per line"'
   {-g+,-groupsize}'[specify the number of octets per group]: :_guard "[0-9]#" "number of octets per group"'
   {-l+,-len}'[specify number of octets to output]: :_guard "[0-9]#" "number of octets to output"'
+  {-o+,-offset}'[add specified offset to displayed file position]:offset'
   {-s,-skip,-seek}'[specify file offset to dump from]: :_guard "[0-9]#" "file offset to dump from (absolute or relative)"'
 
   ':files:_files'
diff --git a/Completion/Unix/Command/_xz b/Completion/Unix/Command/_xz
index 028285a35..01e56022b 100644
--- a/Completion/Unix/Command/_xz
+++ b/Completion/Unix/Command/_xz
@@ -42,7 +42,7 @@ case "$service" in
     "${decomp}--no-sparse[do not create sparse files when decompressing]" \
     '(* --files --files0)--files=-[read list of files to process from file]::file:_files' \
     '(* --files --files0)--files0=-[read null terminated list of files to process from file]::file:_files' \
-    '(-F --format)'{-F,--format}'=[specify file format]:format;(auto xz lzma raw)' \
+    '(-F --format)'{-F,--format}'=[specify file format]:format:(auto xz lzma raw)' \
     '(-C --check)'{-C,--check}'=[integrity check type]:check type:(none crc32 crc64 sha256)' \
     '--memlimit-compress=[set memory usage limit for compression]:memory usage' \
     '--memlimit-decompress=[set memory usage limit for decompression]:memory usage' \
diff --git a/Completion/Unix/Command/_yafc b/Completion/Unix/Command/_yafc
index df9623beb..1e0a601a1 100644
--- a/Completion/Unix/Command/_yafc
+++ b/Completion/Unix/Command/_yafc
@@ -1,28 +1,28 @@
-# compdef yafc
+#compdef yafc
 
 _yafc() {
-    local arguments
-    arguments=(
+  local arguments
+  arguments=(
     '(--anon -a)'{--anon,-a}'[try an anonymous login]'
     '(--debug -d)'{--debug,-d}'[print all messages to/from server]'
     '(--dump-rc -D)'{--dump-rc,-D}'[print the default configuration file]'
-    '(--mechanism -m)'{--mechanism=-,-m}'[specify a security mechanism]:security mechanism:(krb4, krb5, none)'
-    '(--norc -n)'{--norc,-n}'[do not read the users configuration file]'
-    '(--noproxy -p)'{--noproxy,-p}'[do not connect via the proxy]'
-    '(--quiet -q)'{--quiet,-q}'[do not print the welcome message]'
+    '(--mechanism -m)'{--mechanism=-,-m}'[specify a security mechanism]:security mechanism:(krb4 krb5 none)'
+    '(--norc -n)'{--norc,-n}"[don't read the users configuration file]"
+    '(--noproxy -p)'{--noproxy,-p}"[don't connect via the proxy]"
+    '(--quiet -q)'{--quiet,-q}"[don't print the welcome message]"
     '(--rcfile -r)'{--rcfile=-,-r}'[specify a configuration file]:configuration file:_files'
     '(--trace -t)'{--trace=-,-t-}'[specify a trace file]:trace file:_files'
-    '(--noauto -u)'{--noauto,-u}'[do not login automagically]'
+    '(--noauto -u)'{--noauto,-u}"[don't login automatically]"
     '(--noalias -U)'{--noalias,-U}'[as --noauto, but bookmark aliases is disabled]'
     '(--verbose -v)'{--verbose,-v}'[print all responses received]'
-    '(--wait -w)'{--wait,-w=}'[specify a waiting time between connection attempts]:wait time: '
+    '(--wait -w)'{--wait,-w=}'[specify a waiting time between connection attempts]:wait time (seconds)'
     '(--workdir -W)'{--workdir=,-W+}'[use a different working directory]:working directory:_directories'
-    '(--version -V)'{--version,-V}'[print version information]'
-    '(--help -h)'{--help,-h}'[print a short help description]'
+    '(- *)'{--version,-V}'[print version information]'
+    '(- *)'{--help,-h}'[print a short help description]'
     '*:address:_yafc_address'
-    )
+  )
 
-    _arguments -S -s $arguments
+  _arguments -S -s $arguments
 }
 
  (( $+functions[_yafc_bookmarks] )) ||
@@ -30,7 +30,7 @@ _yafc_bookmarks() {
     local bkmfile=~/.yafc/bookmarks
     
     if [[ -f $bkmfile ]]; then
-        local -a bkms
+        local -a bkms expl
         bkms=(${${${(M)"${(f)$(<$bkmfile)}":#machine*alias ##\'*\' #}##machine*alias ##\'}%%\' #}) #" vim syntax goes crazy
         _wanted bookmarks expl 'bookmarks' compadd "$@" -a - bkms
     fi
diff --git a/Completion/Unix/Command/_zfs b/Completion/Unix/Command/_zfs
index f3869da43..553996da0 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/Command/_zip b/Completion/Unix/Command/_zip
index 1040fa977..1b1b6c315 100644
--- a/Completion/Unix/Command/_zip
+++ b/Completion/Unix/Command/_zip
@@ -6,38 +6,28 @@ typeset -A opt_args
 
 case $service in
   zip)
-    _arguments -C -s \
-      '-f[freshen: only changed files]' \
-      '-d[delete entries in zipfile]' \
+    _arguments -C -s -S \
+      '(-u --update)'{-u,--update}'[update: only changed or new files]' \
+      '(-f --freshen)'{-f,--freshen}'[freshen: update existing files only (no files added)]' \
+      '(-FS --filesync)'{-FS,--filesync}'[filesync: update if date or size changed]' \
+      '(-d --delete)'{-d,--delete}'[delete: delete files from archive]' \
+      '(-U --copy)'{-U,--copy}'[copy: select files in archive to copy]' \
       '-r[recurse into directories]' \
-      '-R[PKZIP recursion]' \
+      '(-m --move)'{-m,--move}'[after archive created, delete original files]' \
+      '(-j --junk-paths)'{-j,--junk-paths}'[junk directory names (store just file names)]' \
       '-q[quiet operation]' \
-      '-c[add one-line comments]' \
-      '-b[use "path" for temp file]:path for temporary archive:_files -/' \
-      '-@[read names from stdin]' \
-      '-F[fix zipfile]' \
-      '-FF[try harder to fix zipfile]' \
-      '-A[adjust self-extracting exe]' \
-      '-T[test zipfile integrity]' \
-      '-y[store symbolic links as the link instead of the referenced file]' \
-      '-e[encrypt]' \
-      '-h[show help]' \
-      '-u[update: only changed or new files]' \
-      '-m[move into zipfile (delete files)]' \
-      '-g[allow growing existing zipfile]' \
-      '-j[junk: do not record directory names]' \
-      '-l[convert LF to CR LF]' \
-      '-ll[convert CR LF to LF]' \
-      '-L[display license]' \
       '-v[verbose operation/print version info]' \
-      '-z[add zipfile comment]' \
-      '-t[only do files after or at "mmddyyyy"]:mmddyyyy' \
-      '-tt[only do files before "mmddyyyy"]:mmddyyyy' \
+      '(-c --entry-comments)'{-c,--entry-comments}'[prompt for one-line comment for each entry]' \
+      '(-z --archive-comment)'{-z,--archive-comment}'[prompt for comment for archive]' \
+      '(-@ --names-stdin)'{-@,--names-stdin}'[read names to zip from stdin]' \
       '-o[make zipfile as old as latest entry]' \
-      '-D[do not add directory entries]' \
-      '-J[junk zip file prefix (unzipsfx)]' \
-      '-X[eXclude eXtra file attributes]' \
-      '-n[specify suffixes of files not to be compressed]:suffixes:->suffixes' \
+      '(-i --include)'{-i,--include}'[include files that match a pattern]:*(-*|@):pattern:_files' \
+      '(-x --exclude)'{-x,--exclude}'[exclude files that match a pattern]:*(-*|@):pattern:_files' \
+      '-l[convert LF to CR LF]' \
+      '-ll[convert CR LF to LF]' \
+      '-R[recurse current dir and match patterns]' \
+      '-t+[exclude files modified before specified date]:date (mmddyyyy)' \
+      '-tt+[exclude files modified on or after specified date]:date (mmddyyyy)' \
       '(   -1 -2 -3 -4 -5 -6 -7 -8 -9)-0[store only]' \
       '(-0    -2 -3 -4 -5 -6 -7 -8 -9)-1[compress faster]' \
       '(-0 -1    -3 -4 -5 -6 -7 -8 -9)-2' \
@@ -48,18 +38,60 @@ case $service in
       '(-0 -1 -2 -3 -4 -5 -6    -8 -9)-7' \
       '(-0 -1 -2 -3 -4 -5 -6 -7    -9)-8' \
       '(-0 -1 -2 -3 -4 -5 -6 -7 -8   )-9[compress better]' \
-      '-x[exclude the following names]' \
-      '-i[include only the following names]' \
+      '(-Z --compression-method)'{-Z+,--compression-method=}'[specify compression method]:method:(store deflate bzip2)' \
+      '(-e --encrypt)'{-e,--encrypt}'[encrypt using (weak) PKZip 2.0 encryption, prompt for password]' \
+      '-P+[specify password for standard encryption]:password' \
+      '-s+[create split archive with splits of specified size]:size (MB)' \
+      '-sp[pause after each split to allow changing disks]' \
+      '-sb[ring bell when pausing between splits]' \
+      '-sv[be verbose about creating splits]' \
+      '(-O --out)'{-O,--out=}'[output to new archive]:archive' \
+      '(-FI --fifo)'{-FI,--fifo}'[support reading from a pipe]' \
+      '(-db --display-bytes)'{-db,--display-bytes}'[display running count of bytes processed and bytes to go]' \
+      '(-dc --display-counts)'{-dc,--display-counts}'[display running count of entries done and entries to go]' \
+      '(-dd --display-dots)'{-dd,--display-dots}'[display dots while each entry is zipped]' \
+      '(-dg --display-globaldots)'{-dg,--display-globaldots}'[display dots for the archive instead of each file]' \
+      '(-ds --dot-size)'{-ds,--dot-size=}'[specify size at which a dot is output while processing files]:size [10MB]' \
+      '(-du --display-usize)'{-du,--display-usize}'[display original uncompressed size for each entry as added]' \
+      '(-dv --display-volume)'{-dv,--display-volume}'[display volume (disk) number in format in_disk>out_disk]' \
+      '(-lf --logfile-path)'{-lf,--logfile-path=}'[specify log file]:file:_files' \
+      '(-la --log-append)'{-la,--log-append}'[append to existing log file]' \
+      '(-li --log-info)'{-li,--log-info}'[include info messages in log]' \
+      '(-T --test)'{-T,--test}'[test zipfile integrity]' \
+      '(-TT --unzip-command)'{-TT,--unzip-command=}'[specify command for testing archive]:command [unzip -tqq]:_cmdstring' \
+      '(-F --fix)'{-F,--fix}'[fix zipfile]' \
+      '(-F --fix -FF --fixfix)'{-FF,--fixfix}'[try harder to fix zipfile]' \
+      '(-DF --dif)'{-DF,--dif}'[only include files that have changed or are new as compared to the input archive]' \
+      '-sf[show files to operate on and exit]' \
+      '-su[as -sf but show escaped UTF-8 Unicode names also]' \
+      '-su[as -sf but show escaped UTF-8 Unicode names instead]' \
+      '-UN=[specify Unicode path mismatch handling]:mismatch handling:(Quit Warn Ignore No Escape UTF8)' \
+      '(-A --adjust-sfx)'{-A,--adjust-sfx}'[adjust self-extracting exe]' \
+      '(-J --junk-sfx)'{-J,--junk-sfx}'[junk zip file prefix (unzipsfx)]' \
+      '(-b --temp-path)'{-b,--temp-path}'[specify location for temporary archive]:path for temporary archive:_directories' \
+      '-nw[no wildcards]' \
+      '(-X --no-extra)'{-X,--no-extra}'[eXclude eXtra file attributes]' \
+      '(-y --symlinks)'{-y,--symlinks}'[store symbolic links as the link instead of the referenced file]' \
+      '(-)'{-h,--help}'[display help information]' \
+      '(-)'{-h2,--more-help}'[display extended help information]' \
+      '(-g --grow)'{-g,--grow}'[allow growing existing zipfile]' \
+      '(-L --license)'{-L,--license}'[display license]' \
+      '(-D --no-dir-entries)'{-D,--no-dir-entries}"[don't add directory entries]" \
+      '-n[specify suffixes of files not to be compressed]:suffixes:->suffixes' \
       "(-f -d -R -q -c -b -@ -F -FF -A -T -y -e -h -u -m -g -j -l -ll -L -v -z -t -tt -o -D -J -X -n -0 -1 -2 -3 -4 -5 -6 -7 -8 -9):zip file:_files -g '(#i)*.(zip|xpi|[ejw]ar)(-.)'" \
       '*:file:->files' && ret=0
   ;;
   unzip)
     _arguments -C -s \
-      '(-f -u -l -t -z -d)-p[extract files to pipe]' \
+      '(-Z)-M[page output]' \
+      - unzip \
+      '(-f -u -l -t -z -d -p)-c[extract files to stdout including file names]' \
       '(-p -u -l -t -z)-f[freshen existing files; create none]' \
+      '(-f -u -l -t -z -c -d)-p[extract files to stdout]' \
       '(-p -f -l -t -z)-u[update files; create if necessary]' \
       '(-p -f -u -t -z -d)-l[list files]' \
       '(-p -f -u -l -z -d)-t[test compressed archive data]' \
+      '-T[timestamp archive to latest]' \
       '(-p -f -u -l -t -d)-z[display archive comment]' \
       '(-p -l -t -z)-d+[specify directory to extract files to]:directory:_files -/' \
       '(-p -l -t -z -o)-n[never overwrite existing files]' \
@@ -70,13 +102,28 @@ case $service in
       '-q[quiet]' '-qq[quieter]' \
       '(-l -t -z)-a[auto-convert any text files]' \
       '(-l -t -z)-aa[treat all files as text]' \
+      '(-l -t -z)-b[treat all files as binary]' \
+      '(-l -t -z)-B[save backup copy of each overwritten file]' \
+      '(-DD)-D[skip restoration of timestamps for extracted directories]' \
+      '(-D)-DD[skip restoration of timestamps for all entries]' \
       '-v[verbose/display version info]' \
-      '(-p -z)-L[lowercase (some) filenames]' \
-      '-M[page output]' \
-      '-x[exclude the following names]' \
-      '-Z[zipinfo mode]:zipinfomode:->zipinfo' \
+      '(-c -p -z -LL)-L[lowercase filenames from case-insensitive file systems]' \
+      '(-c -p -z -L)-LL[lowercase all filenames]' \
+      '-K[keep setuid/setgid/sticky permissions]' \
+      '-P[specify password for decryption]:password' \
+      '(-UU)-U[use escapes for all non-ASCII Unicode]' \
+      '(-U)-UU[ignore any Unicode fields]' \
+      '-W[modify pattern matching so only ** matches /]' \
+      '-\:[allow extraction outside of extraction base directory]' \
+      '-\\\^[allow control characters in extracted entries]' \
+      '-i[include the following names]:*-*:pattern' \
+      '-x[exclude the following names]:*-*:pattern' \
       "(-p -f -u -l -t -z -n -o -j -C -X -q -qq -a -aa -v -L -M)1:zip file:_files -g '(#i)*.(zip|xpi|[ejw]ar)(-.)'" \
-      '*:file:->files' && ret=0
+      '*:file:->files' \
+      - help \
+      '-hh[display detailed help information]' \
+      - zipinfo \
+      '-Z[zipinfo mode]:zipinfomode:->zipinfo' && ret=0
   ;;
 esac
 
diff --git a/Completion/Unix/Command/_zpool b/Completion/Unix/Command/_zpool
index 950266896..4d4793eea 100644
--- a/Completion/Unix/Command/_zpool
+++ b/Completion/Unix/Command/_zpool
@@ -237,7 +237,7 @@ _zpool() {
 		_arguments -A "-*" \
 			'-D[Destroyed pools]' \
 			'(-d)*-c[Use cache file]:cache file:_files' \
-			'(-c,-D)*-d[Search for devices or files in directory]:directory:_files -/' \
+			'(-c -D)*-d[Search for devices or files in directory]:directory:_files -/' \
 			'-F[Recovery mode: discard transactions if required]' \
 			'-f[Force import]' \
 			'-l[Display configuration in /dev/chassis location form]' \