about summary refs log tree commit diff
path: root/Completion
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-11-22 12:29:47 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-11-22 12:29:47 +0000
commit3d9d13e918c195f974ff7b2f1dc5b65f6b20a441 (patch)
treed571aef9c8152287ed94dae1199108de80f0b984 /Completion
parenta76b36928c5cbeef3fe015ca30bbf910ab2a107e (diff)
downloadzsh-3d9d13e918c195f974ff7b2f1dc5b65f6b20a441.tar.gz
zsh-3d9d13e918c195f974ff7b2f1dc5b65f6b20a441.tar.xz
zsh-3d9d13e918c195f974ff7b2f1dc5b65f6b20a441.zip
zsh-workers/8720
Diffstat (limited to 'Completion')
-rw-r--r--Completion/Base/_combination40
-rw-r--r--Completion/Base/_describe2
-rw-r--r--Completion/Base/_jobs2
-rw-r--r--Completion/Base/_subscript2
-rw-r--r--Completion/Base/_tilde2
-rw-r--r--Completion/Builtins/_pids2
-rw-r--r--Completion/Builtins/_popd2
-rw-r--r--Completion/Builtins/_sched2
-rw-r--r--Completion/Core/_approximate12
-rw-r--r--Completion/Core/_complete6
-rw-r--r--Completion/Core/_correct6
-rw-r--r--Completion/Core/_expand8
-rw-r--r--Completion/Core/_list6
-rw-r--r--Completion/Core/_main_complete2
-rw-r--r--Completion/Core/_match14
-rw-r--r--Completion/Core/_menu6
-rw-r--r--Completion/Core/_oldlist17
-rw-r--r--Completion/Core/compinit14
-rw-r--r--Completion/User/_groups19
-rw-r--r--Completion/User/_hosts9
-rw-r--r--Completion/User/_my_accounts12
-rw-r--r--Completion/User/_other_accounts12
-rw-r--r--Completion/User/_ports9
-rw-r--r--Completion/User/_rlogin18
-rw-r--r--Completion/User/_socket10
-rw-r--r--Completion/User/_ssh16
-rw-r--r--Completion/User/_telnet6
-rw-r--r--Completion/User/_user_at_host23
-rw-r--r--Completion/User/_users4
29 files changed, 115 insertions, 168 deletions
diff --git a/Completion/Base/_combination b/Completion/Base/_combination
index 69ae973f9..97da22a5f 100644
--- a/Completion/Base/_combination
+++ b/Completion/Base/_combination
@@ -1,24 +1,26 @@
 #autoload
 
 # Usage:
-#   _combination [-s S] V[:K1:...] Ki1[:Ni1]=Pi1 Ki2[:Ni2]=Pi2 ... Kim[:Nim]=Pim Kj[:Nj] EXPL...
+#   _combination [-s S] TAG STYLE \
+#     Ki1[:Ni1]=Pi1 Ki2[:Ni2]=Pi2 ... Kim[:Nim]=Pim Kj[:Nj] EXPL...
 #
-#  It is assumed that V is formed as PRE_K1_..._Kn if `:K1:...' is not specified.
+#  STYLE should be of the form K1-K2-...-Kn.
 #
 # Example: telnet
 #
-#  Assume an user sets the variable `telnet_hosts_ports_users' as:
+#  Assume an user sets the style `hosts-ports-users' as for the my-accounts
+#  tag:
 #
-#    telnet_hosts_ports_users=(
+#    compstyle '*:telnet*:my-accounts' hosts-ports-users \
 #      host0:: host1::user1 host2::user2
 #      mail-server:{smtp,pop3}:
 #      news-server:nntp:
 #      proxy-server:8000:
-#    )
+# 
 #
-#  `_telnet completes' hosts as:
+#  `_telnet' completes hosts as:
 #
-#    _combination telnet_hosts_ports_users \
+#    _combination my-accounts hosts-ports-users \
 #      ${options[-l]:+users=${options[-l]:q}} \
 #      hosts "$expl[@]"
 #
@@ -28,7 +30,7 @@
 # 
 #  `_telnet' completes ports as:
 #
-#    _combination telnet_hosts_ports_users \
+#    _combination my-accounts hosts-ports-users \
 #      ${options[-l]:+users=${options[-l]:q}} \
 #      hosts="${line[2]:q}" \
 #      ports "$expl[@]"
@@ -39,7 +41,7 @@
 #
 #  `_telnet' completes users for an argument of option `-l' as:
 #
-#    _combination telnet_hosts_ports_users \
+#    _combination my-accounts hosts-ports-users \
 #      ${line[2]:+hosts="${line[2]:q}"} \
 #      ${line[3]:+ports="${line[3]:q}"} \
 #      users "$expl[@]"
@@ -48,7 +50,7 @@
 #  the port argument if they are exist. And if it is failed, `_users' is
 #  called.
 
-local sep var keys pats key num tmp
+local sep tag style keys pats key num tmp
 
 if [[ "$1" = -s ]]; then
   sep="$2"
@@ -57,16 +59,11 @@ else
   sep=:
 fi
 
-var=$1
-shift
+tag="$1"
+style="$2"
+shift 2
 
-if [[ $var = *:* ]]; then
-  keys=( ${(s/:/)var} )
-  shift keys
-  var="${var%%:*}"
-else
-  keys=( "${(@s:_:)${var#*_}}" )
-fi
+keys=( ${(s/-/)style} )
 pats=( "${(@)keys/*/*}" )
 
 while [[ "$1" = *=* ]]; do
@@ -81,8 +78,8 @@ key="${1%:*}"
 num="${${1##*:}:-1}"
 shift
 
-if (( ${(P)+${var}} )); then
-  eval "tmp=( \"\${(@M)${var}:#\${(j($sep))~pats}}\" )"
+if _style -a "$tag" "$style" tmp; then
+  eval "tmp=( \"\${(@M)tmp:#\${(j($sep))~pats}}\" )"
   if (( keys[(in:num:)$key] != 1 )); then
     eval "tmp=( \${tmp#\${(j(${sep}))~\${(@)\${(@)keys[2,(rn:num:)\$key]}/*/*}}$sep} )"
   fi
@@ -92,4 +89,3 @@ if (( ${(P)+${var}} )); then
 else
   (( $+functions[_$key] )) && "_$key" "$@"
 fi
-
diff --git a/Completion/Base/_describe b/Completion/Base/_describe
index f1fbbafc6..3d0d8507c 100644
--- a/Completion/Base/_describe
+++ b/Completion/Base/_describe
@@ -16,7 +16,7 @@ fi
 
 _tags "$_type" || return 1
 
-_style "$_type" description && _showd=yes
+_style "$_type" verbose && _showd=yes
 
 _description _expl "$1"
 shift
diff --git a/Completion/Base/_jobs b/Completion/Base/_jobs
index d9297086b..2a1b725b4 100644
--- a/Completion/Base/_jobs
+++ b/Completion/Base/_jobs
@@ -6,7 +6,7 @@ _tags jobs || return 1
 
 _style jobs prefix-needed && [[ "$PREFIX" != %* ]] && return 1
 _style jobs prefix-hidden && pfx=''
-_style jobs description   && desc=yes
+_style jobs verbose       && desc=yes
 
 if [[ "$1" = -r ]]; then
   jids=( "${(@k)jobstates[(R)running*]}" )
diff --git a/Completion/Base/_subscript b/Completion/Base/_subscript
index a3b97a45e..cc3e9c435 100644
--- a/Completion/Base/_subscript
+++ b/Completion/Base/_subscript
@@ -21,7 +21,7 @@ elif [[ ${(Pt)${compstate[parameter]}} = array* ]]; then
   while _tags; do
     if _requested indexes -V expl 'array index'; then
       ind=( {1..${#${(P)${compstate[parameter]}}}} )
-      if _style indexes description; then
+      if _style indexes verbose; then
         list=()
         for i in "$ind[@]"; do
           [[ "$i" = ${PREFIX}*${SUFFIX} ]] &&
diff --git a/Completion/Base/_tilde b/Completion/Base/_tilde
index bd21cd044..d9eb0a887 100644
--- a/Completion/Base/_tilde
+++ b/Completion/Base/_tilde
@@ -24,7 +24,7 @@ while _tags; do
   if _requested directory-stack -V expl 'directory stack' &&
      { ! _style directory-stack prefix-needed ||
        [[ "$PREFIX" = [-+]* ]] }; then
-    if _style directory-stack description; then
+    if _style directory-stack verbose; then
       integer i
 
       lines=("${PWD}" "${dirstack[@]}")
diff --git a/Completion/Builtins/_pids b/Completion/Builtins/_pids
index 597a19477..3fd71fb84 100644
--- a/Completion/Builtins/_pids
+++ b/Completion/Builtins/_pids
@@ -16,7 +16,7 @@ _style -a ps list-arguments listargs
 _style -a ps arguments args
 (( $#listargs )) || listargs=( "$args[@]" )
 
-if _style processes description; then
+if _style processes verbose; then
   list=("${(@Mr:COLUMNS-1:)${(f@)$(ps $listargs 2>/dev/null)}[2,-1]:#[ 	]#${PREFIX}[0-9]#${SUFFIX}[ 	]*${~match}}")
   desc=(-ld list)
 else
diff --git a/Completion/Builtins/_popd b/Completion/Builtins/_popd
index 9b9b0d048..e906571da 100644
--- a/Completion/Builtins/_popd
+++ b/Completion/Builtins/_popd
@@ -13,7 +13,7 @@ _wanted directory-stack -V expl 'directory stack' || return 1
 
 ! _style directory-stack prefix-needed || [[ $PREFIX = [-+]* ]] || return 1
 
-if _style directory-stack description; then
+if _style directory-stack verbose; then
   # get the list of directories with their canonical number
   # and turn the lines into an array, removing the current directory
   lines=("${PWD}" "${dirstack[@]}")
diff --git a/Completion/Builtins/_sched b/Completion/Builtins/_sched
index feb7f21e7..5e1086518 100644
--- a/Completion/Builtins/_sched
+++ b/Completion/Builtins/_sched
@@ -7,7 +7,7 @@ if [[ CURRENT -eq 2 ]]; then
     _wanted -C - jobs expl 'scheduled jobs' || return 1
 
     lines=(${(f)"$(sched)"})
-    if _style jobs description; then
+    if _style jobs verbose; then
       disp=( -ld lines )
     else
       disp=()
diff --git a/Completion/Core/_approximate b/Completion/Core/_approximate
index 910742fee..0c0c8566f 100644
--- a/Completion/Core/_approximate
+++ b/Completion/Core/_approximate
@@ -7,7 +7,7 @@
 
 local _comp_correct _correct_prompt comax
 local cfgacc cfgorig cfgps cfgins
-local curcontext="$curcontext" oldcontext
+local curcontext="${curcontext}" oldcontext
 
 # Only if all global matchers have been tried.
 
@@ -17,23 +17,21 @@ local curcontext="$curcontext" oldcontext
 
 [[ "${#:-$PREFIX$SUFFIX}" -le 1 ]] && return 1
 
-# Probably set initial context.
-
-[[ -z "$curcontext" ]] && curcontext=':approximate'
+[[ "$curcontext" != *:correct ]] && curcontext="${curcontext}:approximate"
 
 oldcontext="$curcontext"
 
-_style -s '' accept cfgacc
+_style -s '' max-errors cfgacc
 _style -s '' original cfgorig
 _style -s '' prompt cfgps
 _style -s '' insert cfgins
 
 # Get the number of errors to accept.
 
-if [[ "$cfgacc" = *[nN]* && ${NUMERIC:-1} -ne 1 ]]; then
+if [[ "$cfgacc" = *numeric* && ${NUMERIC:-1} -ne 1 ]]; then
   # Stop if we also have a `!'.
 
-  [[ "$cfgacc" = *\!* ]] && return 1
+  [[ "$cfgacc" = *not-numeric* ]] && return 1
 
   # Prefer the numeric argument if that has a sensible value.
 
diff --git a/Completion/Core/_complete b/Completion/Core/_complete
index 235265326..1468e46ce 100644
--- a/Completion/Core/_complete
+++ b/Completion/Core/_complete
@@ -4,11 +4,7 @@
 # a normal completion function, but as one possible value for the
 # completer style.
 
-local comp name curcontext="$curcontext" oldcontext
-
-# Probably set initial context.
-
-[[ -z "$curcontext" ]] && curcontext=':complete'
+local comp name curcontext="${curcontext}:complete" oldcontext
 
 oldcontext="$curcontext"
 
diff --git a/Completion/Core/_correct b/Completion/Core/_correct
index abd70ddeb..c958bdb83 100644
--- a/Completion/Core/_correct
+++ b/Completion/Core/_correct
@@ -8,11 +8,7 @@
 # Supported configuration keys are the same as for `_approximate', only
 # starting with `correct'.
 
-local ret=1 opm="$compstate[pattern_match]" curcontext="$curcontext"
-
-# Probably set initial context.
-
-[[ -z "$curcontext" ]] && curcontext=':correct'
+local ret=1 opm="$compstate[pattern_match]" curcontext="${curcontext}:correct"
 
 compstate[pattern_match]='-'
 
diff --git a/Completion/Core/_expand b/Completion/Core/_expand
index 97728bd3b..68c09ddbb 100644
--- a/Completion/Core/_expand
+++ b/Completion/Core/_expand
@@ -8,11 +8,7 @@
 # word from the line.
 
 local exp word="$PREFIX$SUFFIX" group=-V expl expl2 disp orig menu prompt
-local curcontext="$curcontext" expr descr
-
-# Probably set initial context.
-
-[[ -z "$curcontext" ]] && curcontext=':expand'
+local curcontext="${curcontext}:expand" expr descr
 
 # First, see if we should insert all *completions*.
 
@@ -68,7 +64,7 @@ else
   expl=(-n)
 fi
 
-if [[ -n "$menu" && "$menu" != *only* && "$menu" = *showall* ]]; then
+if [[ -n "$menu" && "$menu" != *only* && "$menu" = *show-all* ]]; then
   if [[ -n "$descr" ]]; then
     expl2=(-ld disp -X "${descr//\\%d/all words}")
   else
diff --git a/Completion/Core/_list b/Completion/Core/_list
index 803da2f71..ea2ed36aa 100644
--- a/Completion/Core/_list
+++ b/Completion/Core/_list
@@ -4,11 +4,7 @@
 # insert possible completions only after the list has been shown at
 # least once.
 
-local pre suf curcontext="$curcontext" expr
-
-# Probably set initial context.
-
-[[ -z "$curcontext" ]] && curcontext=':list'
+local pre suf curcontext="${curcontext}:list" expr
 
 # Get the strings to compare.
 
diff --git a/Completion/Core/_main_complete b/Completion/Core/_main_complete
index ba31399b3..51f72d504 100644
--- a/Completion/Core/_main_complete
+++ b/Completion/Core/_main_complete
@@ -91,7 +91,7 @@ if [[ compstate[nmatches] -eq 0 &&
   compadd -UX "${format//\\%d/$str}" -n ''
 fi
 
-_style '' last-prompt always && compstate[last_prompt]=yes
+_style '' last-prompt && compstate[last_prompt]=yes
 
 _lastcomp=( "${(@kv)compstate}" )
 _lastcomp[completer]="$comp"
diff --git a/Completion/Core/_match b/Completion/Core/_match
index 35d7c2ecb..d5556dfcd 100644
--- a/Completion/Core/_match
+++ b/Completion/Core/_match
@@ -9,8 +9,8 @@
 # expand-or-complete function because otherwise the pattern will
 # be expanded using globbing.
 
-local tmp opm="$compstate[pattern_match]" ret=0 curcontext="$curcontext"
-local orig ins
+local tmp opm="$compstate[pattern_match]" ret=0 orig ins
+local curcontext="${curcontext}:match"
 
 # Do nothing if we don't have a pattern or there are still global
 # match specifications to try.
@@ -19,12 +19,8 @@ tmp="${${:-$PREFIX$SUFFIX}#[~=]}"
 [[ "$tmp:q" = "$tmp" ||
    compstate[matcher] -ne compstate[total_matchers] ]] && return 1
 
-# Probably set initial context.
-
-[[ -z "$curcontext" ]] && curcontext=':match'
-
 _style -s '' original orig
-_style -s '' insert ins
+_style -b '' insert-unambiguous ins
 
 # Try completion without inserting a `*'?
 
@@ -36,7 +32,7 @@ if [[ -n "$orig" ]]; then
   compstate[matcher]="$compstate[total_matchers]"
 
   if (( ret )); then
-    [[ "$ins" = unambig* &&
+    [[ "$ins" = yes &&
        $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] && 
         compstate[pattern_insert]=unambiguous
     return 0
@@ -53,7 +49,7 @@ _complete && ret=1
 compstate[pattern_match]="$opm"
 compstate[matcher]="$compstate[total_matchers]"
 
-[[ ret -eq 1 && "$ins" = unambig* &&
+[[ ret -eq 1 && "$ins" = yes &&
    $#compstate[unambiguous] -ge ${#:-${PREFIX}${SUFFIX}} ]] && 
     compstate[pattern_insert]=unambiguous
 
diff --git a/Completion/Core/_menu b/Completion/Core/_menu
index e9558fe05..5b864c6a1 100644
--- a/Completion/Core/_menu
+++ b/Completion/Core/_menu
@@ -1,10 +1,6 @@
 #autoload
 
-local curcontext="$curcontext"
-
-# Probably set initial context.
-
-[[ -z "$curcontext" ]] && curcontext=':menu'
+local curcontext="${curcontext}:menu"
 
 # This completer is an example showing how menucompletion can be
 # implemented with the new completion system.
diff --git a/Completion/Core/_oldlist b/Completion/Core/_oldlist
index 2408613da..ba57ed6b4 100644
--- a/Completion/Core/_oldlist
+++ b/Completion/Core/_oldlist
@@ -1,13 +1,8 @@
 #autoload
 
-local curcontext="$curcontext" list menu
-
-# Probably set initial context.
-
-[[ -z "$curcontext" ]] && curcontext=':oldlist'
+local curcontext="${curcontext}:oldlist" list
 
 _style -s '' list list
-_style -s '' menu menu
 
 # If this is a listing widget and there is already an old list,
 # and either the style :oldlist:list is `always', or it is not `never'
@@ -33,16 +28,12 @@ if [[ -n $compstate[old_list] && $list != never ]]; then
 fi
 
 # If this is a completion widget, and we have a completion inserted already,
-# and the style :oldlist:menu is not never, then we cycle through the
+# and the style :oldlist:menu is `true', then we cycle through the
 # existing list (even if it was generated by another widget).
 
-if [[ $menu = verbose &&
-      $LASTWIDGET = _verbose_list && $WIDGET != _verbose_list &&
-      -z $compstate[old_insert] &&
-      -n $compstate[old_list] ]]; then
+if [[ -z $compstate[old_insert] && -n $compstate[old_list] ]]; then
   compstate[old_list]=keep
-elif [[ $WIDGET = *complete(|-prefix|-word) &&
-        $menu != (never|verbose) ]]; then
+elif [[ $WIDGET = *complete(|-prefix|-word) ]] && _style '' menu; then
   if [[ -n $compstate[old_insert] ]]; then
     compstate[old_list]=keep
     if [[ $WIDGET = *reverse* ]]; then
diff --git a/Completion/Core/compinit b/Completion/Core/compinit
index 34967f8e3..746b6c4d4 100644
--- a/Completion/Core/compinit
+++ b/Completion/Core/compinit
@@ -349,10 +349,10 @@ Have fun
       tmp="'*:urls' local ${${(qqs.:.)val}}"
       ;;
     describe_options)
-      tmp="'*:options' description ${(qq)val}"
+      tmp="'*:options' verbose 'yes'"
       ;;
     describe_values)
-      tmp="'*:values' description ${(qq)val}"
+      tmp="'*:values' verbose 'yes'"
       ;;
     autodescribe_options)
       tmp="'*:options' auto-description ${(qq)val}"
@@ -412,7 +412,7 @@ compstyle '*:options' prefix-hidden yes"
       tmp="'*' completer ${${(qqs.:.)val}}"
       ;;
     last_prompt)
-      tmp="'*' last-prompt ${(qq)val}"
+      tmp="'*' last-prompt 'yes'"
       ;;
     esac
     [[ -n "$tmp" ]] && style="${style}${cmt}compstyle ${tmp}
@@ -426,11 +426,7 @@ compstyle '*:options' prefix-hidden yes"
 
 # Very simple interface for setting styles:
 #
-#   compstyle context -styles... context -styles ...
-#
-# Where context is of the form :ctxt-pats:...:tag-pat.
-#
-# This will be improved if needed. Promised.
+#   compstyle pattern style values...
 
 compstyle() {
   local long
@@ -490,7 +486,7 @@ compstyle() {
 
 # Default styles. This should be executed conditionally somehow.
 
-compstyle '*'        description   'yes'
+compstyle '*'        verbose       'yes'
 compstyle '*'        prefix-needed 'yes'
 compstyle '*'        prefix-hidden 'no'
 compstyle ':correct' accept        '2n'
diff --git a/Completion/User/_groups b/Completion/User/_groups
index f1963a8e7..0007c1791 100644
--- a/Completion/User/_groups
+++ b/Completion/User/_groups
@@ -1,15 +1,18 @@
 #compdef newgrp
 
-local expl
+local expl groups
 
 _wanted groups expl group || return 1
 
-if (( ! $+groups )); then
-  if (( ${+commands[ypcat]} )); then
-    : ${(A)groups:=${${(s: :)$(ypcat group.byname)}%%:*}} # If you use YP
-  else
-    : ${(A)groups:=${${(s: :)$(</etc/group)}%%:*}}
-  fi
+if ! _style -a groups groups groups; then
+  (( $+_cache_groups )) ||
+      if (( ${+commands[ypcat]} )); then
+        : ${(A)_cache_groups:=${${(s: :)$(ypcat group.byname)}%%:*}} # If you use YP
+      else
+        : ${(A)_cache_groups:=${${(s: :)$(</etc/group)}%%:*}}
+      fi
+
+  groups=( "$_cache_groups[@]" )
 fi
 
-compadd "$@" "$expl[@]" - $groups
+compadd "$@" "$expl[@]" - "$groups[@]"
diff --git a/Completion/User/_hosts b/Completion/User/_hosts
index 83480efe4..196f40c83 100644
--- a/Completion/User/_hosts
+++ b/Completion/User/_hosts
@@ -1,8 +1,13 @@
 #compdef ftp ncftp ping rwho rup xping traceroute host
 
-local expl
+local expl hosts
 
-: ${(A)hosts:=${(s: :)${(ps:\t:)${${(f)"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}}
+if ! _style -a hosts hosts hosts; then
+  (( $+_cache_hosts )) ||
+      : ${(A)_cache_hosts:=${(s: :)${(ps:\t:)${${(f)"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}}
+
+  hosts=( "$_cache_hosts[@]" )
+fi
 
 _wanted hosts expl host &&
     compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" "$expl[@]" - "$hosts[@]"
diff --git a/Completion/User/_my_accounts b/Completion/User/_my_accounts
index 34d6269d4..267cdd6f1 100644
--- a/Completion/User/_my_accounts
+++ b/Completion/User/_my_accounts
@@ -1,13 +1,3 @@
 #autoload
 
-local accounts_users_hosts
-
-local varname="$words[1]_accounts"
-
-if [[ ${(P)+varname} -eq 1 ]]; then
-  accounts_users_hosts=( ${(P)varname} )
-else
-  accounts_users_hosts=( $my_accounts )
-fi
-
-_user_at_host "$@"
+_user_at_host -t my-accounts "$@"
diff --git a/Completion/User/_other_accounts b/Completion/User/_other_accounts
index 9e3545e98..b419791e5 100644
--- a/Completion/User/_other_accounts
+++ b/Completion/User/_other_accounts
@@ -1,13 +1,3 @@
 #compdef talk ntalk ytalk finger
 
-local accounts_users_hosts
-
-local varname="$words[1]_accounts"
-
-if [[ ${(P)+varname} -eq 1 ]]; then
-  accounts_users_hosts=( ${(P)varname} )
-else
-  accounts_users_hosts=( $other_accounts )
-fi
-
-_user_at_host "$@"
+_user_at_host -t other-accounts "$@"
diff --git a/Completion/User/_ports b/Completion/User/_ports
index ffd04ce5e..da59fd4ea 100644
--- a/Completion/User/_ports
+++ b/Completion/User/_ports
@@ -1,7 +1,12 @@
 #autoload
 
-local expl
+local expl ports
 
-: ${(A)ports:=${${(M)${${(f)"$(</etc/services)"}:#\#*}#*/tcp}%%[ 	]*}}
+if ! _style ports ports ports; then
+  (( $+_cache_ports )) ||
+      : ${(A)ports:=${${(M)${${(f)"$(</etc/services)"}:#\#*}#*/tcp}%%[ 	]*}}
+
+  ports=( "$_cache_ports[@]" )
+fi
 
 _wanted ports expl port && compadd "$@" "$expl[@]" - "$ports[@]"
diff --git a/Completion/User/_rlogin b/Completion/User/_rlogin
index d732cf8a9..738b6225f 100644
--- a/Completion/User/_rlogin
+++ b/Completion/User/_rlogin
@@ -1,16 +1,6 @@
 #compdef rlogin rsh remsh rcp
 
 _rlogin () {
-  local accounts_users_hosts
-
-  local varname="$words[1]_accounts"
-
-  if (( ${(P)+varname} )); then
-    accounts_users_hosts=( ${(P)varname} )
-  else
-    accounts_users_hosts=( $my_accounts )
-  fi
-
   case "$words[1]" in
   rlogin)
     _arguments -s \
@@ -64,21 +54,21 @@ _rlogin () {
 }
 
 _rlogin_users () {
-  _tags users && _combination accounts_users_hosts users "$@"
+  _tags users && _combination my-accounts users-hosts users "$@"
 }
 
 _rlogin_hosts () {
   _tags hosts &&
       if [[ "$IPREFIX" == *@ ]]; then
-        _combination accounts_users_hosts "users=${IPREFIX/@}" hosts "$@"
+        _combination my-accounts users-hosts "users=${IPREFIX/@}" hosts "$@"
       else
-        _combination accounts_users_hosts \
+        _combination my-accounts users-hosts \
             ${opt_args[-l]:+"users=${opt_args[-l]:q}"} hosts "$@"
       fi
 }
 
 _rlogin_all_hosts () {
-  _tags hosts && _combination accounts_users_hosts hosts "$@"
+  _tags hosts && _combination my-accounts users-hosts hosts "$@"
 }
 
 _rlogin "$@"
diff --git a/Completion/User/_socket b/Completion/User/_socket
index b155e7ad4..45374a403 100644
--- a/Completion/User/_socket
+++ b/Completion/User/_socket
@@ -1,9 +1,9 @@
 #compdef socket
 
-# Parameter used:
+# Style used:
 #
-#  socket_hosts_ports
-#    The array that contains paris `host:port'.
+#  hosts-ports
+#    The style that contains pairs `host:port'.
 
 local curcontext="$curcontext" state line expl
 typeset -A opt_args
@@ -41,14 +41,14 @@ arg1)
     _wanted ports expl 'port to listen' && _ports "$expl[@]"
   else
     _wanted hosts expl 'host' &&
-        _combination socket_hosts_ports hosts "$expl[@]"
+        _combination '' hosts-ports hosts "$expl[@]"
   fi
   ;;
 
 arg2)
   if (( ! $+opt_args[-s] )); then
     _wanted ports expl 'port to connect' &&
-        _combination socket_hosts_ports hosts="${line[2]:q}" ports "$expl[@]"
+        _combination '' hosts-ports hosts="${line[2]:q}" ports "$expl[@]"
   fi
   ;;
 esac
diff --git a/Completion/User/_ssh b/Completion/User/_ssh
index e7c6d37f6..4318caf96 100644
--- a/Completion/User/_ssh
+++ b/Completion/User/_ssh
@@ -4,16 +4,6 @@ _ssh () {
   local curcontext="$curcontext" state lstate line ret=1 expl args tmp
   typeset -A opt_args
 
-  local accounts_users_hosts
-
-  local varname="$words[1]_accounts"
-
-  if (( ${(P)+varname} )); then
-    accounts_users_hosts=( ${(P)varname} )
-  else
-    accounts_users_hosts=( $my_accounts )
-  fi
-
   args=()
 
   # ssh-opt is a pseudo-command used to complete ssh options for `scp -o'.
@@ -227,14 +217,14 @@ _ssh () {
 }
 
 _ssh_users () {
-  _combination accounts_users_hosts users "$@"
+  _combination my-accounts users-hosts users "$@"
 }
 
 _ssh_hosts () {
   if [[ "$IPREFIX" == *@ ]]; then
-    _combination accounts_users_hosts "users=${IPREFIX/@}" hosts "$@"
+    _combination my-accounts users-hosts "users=${IPREFIX/@}" hosts "$@"
   else
-    _combination accounts_users_hosts \
+    _combination my-accounts users-hosts \
       ${opt_args[-l]:+"users=${opt_args[-l]:q}"} hosts "$@"
   fi
 }
diff --git a/Completion/User/_telnet b/Completion/User/_telnet
index 597c0a021..7b86e544c 100644
--- a/Completion/User/_telnet
+++ b/Completion/User/_telnet
@@ -64,14 +64,14 @@ _arguments -C -s \
 case "$state" in
 hosts)
   _wanted hosts expl host &&
-      _combination telnet_hosts_ports_users \
+      _combination '' hosts-ports-users \
           ${opt_args[-l]:+users=${opt_args[-l]:q}} \
           hosts "$expl[@]"
   ;;
 
 ports)
   _wanted ports expl port &&
-      _combination telnet_hosts_ports_users \
+      _combination '' hosts-ports-users \
           ${opt_args[-l]:+users=${opt_args[-l]:q}} \
           hosts="${line[2]:q}" \
           ports "$expl[@]"
@@ -79,7 +79,7 @@ ports)
 
 users)
   _wanted users expl user &&
-      _combination telnet_hosts_ports_users \
+      _combination '' hosts-ports-users \
       ${line[2]:+hosts="${line[2]:q}"} \
       ${line[3]:+ports="${line[3]:q}"} \
       users "$expl[@]"
diff --git a/Completion/User/_user_at_host b/Completion/User/_user_at_host
index 78e5a12aa..1098d2342 100644
--- a/Completion/User/_user_at_host
+++ b/Completion/User/_user_at_host
@@ -1,13 +1,30 @@
 #autoload
 
+# Complete user/host combinations. Normally this looks for the style
+# `users-hosts' for the tag `accounts'. A different tag may be given
+# with `-t tag'.
+# A `-' or `--' as the first argument is ignored.
+
+local tag=accounts
+
+if [[ "$1" = -t?* ]]; then
+  tag="${1[3,-1]}"
+  shift
+elif [[ "$1" = -t ]]; then
+  tag="$2"
+  shift 2
+fi
+
+[[ "$1" = -(|-) ]] && shift
+
 if [[ -prefix 1 *@ ]]; then
-  local user=${PREFIX/@}
+  local user=${PREFIX%%@*}
 
   compset -P 1 '*@'
 
   _wanted -C user-at hosts expl "host for $user" &&
-      _combination accounts_users_hosts users="$user" hosts "$expl[@]" "$@"
+      _combination "${tag}" users-hosts users="$user" hosts "$expl[@]" "$@"
 else
   _wanted users expl "user" &&
-      _combination accounts_users_hosts users -S@ -q "$expl[@]" "$@"
+      _combination "${tag}" users-hosts users -S@ -q "$expl[@]" "$@"
 fi
diff --git a/Completion/User/_users b/Completion/User/_users
index fdef36073..8ddfd8cd7 100644
--- a/Completion/User/_users
+++ b/Completion/User/_users
@@ -3,11 +3,11 @@
 # If a parameter `users' exists and it is an array, we first try to
 # complete only to its elements.
 
-local expl
+local expl users
 
 _wanted users expl user || return 1
 
-[[ "${(t)users}" = *array* ]] &&
+_style -a users users users &&
     compadd "$expl[@]" "$@" - "$users[@]" && return 0
 
 compadd "$@" "$expl[@]" - "${(@k)userdirs}"