Skip to content

Commit 529aff8

Browse files
authored
Merge pull request #1195 from yedayak/tar-long-options
tar: Complete adding files to archive with long options
2 parents 6f03827 + 0518a21 commit 529aff8

File tree

2 files changed

+77
-36
lines changed

2 files changed

+77
-36
lines changed

completions/tar

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,17 @@ _comp_cmd_tar__preparse_cmdline()
203203

204204
for i in "$@"; do
205205
case "$i" in
206-
--delete | --test-label)
206+
--delete | --test-label | --catenate | --concatenate | --extract | --get | --update | --list | --append | --create)
207207
tar_mode=${i:2:100}
208-
tar_mode_arg=$i
209-
break
208+
;;
209+
--bzip2 | --xz | --lzip | --lzma | --lzop | --zstd)
210+
tar_compression_mode=${i:2:100}
211+
;;
212+
--gzip | --gunzip | --ungzip)
213+
tar_compression_mode="gzip"
214+
;;
215+
--compress | --uncompress)
216+
tar_compression_mode="compress"
210217
;;
211218
--*)
212219
# skip
@@ -236,7 +243,7 @@ _comp_cmd_tar__file_option()
236243
local ext="$1"
237244

238245
case "$tar_mode" in
239-
c)
246+
c | create)
240247
# no need to advise user to re-write existing tarball
241248
_comp_compgen_filedir -d
242249
;;
@@ -391,7 +398,7 @@ _comp_cmd_tar__adjust_PREV_from_old_option()
391398
_comp_cmd_tar__extract_like_mode()
392399
{
393400
local i
394-
for i in x d t delete; do
401+
for i in x d t delete extract get list; do
395402
[[ $tar_mode == "$i" ]] && return 0
396403
done
397404
return 1
@@ -437,10 +444,15 @@ _comp_cmd_tar__cleanup_prev()
437444
fi
438445
}
439446

447+
_comp_cmd_tar__is_bsdtar()
448+
{
449+
[[ ${COMP_WORDS[0]} == ?(*/)bsdtar ]]
450+
}
451+
440452
_comp_cmd_tar__detect_ext()
441453
{
442454
local tars='@(@(tar|spkg)?(.@(Z|[bgx]z|bz2|lz?(ma|o)|zst))|t@([abglx]z|b?(z)2|zst)|cbt|gem|xbps)'
443-
if [[ ${COMP_WORDS[0]} == ?(*/)bsdtar ]]; then
455+
if _comp_cmd_tar__is_bsdtar; then
444456
# https://github.com/libarchive/libarchive/wiki/LibarchiveFormats
445457
tars=${tars/%\)/|pax|cpio|iso|zip|@(j|x)ar|mtree|a|7z|warc}
446458
if _comp_cmd_tar__extract_like_mode; then
@@ -453,33 +465,44 @@ _comp_cmd_tar__detect_ext()
453465
fi
454466
ext="$tars"
455467

456-
case "$tar_mode_arg" in
457-
--*)
458-
# Should never happen?
459-
;;
460-
?(-)*[cr]*f)
468+
if ! _comp_cmd_tar__extract_like_mode; then
469+
if ! _comp_cmd_tar__is_bsdtar; then
461470
ext='@(tar|gem|spkg|cbt|xpbs)'
462-
case ${words[1]} in
463-
*a*) ext="$tars" ;;
464-
*z*) ext='t?(ar.)gz' ;;
465-
*Z*) ext='ta@(r.Z|z)' ;;
466-
*[jy]*) ext='t@(?(ar.)bz?(2)|b2)' ;;
467-
*J*) ext='t?(ar.)xz' ;;
468-
esac
469-
;;
470-
+([^ZzJjy])f)
471-
# Pass through using defaults above
472-
;;
473-
*[Zz]*f)
474-
ext='@(@(t?(ar.)|spkg.)@(gz|Z)|taz)'
475-
;;
476-
*[jy]*f)
477-
ext='@(t?(ar.)bz?(2)|spkg|tb2)'
478-
;;
479-
*[J]*f)
480-
ext='@(@(tar|spkg).@(lzma|xz)|t[lx]z)'
481-
;;
482-
esac
471+
fi
472+
case $tar_mode_arg:$tar_compression_mode in
473+
*a*:none | *:auto-compress)
474+
ext="$tars"
475+
;;
476+
*z*:none | *:gzip)
477+
ext='t?(ar.)gz'
478+
;;
479+
*Z*:none | *:compress)
480+
ext='ta@(r.Z|z)'
481+
;;
482+
*[jy]*:none | *:bzip2)
483+
ext='t@(?(ar.)bz?(2)|b2)'
484+
;;
485+
*J*:none | *:xz)
486+
ext='t?(ar.)xz'
487+
;;
488+
esac
489+
else
490+
#TODO: lzip, lzma, lzop
491+
case $tar_mode_arg:$tar_compression_mode in
492+
*[Zz]*f:none | *:gzip | *:compress)
493+
ext='@(@(t?(ar.)|spkg.)@(gz|Z)|taz)'
494+
;;
495+
*[jy]*f:none | *:bzip2)
496+
ext='@(t?(ar.)bz?(2)|spkg|tb2)'
497+
;;
498+
*J*f:none | *:xz)
499+
ext='@(@(tar|spkg).@(lzma|xz)|t[lx]z)'
500+
;;
501+
*:zstd)
502+
ext='t?(ar.)zst'
503+
;;
504+
esac
505+
fi
483506
}
484507

485508
_comp_cmd_tar__gnu()
@@ -490,13 +513,15 @@ _comp_cmd_tar__gnu()
490513
tar_mode tar_mode_arg old_opt_progress="" \
491514
old_opt_used="" old_opt_parsed=()
492515

493-
# Main mode, e.g. -x or -c (extract/creation)
516+
# Main mode, e.g. "x" or "c" or the long forms "extract" or "create"
494517
local tar_mode=none
495518

496519
# The mode argument, e.g. -cpf or -c
497-
# FIXME: handle long options
498520
local tar_mode_arg=
499521

522+
# Compression mode - from long options
523+
local tar_compression_mode=none
524+
500525
if [[ -v _comp_cmd_tar__debug ]]; then
501526
set -x
502527
local PS4='$BASH_SOURCE:$LINENO: '
@@ -681,12 +706,13 @@ _comp_cmd_tar__posix()
681706
# The mode argument, e.g. -cpf or -c
682707
local tar_mode_arg=
683708

709+
# Compression mode - from long options
710+
local tar_compression_mode=none
711+
684712
local cur prev words cword was_split comp_args
685713

686714
_comp_initialize -s -- "$@" || return
687715

688-
tar_mode=none
689-
690716
# relatively compatible modes are {c,t,x}
691717
# relatively compatible options {b,f,m,v,w}
692718
short_arg_req="fb"

test/t/test_tar.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,19 @@ def test_22(self, bash, completion):
117117
"""Test listing escaped chars in old option."""
118118
assert completion == "c/"
119119

120+
# Test long options (gnu style)
121+
@pytest.mark.complete("tar --create --file created.tar ", cwd="tar")
122+
def test_23(self, completion):
123+
assert completion == "archive.tar.xz dir/ dir2/ escape.tar".split()
124+
125+
# Test detection of file type by extension, J is for .xz
126+
@pytest.mark.complete("tar xJf ", cwd="tar")
127+
def test_24(self, completion):
128+
assert completion == "archive.tar.xz dir/ dir2/".split()
129+
130+
# Test compression detection of gnu style options
131+
@pytest.mark.complete("tar --extract --xz --file ", cwd="tar")
132+
def test_25(self, completion):
133+
assert completion == "archive.tar.xz dir/ dir2/".split()
134+
120135
# TODO: "tar tf escape.tar a/b"

0 commit comments

Comments
 (0)