From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19910 invoked from network); 15 Dec 1999 20:30:27 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 15 Dec 1999 20:30:27 -0000 Received: (qmail 4763 invoked by alias); 15 Dec 1999 20:30:20 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 9067 Received: (qmail 4754 invoked from network); 15 Dec 1999 20:30:19 -0000 To: zsh-workers@sunsite.auc.dk Subject: PATCH: zftp functions with styles and avoiding patcomps problems In-reply-to: "Sven Wischnowsky"'s message of "Tue, 14 Dec 1999 11:13:03 +0100." <199912141013.LAA29707@beta.informatik.hu-berlin.de> Date: Wed, 15 Dec 1999 20:31:15 +0000 From: Peter Stephenson Message-Id: Sven Wischnowsky wrote: > - _patcomps and _postpatcomps are now assocs (we can do this now that > we have the (K) subscript flag) zfinit uses these for checking whether new completion for zftp is loaded (and hence old completion is not needed). I've also modified the functions to use styles instead of keys to zfconfig. The existing keys are carried over to styles in the obvious way; the context looks like e.g. :zftp:zfput:. There are two additional keys: titlebar (boolean), which determines whether zftp_chpwd alters your titlebar (defaults on if you don't set it), and chpwd, which determines whether zftp_chpwd calls chpwd after you close the connection (defaults to whether or not you have chpwd defined when zfinit runs). One more change: zfput now takes a -r option to put directories recursively. This should be very useful for uploads. Currently the -r option requires the remote machine to understand /'s as directory separators, and none of the other commands has a recursive option. Both of these could be probably be improved if necessary. --- Doc/Zsh/zftpsys.yo.zf Fri Dec 10 19:48:31 1999 +++ Doc/Zsh/zftpsys.yo Wed Dec 15 19:16:57 1999 @@ -271,10 +271,15 @@ subsect(Sending files) startitem() findex(zfput) -item(tt(zfput var(file1) ...))( +item(tt(zfput [ -r ] var(file1) ...))( Send all the var(file1) ... given separately to the remote server. If a filename contains a `tt(/)', the full filename is used locally to find the file, but only the basename is used for the remote file name. + +With the option tt(-r), if any of the var(files) are directories they are +sent recursively with all their subdirectories, including files beginning +with `tt(.)'. This requires that the remote machine understand UNIX file +semantics. as `tt(/)' is used as a directory separator. ) findex(zfuput) item(tt(zfuput [ -vs ] var(file1) ...))( @@ -486,11 +491,11 @@ This function shows the status of the transfer. It will not write anything unless the output is going to a terminal; however, if you transfer files in the background, you should turn off progress reports by hand using -`tt(zfconfig[progress]=none)'. (Background file transfers don't work on all -OSes.) Note also that if you alter it, any output em(must) be to standard -error, as standard output may be a file being received. The form of the -progess meter, or whether it is used at all, can be configured without -altering the function, as described in the next section. +`tt(zstyle ':zftp:*' progress none)'. Note also that if you alter it, any +output em(must) be to standard error, as standard output may be a file +being received. The form of the progess meter, or whether it is used at +all, can be configured without altering the function, as described in the +next section. ) findex(zffcache) item(tt(zffcache))( @@ -504,39 +509,78 @@ subsect(Configuration) cindex(zftp function system, configuration) -pindex(zfconfig) +cindex(zftp function system, styles) +cindex(styles in zftp functions) -The tt(zfinit) function defines an associative array tt(zfconfig). -Elements of this may subsequently be set to change the behaviour of the -tt(zftp) functions using standard syntax (for example, -`tt(zfconfig[progress]=percent)'. tt(zfconfig) may also contain -various other values used by the function system, so it should not be used -as the target of an assignment for a complete array. The following keys -are understood. +Various styles are available using the standard shell style mechanism, +described in +ifzman(zmanref(zshmodules))\ +ifnzman(noderef(The zutil Module)). Briefly, the +command `tt(zstyle ':zftp:*') var(style) var(value) ...'. +defines the var(style) to have value var(value) (more than one may be +given, although that is not useful in the cases described here). These +values will then be used throughout the zftp function system. For more +precise control, the first argument, which gives a context in which the +style applies, can be modified to include a particular function, as for +example `tt(:zftp:zfget:)': the style will then have the given value only +in the tt(zfget) function. Values for the same style in different contexts +may be set; the most specific function will be used, where +strings are held to be more specific than patterns, and longer patterns and +shorter patterns. Note that only the top level function name, as called by +the user, is used; calling of lower level functions is transparent to the +user. Hence modifications to the title bar in tt(zftp_chpwd) use the +contexts tt(:zftp:zfopen:), tt(:zftp:zfcd:), etc., depending where it was +called from. The following styles are understood: startitem() item(tt(progress))( Controls the way that tt(zftp_progress) reports on the progress of a transfer. If empty, unset, or `tt(none)', no progress report is made; if -`tt(bar)' (the default), a growing bar of inverse video is shown; if -`tt(percent)' (or any other string, though this may change in future), the -percentage of the file transferred is shown. The bar meter requires that -the width of the terminal be available via the tt($COLUMNS) parameter -(normally this is set automatically). If the size of the file being -transferred is not available, tt(bar) and tt(percent) meters will simply -show the number of bytes transferred so far. +`tt(bar)' a growing bar of inverse video is shown; if `tt(percent)' (or any +other string, though this may change in future), the percentage of the file +transferred is shown. The bar meter requires that the width of the +terminal be available via the tt($COLUMNS) parameter (normally this is set +automatically). If the size of the file being transferred is not +available, tt(bar) and tt(percent) meters will simply show the number of +bytes transferred so far. + +When tt(zfinit) is run, if this style is not defined for the context +tt(:zftp:*), it will be set to `bar'. ) item(tt(update))( Specifies the minimum time interval between updates of the progress meter in seconds. No update is made unless new data has been received, so the actual time interval is limited only by tt($ZFTP_TIMEOUT). + +As described for tt(progress), tt(zfinit) will force this to default to 1. ) item(tt(remote_glob))( -If set to a non-zero length, filename generation (globbing) is +If set to `1', `yes' or `true', filename generation (globbing) is performed on the remote machine instead of by zsh itself; see below. ) +item(tt(titlebar))( +If set to `1', `yes' or `true', tt(zftp_chpwd) will put the remote host and +remote directory into the titlebar of terminal emulators such as xterm or +sun-cmd that allow this. + +As described for tt(progress), tt(zfinit) will force this to default to 1. +) +item(tt(chpwd))( +If set to `1' `yes' or `true', tt(zftp_chpwd) will call the function +tt(chpwd) when a connection is closed. This is useful if the remote host +details were put into the terminal title bar by tt(zftp_chpwd) and your +usual tt(chpwd) also modifies the title bar. + +When tt(zfinit) is run, it will determine whether tt(chpwd) exists and if +so it will set the default value for the style to 1 if none exists +already. +) enditem() +Note that there is also an associative array tt(zfconfig) which contains +values used by the function system. This should not be modified or +overwritten. + subsect(Remote globbing) cindex(zftp function system, remote globbing) @@ -554,13 +598,12 @@ if retrieved, will be cached, so that subsequent globs in the same directory without an intervening tt(zfcd) are much faster. -If the key tt(remote_glob) of the tt(zfconfig) associative array (see -above) is set to a non-zero length, globbing is instead performed on the -remote host: the server is asked for a list of matching files. This is -highly dependent on how the server is implemented, though typically UNIX -servers will provide support for basic glob patterns. This may in some -cases be faster, as it avoids retrieving the entire list of directory -contents. +If the tt(remote_glob) style (see above) is set, globbing is instead +performed on the remote host: the server is asked for a list of matching +files. This is highly dependent on how the server is implemented, though +typically UNIX servers will provide support for basic glob patterns. This +may in some cases be faster, as it avoids retrieving the entire list of +directory contents. subsect(Automatic and temporary reopening) cindex(zftp function system, automatic reopening) --- Functions/Zftp/zfanon.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfanon Wed Dec 15 18:31:05 1999 @@ -2,6 +2,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfanon: local opt opt_1 dir while getopts :1 opt; do --- Functions/Zftp/zfcd.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfcd Wed Dec 15 18:31:05 1999 @@ -20,6 +20,7 @@ # work just as long as the directory structures under the home match. emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfcd: if [[ $1 = /* ]]; then zfautocheck -dn || return 1 --- Functions/Zftp/zfcget.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfcget Wed Dec 15 18:31:05 1999 @@ -12,6 +12,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfcget: local loc rem stat=0 opt opt_G opt_t remlist locst remst local tmpfile=${TMPPREFIX}zfcget$$ rstat tsize --- Functions/Zftp/zfclose.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfclose Wed Dec 15 18:31:05 1999 @@ -1,3 +1,4 @@ # function zfclose { +[[ $curcontext = :zf*: ]] || local curcontext=:zfclose: zftp close # } --- Functions/Zftp/zfcput.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfcput Wed Dec 15 18:31:06 1999 @@ -12,6 +12,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfcput: local loc rem stat=0 locst remst offs tailtype local tmpfile=${TMPPREFIX}zfcget$$ rstat --- Functions/Zftp/zfdir.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfdir Wed Dec 15 18:31:06 1999 @@ -22,6 +22,7 @@ emulate -L zsh setopt extendedglob +[[ $curcontext = :zf*: ]] || local curcontext=:zfdir: local file opt optlist redir i newargs force local curdir=$zfconfig[curdir_$ZFTP_SESSION] local otherdir=$zfconfig[otherdir_$ZFTP_SESSION] --- Functions/Zftp/zfgcp.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfgcp Wed Dec 15 18:31:06 1999 @@ -16,6 +16,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfgcp: local opt remlist rem loc opt_G opt_t integer stat do_close --- Functions/Zftp/zfget.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfget Wed Dec 15 18:31:06 1999 @@ -19,6 +19,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfget: local loc rem opt remlist opt_G opt_t opt_c integer stat do_close --- Functions/Zftp/zfgoto.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfgoto Wed Dec 15 18:31:06 1999 @@ -8,6 +8,7 @@ emulate -L zsh setopt extendedglob +[[ $curcontext = :zf*: ]] || local curcontext=:zfgoto: # Set ZFTP_BMFILE if not already set. This should agree with # the corresponding line in zfmark. --- Functions/Zftp/zfhere.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfhere Wed Dec 15 18:31:06 1999 @@ -1,5 +1,6 @@ # function zfhere { # Change to the directory corresponding to $PWD on the server. # See zfcd for how this works. +[[ $curcontext = :zf*: ]] || local curcontext=:zfhere: zfcd $PWD # } --- Functions/Zftp/zfinit.zf Wed Dec 15 18:36:29 1999 +++ Functions/Zftp/zfinit Wed Dec 15 19:10:43 1999 @@ -1,10 +1,19 @@ emulate -L zsh -[[ $1 = -n ]] || zmodload -e zftp || zmodload -ia zftp +[[ $1 = -n ]] || zmodload -e zftp || zmodload -ia zftp || return 1 + +if zmodload -i zutil; then + local arr + # Set defaults for styles if none set. + zstyle -g arr ':zftp:*' progress || zstyle ':zftp:*' progress bar + zstyle -g arr ':zftp:*' update || zstyle ':zftp:*' update 1 + zstyle -g arr ':zftp:*' titlebar || zstyle ':zftp:*' titlebar true + if functions chpwd >&/dev/null && ! zstyle -g arr ':zftp:*' chpwd; then + zstyle ':zftp:*' chpwd true + fi -if [[ ${+zfconfig} = 0 ]]; then typeset -gA zfconfig - zfconfig=(progress bar update 1 lastsession default) + zfconfig=(lastsession default) fi alias zfcd='noglob zfcd' @@ -22,7 +31,7 @@ # zftp completions: only use these if new-style completion is not # active. # -if [[ ${#_patcomps} -eq 0 || ${_patcomps[(i)zf*]} -gt ${#_patcomps} ]]; then +if [[ ${#_patcomps} -eq 0 || -z ${_patcomps[(i)zf*]} ]]; then # only way of getting that noglob out of the way: this is unnecessary with # widget-based completion setopt completealiases @@ -55,3 +64,5 @@ compctl -s '$(zftp session)' -S : -x 'C[0,*:*]' \ -K zftransfer_match -- zftransfer fi + +return 0 --- Functions/Zftp/zfls.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfls Wed Dec 15 18:31:06 1999 @@ -1,6 +1,7 @@ # function zfls { emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfls: # directory hack, see zfcd if [[ $1 = $HOME || $1 = $HOME/* ]]; then --- Functions/Zftp/zfmark.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfmark Wed Dec 15 18:31:06 1999 @@ -7,6 +7,7 @@ emulate -L zsh setopt extendedglob +[[ $curcontext = :zf*: ]] || local curcontext=:zfmark: # Set ZFTP_BMFILE if not already set. This should agree with # the corresponding line in zfgoto. --- Functions/Zftp/zfopen.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfopen Wed Dec 15 18:31:06 1999 @@ -7,6 +7,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfopen: local opt dir opt_1 setparams while getopts :1 opt; do --- Functions/Zftp/zfparams.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfparams Wed Dec 15 18:31:06 1999 @@ -1,6 +1,7 @@ # function zfparams { emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfparams: if [[ $# -eq 1 && $1 = - ]]; then # Delete existing parameter set. --- Functions/Zftp/zfpcp.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfpcp Wed Dec 15 18:31:06 1999 @@ -14,6 +14,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfpcp: local rem loc integer stat do_close --- Functions/Zftp/zfput.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfput Wed Dec 15 18:31:06 1999 @@ -3,19 +3,64 @@ # off any directory parts to get the remote filename (i.e. always # goes into current remote directory). Use zfpcp to specify new # file name or new directory at remote end. +# +# -r means put recursively: any directories encountered will have +# all their contents to arbitrary depth transferred. Note that +# this creates the required directories. Any files in subdirectories +# whose names begin with a `.' will also be included. emulate -L zsh -local loc rem -integer stat do_close +[[ $curcontext = :zf*: ]] || local curcontext=:zfput: +local opt opt_r +integer stat do_close abort + +while getopts :r opt; do + [[ $opt = '?' ]] && print "zfget: bad option: -$OPTARG" && return 1 + eval "opt_$opt=1" +done +(( OPTIND > 1 )) && shift $(( OPTIND - 1 )) zfautocheck -for loc in $*; do - rem=${loc:t} - zftp put $rem <$loc - [[ $? == 0 ]] || stat=$? -done +zfput_sub() { + local subdirs loc rem + integer stat + subdirs=() + + for loc in $*; do + if [[ -n $opt_r ]]; then + if [[ -d $loc ]]; then + subdirs=($subdirs $loc) + continue + else + rem=$loc + fi + else + rem=${loc:t} + fi + + zftp put $rem <$loc + (( $? )) && stat=$? + if ! zftp test; then + abort=1 + (( stat )) || stat=1 + break; + fi + done + + while (( $#subdirs && ! abort )); do + zftp mkdir ${subdirs[1]} + zfput_sub ${subdirs[1]}/*(ND) + (( $? )) && stat=$? + shift subdirs + done + + return $stat +} + +zfput_sub $* +stat=$? (( $do_close )) && zfclose --- Functions/Zftp/zfsession.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfsession Wed Dec 15 18:31:06 1999 @@ -3,6 +3,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfsession: local opt opt_l opt_v opt_o opt_d hadopts while getopts ":lovd" opt; do --- Functions/Zftp/zfstat.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfstat Wed Dec 15 18:31:06 1999 @@ -6,6 +6,7 @@ setopt localoptions unset unsetopt ksharrays +[[ $curcontext = :zf*: ]] || local curcontext=:zfstat: local i stat=0 opt opt_v while getopts :v opt; do --- Functions/Zftp/zftp_chpwd.zf Fri Dec 10 19:48:30 1999 +++ Functions/Zftp/zftp_chpwd Wed Dec 15 18:31:06 1999 @@ -22,14 +22,13 @@ zfconfig[lastdir_$ZFTP_SESSION]= # return the display to standard - # uncomment the following line if you have a chpwd which shows directories - chpwd + zstyle -t ":zftp$curcontext" chpwd && chpwd else [[ -n $ZFTP_PWD ]] && zfconfig[lastdir_$ZFTP_SESSION]=$ZFTP_PWD zfconfig[lastloc_$ZFTP_SESSION]="$ZFTP_HOST:$ZFTP_PWD" zfconfig[lastuser_$ZFTP_SESSION]="$ZFTP_USER" local args - if [[ -t 1 && -t 2 ]]; then + if [[ -t 1 && -t 2 ]] && zstyle -t ":zftp$curcontext" titlebar; then local str=$zfconfig[lastloc_$ZFTP_SESSION] [[ ${#str} -lt 70 ]] && str="%m: %~ $str" case $TERM in --- Functions/Zftp/zftp_progress.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zftp_progress Wed Dec 15 18:45:56 1999 @@ -1,7 +1,7 @@ # function zftp_progress { # Basic progress metre, showing the percent of the file transferred. # You want growing bars? You gottem. -# zfconfig keys: +# styles used (context :zftp:zfparent_function:): # progress # empty or `none' no progress meter # `bar' use a growing bar of inverse video @@ -11,16 +11,17 @@ # update # Minimum time in seconds between updates of the progress display. -# Don't show progress unless stderr is a terminal -[[ ! -t 2 || ${zfconfig[progress]} = (|none) ]] && return 0 +local style update=1 -# Tunable parameters. -# How many seconds to wait before printing an updated progress report. -integer update=${zfconfig[update]:-1} # What style: either bar for growing bars, or anything else for simple # percentage. For bar we need to have the terminal width in COLUMNS, # which is often set automatically, but you never know. -local style=${zfconfig[progress]} +zstyle -s ":zftp$curcontext" progress style +# How many seconds to wait before printing an updated progress report. +zstyle -s ":zftp$curcontext" update update + +# Don't show progress unless stderr is a terminal +[[ ! -t 2 || $style = (|none) ]] && return 0 if [[ -n $ZFTP_TRANSFER ]]; then # avoid a `parameter unset' message --- Functions/Zftp/zftransfer.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zftransfer Wed Dec 15 18:46:09 1999 @@ -4,6 +4,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zftransfer: local sess1 sess2 file1 file2 oldsess=${ZFTP_SESSION} if [[ $# -ne 2 ]]; then @@ -39,7 +40,9 @@ # the size from the pipe --- and if it does, it's probably wrong. # To avoid that, try to get the size and set it for the progress to # see. -if [[ $zfconfig[progress] != none ]]; then +local style +zstyle -s ':zftp:zftransfer:' progress style +if [[ -n $style && $style != none ]]; then local ZFTP_TSIZE array tmpfile=${TMPPREFIX}zft$$ zftp remote $file1 >$tmpfile 2>/dev/null array=($(<$tmpfile)) @@ -49,7 +52,7 @@ # We do the RHS of the pipeline in a subshell, too, so that # the LHS can get SIGPIPE when it exits. -{ zfconfig[progress]=none +{ zstyle '*' progress none zftp get $file1 } | ( zftp session $sess2 zfautocheck && zftp put $file2 ) --- Functions/Zftp/zftype.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zftype Wed Dec 15 18:31:06 1999 @@ -1,5 +1,6 @@ # function zftype { local type zftmp=${TMPPREFIX}zftype$$ +[[ $curcontext = :zf*: ]] || local curcontext=:zftype: zfautocheck -d --- Functions/Zftp/zfuget.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfuget Wed Dec 15 18:31:06 1999 @@ -25,6 +25,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfuget: local loc rem locstats remstats doit tmpfile=${TMPPREFIX}zfuget$$ local rstat remlist opt opt_v opt_s opt_G opt_t integer stat do_close --- Functions/Zftp/zfuput.zf Sun Nov 28 17:42:27 1999 +++ Functions/Zftp/zfuput Wed Dec 15 18:31:06 1999 @@ -11,6 +11,7 @@ emulate -L zsh +[[ $curcontext = :zf*: ]] || local curcontext=:zfuput: local loc rem locstats remstats doit tmpfile=${TMPPREFIX}zfuput$$ local rstat opt opt_v opt_s integer stat do_close -- Peter Stephenson