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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
#compdef tar gtar star bsdtar
# Tar completion. Features:
# - Tries to collect tar commands from second position, single letter
# option, and long options.
# - `tar' can be called anything, will use the correct name
# - Uses the function `_tar_archive' to complete archive files.
# - Tries to find out if compressed archives should be used.
# - 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)
# - Things like --directory=... are also completed correctly.
local _tar_cmd tf tmp tmpb del index
# First we collect in `_tar_cmd' single letter options describing what
# should be done with the archive and if it is compressed. This
# collected from options arguments that start with only one hyphen,
# from some of the possible long options, and from the second word if
# that does not start with a hyphen.
if _pick_variant gnu=GNU libarchive=libarchive unix --version; then
case "$($service --version)" in
("tar (GNU tar) "(#b)([0-9.-]##)*)
autoload -z is-at-least
is-at-least 1.14.91 "$match[1]" || _cmd_variant[$service]="gnu-old"
;;
esac
fi
tmp=("${(@M)words:#-[^-]*}")
_tar_cmd="${(j::)tmp#-}"
(( $words[(I)--(un|)gzip] )) && _tar_cmd="z$_tar_cmd"
(( $words[(I)--(un|)compress] )) && _tar_cmd="Z$_tar_cmd"
(( $words[(I)--bzip2] )) && _tar_cmd="j$_tar_cmd"
(( $words[(I)--xz] )) && _tar_cmd="J$_tar_cmd"
(( $words[(I)--list] )) && _tar_cmd="t$_tar_cmd"
(( $words[(I)--(extract|get)] )) && _tar_cmd="x$_tar_cmd"
(( $words[(I)--create] )) && _tar_cmd="c$_tar_cmd"
# Other ways of finding out what we're doing: first
# look in the first argument if it's not an option
if [[ "$words[2]" = *[txcdruA]*~-* ]]; then
_tar_cmd="$words[2]$_tar_cmd"
elif [[ $_tar_cmd != *[txcdruA]* && CURRENT -gt 2 ]]; then
# look for more obscure long options: these aren't all handled.
(( $words[(I)--(diff|compare)] )) && _tar_cmd="d$_tar_cmd"
(( $words[(I)--append] )) && _tar_cmd="r$_tar_cmd"
(( $words[(I)--update] )) && _tar_cmd="u$_tar_cmd"
(( $words[(I)--(con|)catenate] )) && _tar_cmd="A$_tar_cmd"
(( $words[(I)--delete] )) && del=1
fi
# Next, we try to find the archive name and store it in `tf'. The name
# is searched after a `--file=' long option, in the third word if the
# second one didn't start with a hyphen but contained a `f', and after
# an option argument starting with only one hyphen and containing a `f'.
# unless that option argument also contains a `C'.
tmp="$words[(I)--file=*]"
tmpb="$words[(I)-*Cf*~--*]"
if (( tmp )); then
tf=${~words[tmp][8,-1]}
_tar_cmd="f$_tar_cmd"
elif [[ "$words[2]" != -* && "$words[2]" = *f* ]]; then
tf=${~words[3]}
_tar_cmd="f$_tar_cmd"
elif (( tmpb )); then
tf=${~words[tmpb+2]}
wdir=${~words[tmpb+1]}
_tar_cmd="Cf$_tar_cmd"
else
tmp="${words[(I)-*f*~--*]}"
if (( tmp )); then
tf=${~words[tmp+1]}
_tar_cmd="f$_tar_cmd"
fi
fi 2>/dev/null
# See if we should use a path prefix. We have to use eval as the dir can
# be any unevaluated thing which appears on the command line, including a
# parameter.
# This isn't used right now.
tmp=${words[(r)--dir[a-z]#=*]}
if [[ -n $tmp ]]; then
eval "wdir=(${tmp#*=})"
fi
# Now we complete...
if [[ "$PREFIX" = --* ]]; then
# ...long options after `--'.
_arguments -- -l '--owner=*:user:_users' \
'--group=*:group:_groups' \
'--atime-preserve*::method:(replace system)' \
'--*-script=NAME:script file:_files' \
'--format=*:format:(gnu oldgnu pax posix ustar v7)' \
'--quoting-style=*:quoting style:(literal shell shell-always c c-maybe escape locale clocale)' \
'--totals*=SIGNAL*::signal:(HUP QUIT INT USR1 USR2)' \
'*=(PROG|COMMAND)*:program:_command_names -e' \
'*=ARCHIVE*:archive: _tar_archive' \
'*=FILE*:file:_files' \
'*=DIR*:directory:_files -/' \
'*=CONTROL*::version control:(t numbered nil existing never simple)'
elif [[ ( CURRENT -gt 2 && "$words[CURRENT-1]" = -[^C]#f* &&
"$words[CURRENT-1]" != --* ) ||
( CURRENT -eq 3 && "$words[2]" = [^C]#f* && "$words[2]" != -* ) ||
( CURRENT -gt 2 && "$words[CURRENT-2]" = -*C*f* &&
"$words[CURRENT-2]" != --* && "$words[CURRENT-1]" != --* ) ||
( CURRENT -eq 4 && "$words[2]" = *C*f* && "$words[2]" != -* ) ]]; then
# ...archive files if we think they are wanted here.
_tar_archive
elif [[ ( CURRENT -gt 2 && "$words[CURRENT-1]" = -[^f]#C*) ||
( CURRENT -eq 3 && "$words[2]" = [^f]#C* ) ]]; then
# a directory for -C
_directories
elif [[ ( "$_tar_cmd" = *[xt]* || -n $del ) && -n "$tf" ]]; then
# ...and files from the archive if we found an archive name and tar
# commands. 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. We skip this test if the alleged archive is not a file.
local largs=-tf expl
if [[ $_tar_cmd = *z* ]]; then
largs=-tzf
elif [[ $_tar_cmd = *j* ]]; then
largs=-tjf
elif [[ $_tar_cmd = *y* ]]; then
largs=-tyf
elif [[ $_tar_cmd = *Z* ]]; then
largs=-tZf
elif [[ $_tar_cmd = *I* ]]; then
largs=-tIf
elif [[ $_tar_cmd = *J* ]]; then
largs=-tJf
else
# Some random compression program
tmp="${words[(r)--use-comp*]}"
[[ -n $tmp ]] && largs=($tmp -tf)
fi
if [[ $tf != $_tar_cache_name && -f $tf ]]; then
_tar_cache_list=("${(@f)$($words[1] $largs $tf)}")
_tar_cache_name=$tf
fi
_wanted files expl 'file from archive' _multi_parts / _tar_cache_list
elif (( CURRENT == 2 )); then
# ignore leading - since we complete option letters anyway
compset -P -
_values -s '' 'tar function' \
'(c t u x)A[append to an archive]' \
'(A t u x)c[create a new archive]' \
'(A c u x)t[list archive contents]' \
'(A c t x)u[update archive]' \
'(A c t u)x[extract files from an archive]' \
'v[verbose output]' \
'f[specify archive file or device]'
else
if ! (( index=$words[(I)-*C*] )); then
if [[ $words[2] = [^f]#C* ]]; then
index=1
elif [[ $words[2] = *f*C* ]]; then
index=2
fi
fi
if (( index )); then
index=${~${(Q)words[index+1]}}
[[ $index = (.|..|)/* ]] || index=~+/$index
_files -W $index
else
_files
fi
fi
|