Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: PATCH: _hosts, _hostports, _telnet and _socket
- X-seq: zsh-workers 7815
- From: Tanaka Akira <akr@xxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx (Zsh hackers list)
- Subject: Re: PATCH: _hosts, _hostports, _telnet and _socket
- Date: 14 Sep 1999 03:20:15 +0900
- In-reply-to: Peter Stephenson's message of "Mon, 13 Sep 1999 11:09:11 +0200"
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
- References: <199909130909.LAA14546@xxxxxxxxxxxx>
In article <199909130909.LAA14546@xxxxxxxxxxxx>,
Peter Stephenson <pws@xxxxxx> 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
Messages sorted by:
Reverse Date,
Date,
Thread,
Author