about summary refs log tree commit diff
path: root/Completion
diff options
context:
space:
mode:
Diffstat (limited to 'Completion')
-rw-r--r--Completion/Base/Utility/_combination94
1 files changed, 94 insertions, 0 deletions
diff --git a/Completion/Base/Utility/_combination b/Completion/Base/Utility/_combination
new file mode 100644
index 000000000..dcb3269cd
--- /dev/null
+++ b/Completion/Base/Utility/_combination
@@ -0,0 +1,94 @@
+#autoload
+
+# Usage:
+#   _combination [-s S] TAG STYLE \
+#     Ki1[:Ni1]=Pi1 Ki2[:Ni2]=Pi2 ... Kim[:Nim]=Pim Kj[:Nj] EXPL...
+#
+#  STYLE should be of the form K1-K2-...-Kn.
+#
+# Example: telnet
+#
+#  Assume an user sets the style `users-hosts-ports' as for the my-accounts
+#  tag:
+#
+#    zstyle ':completion:*:*:telnet:*:my-accounts' users-hosts-ports \
+#      @host0: user1@host1: user2@host2:
+#      @mail-server:{smtp,pop3}
+#      @news-server:nntp
+#      @proxy-server:8000
+# 
+#
+#  `_telnet' completes hosts as:
+#
+#    _combination my-accounts users-hosts-ports \
+#      ${opt_args[-l]:+users=${opt_args[-l]:q}} \
+#      hosts "$expl[@]"
+#
+#  This completes `host1', `host2', `mail-server', `news-server' and
+#  `proxy-server' according to the user given with `-l' if it is exists.
+#  And if it is failed, `_hosts' is called.
+# 
+#  `_telnet' completes ports as:
+#
+#    _combination my-accounts users-hosts-ports \
+#      ${opt_args[-l]:+users=${opt_args[-l]:q}} \
+#      hosts="${line[2]:q}" \
+#      ports "$expl[@]"
+#
+#  This completes `smtp', `pop3', `nntp' and `8000' according to the
+#  host argument --- $line[2] and the user option argument if it is
+#  exists. And if it is failed, `_ports' is called.
+#
+#  `_telnet' completes users for an argument of option `-l' as:
+#
+#    _combination my-accounts users-hosts-ports \
+#      ${line[2]:+hosts="${line[2]:q}"} \
+#      ${line[3]:+ports="${line[3]:q}"} \
+#      users "$expl[@]"
+#
+#  This completes `user1' and `user2' according to the host argument and
+#  the port argument if they are exist. And if it is failed, `_users' is
+#  called.
+
+local sep tag style keys pats key num tmp
+
+if [[ "$1" = -s ]]; then
+  sep="$2"
+  shift 2
+elif [[ "$1" = -s* ]]; then
+  sep="${1[3,-1]}"
+  shift
+else
+  sep=:
+fi
+
+tag="$1"
+style="$2"
+shift 2
+
+keys=( ${(s/-/)style} )
+pats=( "${(@)keys/*/*}" )
+
+while [[ "$1" = *=* ]]; do
+  tmp="${1%%\=*}"
+  key="${tmp%:*}"
+  num="${${tmp##*:}:-1}"
+  pats[$keys[(in:num:)$key]]="${1#*\=}"
+  shift
+done
+
+key="${1%:*}"
+num="${${1##*:}:-1}"
+shift
+
+if zstyle -a ":completion:${curcontext}:$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
+  tmp=( ${tmp%%${~sep}*} )
+
+  compadd "$@" -a tmp || { (( $+functions[_$key] )) && "_$key" "$@" }
+else
+  (( $+functions[_$key] )) && "_$key" "$@"
+fi