about summary refs log tree commit diff
path: root/Completion/Unix/Type
diff options
context:
space:
mode:
Diffstat (limited to 'Completion/Unix/Type')
-rw-r--r--Completion/Unix/Type/_canonical_paths3
-rw-r--r--Completion/Unix/Type/_diff_options66
-rw-r--r--Completion/Unix/Type/_files45
-rw-r--r--Completion/Unix/Type/_ldap_attributes27
-rw-r--r--Completion/Unix/Type/_ldap_filters91
-rw-r--r--Completion/Unix/Type/_path_commands13
-rw-r--r--Completion/Unix/Type/_path_files2
-rw-r--r--Completion/Unix/Type/_remote_files5
-rw-r--r--Completion/Unix/Type/_ssh_hosts18
-rw-r--r--Completion/Unix/Type/_tar_archive2
-rw-r--r--Completion/Unix/Type/_time_zone3
-rw-r--r--Completion/Unix/Type/_umountable10
-rw-r--r--Completion/Unix/Type/_zfs_dataset15
-rw-r--r--Completion/Unix/Type/_zfs_keysource_props15
14 files changed, 227 insertions, 88 deletions
diff --git a/Completion/Unix/Type/_canonical_paths b/Completion/Unix/Type/_canonical_paths
index a8fbbb524..1444bc165 100644
--- a/Completion/Unix/Type/_canonical_paths
+++ b/Completion/Unix/Type/_canonical_paths
@@ -42,7 +42,8 @@ _canonical_paths_add_paths () {
     # ### Ideally, this codepath would do what the 'if' above does,
     # ### but telling compadd to pretend the "word on the command line"
     # ### is ${"the word on the command line"/$origpref/$canpref}.
-    matches+=(${${(M)files:#$canpref*}/$canpref/$origpref})
+    # ### The following approximates that.
+    matches+=(${(q)${(M)files:#$canpref*}/$canpref/$origpref})
   fi
 
   for subdir in $expref?*(@); do
diff --git a/Completion/Unix/Type/_diff_options b/Completion/Unix/Type/_diff_options
index dfa9889f2..03ea1d7fe 100644
--- a/Completion/Unix/Type/_diff_options
+++ b/Completion/Unix/Type/_diff_options
@@ -1,6 +1,6 @@
 #autoload
 
-local of ofwuc ouc oss ofwy ofwg ofwl cmd variant
+local of ofwuc ouc oss ofwy ofwg ofwl cmd variant ign
 local -a args
 
 cmd="$1"
@@ -25,7 +25,10 @@ _diff_palette() {
   return ret
 }
 
-if _pick_variant -r variant -c $cmd gnu=GNU unix -v || [[ $OSTYPE = freebsd<12->.* ]]; then
+if _pick_variant -r variant -c $cmd gnu=GNU unix -v ||
+  [[ $OSTYPE = (freebsd<12->|darwin<22->).* ]]; then
+  (( $#words > 2 )) && ign='!'
+
   # output formats
   of="-y --side-by-side -n --rcs -e -f --ed -q --brief -c -C --context -u -U \
   --unified --old-group-format --new-group-format --changed-group-format \
@@ -61,29 +64,28 @@ if _pick_variant -r variant -c $cmd gnu=GNU unix -v || [[ $OSTYPE = freebsd<12->
   --unchanged-group-format"
 
   if [[ $variant = gnu ]]; then
-    (( $#words > 2 )) || args+=(
-      '(-v --version)'{-v,--version}'[display version information]'
-      '--help[display usage information]'
-    )
     args+=(
       '(-H --speed-large-files)'{-H,--speed-large-files}'[assume large files and many small changes]'
       '(-E --ignore-tab-expansion)'{-E,--ignore-tab-expansion}'[ignore changes due to tab expansion]'
       '(-Z --ignore-trailing-space)'{-Z,--ignore-trailing-space}'[ignore white space at line end]'
-      "($ofwuc $oss -F --show-function-line)"{-F+,--show-function-line=}'[show the most recent line matching regex]:regex'
       "($ofwy $ouc)--left-column[output only left column of common lines]"
       "($ofwg $ouc $oss)--old-group-format=[set old group format]:old group format"
       "($ofwg $ouc $oss)--new-group-format=[set new group format]:new group format"
       "($ofwl $ouc $oss)--unchanged-line-format=[set unchanged line format]:unchanged line format"
-      '(--to-file)--from-file=[compare specified file to all operands]:from file:_files' \
-      '(--from-file)--to-file=[compare all operands to specified file]:to file:_files' \
-      '--color=-[use colors in output]::when [auto]:(never always auto)'
+      '(--to-file)--from-file=[compare specified file to all operands]:from file:_files'
+      '(--from-file)--to-file=[compare all operands to specified file]:to file:_files'
       '--palette=[specify colors to use]:color:_diff_palette'
+      "${ign}(1 2)-v[display version information]"
     )
   else
     args+=( '!--speed-large-files' )
+    if [[ $OSTYPE = darwin<22->.* ]]; then
+      args+=( '(-A --algorithm)'{-A+,--algorithm=}'[specify the algorithm to use]:algorithm:(myers patience stone)' )
+    fi
   fi
 
   _arguments -s $args \
+    '--color=-[use colors in output]::when [auto]:(never always auto)' \
     '(-i --ignore-case)'{-i,--ignore-case}'[case insensitive]' \
     '--ignore-file-name-case[ignore case when comparing file names]' \
     '!(--ignore-file-name-case)--no-ignore-file-name-case' \
@@ -99,6 +101,7 @@ if _pick_variant -r variant -c $cmd gnu=GNU unix -v || [[ $OSTYPE = freebsd<12->
     "($of $oss)-u[output a unified diff]" \
     "($ofwuc $oss)*"{-L+,--label=}'[set label to use instead of file name and timestamp]:label' \
     "($ofwuc $oss -p --show-c-function)"{-p,--show-c-function}'[show C function of each change]' \
+    "($ofwuc $oss -F --show-function-line)"{-F+,--show-function-line=}'[show the most recent line matching regex]:regex' \
     "($of $ouc $oss)"{-q,--brief}'[output only whether files differ]' \
     "($of $ouc $oss -e --ed)"{--ed,-e}'[output an ed script]' \
     "!($of $ouc $oss)--normal" \
@@ -127,39 +130,52 @@ if _pick_variant -r variant -c $cmd gnu=GNU unix -v || [[ $OSTYPE = freebsd<12->
     "($of $ouc)"{-y,--side-by-side}'[output in two columns]' \
     "($ofwy $ouc)--suppress-common-lines[don't output common lines]" \
     "($ofwy $ouc --width -W)"{--width=,-W+}'[set size of line]:number of characters per line' \
+    "${ign}(1 2)--version[display version information]" \
+    "${ign}(1 2)--help[display usage information]" \
     "$@"
 else
   of='-c -e -f'
   case $OSTYPE in
     openbsd*|solaris2.<9->)
       of+=' -u -U'
+    ;|
+    openbsd*|solaris*)
+      of+=' -n -C -D'
+    ;|
+    solaris*)
+      of+=' -h'
+    ;|
+    openbsd*)
+      of+=' -q'
+    ;|
+    # modifications to "$of" should be done above this line so that it is
+    # uniformly defined while constructing $args
+    openbsd*|solaris2.<9->)
       args+=(
-	"($of)-u[output a unified diff]"
-	"($of)-U+[output a unified diff]:lines of context"
+        "($of)-u[output a unified diff]"
+        "($of)-U+[output a unified diff]:lines of context"
       )
     ;|
     openbsd*|solaris*)
       args+=(
-	"($of)-C+[output a context diff]:lines of context"
-	"($of)-D+[output merged file with preprocessor directives]:preprocessor symbol"
-	'-i[case insensitive]'
-	'-l[long output format (paginate with pr(1))]'
-	'-s[report on identical files]'
-	'-t[expand tabs in output lines]'
+        "($of)-C+[output a context diff]:lines of context"
+        "($of)-D+[output merged file with preprocessor directives]:preprocessor symbol"
+        '-i[case insensitive]'
+        '-s[report on identical files]'
+        '-t[expand tabs in output lines]'
       )
     ;|
     solaris*)
-      of+=' -h -n'
       args+=(
-	'-w[ignore all white space]'
-	"($of)-h[do a fast, half-hearted job]"
-	"($of)-n[output a reversed ed script]"
+        '-w[ignore all white space]'
+        "($of)-h[do a fast, half-hearted job]"
+        "($of)-n[output a reversed ed script]"
         '-S+[set first file in comparison]:start with file:_files'
+        '-l[long output format (paginate with pr(1))]'
       )
     ;;
     openbsd*)
-      of+=' -n -q -u -C -D -U'
-      args=(
+      args+=(
         "($of)-n[output an rcsdiff(1)-compatible diff]"
         "($of)-q[only print a line when the files differ; does not produce a list of changes]"
         '-a[treat all files as ASCII text]'
@@ -173,7 +189,7 @@ else
         '-P[treat absent files in the second directory as if they were empty]'
         '-S[start a directory diff from a file name]:file name:_files'
         '*-X[exclude files and subdirectories whose basenames match lines in a file]:file name:_files'
-        '-x[exclude files and subdirectories whose basenames match a pattern]:pattern'
+        '*-x[exclude files and subdirectories whose basenames match a pattern]:pattern'
       )
     ;;
   esac
diff --git a/Completion/Unix/Type/_files b/Completion/Unix/Type/_files
index 4ddec1e12..f03b4a148 100644
--- a/Completion/Unix/Type/_files
+++ b/Completion/Unix/Type/_files
@@ -92,7 +92,10 @@ for def in "$pats[@]"; do
     pat="${${sdef%%:${tag}*}//\\:/:}"
 
     if [[ "$sdef" = *:${tag}:* ]]; then
+      # If the file-patterns spec includes a description, use it and give the
+      # group/description options from it precedence over passed in parameters.
       descr="${(Q)sdef#*:${tag}:}"
+      end=
     else
       if (( $opts[(I)-X] )); then
         descr=
@@ -108,26 +111,30 @@ for def in "$pats[@]"; do
       while _next_label "$tag" expl "$descr"; do
         _comp_ignore=( $_comp_ignore $ign )
         if [[ -n "$end" ]]; then
-          if _path_files -g "$pat" "$opts[@]" "$expl[@]"; then
-	    ret=0
-	  elif [[ $PREFIX$SUFFIX != */* ]] && zstyle -a ":completion:${curcontext}:$tag" recursive-files rfiles; then
-	    for rfile in $rfiles; do
-	      if [[ $PWD/ = ${~rfile} ]]; then
-		if [[ -z $subtree ]]; then
-		  subtree=( **/*(/) )
-		fi
-		for prepath in $subtree; do
-		  oprefix=$PREFIX
-		  PREFIX=$prepath/$PREFIX
-		  _path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
-		  PREFIX=$oprefix
-		done
-		break
-	      fi
-	    done
-	  fi
+          expl=( "$opts[@]" "$expl[@]" )
         else
-          _path_files "$expl[@]" -g "$pat" "$opts[@]" && ret=0
+          expl+=( "$opts[@]" )
+        fi
+
+        if _path_files -g "$pat" "$expl[@]"; then
+          ret=0
+        elif [[ $PREFIX$SUFFIX != */* ]] && \
+            zstyle -a ":completion:${curcontext}:$tag" recursive-files rfiles
+        then
+          for rfile in $rfiles; do
+            if [[ $PWD/ = ${~rfile} ]]; then
+              if [[ -z $subtree ]]; then
+                subtree=( **/*(/) )
+              fi
+              for prepath in $subtree; do
+                oprefix=$PREFIX
+                PREFIX=$prepath/$PREFIX
+                _path_files -g "$pat" "$expl[@]" && ret=0
+                PREFIX=$oprefix
+              done
+              break
+            fi
+          done
         fi
       done
       (( ret )) || break
diff --git a/Completion/Unix/Type/_ldap_attributes b/Completion/Unix/Type/_ldap_attributes
new file mode 100644
index 000000000..0711cfbf1
--- /dev/null
+++ b/Completion/Unix/Type/_ldap_attributes
@@ -0,0 +1,27 @@
+#autoload
+
+local -a expl attrs
+
+# These come from dumping attributes from basic installations of both openldap
+# and FreeIPA and combining results. It is possible to have custom additions so
+# a definitive list is not possible Hence the use of -x with compadd.
+#
+attrs=(
+  associatedDomain authenticationMethod automountInformation automountKey
+  automountMapName bindTimeLimit cACertificate;binary cn dc defaultSearchBase
+  defaultServerList description displayName dn followReferrals gecos gidNumber
+  givenName homeDirectory info initials ipaCertIssuerSerial ipaCertSubject
+  ipaConfigString ipaKeyExtUsage ipaKeyTrust ipaNTSecurityIdentifier
+  ipaPublicKey ipaUniqueID ipHostNumber loginShell mail member memberUid
+  mepManagedBy nisDomain nisNetgroupTriple o objectClass objectClassMap ou
+  pwdAllowUserChange pwdAttribute pwdCheckQuality pwdExpireWarning
+  pwdFailureCountInterval pwdGraceAuthNLimit pwdInHistory pwdLockout
+  pwdLockoutDuration pwdMaxAge pwdMaxFailure pwdMinAge pwdMinLength
+  pwdMustChange pwdSafeModify searchTimeLimit serviceSearchDescriptor sn
+  telephoneNumber uid uidNumber userCertificate;binary userPKCS12
+  userSMIMECertificate
+)
+
+_description ldap-attributes expl "ldap attribute"
+compadd "${@:/-X/-x}" "${expl[@]:/-X/-x}" \
+    -M 'm:{a-zA-Z}={A-Za-z} r:[^A-Z]||[A-Z]=* r:|=*' -a attrs
diff --git a/Completion/Unix/Type/_ldap_filters b/Completion/Unix/Type/_ldap_filters
new file mode 100644
index 000000000..5e0e30f01
--- /dev/null
+++ b/Completion/Unix/Type/_ldap_filters
@@ -0,0 +1,91 @@
+#autoload
+
+# LDAP search filters conforming to RFC4515
+
+local -a expl excl optype disp end pre
+local -i nest=0
+local open='(' close=')' andop='&' orop='|'
+
+[[ -prefix - ]] && return 1
+
+local -a matchingrules=( # From RFC4517
+  bitStringMatch booleanMatch caseExactIA5Match
+  caseExactMatch caseExactOrderingMatch caseExactSubstringsMatch
+  caseIgnoreIA5Match caseIgnoreIA5SubstringsMatch caseIgnoreListMatch
+  caseIgnoreListSubstringsMatch caseIgnoreMatch caseIgnoreOrderingMatch
+  caseIgnoreSubstringsMatch directoryStringFirstComponentMatch
+  distinguishedNameMatch generalizedTimeMatch generalizedTimeOrderingMatch
+  integerFirstComponentMatch integerMatch integerOrderingMatch keywordMatch
+  numericStringMatch numericStringOrderingMatch numericStringSubstringsMatch
+  objectIdentifierFirstComponentMatch objectIdentifierMatch octetStringMatch
+  octetStringOrderingMatch telephoneNumberMatch telephoneNumberSubstringsMatch
+  uniqueMemberMatch wordMatch
+)
+local -a classes=( # Sampled from real servers, arbitrary other values allowed
+  automount automountMap cosTemplate dcObject device dnaSharedConfig domain
+  domainRelatedObject DUAConfigProfile extensibleObject groupOfNames
+  groupOfPrincipals ieee802device inetOrgPerson inetuser ipaassociation ipaca
+  ipacaacl ipaCertificate ipaCertMapConfigObject ipacertprofile ipaConfigObject
+  ipaDomainIDRange ipaDomainLevelConfig ipaGuiConfig ipahbacrule ipahbacservice
+  ipahbacservicegroup ipahost ipahostgroup ipaIDrange ipaKeyPolicy
+  ipakrbprincipal ipaNameResolutionData ipaNTDomainAttrs ipaNTGroupAttrs
+  ipaNTUserAttrs ipaobject ipaPublicKeyObject ipaReplTopoManagedServer
+  ipaservice ipaSshGroupOfPubKeys ipasshhost ipasshuser ipasudorule
+  ipaSupportedDomainLevelConfig ipaTrustedADDomainRange ipaUserAuthTypeClass
+  ipausergroup ipHost krbContainer krbprincipal krbprincipalaux
+  krbrealmcontainer krbTicketPolicyAux mepManagedEntry mepOriginEntry
+  nestedGroup nisDomainObject nisNetgroup nsContainer nsDS5Replica nshost
+  organization organizationalPerson organizationalRole organizationalUnit
+  person pilotObject pkiCA pkiuser posixAccount posixGroup pwdPolicy
+  shadowAccount simpleSecurityObject top
+)
+
+compquote open close andop orop
+open=${(q)open} close=${(q)close}
+# default to double rather than backslash quoting
+[[ -z $compstate[quote] && -z $PREFIX ]] && pre='"('
+
+zstyle -s ":completion:${curcontext}:operators" list-separator sep || sep=--
+print -v disp -f "%s $sep %s" \| or \& and \! not
+end=( ") $sep end" )
+excl=( ! \\\| \& ) # compadd -F uses globs: only | needs quoting
+
+local -a query=(
+  \( /$'*\0[ \t\n]#'/ \) # strip off any preceding arguments
+  \(
+    \( "/${open}!/" -'optype[++nest]=1;pre=""'
+    \| "/${open}${(q)orop}/" -'optype[++nest]=2;pre=""'
+    \| "/${open}${andop}/" -'optype[++nest]=3;pre=""'
+    \| '/[]/' ':operators:operator:compadd -F "( ${(q)excl[optype[nest]]} )" -d disp -P ${pre:-${(Q)open}} -S ${(Q)open} \| \& \!' \)
+  \|
+    \( "/${open}[^\\)]##/" "%$close%" # pass over whole var=value, needed due to lack of backtracking after the following
+    \| "/${open}(#i)homeDirectory=/" '/[]/' ':directories:directory:_directories -P / -W / -r ") \t\n\-"'
+    \| "/${open}(#i)loginShell=/" '/[]/' ':shells:shell:compadd -S ${(Q)close} ${(f)^"$(</etc/shells)"}(N)'
+    \| "/${open}(#i)mail=/" '/[]/' ':email-addresses:mail:_email_addresses -S ${(Q)close}'
+    \| "/${open}(#i)objectClass=/" '/[]/' ':object-classes:class:compadd -S ${(Q)close} -M "m:{a-zA-Z}={A-Za-z} r:[^A-Z]||[A-Z]=* r:|=*" -a classes'
+    \| "/${open}(#i)(automountKey|(member|)uid)=/" '/[]/' ':users:username:_users -S ${(Q)close}'
+    \| "/${open}(#i)cn=/" '/[]/' ':cn:cn: _alternative "users:user:_users -S ${close}" "groups:group:_groups -S ${close}" "hosts:host:_hosts -S ${close}"'
+    \|
+      '/[^:=<>~]##/' '%[=:<>~]%' -'pre=""'
+      ':object-types:object type:_ldap_attributes -P ${pre:-${(Q)open}}  -S = -r ":=~<> \t\n\-"'
+      \(
+        '/:/'
+        '/[^:]##:=/' ':matching-rules:matching rule:compadd -S ":=" -a matchingrules'
+      \|
+        '/([~<>]|)=/' ':operators:operator:compadd -S "" "<=" \>= \~='
+      \)
+      '/[^\\)]##/' "%$close%" ': _message -e object-values "object value (* for presence check)"'
+    \)
+    "/$close/" -'(( nest ))' ':brackets:bracket:compadd ${=query[nest]:+-S ""} \)'
+    \(
+      # This use of -P/-d and an empty match works around a limitation/bug where
+      # mixed use of -P removes any quoting
+      "/$close/" ':operators:operator:compadd ${=query[nest-1]:+-S ""} -d end -P ${(Q)close} ""'
+      \( // -'(( --nest ))' \| '//' -'((!nest))' '/[]/' ': compadd ""' \)
+    \) \#
+    // -'(( nest && optype[nest] > 1 ))'
+  \) \#
+)
+
+_regex_arguments _ldap_search_filters "$query[@]"
+_ldap_search_filters
diff --git a/Completion/Unix/Type/_path_commands b/Completion/Unix/Type/_path_commands
index 66795ae0f..4d5a6c5af 100644
--- a/Completion/Unix/Type/_path_commands
+++ b/Completion/Unix/Type/_path_commands
@@ -87,18 +87,19 @@ fi
 # 'if' block move up to the "_command_names -" branch of _command_names?
 if [[ -o path_dirs ]]; then
   local -a path_dirs
-  path_dirs=(${^path}/*(/N:t))
-  (( ${#path_dirs} )) &&
-  _wanted path-dirs expl 'directory in path' compadd "$@" -a path_dirs && ret=0
 
   if [[ $PREFIX$SUFFIX = */* ]]; then
+    path_dirs=( ${path:#.} )
     # Find command from path, not hashed
-    _wanted commands expl 'external command' _path_files -W path -g '*(*)' &&
-    ret=0
+    _wanted commands expl 'external command' _path_files -W path_dirs -g '*(-*)' && ret=0
+  else
+    path_dirs=(${^path}/*(/N:t))
+    (( ${#path_dirs} )) &&
+        _wanted path-dirs expl 'directory in path' compadd "$@" -S / -a path_dirs && ret=0
   fi
 fi
 
-return $ret
+return ret
 }
 
 _path_commands "$@"
diff --git a/Completion/Unix/Type/_path_files b/Completion/Unix/Type/_path_files
index 06d9d8d51..d46dcbe5a 100644
--- a/Completion/Unix/Type/_path_files
+++ b/Completion/Unix/Type/_path_files
@@ -734,7 +734,7 @@ for prepath in "$prepaths[@]"; do
 	      compadd "$tmp4[@]" -s "${Uopt:+$ISUFFIX}" $listopts - "$tmpdisp"
 	    done
           else
-            [[ -n "$compstate[pattern_match]" ]] && SUFFIX="${SUFFIX:s./.*/}*"
+            [[ -n "$compstate[pattern_match]" ]] && SUFFIX="${SUFFIX:gs./.*/}*"
 
             for i in "$tmp1[@]"; do
 	      _list_files i "$prepath$realpath$testpath"
diff --git a/Completion/Unix/Type/_remote_files b/Completion/Unix/Type/_remote_files
index b537406a0..93e1b7f43 100644
--- a/Completion/Unix/Type/_remote_files
+++ b/Completion/Unix/Type/_remote_files
@@ -85,12 +85,15 @@ if zstyle -T ":completion:${curcontext}:files" remote-access; then
     remdispf=( ${(M)remdispf:#${~glob[2]}} )
   fi
 
+  local -a autoremove
+  [[ -o autoremoveslash ]] && autoremove=(-r "/ \t\n\-")
+
   _tags remote-files
   while _tags; do
     while _next_label remote-files expl ${suf:-remote directory}; do
       [[ -n $suf ]] &&
           compadd "$args[@]" "$expl[@]" -d remdispf -- ${(q)remdispf%[*=|]} && ret=0
-      compadd ${suf:+-S/} -r "/ \t\n\-" "$args[@]" "$expl[@]" -d remdispd \
+      compadd ${suf:+-S/} $autoremove "$args[@]" "$expl[@]" -d remdispd \
 	-- ${(q)remdispd%/} && ret=0
     done
     (( ret )) || return 0
diff --git a/Completion/Unix/Type/_ssh_hosts b/Completion/Unix/Type/_ssh_hosts
index bd5366425..b50e1c16a 100644
--- a/Completion/Unix/Type/_ssh_hosts
+++ b/Completion/Unix/Type/_ssh_hosts
@@ -20,10 +20,11 @@ if [[ -r $config ]]; then
   local key line host
   local -a lines=("${(@f)$(<"$config")}") 2>/dev/null
   local -a match_args
-  while (($#lines)); do
-    IFS=$'=\t ' read -r key line <<<"${lines[1]}"
+  local idx=1
+  while (( idx <= $#lines )); do
+    IFS=$'=\t ' read -r key line <<<"${lines[idx]}"
     if [[ "$key" == ((#i)match) ]]; then
-      match_args=(${(z)line})
+      match_args=( ${(Z.C.)line} )
       while [[ $#match_args -ge 2 ]]; do
 	if [[ "${match_args[1]}" == (#i)(canonical|final|(|original)host) ]]; then
 	  key="Host"
@@ -35,15 +36,12 @@ if [[ -r $config ]]; then
     fi
     case "$key" in
     ((#i)include)
-      lines[1]=("${(@f)$(cd $HOME/.ssh; cat ${(z)~line})}") 2>/dev/null;;
+      lines[idx]=( "${(@f)$(cd $HOME/.ssh; cat ${(Z.C.)~line} 2>/dev/null)}" ) ;;
     ((#i)host(|name))
-      for host in ${(z)line}; do
-	case $host in
-	(*[*?]*) ;;
-	(*) config_hosts+=("$host") ;;
-	esac
+      for host in ${(Z.C.)line}; do
+        [[ $host != *[*?%]* ]] && config_hosts+=( $host )
       done ;&
-    (*) shift lines;;
+    (*) (( ++idx ));;
     esac
   done
   if (( ${#config_hosts} )); then
diff --git a/Completion/Unix/Type/_tar_archive b/Completion/Unix/Type/_tar_archive
index 00555156b..bc49c4a3a 100644
--- a/Completion/Unix/Type/_tar_archive
+++ b/Completion/Unix/Type/_tar_archive
@@ -23,7 +23,7 @@ if [[ "$1" = *[urtx]* ]]; then
   elif [[ "$_cmd_variant[$service]" == gnu ]]; then
     _files "$expl[@]" -g '*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|.zst|lzo|)|(tbz|tgz|txz|tzst|taz|taZ|tz2|tbz2|tlz))(-.)'
   elif [[ "$_cmd_variant[$service]" == libarchive ]]; then
-    _files "$expl[@]" -g '*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|.zst|lzo|)|(tbz|tgz|txz|zip|tzst|tzo|taz|tbz2|tz2|tlz|tZ))(-.)'
+    _files "$expl[@]" -g '*.((tar|TAR|cpio)(.gz|.GZ|.Z|.bz2|.lzma|.xz|.zst|lzo|)|(tbz|tgz|txz|tzst|tzo|taz|tbz2|tz2|tlz|tZ|7z|ar|iso|deb|cab|lha|mtree|rar|warc|xar|zip))(-.)'
   else
     _files "$expl[@]" -g '*.(tar|TAR)(-.)'
   fi
diff --git a/Completion/Unix/Type/_time_zone b/Completion/Unix/Type/_time_zone
index cd924bbc7..a7b63adcd 100644
--- a/Completion/Unix/Type/_time_zone
+++ b/Completion/Unix/Type/_time_zone
@@ -6,4 +6,5 @@ if (( ! $+_zoneinfo_dirs )); then
   _zoneinfo_dirs=( /usr/{share,lib,share/lib}/{zoneinfo*,locale/TZ}(/) )
 fi
 
-_wanted time-zones expl 'time zone' _files -W _zoneinfo_dirs "$@" -
+_wanted time-zones expl 'time zone' \
+  _files -g '[A-Z]*' -M 'm:{a-z}={A-Z}' -W _zoneinfo_dirs "$@" -
diff --git a/Completion/Unix/Type/_umountable b/Completion/Unix/Type/_umountable
index 7ffce5bb4..0111555b6 100644
--- a/Completion/Unix/Type/_umountable
+++ b/Completion/Unix/Type/_umountable
@@ -1,15 +1,21 @@
 #autoload
 local tmp
-local dev_tmp dpath_tmp mp_tmp mline
+local -a dev_tmp dpath_tmp mp_tmp mline
 
 case "$OSTYPE" in
-linux*|irix*)
+linux*)
+  tmp=( "${(@f)$(< /proc/self/mounts)}" )
+  dev_tmp=( "${(@)${(@)tmp%% *}:#none}" )
+  mp_tmp=( "${(@)${(@)tmp#* }%% *}" )
+  ;;
+irix*)
   tmp=( "${(@f)$(< /etc/mtab)}" )
   dev_tmp=( "${(@)${(@)tmp%% *}:#none}" )
   mp_tmp=( "${(@)${(@)tmp#* }%% *}" )
   ;;
 freebsd*|dragonfly*)
   /sbin/mount | while read mline; do
+    [[ $mline[(w)1] = map ]] && continue
     dev_tmp+=( $mline[(w)1] )
     mp_tmp+=( $mline[(w)3] )
   done
diff --git a/Completion/Unix/Type/_zfs_dataset b/Completion/Unix/Type/_zfs_dataset
index 63384afc6..7edcfd5d7 100644
--- a/Completion/Unix/Type/_zfs_dataset
+++ b/Completion/Unix/Type/_zfs_dataset
@@ -11,10 +11,12 @@ local expl_type
 # -t takes arguments (what kinds of datasets) and can appear multiple times
 zparseopts -D -E e:=expl_type_arr p=paths_allowed r1=rsrc r2=rdst t+:=type
 
-[[ -n $type[(r)fs] ]]    && typearg=( filesystem )
-[[ -n $type[(r)vol] ]]   && typearg=( $typearg volume )
-[[ -n $type[(r)snap] ]]  && typearg=( $typearg snapshot )
-[[ -n $type[(r)share] ]]  && typearg=( $typearg share )
+[[ -n $type[(r)fs] ]] && typearg=( filesystem )
+[[ -n $type[(r)vol] ]] && typearg+=( volume )
+[[ -n $type[(r)snap] ]] && typearg+=( snapshot )
+[[ -n $type[(r)share] && $implementation = solaris ]] && typearg+=( share )
+[[ -n $type[(r)bookmark] && $implementation = openzfs ]] &&
+    typearg+=( bookmark )
 if [[ -n $typearg ]]; then
 	typearg=( -t ${(j:,:)typearg} )
 # We know we're in zfs list if paths_allowed is non-empty.
@@ -58,7 +60,7 @@ if [[ ${#rdst} -gt 0 ]]; then
 fi
 
 if [[ -n $type[(r)clone] ]]; then
-	datasetlist=( ${(f)"$(zfs list -H -o name,origin -t filesystem 2>/dev/null | awk -F $'\t' "\$2 != \"-\" {print \$1}")":#no cloned filesystems available} )
+  datasetlist=( ${(f)"$(zfs list -H -o name,origin -t filesystem 2>/dev/null | awk -F$'\t' "\$2 != \"-\" {print \$1}")":#no cloned filesystems available} )
 else
 	datasetlist=( ${(f)"$(zfs list -H -o name $typearg 2>/dev/null)":#no datasets available} )
 fi
@@ -74,4 +76,5 @@ if [[ -n $expl_type_arr[2] ]]; then
 	expl_type=$expl_type_arr[2]
 fi
 
-_wanted dataset expl "$expl_type" _multi_parts "$@" -q / datasetlist
+_description datasets expl "$expl_type"
+_multi_parts "$@" "$expl[@]" -q / datasetlist
diff --git a/Completion/Unix/Type/_zfs_keysource_props b/Completion/Unix/Type/_zfs_keysource_props
deleted file mode 100644
index 01f63257a..000000000
--- a/Completion/Unix/Type/_zfs_keysource_props
+++ /dev/null
@@ -1,15 +0,0 @@
-#autoload
-
-local -a suf
-local expl
-
-compset -S ",*" || suf=(-S ,)
-if compset -P 1 "*,"; then
-	_alternative "zfs-keylocator-prompt:\"prompt\" locator:(prompt)" \
-		"zfs-keylocator-file:file locator:_path_files" \
-		"zfs-keylocator-pkcs11:PKCS#11 locator: " \
-		"zfs-keylocator-https:HTTPS URL locator: "
-else
-	_description format expl "keysource format"
-	compadd $suf -q "$expl[@]" "$@" raw hex passphrase
-fi