about summary refs log tree commit diff
path: root/Misc
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-08-12 22:59:04 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-08-12 22:59:04 +0000
commit8d1b4b1358db02d6c9426e4bb3553583e11bf112 (patch)
treea3095364536d55f8356ac99559e440cc91f33eb1 /Misc
parent5714953c514a5fea35dcd819caf1afef4d92a13b (diff)
downloadzsh-8d1b4b1358db02d6c9426e4bb3553583e11bf112.tar.gz
zsh-8d1b4b1358db02d6c9426e4bb3553583e11bf112.tar.xz
zsh-8d1b4b1358db02d6c9426e4bb3553583e11bf112.zip
Sync up with zsh-3_1_6-pws-1.
Diffstat (limited to 'Misc')
-rw-r--r--Misc/.lastloc2
-rw-r--r--Misc/new-completion-examples453
-rw-r--r--Misc/zftp-functions1281
3 files changed, 0 insertions, 1736 deletions
diff --git a/Misc/.lastloc b/Misc/.lastloc
deleted file mode 100644
index 8ba7dd946..000000000
--- a/Misc/.lastloc
+++ /dev/null
@@ -1,2 +0,0 @@
-(("/home/user2/pws/src/zsh-3.1.5/Misc/globtests.ksh" . 2763)
- ("/home/user2/pws/src/zsh-3.1.5/Misc/globtests" . 3123))
diff --git a/Misc/new-completion-examples b/Misc/new-completion-examples
deleted file mode 100644
index 659679891..000000000
--- a/Misc/new-completion-examples
+++ /dev/null
@@ -1,453 +0,0 @@
-# Define a new widget behaving like `expand-or-complete' but calling the
-# function `main-complete' to generate matches.
-
-zle -c my-comp expand-or-complete main-complete
-
-bindkey '\C-i' my-comp
-
-
-# Below is a proposed main loop and the things it needs.
-
-# One associative array for normal completions and one for patterns.
-
-typeset -A comps
-
-
-# These may be used to define completion handlers. First argument is the
-# name of the function/variable containing the definition, the other
-# arguments are the command names for which this definition should be used.
-# With only one argument the function/variable-name __$1 is used.
-
-defcomp() {
-  local v
-
-  if [[ $# -eq 1 ]] then
-    comps[$1]="__$1"
-  else
-    v="$1"
-    shift
-    for i; do
-      comps[$i]="$v"
-    done
-  fi
-}
-
-defpatcomp() {
-  if [[ ${+patcomps} == 1 ]] then
-    patcomps=("$patcomps[@]" "$2 $1" )
-  else
-    patcomps=( "$2 $1" )
-  fi
-}
-
-
-# These can be used to easily save and restore the state of the special
-# variables used by the completion code.
-
-alias compsave='local _opre _oipre _oargs _ocur;_opre="$PREFIX";_oipre="$IPREFIX";_oargs=( "$@" );_ocur="$CURRENT"'
-alias compreset='PREFIX="$_opre";IPREFIX="$_oipre";argv=( "$_oargs[@]" );CURRENT="$_ocur"'
-
-# This is an easy way to get completion for sub-commands.
-
-alias compsub='do-complete "$@" || return 1'
-
-# This searches $1 in the array for normal completions and calls the result.
-
-compalso() {
-  1="$comps[$1]"
-  [[ -z "$1" ]] || call-complete "$@"
-}
-
-# This generates matches. The first argument is something we got from one
-# of the associative arrays above. This is expected to be either the name
-# of a variable in which case we use its value as arguments to complist,
-# or it is the name of a function in which case we call this function with
-# the arguments from the command line as its arguments.
-
-call-complete() {
-  local var
-
-  eval var\=\$\{\+$1\}
-  if [[ "$var" == 0 ]] then
-    "$@"
-  else
-    eval complist \$\{${1}\[\@\]\}
-  fi
-}
-
-# The main loop of the competion code. This is what is called when TAB is
-# pressed. The completion code gives us the special variables and the
-# arguments from the command line are gives as positional parameters.
-
-main-complete() {
-  emulate -R zsh
-  local comp
-  setopt localoptions nullglob rcexpandparam globdots
-  unsetopt markdirs globsubst shwordsplit nounset
-
-  # An entry for `--first--' is the replacement for `compctl -T'
-  # The `|| return 1' is used throughout: if a function producing matches
-  # returns non-zero this is interpreted as `do not try to produce more matches'
-  # (this is the replacement for `compctl -t').
-
-  comp="$comps[--first--]"
-  [[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
-
-  # For arguments we use the `do-complete' function below called via the
-  # convenience alias `compsub'.
-
-  if [[ $CONTEXT == argument || $CONTEXT == command ]] then
-    compsub
-  else
-    # Let's see if we have a special completion definition for the other
-    # possible contexts.
-
-    comp=''
-
-    case $CONTEXT in
-    redirect)  comp="$comps[--redir--]";;
-    math)   comp="$comps[--math--]";;
-    subscript) comp="$comps[--subscr--]";;
-    value)  comp="$comps[--value--]";;
-    condition)   comp="$comps[--cond--]";;
-    esac
-
-    # If not, we use default completion, if any.
-
-    [[ -z "$comp" ]] && comp="$comps[--default--]"
-    [[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
-  fi
-}
-
-# This does completion for a command (in command position and for the
-# arguments).
-
-do-complete() {
-  local comp cmd1 cmd2 pat val
-
-  # Completing in command position? If not we set up `cmd1' and `cmd2' as
-  # two strings we have search in the completion definition arrays (e.g.
-  # a path and the last path name component).
-
-  if [[ $CONTEXT == command ]] then
-    comp="$comps[--command--]"
-    [[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
-    return 0
-  elif [[ "$COMMAND[1]" == '=' ]] then
-    eval cmd1\=$COMMAND
-    cmd2="$COMMAND[2,-1]"
-  elif [[ "$COMMAND" == */* ]] then
-    cmd1="$COMMAND"
-    cmd2="${COMMAND:t}"
-  else
-    cmd1="$COMMAND"
-    eval cmd2=$(whence -p $COMMAND)
-  fi
-
-  # See if there are any matching pattern completions.
-
-  for i in "$patcomps[@]"; do
-    pat="${i% *}"
-    val="${i#* }"
-    if [[ "$cmd1" == $~pat || "$cmd2" == $~pat ]] then
-      call-complete "$val" "$@" || return 1
-    fi
-  done
-
-  # Now look up the two names in the normal completion array.
-
-  comp="${comps[$cmd1]:-$comps[$cmd2]}"
-
-  # And generate the matches, probably using default completion.
-
-  [[ -z "$comp" ]] && comp="$comps[--default--]"
-  [[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
-}
-
-# Do sub-completion for pre-command modifiers.
-
-defcomp __precmd - noglob nocorrect exec command builtin
-__precmd() {
-  COMMAND="$1"
-  shift
-  (( CURRENT-- ))
-  if [[ CURRENT -eq 0 ]] then
-    CONTEXT=command
-  else
-    CONTEXT=argument
-  fi
-  compsub
-}
-
-# Utility function for in-path completion.
-# First argument should be an complist-option (e.g. -f, -/, -g). The other
-# arguments should be glob patterns, one per argument.
-# E.g.: files -g '*.tex' '*.texi'
-# This is intended as a replacement for `complist -f', `complist -/', and
-# `complist -g ...' (but don't use it with other options).
-# This function behaves as if you have a matcher definition like:
-#   compctl -M 'r:|[-.,_/]=* r:|=* m:{a-z}={A-Z} m:-=_ m:.=,'
-# so you may want to modify this.
-
-pfiles() {
-  local nm str pa pre epre a b c s rest
-
-  setopt localoptions nullglob rcexpandparam globdots extendedglob
-  unsetopt markdirs globsubst shwordsplit nounset
-
-  nm=$NMATCHES
-  if [[ $# -eq 0 ]] then
-    complist -f
-  elif [[ "$1" = -g ]] then
-    complist -g "$argv[2,-1]"
-    shift
-  else
-    complist $1
-    shift
-  fi
-  [[ -nmatches nm ]] || return
-
-  str="$PREFIX*$SUFFIX"
-
-  [[ -z "$1" ]] && 1='*'
-  if [[ $str[1] = \~ ]] then
-    pre="${str%%/*}/"
-    eval epre\=$pre
-    str="${str#*/}"
-    pa=''
-  else
-    pre=''
-    epre=''
-    if [[ $str[1] = / ]] then
-      str="$str[2,-1]"
-      pa='/'
-    else
-      pa=''
-    fi
-  fi
-  str="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
-  while [[ "$str" = */* ]] do
-    rest="${str#*/}"
-    a="${epre}${pa}(#l)${str%%/*}(-/)"
-    a=( $~a )
-    if [[ $#a -eq 0 ]] then
-      return
-    elif [[ $#a -gt 1 ]] then
-      c=()
-      s=( $rest$@ )
-      s=( "${(@)s:gs.**.*.}" )
-      for i in $a; do
-        b=( $~i/(#l)$~s )
-        eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
-        [[ $#b -ne 0 ]] && c=( $c $i )
-      done
-      if [[ $#c -eq 0 ]] then
-        return
-      elif [[ $#c -ne 1 ]] then
-        a="$epre$pa"
-        c=( $~c/(#l)$~s )
-        eval c\=\( \$\{c:/\*\(${(j:|:)fignore}\)\} \)
-	c=( ${c#$a} )
-        for i in $c; do
-          compadd -p "$pre$pa" -W "$a" -s "/${i#*/}" -f "${i%%/*}"
-        done
-	return
-      fi
-      a=( "$c[1]" )
-    fi
-    a="$a[1]"
-    pa="$pa${a##*/}/"
-    str="$rest"
-  done
-  a="$epre$pa"
-  s=( $str$@ )
-  s=( "${(@)s:gs.**.*.}" )
-  b=( $~a(#l)$~s )
-  eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
-  compadd -p "$pre$pa" -W "$epre$pa" -f ${b#$a}
-}
-
-# Utility function for completing files of a given type or any file.
-# In many cases you will want to call this one instead of pfiles().
-
-files() {
-  local nm
-
-  nm=$NMATCHES
-  pfiles "$@"
-
-  [[ $# -ne 0 && -nmatches nm ]] && pfiles
-}
-
-# Simple default, command, and math completion defined with variables.
-
-defcomp __default --default--
-__default() {
-  files
-}
-
-defcomp __command --command--
-__command=( -c )
-
-defcomp __math --math--
-__math=( -v )
-
-defcomp __subscr --subscr--
-__subscr() {
-  compalso --math-- "$@"
-  # ...probably other stuff
-}
-
-# A simple pattern completion, just as an example.
-
-defpatcomp __x_options '*/X11/*'
-__x_options() {
-  complist -J options -k '(-display -name -xrm)'
-}
-
-# A better example: completion for `find'.
-
-defcomp find
-__find() {
-  compsave
-
-  if [[ -mbetween -(ok|exec) \\\; ]] then
-    compsub
-  elif [[ -iprefix - ]] then
-    complist -s 'daystart {max,min,}depth follow noleaf version xdev \
-	{a,c,}newer {a,c,m}{min,time} empty false {fs,x,}type gid inum links \
-	{i,}{l,}name {no,}{user,group} path perm regex size true uid used \
-	exec {f,}print{f,0,} ok prune ls'
-    compreset
-  elif [[ -position 1 ]] then
-    complist -g '. ..'
-    files -g '(-/)'
-  elif [[ -mcurrent -1 -((a|c|)newer|fprint(|0|f)) ]] then
-    files
-  elif [[ -current -1 -fstype ]] then
-    complist -k '(ufs 4.2 4.3 nfs tmp mfs S51K S52K)'
-  elif [[ -current -1 -group ]] then
-    complist -k groups
-  elif [[ -current -1 -user ]] then
-    complist -u
-  fi
-}
-
-# Various completions...
-
-defcomp __gunzip gunzip zcat
-__gunzip() {
-  files -g '*.[gG][z]'
-}
-
-defcomp gzip
-__gzip() {
-  files -g '*~*.[gG][zZ]'
-}
-
-defcomp xfig
-__xfig() {
-  files -g '*.fig'
-}
-
-defcomp __make make gmake
-__make() {
-  complist -s "\$(awk '/^[a-zA-Z0-9][^/ 	]+:/ {print \$1}' FS=: [mM]akefile)"
-}
-
-defcomp __ps gs ghostview gview psnup psselect pswrap pstops pstruct lpr
-__ps() {
-  files -g '*([pP][sS]|eps)'
-}
-
-defcomp __which which whence
-__which=( -caF )
-
-defcomp __rlogin rlogin rsh ssh
-__rlogin() {
-  if [[ -position 1 ]] then
-    complist -k hosts
-  elif [[ -position 2 ]] then
-    complist -k '(-l)'
-  elif [[ -position 3 && -word 1 artus ]] then
-    complist -k '(puck root)'
-  fi
-}
-
-defcomp __dvi xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
-__dvi() {
-  files -g '*.(dvi|DVI)'
-}
-
-defcomp __dirs rmdir df du dircmp cd
-__dirs() {
-  files -/ '*(-/)'
-}
-
-defcomp __jobs fg bg jobs
-__jobs=(-j -P '%?')
-
-defcomp kill
-__kill() {
-  if [[ -iprefix '-' ]] then
-    complist -k signals
-  else
-    complist -P '%?' -j
-  fi
-}
-
-defcomp __uncompress uncompress zmore
-__uncompress() {
-  files -g '*.Z'
-}
-
-defcomp compress
-__compress() {
-  files -g '*~*.Z'
-}
-
-defcomp __tex tex latex glatex slitex gslitex
-__tex() {
-  files -g '*.(tex|TEX|texinfo|texi)'
-}
-
-defcomp __options setopt unsetopt
-__options=(-M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o)
-
-defcomp __funcs unfunction
-__funcs=(-F)
-
-defcomp __aliases unalias
-__aliases=(-a)
-
-defcomp __vars unset
-__vars=(-v)
-
-defcomp __enabled disable
-__enabled=(-FBwa)
-
-defcomp __disabled enable
-__disabled=(-dFBwa)
-
-defcomp __pdf acroread
-__pdf() {
-  files -g '*.(pdf|PDF)'
-}
-
-defcomp tar
-__tar() {
-  local nm tf
-  compsave
-
-  tf="$2"
-  nm=$NMATCHES
-  if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]] then
-    complist -k "( $(tar tf $tf) )"
-    compreset
-  elif [[ -mword 1 *c*f* && -position 3 100000 ]] then
-    files
-    compreset
-  elif [[ -mcurrent -1 *f* && -position 2 ]] then
-    files -g '*.(tar|TAR)'
-  fi
-}
diff --git a/Misc/zftp-functions b/Misc/zftp-functions
deleted file mode 100644
index a07e46d72..000000000
--- a/Misc/zftp-functions
+++ /dev/null
@@ -1,1281 +0,0 @@
-# zftp is a loadable module implementing an FTP client as a builtin
-# command so that you can use the shell command language and line
-# editing to make life easier.  If your system has dynamically
-# load libraries and zsh was compiled to use them, it is probably
-# somewhere where it can be loaded at run time.  Otherwise, it depends
-# whether the shell was compiled with zftp already built into it.
-#
-# Here is a suite of functions, plus assorted other code, to make
-# zftp work smoothly.
-#
-# Completion is implemented in a fairly natural way, except that
-# very little support has been provided for non-UNIX remote hosts.
-# On such machines, the safest thing to do is only try to complete
-# files in the current directory; this should be OK.
-#
-# Remote globbing for commands which retrieve files is also
-# implemented.  This can be done in two different ways.  The default
-# is for zsh to do the globbing locally.  The advantage is that full
-# zsh pattern matching (respecting the setting of extendedglob) is
-# possible, and no assumption (apart from the restrictions on
-# directory handling noted above) is made about the behaviour of the
-# server.  The disadvantage is that the entire filename list for the
-# current directory must be retrieved, and then zsh must laboriously
-# do pattern matching against every file, so it is potentially slow
-# for large directories.  Only the non-directory part of file names is
-# globbed.
-#
-# The alternative will be used if $zfrglob has non-zero length.
-# Zsh then sends the pattern to the server for globbing.  Best of
-# luck.
-#
-# To support remote globbing, some functions have been aliased
-# with 'noglob' in front.  Currently, this has a dire effect on
-# completion unless the completeinaliases option is set, so
-# it is set below.  This can conceivably cause you problems
-# if you expect completion for aliases automatically to give you
-# completion for the base command.  I suspect that most people
-# don't even know that happens.
-#
-# The following functions are provided.
-#
-# General status changing and displaying functions:
-# zfparams
-#   Simple front end to `zftp params', except it will automatically
-#   query host, user and password.  These are then stored to be
-#   used with a `zfopen' with no arguments.
-# zfopen [ host [ user ... ] ]
-#   Open a connection and login.  Unless the option -1 (once)
-#   is given, will store the parameters for the open (including
-#   a password which is prompted for and not echoed) so that
-#   if you call zfopen subsequently without arguments it will
-#   reopen the same connection.
-# zfanon anonftphost
-#   Open a connection for anonymous FTP.  Tries to guess an
-#   email address to use as the password, unless $EMAIL_ADDR is
-#   already set.  The first time, will tell you what it has guessed.
-#   It's rude to set EMAIL_ADDR=mozilla.
-# zfcd [ dir | old new ]
-#   Change directory on the server.  This tries to mimic the behaviour
-#   of the shell's cd.  In particular,
-#    zfcd           change to '~' on server, if it interprets it
-#    zfcd -         change to previous directory of current connection
-#    zfcd OLD NEW   change directory from fooOLDbar to fooNEWbar
-#   One piece of magic is builtin:  an initial part of the directory
-#   matching $HOME is translated back to `~'.  Most UNIX servers
-#   recognise the usual shell convention.  So things like `zfcd $PWD'
-#   is useful provide you are under your home directory and the
-#   structure on the remote machine mirrors that on the local.
-# zfhere
-#   Synonym for `zfcd $PWD', see above.
-# zfdir [args]
-#   Show a long diretory list of the remote connection.  Any
-#   arguments are passed on to the server, apart from options.
-#   Currently this always uses a pager to show the directory
-#   list.  Caching is implemented:  zfdir on its own always shows
-#   the current diretory, which is cached; zfdir with some other
-#   directory arguments shows that, which is cached separately
-#   and can be reviewed with `zfdir -r'.  Other options:
-#    -f  force reget, overriding the cache, in case something's changed
-#    -d  delete the cache, but don't show anything.
-#   To pass options to the server, use e.g. `zfdir -- -C'.
-#   This also has the zfcd ~ hack.
-# zfls [args]
-#   Short list of the long directory, depending on what [args]
-#   do to the server.  No options, no caching, no pager.
-# zftype [ a[scii] | i[mage] | b[inary] ]
-#   Set or display the transfer type; currently only ASCII
-#   and image (same as binary) types are supported.
-# zfclose
-#   Close the connection.
-# zfstat
-#   Print the zftp status from local variables; doesn't do any network
-#   operations unless -v is supplied, in which case the server is
-#   asked for its views on the status, too.
-#
-# Functions for retrieving data:
-#   All accept the following options:
-#    -G   Don't do remote globbing (see above); the default is to do it.
-#    -t   Try to set local files to the same time as the remote ones.
-#         Unfortunately we only know the remote time in GMT, so it's
-#         a little tricky and you need perl 5 (installed as `perl')
-#         for this to work.  Suggestions welcome.
-# zfget file1 file2 ...
-#   Retrieve each file from the server.  The remote file is the
-#   full name given, the local file is the non-directory part of that
-#   (assuming UNIX file paths).
-# zfuget file1 file2 ..
-#   Get with update.  Check remote and local sizes and times and
-#   retrieve files which are newer on the server.  Will query
-#   hard cases, which are where the remote file is newer but a
-#   different size, or is older but the same size.  With option -s
-#   (silent) assumes it's best to retrieve the files in both those
-#   cases.  With -v (may be combined with -s), print the information
-#   about the files being considered.
-# zfcget file1 ...
-#   Assuming file1 was incompletely retrieved, try to get the rest of
-#   it.  This relies on a normal UNIX server behaviour which is not
-#   as specified in the FTP standard and hence is not universal.
-# zfgcp file1 file2
-# zfgcp file1 file2 ... dir
-#   Get with the behaviour of cp, i.e. copy remote file1 to local
-#   file2, or get remote fileN into local diretory dir.
-#
-# Function for sending data:
-# zfput file1 file2 ...
-#   Put the local files onto the server under the same name.  The
-#   local files are exactly as given; the remote files are the
-#   non-diretory parts of that. 
-# zfuput file1 file2 ..
-#   Put the local files onto the server, with update.  Works
-#   similarly to zfuget.
-#
-# Utility functions:
-# zftp_chpwd
-#   Show the new directory when it changes; try to put it into
-#   an xterm on shelltool header.  Works best alongside chpwd.
-# zftp_progress
-#   Show the percentage of a file retrieved as it is coming; if the
-#   size is not available show the size transferred so far.  The
-#   percentage may be wrong if sending data from a local pipe.
-#   If you transfer files in the background, you should undefine
-#   this before the transfer.  It is smart enough not to print
-#   anything when stderr is not a terminal.
-# zfcd_match
-#   Function for remote directory completion.
-# zfget_match
-#   Function for remote filename completion.
-# zfrglob varname
-#   This is used for the remote globbing.  The pattern resides
-#   in $varname (note extra level of indirection), and on return
-#   $varname will contain the list of matching files.
-# zfrtime locfile remfile [ time ]
-#   This sad thing does the setting of local file times to those
-#   of the remote, see horror story above.
-
-zmodload -ia zftp
-
-alias zfcd='noglob zfcd'
-alias zfget='noglob zfget'
-alias zfls='noglob zfls'
-alias zfdir='noglob zfdir'
-alias zfuget='noglob zfuget'
-# only way of getting that noglob out of the way at the moment
-setopt completealiases
-
-#
-# zftp completions
-#
-compctl -f -x 'p[1]' \
-  -k '(open params user login type ascii binary mode put putat
-  get getat append appendat ls dir local remote mkdir rmdir delete
-  close quit)'  - \
-  'w[1,cd][1,ls][1,dir][1,rmdir]' -K zfcd_match -S/ -q - \
-  'W[1,get*]' -K zfget_match - 'w[1,delete][1,remote]' -K zfget_match - \
-  'w[1,open][1,params]' -k hosts -- zftp
-compctl -K zfcd_match -S/ -q zfcd zfdir zfls
-compctl -K zfget_match zfget zfgcp zfuget zfcget
-compctl -k hosts zfopen zfparams
-
-function zfanon {
-  local opt optlist once
-  
-  while [[ $1 = -* ]]; do
-    if [[ $1 = - || $1 = -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $optlist[$i] in
-        1) once=1
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  if [[ -z $EMAIL_ADDR ]]; then
-    # Exercise in futility.  There's a poem by Wallace Stevens
-    # called something like `N ways of looking at a blackbird',
-    # where N is somewhere around 0x14 to 0x18.  Now zftp is
-    # ashamed to prsent `N ways of looking at a hostname'.
-    local domain host
-    # First, maybe we've already got it.  Zen-like.
-    if [[ $HOST = *.* ]]; then
-      # assume this is the full host name
-      host=$HOST
-    elif [[ -f /etc/resolv.conf ]]; then
-      # Next, maybe we've got resolv.conf.
-      domain=$(awk '/domain/ { print $2 }' /etc/resolv.conf)
-      [[ -n $domain ]] && host=$HOST.$domain
-    fi
-    # Next, maybe we've got nlsookup.  May not work on LINUX.
-    [[ -z $host ]] && host=$(nslookup $HOST | awk '/Name:/ { print $2 }')
-    if [[ -z $host ]]; then
-      # we're running out of ideas, but this should work.
-      # after all, i wrote it...
-      # don't want user to know about this, too embarrassed.
-      local oldvb=$ZFTP_VERBOSE oldtm=$ZFTP_TMOUT
-      ZFTP_VERBOSE=
-      ZFTP_TMOUT=5
-      if zftp open $host >& /dev/null; then
-        host=$ZFTP_HOST
-        zftp close $host
-      fi
-      ZFTP_VERBOSE=$oldvb
-      ZFTP_TMOUT=$oldtm
-    fi
-    if [[ -z $host ]]; then
-      print "Can't get your hostname.  Define \$EMAIL_ADDR by hand."
-      return 1;
-    fi
-    EMAIL_ADDR="$USER@$host"
-    print "Using $EMAIL_ADDR as anonymous FTP password."
-  fi
-  
-  if [[ $once = 1 ]]; then
-    zftp open $1 anonymous $EMAIL_ADDR
-  else
-    zftp params $1 anonymous $EMAIL_ADDR
-    zftp open
-  fi
-}
-
-function zfcd {
-  # zfcd:  change directory on the remote server.
-  #
-  #  Currently has the following features:
-  # --- an initial string matching $HOME in the directory is turned back into ~
-  #     to be re-interpreted by the remote server.
-  # --- zfcd with no arguments changes directory to '~'
-  # --- `zfcd old new' and `zfcd -' work analagously to cd
-  # --- if the connection is not currently open, it will try to
-  #     re-open it with the stored parameters as set by zfopen.
-  #     If the connection timed out, however, it won't know until
-  #     too late.  In that case, just try the same zfcd command again
-  #     (but now `zfcd -' and `zfcd old new' won't work).
-  
-  # hack: if directory begins with $HOME, turn it back into ~
-  # there are two reasons for this:
-  #   first, a ~ on the command line gets expanded even with noglob.
-  #     (I suppose this is correct, but I wouldn't like to swear to it.)
-  #   second, we can no do 'zfcd $PWD' and the like, and that will
-  #     work just as long as the directory structures under the home match.
-  
-  # Autoopen:  if not already open, hope there are parameters set up to
-  # do so.  If not, we get the right error message, so no harm done.
-  [[ -z $ZFTP_HOST ]] && { zfopen  || return 1; }
-  
-  if [[ $1 = $HOME || $1 = $HOME/* ]]; then
-    1="~${1#$HOME}"
-  fi
-  
-  if (( $# == 0 )); then
-    # Emulate `cd' behaviour
-    set -- '~'
-  elif [[ $# -eq 1 && $1 = - ]]; then
-    # Emulate `cd -' behaviour.
-    set -- $zflastdir
-  elif [[ $# -eq 2 ]]; then
-    # Emulate `cd old new' behaviour.
-    # We have to find a character not in $1 or $2; ! is a good bet.
-    eval set -- "\${ZFTP_PWD:s!$1!$2!}"
-  fi
-  
-  # We have to remember the current directory before changing it
-  # if we want to keep it.
-  local lastdir=$ZFTP_PWD
-  
-  zftp cd "$@"  &&  zflastdir=$lastdir
-}
-
-function zfcd_match {
-  # see zfcd for details of this hack
-  if [[ $1 = $HOME || $1 = $HOME/* ]]; then
-    1="~${1#$HOME}"
-  fi
-  
-  # error messages only
-  local ZFTP_VERBOSE=45
-  # should we redirect 2>/dev/null or let the user see it?
-  
-  if [[ $ZFTP_SYSTEM = UNIX* ]]; then
-    # hoo, aren't we lucky: this makes things so much easier
-    setopt localoptions rcexpandparam
-    local dir
-    if [[ $1 = ?*/* ]]; then
-      dir=${1%/*}
-    elif [[ $1 = /* ]]; then
-      dir=/
-    fi
-    # If we're using -F, we get away with using a directory
-    # to list, but not a glob.  Don't ask me why.
-    # I hate having to rely on awk here.
-    reply=($(zftp ls -F $dir | 
-    awk '/\/$/ { print substr($1, 0, length($1)-1) }'))
-    if [[ $dir = / ]]; then
-      reply=(${dir}$reply)
-    elif [[ -n $dir ]]; then
-      reply=($dir/$reply)
-    fi
-  else
-    # I simply don't know what to do here.
-    # Just use the list of files for the current directory.
-    zfget_match $*
-  fi
-  
-}
-
-function zfcget {
-  # Continuation get of files from remote server.
-  # For each file, if it's shorter here, try to get the remainder from
-  # over there.  This requires the server to support the REST command
-  # in the way many do but RFC959 doesn't specify.
-  # Options:
-  #   -G   don't to remote globbing, else do
-  #   -t   update the local file times to the same time as the remote.
-  #        Currently this only works if you have the `perl' command,
-  #        and that perl is version 5 with the standard library.
-  #        See the function zfrtime for more gory details.
-  
-  setopt localoptions
-  unsetopt ksharrays shwordsplit
-  
-  local loc rem stat=0 optlist opt nglob remlist locst remst
-  local tmpfile=${TMPPREFIX}zfcget$$ rstat tsize time
-  
-  while [[ $1 = -* ]]; do
-    if [[ $1 = - || $1 = -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $optlist[$i] in
-        G) nglob=1
-  	 ;;
-        t) time=1
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  for remlist in $*; do
-    # zfcd directory hack to put the front back to ~
-    if [[ $remlist = $HOME || $remlist = $HOME/* ]]; then
-      remlist="~${remlist#$HOME}"
-    fi
-    if [[ $nglob != 1 ]]; then
-      zfrglob remlist
-    fi
-    if (( $#remlist )); then
-      for rem in $remlist; do
-        loc=${rem:t}
-        if [[ ! -f $loc ]]; then
-  	# File does not yet exist
-  	zftp get $rem >$loc || stat=$?
-        else
-  	# Compare the sizes.
-  	locst=($(zftp local $loc))
-  	zftp remote $rem >$tmpfile
-  	rstat=$?
-  	remst=($(<$tmpfile))
-  	rm -f $tmpfile
-  	if [[ $rstat = 2 ]]; then
-  	  print "Server does not support SIZE command.\n" \
-  	  "Assuming you know what you're doing..." 2>&1
-  	  zftp getat $rem $locst[1] >>$loc || stat=$?
-  	  continue
-  	elif [[ $rstat = 1 ]]; then
-  	  print "Remote file not found: $rem" 2>&1
-  	  continue
-  	fi
-  	if [[ $locst[1] -gt $remst[1] ]]; then
-  	  print "Local file is larger!" 2>&1
-  	  continue;
-  	elif [[ $locst[1] == $remst[1] ]]; then
-  	  print "Files are already the same size." 2>&1
-  	  continue
-  	else
-  	  if zftp getat $rem $locst[1] >>$loc; then
-  	    [[ $time = 1 ]] && zfrtime $loc $rem $remst[2]
-  	  else
-  	    stat=1
-  	  fi
-  	fi
-        fi
-      done
-    fi
-  done
-  
-  return $stat
-}
-
-function zfclose {
-  zftp close
-}
-
-function zfdir {
-  # Long directory of remote server.
-  # The remote directory is cached.  In fact, two caches are kept:
-  # one of the standard listing of the current directory, i.e. zfdir
-  # with no arguments, and another for everything else.
-  # To access the appropriate cache, just use zfdir with the same
-  # arguments as previously.  zfdir -r will also re-use the `everything
-  # else' cache; you can always reuse the current directory cache just
-  # with zfdir on its own.
-  #
-  # The current directory cache is emptied when the directory changes;
-  # the other is kept until a new zfdir with a non-empty argument list.
-  # Both are removed when the connection is closed.
-  #
-  # zfdir -f will force the existing cache to be ignored, e.g. if you know
-  #          or suspect the directory has changed.
-  # zfdir -d will remove both caches without listing anything.
-  # If you need to pass -r, -f or -d to the dir itself, use zfdir -- -d etc.
-  
-  setopt localoptions unset
-  unsetopt shwordsplit ksharrays
-  
-  local file opt optlist redir i newargs force
-  
-  while [[ $1 = -* ]]; do
-    if [[ $1 = - || $1 = -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $optlist[$i] in
-        r) redir=1
-  	 ;;
-        f) force=1
-  	 ;;
-        d) [[ -n $zfcurdir && -f $zfcurdir ]] && rm -f $zfcurdir
-  	 [[ -n $zfotherdir && -f $zfotherdir ]] && rm -f $zfotherdir
-  	 zftp_fcache=()
-  	 return 0
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  # directory hack, see zfcd
-  for (( i = 1; i <= $#argv; i++ )); do
-    if [[ $argv[$i] = $HOME || $argv[$i] = $HOME/* ]]; then
-      argv[$i]="~${argv[$i]#$HOME}"
-    fi
-  done
-  
-  if [[ $# -eq 0 ]]; then
-    # Cache it in the current directory file.  This means that repeated
-    # calls to zfdir with no arguments always use a cached file.
-    [[ -z $zfcurdir ]] && zfcurdir=${TMPPREFIX}zfcurdir$$
-    file=$zfcurdir
-  else
-    # Last directly looked at was not the current one, or at least
-    # had non-standard arguments.
-    [[ -z $zfotherdir ]] && zfotherdir=${TMPPREFIX}zfotherdir$$
-    file=$zfotherdir
-    newargs="$*"
-    if [[ -f $file && $redir != 1 && $force -ne 1 ]]; then
-      # Don't use the cached file if the arguments changed.
-      [[ $newargs = $zfotherargs ]] || rm -f $file
-    fi
-    zfotherargs=$newargs
-  fi
-  
-  if [[ $force -eq 1 ]]; then
-    rm -f $file
-    # if it looks like current directory has changed, better invalidate
-    # the filename cache, too.
-    (( $# == 0 )) && zftp_fcache=()
-  fi
-  
-  if [[ -n $file && -f $file ]]; then
-    eval ${PAGER:-more} \$file
-  else
-    zftp dir $* | tee $file | eval ${PAGER-:more}
-  fi
-}
-
-function zfgcp {
-  # ZFTP get as copy:  i.e. first arguments are remote, last is local.
-  # Supposed to work exactly like a normal copy otherwise, i.e.
-  #  zfcp rfile lfile
-  # or
-  #  zfcp rfile1 rfile2 rfile3 ... ldir
-  # Options:
-  #   -G   don't to remote globbing, else do
-  #   -t   update the local file times to the same time as the remote.
-  #        Currently this only works if you have the `perl' command,
-  #        and that perl is version 5 with the standard library.
-  #        See the function zfrtime for more gory details.
-  
-  setopt localoptions
-  unsetopt shwordsplit
-  
-  local opt optlist nglob remlist rem loc stat=0 time
-  
-  while [[ $1 == -* ]]; do
-    if [[ $1 == - || $1 == -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $opt in
-        G) nglob=1
-  	 ;;
-        t) time=1
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  # hmm, we should really check this after expanding the glob,
-  # but we shouldn't expand the last argument remotely anyway.
-  if [[ $# -gt 2 && ! -d $argv[-1] ]]; then
-    print "zfgcp:  last argument must be a directory." 2>&1
-    return 1
-  elif [[ $# == 1 ]]; then
-    print "zfgcp:  not enough arguments." 2>&1
-    return 1
-  fi
-  
-  if [[ -d $argv[-1] ]]; then
-    local dir=$argv[-1]
-    argv[-1]=
-    for remlist in $*; do
-      # zfcd directory hack to put the front back to ~
-      if [[ $remlist = $HOME || $remlist = $HOME/* ]]; then
-        remlist="~${remlist#$HOME}"
-      fi
-      if [[ $nglob != 1 ]]; then
-        zfrglob remlist
-      fi
-      if (( $#remlist )); then
-        for rem in $remlist; do
-  	loc=$dir/${rem:t}
-  	if zftp get $rem >$loc; then
-  	  [[ $time = 1 ]] && zfrtime $rem $loc
-  	else
-  	  stat=1
-  	fi
-        done
-      fi
-    done
-  else
-    zftp get $1 >$2 || stat=$?
-  fi
-  return $stat
-}
-
-function zfget {
-  # Get files from remote server.  Options:
-  #   -G   don't to remote globbing, else do
-  #   -t   update the local file times to the same time as the remote.
-  #        Currently this only works if you have the `perl' command,
-  #        and that perl is version 5 with the standard library.
-  #        See the function zfrtime for more gory details.
-  
-  local loc rem stat=0 optlist opt nglob remlist time
-  
-  while [[ $1 == -* ]]; do
-    if [[ $1 == - || $1 == -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $opt in
-        G) nglob=1
-  	 ;;
-        t) time=1
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  for remlist in $*; do
-    # zfcd directory hack to put the front back to ~
-    if [[ $remlist == $HOME || $remlist == $HOME/* ]]; then
-      remlist="~${remlist#$HOME}"
-    fi
-    if [[ $nglob != 1 ]]; then
-      zfrglob remlist
-    fi
-    if (( $#remlist )); then
-      for rem in $remlist; do
-        loc=${rem:t}
-        if zftp get $rem >$loc; then
-  	[[ $time = 1 ]] && zfrtime $rem $loc
-        else
-  	stat=1
-        fi
-      done
-    fi
-  done
-  
-  return $stat
-}
-
-function zfget_match {
-  # the zfcd hack:  this may not be necessary here
-  if [[ $1 == $HOME || $1 == $HOME/* ]]; then
-    1="~${1#$HOME}"
-  fi
-  
-  
-  if [[ $ZFTP_SYSTEM == UNIX* && $1 == */* ]]; then
-    # On the first argument to ls, we usually get away with a glob.
-    reply=($(zftp ls "$1*$2"))
-  else
-    if (( $#zftp_fcache == 0 )); then
-      # Always cache the current directory and use it
-      # even if the system is UNIX.
-      zftp_fcache=($(zftp ls))
-    fi
-    reply=($zftp_fcache);
-  fi
-}
-
-function zfhere {
-  # Change to the directory corresponding to $PWD on the server.
-  # See zfcd for how this works.
-  zfcd $PWD
-}
-
-function zfls {
-  # directory hack, see zfcd
-  if [[ $1 = $HOME || $1 = $HOME/* ]]; then
-    1="~${1#$HOME}"
-  fi
-  zftp ls $*
-}
-
-function zfopen {
-  # Use zftp params to set parameters for open, rather than sending
-  # them straight to open.  That way they are stored for a future open
-  # command.
-  #
-  # With option -1 (just this 1ce), don't do that.
-  
-  local optlist opt once
-  
-  while [[ $1 = -* ]]; do
-    if [[ $1 = - || $1 = -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $optlist[$i] in
-        1) once=1
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  # This is where we should try and do same name-lookupage in
-  # both .netrc and .ncftp/bookmarks .  We could even try saving
-  # the info in their for new hosts, like ncftp does.
-  
-  if [[ $once = 1 ]]; then
-    zftp open $*
-  else
-    # set parameters, but only if there was at least a host
-    (( $# > 0 )) && zfparams $*
-    # now call with no parameters
-    zftp open
-  fi
-}
-
-function zfparams {
-    # Set to prompt for any user or password if not given.
-    # Don't worry about accounts here.
-    if (( $# > 0 )); then
-      (( $# < 2 )) && 2='?'
-      (( $# < 3 )) && 3='?'
-    fi
-    zftp params $*
-}
-
-function zfput {
-  # Simple put:  dump every file under the same name, but stripping
-  # off any directory parts.
-  local loc rem stat=0
-  for loc in $*; do
-    rem=${loc:t}
-    zftp put $rem <$loc
-    [[ $? == 0 ]] || stat=$?
-  done
-  return $stat
-}
-
-function zfrglob {
-  # Do the remote globbing for zfput, etc.
-  # We have two choices:
-  #  (1) Get the entire file list and match it one by one
-  #      locally against the pattern.
-  #      Causes problems if we are globbing directories (rare, presumably).
-  #      But: we can cache the current directory, which
-  #      we need for completion anyway.  Works on any OS if you
-  #      stick with a single directory.  This is the default.
-  #  (2) Use remote globbing, i.e. pass it to ls at the site.
-  #      Faster, but only works with UNIX, and only basic globbing.
-  #      We do this if $zfrglob is non-null.
-  
-  # There is only one argument, the variable containing the
-  # pattern to be globbed.  We set this back to an array containing
-  # all the matches.
-  setopt localoptions unset
-  unsetopt ksharrays
-  
-  local pat dir nondir files i
-  
-  eval pat=\$$1
-  
-  # Check if we really need to do anything.  Look for standard
-  # globbing characters, and if extendedglob is set and we are
-  # using zsh for the actual pattern matching also look for
-  # extendedglob characters.
-  if [[ $remlist != *[][*?]* &&
-    ( -n $zfrglob || ! -o extendedglob || $remlist != *[(|)~#^]* ) ]]; then
-    return 0
-  fi
-  
-  if [[ $zfrglob != '' ]]; then
-    eval "$1=(\$(zftp ls \"$pat\" 2>/dev/null))"
-  else
-    if [[ $ZFTP_SYSTEM = UNIX* && $pat = */* ]]; then
-      # not the current directory and we know how to handle paths
-      if [[ $pat = ?*/* ]]; then
-        # careful not to remove too many slashes
-        dir=${pat%/*}
-      else
-        dir=/
-      fi
-      nondir=${pat##*/}
-      files=($(zftp ls "$dir" 2>/dev/null))
-    else
-      # we just have to do an ls and hope that's right
-      nondir=$pat
-      if (( $#zftp_fcache == 0 )); then
-        zftp_fcache=($(zftp ls))
-      fi
-      files=($zftp_fcache)
-    fi
-    # now we want to see which of the $files match $nondir
-    for (( i = 1; i <= $#files; i++)); do
-      # empty words are elided in array assignment
-      [[ $files[$i] = ${~nondir} ]] || files[$i]=''
-    done
-    eval "$1=(\$files)"
-  fi
-}
-
-function zfrtime {
-  # Set the modification time of file LOCAL to that of REMOTE.
-  # If the optional TIME is passed, it should be in the FTP format
-  # CCYYMMDDhhmmSS, i.e. no dot before the seconds, and in GMT.
-  # This is what both `zftp remote' and `zftp local' return.
-  #
-  # Unfortunately, since the time returned from FTP is GMT and
-  # your file needs to be set in local time, we need to do some
-  # hacking around with time.  At the moment this requires perl 5
-  # with the standard library.
-  
-  setopt localoptions unset
-  unsetopt ksharrays
-  
-  local time gmtime loctime
-  
-  if [[ -n $3 ]]; then
-    time=$3
-  else
-    time=($(zftp remote $2 2>/dev/null))
-    [[ -n $time ]] && time=$time[2]
-  fi
-  [[ -z $time ]] && return 1
-  
-  # Now's the real *!@**!?!.  We have the date in GMT and want to turn
-  # it into local time for touch to handle.  It's just too nasty
-  # to handle in zsh; do it in perl.
-  if perl -mTime::Local -e '($file, $t) = @ARGV;
-  $yr = substr($t, 0, 4) - 1900;
-  $mon = substr($t, 4, 2) - 1;
-  $mday = substr($t, 6, 2) + 0;
-  $hr = substr($t, 8, 2) + 0;
-  $min = substr($t, 10, 2) + 0;
-  $sec = substr($t, 12, 2) + 0;
-  $time = Time::Local::timegm($sec, $min, $hr, $mday, $mon, $yr);
-  utime $time, $time, $file and return 0;' $1 $time 2>/dev/null; then
-    print "Setting time for $1 failed.  Need perl 5." 2>1
-  fi
-  
-  # If it wasn't for the GMT/local time thing, it would be this simple.
-  #
-  # time="${time[1,12]}.${time[13,14]}"
-  #
-  # touch -t $time $1
-  
-}
-
-function zfstat {
-  # Give a zftp status report using local variables.
-  # With option -v, connect the remote host and ask it what it
-  # thinks the status is.  
-  
-  setopt localoptions unset
-  unsetopt ksharrays
-  
-  local i stat=0 opt optlist verbose
-  
-  while [[ $1 = -* ]]; do
-    if [[ $1 = - || $1 = -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $opt in
-        v) verbose=1
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  # hack:  in case the status from a subshell process hasn't been
-  # fixed yet
-  zftp type >&/dev/null
-  
-  if [[ -n $ZFTP_HOST ]]; then
-    print "Host:\t\t$ZFTP_HOST"
-    print "IP:\t\t$ZFTP_IP"
-    [[ -n $ZFTP_SYSTEM ]] && print "System type:\t$ZFTP_SYSTEM"
-    if [[ -n $ZFTP_USER ]]; then
-      print "User:\t\t$ZFTP_USER "
-      [[ -n $ZFTP_ACCOUNT ]] && print "Account:\t$AFTP_ACCOUNT"
-      print "Directory:\t$ZFTP_PWD"
-      print -n "Transfer type:\t"
-      if [[ $ZFTP_TYPE = "I" ]]; then
-        print Image
-      elif [[ $ZFTP_TYPE = "A" ]]; then
-        print Ascii
-      else
-        print Unknown
-      fi
-      print -n "Transfer mode:\t"
-      if [[ $ZFTP_MODE = "S" ]]; then
-        print Stream
-      elif [[ $ZFTP_MODE = "B" ]]; then
-        print Block
-      else
-        print Unknown
-      fi
-    else
-      print "No user logged in."
-    fi
-  else
-    print "Not connected."
-    stat=1
-  fi
-  
-  # things which may be set even if not connected:
-  [[ -n $ZFTP_REPLY ]] && print "Last reply:\t$ZFTP_REPLY"
-  print "Verbosity:\t$ZFTP_VERBOSE"
-  print -n "Preferences:\t"
-  for (( i = 1; i <= ${#ZFTP_PREFS}; i++ )); do
-    case $ZFTP_PREFS[$i] in
-      [pP]) print -n "Passive "
-  	  ;;
-      [sS]) print -n "Sendport "
-  	  ;;
-      [dD]) print -n "Dumb "
-  	  ;;
-      *) print -n "$ZFTP_PREFS[$i]???"
-    esac
-  done
-  print
-  
-  if [[ -n $ZFTP_HOST && $verbose = 1 ]]; then
-    print "Status of remote server:"
-    # make sure we print the reply
-    local ZFTP_VERBOSE=045
-    zftp quote STAT
-  fi
-  
-  return $stat
-}
-
-function zftp_chpwd {
-  # You may want to alter chpwd to call this when $ZFTP_USER is set.
-  # If so, call it with a non-zero first argument so it doesn't
-  # print the new FTP directory.
-  
-  # Cancel the filename cache for the current directory.
-  zftp_fcache=()
-  # ...and also empty the stored directory listing cache.
-  # As this function is called when we close the connection, this
-  # is the only place we need to do these two things.
-  [[ -n $zfcurdir && -f $zfcurdir ]] && rm -f $zfcurdir
-  
-  if [[ -z $ZFTP_USER ]]; then
-    # last call, after an FTP logout
-  
-    # delete the non-current cached directory
-    [[ -n $zfotherdir && -f $zfotherdir ]] && rm -f $zfotherdir
-    zfotherargs=
-  
-    # don't keep zflastdir between opens
-    zflastdir=
-  
-    # return the display to standard
-    # uncomment the following line if you have a chpwd which shows directories
-    # chpwd
-  else
-    [[ -z $zflastdir ]] && zflastdir=$ZFTP_PWD
-    local args
-    if [[ -t 1 && -t 2 ]]; then
-      local str="$ZFTP_HOST:$ZFTP_PWD"
-      [[ -z $1 ]] && print $str
-      [[ ${#str} -lt 70 ]] && str="%m: %~  $str"
-      case $TERM in
-        sun-cmd) print -n -P "\033]l$str\033\\"
-  	       ;;
-        xterm) print -n -P "\033]2;$str\a"
-  	     ;;
-      esac
-    fi
-  fi
-}
-
-function zftp_progress {
-  # Basic progress metre, showing the percent of the file transferred.
-  # You want growing bars?  You gotta write growing bars.
-  
-  # Don't show progress unless stderr is a terminal
-  [[ ! -t 2 ]] && return 0
-  
-  if [[ $ZFTP_TRANSFER = *F ]]; then
-    print 1>&2
-  elif [[ -n $ZFTP_TRANSFER ]]; then
-    if [[ -n $ZFTP_SIZE ]]; then
-      local frac="$(( ZFTP_COUNT * 100 / ZFTP_SIZE ))%"
-      print -n "\r$ZFTP_FILE ($ZFTP_SIZE bytes): $ZFTP_TRANSFER $frac" 1>&2
-    else
-      print -n "\r$ZFTP_FILE: $ZFTP_TRANSFER $ZFTP_COUNT" 1>&2
-    fi
-  fi
-}
-
-function zftype {
-  local type
-  
-  if (( $# == 0 )); then
-    type=$(zftp type)
-    if [[ $type = I ]]; then
-      print "Current type is image (binary)"
-      return 0
-    elif [[ $type = A ]]; then
-      print "Current type is ASCII"
-      return 0
-    else
-      return 1
-    fi
-  else
-    if [[ $1 == [aA]([sS][cC]([iI][iI]|)|) ]]; then
-      type=A
-    elif [[ $1 == [iI]([mM]([aA][gG][eE]|)|) ||
-      $1 == [bB]([iI][nN]([aA][rR][yY]|)|) ]]; then
-      type=I
-    else
-      print "Type not recognised:  $1" 2>&1
-      return 1
-    fi
-    zftp type $type
-  fi
-}
-
-function zfuget {
-  # Get a list of files from the server with update.
-  # In other words, only retrieve files which are newer than local
-  # ones.  This depends on the clocks being adjusted correctly
-  # (i.e. if one is fifteen minutes out, for the next fifteen minutes
-  # updates may not be correctly calculated).  However, difficult
-  # cases --- where the files are the same size, but the remote is newer,
-  # or have different sizes, but the local is newer -- are prompted for.
-  #
-  # Files are globbed on the remote host --- assuming, of course, they
-  # haven't already been globbed local, so use 'noglob' e.g. as
-  # `alias zfuget="noglob zfuget"'.
-  #
-  # Options:
-  #  -G    Glob:     turn off globbing
-  #  -v    verbose:  print more about the files listed.
-  #  -s    silent:   don't ask, just guess.  The guesses are:
-  #                - if the files have different sizes but remote is older ) grab
-  #                - if they have the same size but remote is newer        )
-  #                  which is safe if the remote files are always the right ones.
-  #   -t   time:     update the local file times to the same time as the remote.
-  #                  Currently this only works if you have the `perl' command,
-  #                  and that perl is version 5 with the standard library.
-  #                  See the function zfrtime for more gory details.
-  
-  setopt localoptions
-  unsetopt ksharrays shwordsplit
-  
-  local loc rem stat=0 locstats remstats doit tmpfile=${TMPPREFIX}zfuget$$
-  local rstat remlist verbose optlist opt bad i silent nglob time
-  
-  zfuget_print_time() {
-    local tim=$1
-    print -n "$tim[1,4]/$tim[5,6]/$tim[7,8] $tim[9,10]:$tim[11,12].$tim[13,14]"
-    print -n GMT
-  }
-  
-  zfuget_print () {
-    print -n "\nremote $rem ("
-    zfuget_print_time $remstats[2]
-    print -n ", $remstats[1] bytes)\nlocal $loc ("
-    zfuget_print_time $locstats[2]
-    print ", $locstats[1] bytes)"
-  }
-  
-  while [[ $1 = -* ]]; do
-    if [[ $1 = - || $1 = -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $optlist[$i] in
-        v) verbose=1
-  	 ;;
-        s) silent=1
-  	 ;;
-        G) nglob=1
-  	 ;;
-        t) time=1
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  [[ -n $bad ]] && return 1
-  
-  for remlist in $*; do
-    # zfcd directory hack to put the front back to ~
-    if [[ $remlist == $HOME || $remlist == $HOME/* ]]; then
-      remlist="~${remlist#$HOME}"
-    fi
-    if [[ $nglob != 1 ]]; then
-      zfrglob remlist
-    fi
-    if (( $#remlist )); then
-      for rem in $remlist; do
-        loc=${rem:t}
-        doit=y
-        remstats=()
-        if [[ -f $loc ]]; then
-  	zftp local $loc >$tmpfile
-  	locstats=($(<$tmpfile))
-  	zftp remote $rem >$tmpfile
-  	rstat=$?
-  	remstats=($(<$tmpfile))
-  	rm -f $tmpfile
-  	if [[ $rstat = 2 ]]; then
-  	  print "Server does not implement full command set required." 1>&2
-  	  return 1
-  	elif [[ $rstat = 1 ]]; then
-  	  print "File not found on server: $rem" 1>&2
-  	  stat=1
-  	  continue
-  	fi
-  	[[ $verbose = 1 ]] && zfuget_print
-  	if (( $locstats[1] != $remstats[1] )); then
-  	  # Files have different sizes
-  	  if [[ $locstats[2] > $remstats[2] && $silent != 1 ]]; then
-  	    [[ $verbose != 1 ]] && zfuget_print
-  	    print "Local file $loc more recent than remote," 1>&2
-  	    print -n "but sizes are different.  Transfer anyway [y/n]? " 1>&2
-  	    read -q doit
-  	  fi
-  	else
-  	  # Files have same size
-  	  if [[ $locstats[2] < $remstats[2] ]]; then
-  	    if [[ $silent != 1 ]]; then
-  	      [[ $verbose != 1 ]] && zfuget_print
-  	      print "Local file $loc has same size as remote," 1>&2
-  	      print -n "but local file is older. Transfer anyway [y/n]? " 1>&2
-  	      read -q doit
-  	    fi
-  	  else
-  	    # presumably same file, so don't get it.
-  	    [[ $verbose = 1 ]] && print Not transferring
-  	    doit=n
-  	  fi
-  	fi
-        else
-  	[[ $verbose = 1 ]] && print New file $loc
-        fi
-        if [[ $doit = y ]]; then
-  	if zftp get $rem >$loc; then
-  	  if [[ $time = 1 ]]; then
-  	    # if $remstats is set, it's second element is the remote time
-  	    zfrtime $loc $rem $remstats[2]
-  	  fi
-  	else
-  	  stat=$?
-  	fi
-  	
-        fi
-      done
-    fi
-  done
-  return $stat
-}
-
-function zfuput {
-  # Put a list of files from the server with update.
-  # See zfuget for details.
-  #
-  # Options:
-  #  -v    verbose:  print more about the files listed.
-  #  -s    silent:   don't ask, just guess.  The guesses are:
-  #                - if the files have different sizes but remote is older ) grab
-  #                - if they have the same size but remote is newer        )
-  #                  which is safe if the remote files are always the right ones.
-  
-  setopt localoptions
-  unsetopt ksharrays shwordsplit
-  
-  local loc rem stat=0 locstats remstats doit tmpfile=${TMPPREFIX}zfuput$$
-  local rstat verbose optlist opt bad i silent
-  
-  zfuput_print_time() {
-    local tim=$1
-    print -n "$tim[1,4]/$tim[5,6]/$tim[7,8] $tim[9,10]:$tim[11,12].$tim[13,14]"
-    print -n GMT
-  }
-  
-  zfuput_print () {
-    print -n "\nremote $rem ("
-    zfuput_print_time $remstats[2]
-    print -n ", $remstats[1] bytes)\nlocal $loc ("
-    zfuput_print_time $locstats[2]
-    print ", $locstats[1] bytes)"
-  }
-  
-  while [[ $1 = -* ]]; do
-    if [[ $1 = - || $1 = -- ]]; then
-      shift;
-      break;
-    fi
-    optlist=${1#-}
-    for (( i = 1; i <= $#optlist; i++)); do
-      opt=$optlist[$i]
-      case $optlist[$i] in
-        v) verbose=1
-  	 ;;
-        s) silent=1
-  	 ;;
-        *) print option $opt not recognised >&2
-  	 ;;
-      esac
-    done
-    shift
-  done
-  
-  [[ -n $bad ]] && return 1
-  
-  if [[ $ZFTP_VERBOSE = *5* ]]; then
-    # should we turn it off locally?
-    print "Messages with code 550 are harmless." >&2
-  fi
-  
-  for loc in $*; do
-    rem=${loc:t}
-    doit=y
-    remstats=()
-    if [[ ! -f $loc ]]; then
-      print "$loc: file not found" >&2
-      stat=1
-      continue
-    fi
-    zftp local $loc >$tmpfile
-    locstats=($(<$tmpfile))
-    zftp remote $rem >$tmpfile
-    rstat=$?
-    remstats=($(<$tmpfile))
-    rm -f $tmpfile
-    if [[ $rstat = 2 ]]; then
-      print "Server does not implement full command set required." 1>&2
-      return 1
-    elif [[ $rstat = 1 ]]; then
-      [[ $verbose = 1 ]] && print New file $loc
-    else
-      [[ $verbose = 1 ]] && zfuput_print
-      if (( $locstats[1] != $remstats[1] )); then
-        # Files have different sizes
-        if [[ $locstats[2] < $remstats[2] && $silent != 1 ]]; then
-  	[[ $verbose != 1 ]] && zfuput_print
-  	print "Remote file $rem more recent than local," 1>&2
-  	print -n "but sizes are different.  Transfer anyway [y/n]? " 1>&2
-  	read -q doit
-        fi
-      else
-        # Files have same size
-        if [[ $locstats[2] > $remstats[2] ]]; then
-  	if [[ $silent != 1 ]]; then
-  	  [[ $verbose != 1 ]] && zfuput_print
-  	  print "Remote file $rem has same size as local," 1>&2
-  	  print -n "but remote file is older. Transfer anyway [y/n]? " 1>&2
-  	  read -q doit
-  	fi
-        else
-  	# presumably same file, so don't get it.
-  	[[ $verbose = 1 ]] && print Not transferring
-  	doit=n
-        fi
-      fi
-    fi
-    if [[ $doit = y ]]; then
-      zftp put $rem <$loc || stat=$?
-    fi
-  done
-  return $stat
-}