about summary refs log tree commit diff
path: root/Completion/User/_tar
blob: 84c490f1ed7c4552773fdf6e23a6a09d3ffe7346 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#defcomp tar

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

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=("${(@f)$($words[1] $largs $tf)}")
    tar_cache_name=$tf
  fi
  _multi_parts / tar_cache_list
elif [[ "$tcmd" = *c*f* && $CURRENT -ge 4 ]] then
  _files
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