From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18600 invoked from network); 2 Mar 1999 10:52:06 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 2 Mar 1999 10:52:06 -0000 Received: (qmail 24063 invoked by alias); 2 Mar 1999 10:51:35 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 5602 Received: (qmail 24012 invoked from network); 2 Mar 1999 10:51:28 -0000 Message-Id: <9903021035.AA58126@ibmth.df.unipi.it> To: zsh-workers@sunsite.auc.dk (Zsh hackers list) Subject: PATCH: 3.1.5-pws-10: _tar Date: Tue, 02 Mar 1999 11:35:01 +0100 From: Peter Stephenson Here's an enhancement to the completion for tar; a lot of it is just comment, which doesn't clog your shell. Its main feature is that completing files for extraction is now pretty close to ordinary file handling. It also handles GNU long arguments, but this is a little erratic in combination with other arguments, since it always assumes the basic commands are in second position and the archive name in third. This could do with some more work. --- Completion/User/_tar.bk Mon Mar 1 13:50:36 1999 +++ Completion/User/_tar Tue Mar 2 11:30:16 1999 @@ -1,11 +1,94 @@ #defcomp tar -local fl="$words[2]" tf="$words[3]" +# Tar completion. Features: +# - Assumes tar commands are in second position, tar archive is in third +# e.g. tar xvzf zsh-3.0.5.tar.gz ... +# Could search better. Send me the patch. +# - `tar' can be called anything, will use the correct name +# - Preferentially completes *.tar and *.TAR files in third position +# - unless z or Z appears in the commands, in which case prefer *.tar.gz +# and similar (GNU tar). +# - From fourth position on, if command is x or t, completes files inside +# archive. This is supposed to look pretty much as if the files are +# in an ordinary directory hierarchy. Handles extraction from compressed +# archives (GNU tar). +# - Anywhere -- appears, gets a list of long options to complete from +# tar itself (GNU tar); this needs perl. If you have GNU tar but not +# perl: your system manager is weird. +# - Things like --directory=... are also completed correctly. -if [[ ( "$fl" = *t*f* || "$fl" = *x*f* ) && -position 4 100000 ]]; then - compgen -k "( $(tar tf $tf) )" -elif [[ "$fl" = *c*f* && -position 4 100000 ]]; then +emulate -LR zsh +setopt extendedglob + +local nm=$NMATCHES tcmd="$words[2]" tf="$words[3]" + +if [[ $PREFIX = *=* ]]; then + # For GNU tar arguments like --directory= + IPREFIX=${PREFIX%%\=*}= + PREFIX=${PREFIX#*=} + if [[ $IPREFIX = --directory* ]]; then + _path_files -/ + else + _files + fi +elif [[ $PREFIX = --* ]]; then + # gnu tar, generate completions from --help + # ones followed by = get that as a suffix + local -a ownlist eqlist + local comp + $words[1] --help | + perl -ne 'while (/--[^[\s,='\'']+=?/g) { print "$&\n"; }' | + while read comp; do + if [[ $comp = *= ]]; then + eqlist[$#eqlist+1]=${comp%=} + else + ownlist[$#ownlist+1]=$comp + fi + done + compgen -S '=' -k eqlist + compgen -k ownlist +elif [[ "$tcmd" = *[tx]*f* && $CURRENT -ge 4 ]] then + # Listing or extracting a particular file. We run `tar t...' + # on the file, keeping the list of filenames cached, plus the + # name of the tarfile so we know if it changes. + local largs=-tf + [[ $words[2] = *z* ]] && largs=-tzf + [[ $words[2] = *Z* ]] && largs=-tZf + if [[ $tf != $tar_cache_name ]]; then + tar_cache_list=($($words[1] $largs $tf)) + tar_cache_name=$tf + fi + + local pref matched matchdir + # Now generate the matches. First, treat a directory prefix + # separately, just like for real files. + [[ $PREFIX = */* ]] && pref="${PREFIX%/*}/" + if [[ $SUFFIX != */* ]]; then + # From inner to outer: + # Filter out anything which does not match what's on the line, + # remembering no / should come between $PREFIX and $SUFFIX; + # remove $pref from the remainder; + # filter out anything with extra directories beyond what we need. + matched=( + ${${${tar_cache_list##^${~PREFIX}[^/]#${~SUFFIX}*}#$pref}##*/*?} + ) + # We need to separate matches with a slash at the end, where + # something else could be completed. Instead of making the slash + # a suffix, since that wouldn't appear in the listing, we leave + # it but add matches with an empty suffix. + matchdir=(${matched##^*/}) + (( $#matchdir )) && compadd -p "$pref" -S '' $matchdir + matched=(${matched##*/}) + (( $#matched )) && compadd -p "$pref" $matched + else + # Completing in the middle: don't trim trailing suffixes. + matched=(${tar_cache_list##^${~PREFIX}*${~SUFFIX}#$pref}) + (( $#matched )) && compadd -p "$pref" $matched + fi +elif [[ "$tcmd" = *c*f* && $CURRENT -ge 4 ]] then _files -elif [[ "$words[CURRENT-1]" = *f* && CURRENT -eq 3 ]]; then +elif [[ "$tcmd" = *[zZ]*f* && $CURRENT -eq 3 ]] then + _files -g '*.((tar|TAR).(gz|Z)|.tgz)' +elif [[ "$tcmd" = *f* && $CURRENT -eq 3 ]] then _files -g '*.(tar|TAR)' fi -- Peter Stephenson Tel: +39 050 844536 WWW: http://www.ifh.de/~pws/ Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy