zsh-users
 help / color / mirror / code / Atom feed
* Another tar-completion function
@ 1998-03-23 17:09 Peter Stephenson
  1998-03-23 19:14 ` Adam Spiers
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Stephenson @ 1998-03-23 17:09 UTC (permalink / raw)
  To: Zsh users list

Here is my completion function for extracting individual files from a
tar archive.  I realise there are others around with different
argument handling, which look for a -f argument to find the archive
name, for example, whereas this simply assumes the options are all in
the first argument and the archive is the second.  This just happens
to fit my normal usage.

I'm posting it because I've improved the way files for extracting are
completed, directory by directory as with -f.  There are a couple of
limitations, noted in the comments, which are related to well-known
(and potentially removable) zsh limitations: you can't tell zsh not to
list a common prefix with completions (the directory path is omitted
if and only if zsh knows it is completing files), and you can't tell
zsh not to insert a space after a unique completion (again, a space is
not inserted if and only if zsh knows it has completed a directory).
This means that it has the annoying features that it prints overlong
completion lists and you have to backspace every time it inserts a
directory.

Anyway, this part of the script (from `Now prune the list...') could
easily be added onto any other completion function which uses
`virtual' paths.


tarnames () {
# Completion function for use with tar:
# get the names of files in the tar archive to extract.
#
# Author: Peter Stephenson <pws@ifh.de>
#
# The main claim to fame of this particular function is that it
# completes directories in the tar-file in a manner very roughly
# consistent with `compctl -f'.  There are two bugs:  first, the whole
# path prefix up to the present is listed with ^D, not just the new
# part to add; second, after a unique completion a space is always
# inserted, even if the completion ends with a slash.  These are
# currently limitations of zsh.
#
# This only works for the (fairly common) tar argument style where
# the arguments are bunched into the first argument, and the second
# argument is the name of the tarfile.  For example,
#  tar xvzf zsh-3.1.2.tar.gz ...
# You can only use compressed/gzipped files if tar is GNU tar,
# although the correct name for the tar programme will be inferred
# (maybe you need to add gtar or gnutar to the end of the compctl).
#
# This is my completion for tar; it will do the following:
#  1) Look for .tar.gz, .taz, .tar.z, .tar.Z files for argument 2 (for gnu tar)
#  2) Offer c, t, x files at the start of argument 1 )  pretty pointless,
#  3) Offer to add v, z, f flags to argument 1       )   but, well.
#  4) When extracting (x first in arg 1), look in the tar file itself
#     (arg 2) for files to complete for subsequent arguments.
# compctl -f -x 'p[2] C[-1,*z*f]' -g '*.(taz|tar.(gz|z|Z)|tgz)' \
#  - 'p[2] C[-1,*Z*f]' -g '*.(tar.Z|taz)' \
#  - 'p[1] N[-1,ctxvzZ]' -k "(v z f)" - 'p[1] s[]' -k "(c t x)" -S '' \
#  - 'p[3,-1] W[1,x*]' -K tarnames -- tar
# With newer zsh, you might want to change the -g to -/g.

local line list=tf
read -cA line
# $line[2] is the first argument:  check for possible compression args (GNU).
# (This is harmless when used with non-GNU tar, but then the file must
# be uncompressed to be able to use it with tar anyway.)
[[ $line[2] = *z* ]] && list=tfz
# $line[1] is the command name:  something like tar or gnutar.
# $line[3] is the name of the tar archive.

# cache contents for multiple completion: note tar_cache_name
# and tar_cache_list are not local.  Assumes all files with the
# same name are the same file, even if in different directories:
# you can trick it with $PWD/file on the command line.
if [[ $line[3] != $tar_cache_name ]]; then
  tar_cache_list=($($line[1] $list $line[3]))
  tar_cache_name=$line[3]
fi

# Now prune the list to include only appropriate directories.
local file new
reply=()
if [[ $1 = */* ]]; then
  local sofar=${1%/*}/
  for file in $tar_cache_list; do
    if [[ $file = $sofar* ]]; then
      new=${file#$sofar}
      if [[ $new = */* ]]; then
	new=$sofar${new%%/*}/
      else
	new=$file
      fi
      if [[ $1 != */ || $new != $1 ]]; then
	reply=($reply $new)
      fi
    fi
  done
else
  for file in $tar_cache_list; do
    if [[ $file = */* ]]; then
      new=${file%%/*}/
    else
      new=$file
    fi
    reply=($reply $new)
  done
fi
}

-- 
Peter Stephenson <pws@ifh.de>       Tel: +39 50 844536
WWW:  http://www.ifh.de/~pws/
Gruppo Teorico, Dipartimento di Fisica
Piazza Torricelli 2, 56100 Pisa, Italy


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Another tar-completion function
  1998-03-23 17:09 Another tar-completion function Peter Stephenson
@ 1998-03-23 19:14 ` Adam Spiers
  1998-03-23 20:07   ` Andrew Main
  0 siblings, 1 reply; 3+ messages in thread
From: Adam Spiers @ 1998-03-23 19:14 UTC (permalink / raw)
  To: Zsh users list

Peter Stephenson (pws@ifh.de) wrote:
> Here is my completion function for extracting individual files from a
> tar archive.  I realise there are others around with different
> argument handling, which look for a -f argument to find the archive
> name, for example, whereas this simply assumes the options are all in
> the first argument and the archive is the second.  This just happens
> to fit my normal usage.

I thought I'd post my version as there's a vague chance someone
might benefit from it.  I very much doubt it's quite as nice as
yours (I haven't got time to examine yours in close detail), but
I think it does roughly the same thing and doesn't have the
problem where you have to backspace every time it inserts a
directory.


-------- 8< -------- 8< --------

# General function for completing (symlinks to) directories, and
# files matching a glob pattern supplied as second argument.
# First argument is the prefix passed directly from -K.  I think
# it has to be done in stages using files2 and links2 because
# funny things happen if you try to do too much expansion and
# interpolation all at once.

compctl_dfl () {
	local dirs files files2 links links2
	dirs=( $1*(/N) )
	files=( $1$2(N) )
	links=( $1*(@N) )
	files2=( ${^files}" " )
	links2=( ${^links}"/" )
	reply=( ${dirs:-''} ${links2:-''} ${files:-''} )
}

# Functions called directly from compctl

compctl_targz () {
	compctl_dfl ${1:-''} "*.(tar.gz|t[ag]z|tar.Z|tz|tarZ)"
}

compctl_tar () {
	compctl_dfl ${1:-''} "*.tar"
}

# And here's the compctl:

compctl -f -g '*(-/)' -x 'p[1],s[-]' -k '(ztvf zcvf zxvf tvf cvf xvf -ztvf -zcvf -zxvf -tvf -cvf -xvf)' - 'W[1,*c*]' -f -g '*(-/)' - 'W[1,*(z*f|f*z)*] p[2]' -K compctl_targz -Q -S '' - 'W[1,*f*] p[2]' -K compctl_tar -Q -S '' -- gnutar gtar tar

-------- 8< -------- 8< --------

It could be laughably wrong but it works for me :-)

If any of the /real/ zsh gurus (I'm just a newbie) would care to
comment then please do.

Will there be a new zefram release or something soon that will
render all this hackery unnecessary?

--
Adam Spiers, Computing Officer, New College, Oxford University, UK **
violoncello/modern jazz/juggling/cycling/Perl/Linux fanatic, M$ hater
e-mail: adam.spiers@new.ox.ac.uk  WWW: http://www.new.ox.ac.uk/~adam/


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Another tar-completion function
  1998-03-23 19:14 ` Adam Spiers
@ 1998-03-23 20:07   ` Andrew Main
  0 siblings, 0 replies; 3+ messages in thread
From: Andrew Main @ 1998-03-23 20:07 UTC (permalink / raw)
  To: adam.spiers; +Cc: zsh-users

Adam Spiers wrote:
>Will there be a new zefram release or something soon that will
>render all this hackery unnecessary?

There will be a new zefram release soon -- I'm actively working on
it this week -- but it won't change the relevance of these compctls.
I don't think *anything* could make hackery unnecessary with zsh.

-zefram


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1998-03-23 20:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-03-23 17:09 Another tar-completion function Peter Stephenson
1998-03-23 19:14 ` Adam Spiers
1998-03-23 20:07   ` Andrew Main

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).