zsh-workers
 help / color / mirror / code / Atom feed
From: Tanaka Akira <akr@jaist.ac.jp>
To: zsh-workers@sunsite.auc.dk (Zsh hackers list)
Subject: Re: PATCH: _hosts, _hostports, _telnet and _socket
Date: 14 Sep 1999 03:20:15 +0900	[thread overview]
Message-ID: <rsqemg2hdwg.fsf@crane.jaist.ac.jp> (raw)
In-Reply-To: Peter Stephenson's message of "Mon, 13 Sep 1999 11:09:11 +0200"

In article <199909130909.LAA14546@paris.ifh.de>,
  Peter Stephenson <pws@ifh.de> writes:

> I'd have said there was room for an autoloaded function _ports, which can
> use telnet_ports and then default to something like
>   awk '/^[a-z]/ { print $1 }' /etc/services
> if nothing turns up.  As Bart implied, it might be useful to have it
> index on commands, too:  you could have the convention, say, that
> commands had a trailing * added (quoted, obviously).  Then _ports
> could be called like "_ports <cmd> <host>".  You could make it search
> the assoc array <cmd>_ports, which is sort of what's happening with
> telnet_ports and socket_ports.  In that case indexing on commands is
> perhaps superflous and you could have a special key (e.g. '*') giving
> a default port.

Hm. As Adam Spiers mentioned, relations between host-port aren't
special. And I found that `telnet' has `-l' option that specifies
`user'.  I think the argument of `-l' should be considered when
completion. So, I prefer more general way to specify such relations.

I made `_combination' and `_ports' and modified `_socket' and
`_telnet' to use them.

# Is there a better name for `_combination'?

Now `_telnet' can handle following 7 situations.

% telnet <TAB>		    # completes hosts.
% telnet -l USER <TAB>	    # completes hosts restricted by `USER'.
% telnet HOST <TAB>	    # completes ports restricted by `HOST'.
% telnet -l USER HOST <TAB> # completes ports restricted by `USER' and `HOST'.
% telnet -l <TAB>	    # completes users.
% telnet HOST -l <TAB>	    # completes users restricted by `HOST'.
% telnet HOST PORT -l <TAB> # completes users restricted by `HOST' and `PORT'.

For this, you should define the variable `telnet_hosts_ports_users' as
like:

telnet_hosts_ports_users=(
  host0::
  host1::user1
  host2::user2
  mail-server:{smtp,pop3}:
  news-server:nntp:
  proxy-server:8000:
)

The variable `telnet_hosts_ports_users' is an (normal) array of
strings formed as "host:port:user".

Also, `_telnet' uses `_hosts', `_ports' and `_users' (through
`_combination') if `telnet_hosts_ports_users' cannot match a command
line or it is not defined.

--- /dev/null	Tue Sep 14 02:14:47 1999
+++ Completion/User/_combination	Tue Sep 14 02:30:06 1999
@@ -0,0 +1,85 @@
+#autoload
+
+# Usage:
+#   _combination [-s SEP] VARIABLE KEYi=PATi KEYj=PATj ... KEYm=PATm KEY EXPL...
+#
+#  VARIABLE must be formd as PREFIX_KEY1_..._KEYn.
+#
+# Example: telnet
+#
+#  Assume an user sets the variable `telnet_hosts_ports_users' as:
+#
+#    telnet_hosts_ports_users=(
+#      host0:: host1::user1 host2::user2
+#      mail-server:{smtp,pop3}:
+#      news-server:nntp:
+#      proxy-server:8000:
+#    )
+#
+#  `_telnet completes' hosts as:
+#
+#    _combination telnet_hosts_ports_users \
+#      ${options[-l]:+users=${options[-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 telnet_hosts_ports_users \
+#      ${options[-l]:+users=${options[-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 telnet_hosts_ports_users \
+#      ${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 var keys pats key tmp
+
+if [[ "$1" = -s ]]; then
+  sep="$2"
+  shift 2
+else
+  sep=:
+fi
+
+var=$1
+shift
+
+keys=( "${(@s:_:)${var#*_}}" )
+pats=( "${(@)keys/*/*}" )
+
+while [[ "$1" = *=* ]]; do
+  pats[$keys[(i)${1%%\=*}]]="${1#*\=}"
+  shift
+done
+
+key="$1"
+shift
+
+if (( ${(P)+${var}} )); then
+  eval "tmp=( \"\${(@M)${var}:#\${(j!$sep!)~pats}}\" )"
+  if (( keys[(i)$key] != 1 )); then
+    eval "tmp=( \${tmp#\${(j!${sep}!)~\${(@)\${(@)keys[2,(r)\$key]}/*/*}}$sep} )"
+  fi
+  tmp=( ${tmp%%$sep*} )
+
+  compadd "$@" - $tmp || { builtin functions _$key >&- && _$key "$@" }
+else
+  builtin functions _$key >&- && _$key "$@"
+fi
+
--- /dev/null	Tue Sep 14 02:14:47 1999
+++ Completion/User/_ports	Tue Sep 14 02:04:51 1999
@@ -0,0 +1,8 @@
+#autoload
+
+local expl
+
+: ${(A)ports:=${${(M)${${(f)"$(</etc/services)"}:#\#*}#*/tcp}%%[ 	]*}}
+
+_description expl port
+compadd "$@" "$expl[@]" - "$ports[@]"
Index: Completion/User/_socket
===================================================================
RCS file: /projects/zsh/zsh/Completion/User/_socket,v
retrieving revision 1.1.1.2
diff -u -F^( -r1.1.1.2 _socket
--- _socket	1999/09/12 03:38:21	1.1.1.2
+++ _socket	1999/09/13 17:34:59
@@ -2,11 +2,9 @@
 
 # Parameter used:
 #
-#  socket_ports
-#    The associative array that maps a host name to a space-separated list of 
-#    ports.
+#  socket_hosts_ports
+#    The array that contains paris `host:port'.
 
-
 local state line expl
 typeset -A options
 
@@ -28,18 +26,14 @@
     _message 'port to listen'
   else
     _description expl 'host'
-    compadd "$expl[@]" - ${(k)socket_ports} || _hosts "$expl[@]"
+    _combination socket_hosts_ports hosts "$expl[@]"
   fi
   ;;
 
 arg2)
   if (( ! $+options[-s] )); then
     _description expl 'port to connect'
-    if (( $+socket_ports )); then
-      compadd "$expl[@]" - ${=socket_ports[$line[2]]};
-    else
-      _message 'port to connect';
-    fi
+    _combination socket_hosts_ports hosts="${line[2]:q}" ports "$expl[@]"
   fi
   ;;
 esac
Index: Completion/User/_telnet
===================================================================
RCS file: /projects/zsh/zsh/Completion/User/_telnet,v
retrieving revision 1.1.1.2
diff -u -F^( -r1.1.1.2 _telnet
--- _telnet	1999/09/12 03:38:21	1.1.1.2
+++ _telnet	1999/09/13 17:34:59
@@ -2,10 +2,12 @@
 
 # Parameter used:
 #
-#  telnet_ports
-#    The associative array that maps a host name to a space-separated list of
-#    ports.
+#  telnet_hosts_ports_users
+#    The array that contains 3-tuples `host:port:user'.
 
+local state line expl
+typeset -A options
+
 _arguments -s \
   -{F,f,x} \
   '-8[allow 8-Bit data]' \
@@ -19,9 +21,33 @@
   '-d[debug mode]' \
   '-e+[specify escape character]:escape character:' \
   '-k+:realm:' \
-  '-l+[specify user]:user:' \
+  '-l+[specify user]:user:->users' \
   '-n+[specify tracefile]:tracefile:_files' \
   '-r[rlogin like user interface]' \
-  ':host:{ compadd "$expl[@]" - ${(k)telnet_ports} || _hosts "$expl[@]" }' \
-  ':port:{ if (( $+telnet_ports )); then compadd "$expl[@]" - ${=telnet_ports[$line[2]]}; else _message "port"; fi }'
+  ':host:->hosts' \
+  ':port:->ports'
+
+case "$state" in
+hosts)
+  _description expl 'host'
+  _combination telnet_hosts_ports_users \
+    ${options[-l]:+users=${options[-l]:q}} \
+    hosts "$expl[@]"
+  ;;
+
+ports)
+  _description expl 'port'
+  _combination telnet_hosts_ports_users \
+    ${options[-l]:+users=${options[-l]:q}} \
+    hosts="${line[2]:q}" \
+    ports "$expl[@]"
+  ;;
 
+users)
+  _description expl 'user'
+  _combination telnet_hosts_ports_users \
+    ${line[2]:+hosts="${line[2]:q}"} \
+    ${line[3]:+ports="${line[3]:q}"} \
+    users "$expl[@]"
+  ;;
+esac
-- 
Tanaka Akira


  reply	other threads:[~1999-09-13 18:20 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-09-12  0:00 Tanaka Akira
1999-09-12  2:20 ` Bart Schaefer
1999-09-12  3:36   ` Tanaka Akira
1999-09-12 21:25     ` Adam Spiers
1999-09-13 14:06       ` Clint Adams
1999-09-13  9:09     ` Peter Stephenson
1999-09-13 18:20       ` Tanaka Akira [this message]
1999-09-14 14:25       ` Clint Adams
1999-09-12 11:26 ` Andrej Borsenkow
1999-09-12 12:26   ` Tanaka Akira
1999-09-17  0:57     ` Tanaka Akira
1999-09-19  0:49       ` Bart Schaefer
1999-09-14  8:34 Sven Wischnowsky
1999-09-15 12:56 ` Tanaka Akira

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=rsqemg2hdwg.fsf@crane.jaist.ac.jp \
    --to=akr@jaist.ac.jp \
    --cc=zsh-workers@sunsite.auc.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).