Skip to content

Commit

Permalink
Merge pull request #1195 from yedayak/tar-long-options
Browse files Browse the repository at this point in the history
tar: Complete adding files to archive with long options
  • Loading branch information
akinomyoga authored Aug 23, 2024
2 parents 6f03827 + 0518a21 commit 529aff8
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 36 deletions.
98 changes: 62 additions & 36 deletions completions/tar
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,17 @@ _comp_cmd_tar__preparse_cmdline()

for i in "$@"; do
case "$i" in
--delete | --test-label)
--delete | --test-label | --catenate | --concatenate | --extract | --get | --update | --list | --append | --create)
tar_mode=${i:2:100}
tar_mode_arg=$i
break
;;
--bzip2 | --xz | --lzip | --lzma | --lzop | --zstd)
tar_compression_mode=${i:2:100}
;;
--gzip | --gunzip | --ungzip)
tar_compression_mode="gzip"
;;
--compress | --uncompress)
tar_compression_mode="compress"
;;
--*)
# skip
Expand Down Expand Up @@ -236,7 +243,7 @@ _comp_cmd_tar__file_option()
local ext="$1"

case "$tar_mode" in
c)
c | create)
# no need to advise user to re-write existing tarball
_comp_compgen_filedir -d
;;
Expand Down Expand Up @@ -391,7 +398,7 @@ _comp_cmd_tar__adjust_PREV_from_old_option()
_comp_cmd_tar__extract_like_mode()
{
local i
for i in x d t delete; do
for i in x d t delete extract get list; do
[[ $tar_mode == "$i" ]] && return 0
done
return 1
Expand Down Expand Up @@ -437,10 +444,15 @@ _comp_cmd_tar__cleanup_prev()
fi
}

_comp_cmd_tar__is_bsdtar()
{
[[ ${COMP_WORDS[0]} == ?(*/)bsdtar ]]
}

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

case "$tar_mode_arg" in
--*)
# Should never happen?
;;
?(-)*[cr]*f)
if ! _comp_cmd_tar__extract_like_mode; then
if ! _comp_cmd_tar__is_bsdtar; then
ext='@(tar|gem|spkg|cbt|xpbs)'
case ${words[1]} in
*a*) ext="$tars" ;;
*z*) ext='t?(ar.)gz' ;;
*Z*) ext='ta@(r.Z|z)' ;;
*[jy]*) ext='t@(?(ar.)bz?(2)|b2)' ;;
*J*) ext='t?(ar.)xz' ;;
esac
;;
+([^ZzJjy])f)
# Pass through using defaults above
;;
*[Zz]*f)
ext='@(@(t?(ar.)|spkg.)@(gz|Z)|taz)'
;;
*[jy]*f)
ext='@(t?(ar.)bz?(2)|spkg|tb2)'
;;
*[J]*f)
ext='@(@(tar|spkg).@(lzma|xz)|t[lx]z)'
;;
esac
fi
case $tar_mode_arg:$tar_compression_mode in
*a*:none | *:auto-compress)
ext="$tars"
;;
*z*:none | *:gzip)
ext='t?(ar.)gz'
;;
*Z*:none | *:compress)
ext='ta@(r.Z|z)'
;;
*[jy]*:none | *:bzip2)
ext='t@(?(ar.)bz?(2)|b2)'
;;
*J*:none | *:xz)
ext='t?(ar.)xz'
;;
esac
else
#TODO: lzip, lzma, lzop
case $tar_mode_arg:$tar_compression_mode in
*[Zz]*f:none | *:gzip | *:compress)
ext='@(@(t?(ar.)|spkg.)@(gz|Z)|taz)'
;;
*[jy]*f:none | *:bzip2)
ext='@(t?(ar.)bz?(2)|spkg|tb2)'
;;
*J*f:none | *:xz)
ext='@(@(tar|spkg).@(lzma|xz)|t[lx]z)'
;;
*:zstd)
ext='t?(ar.)zst'
;;
esac
fi
}

_comp_cmd_tar__gnu()
Expand All @@ -490,13 +513,15 @@ _comp_cmd_tar__gnu()
tar_mode tar_mode_arg old_opt_progress="" \
old_opt_used="" old_opt_parsed=()

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

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

# Compression mode - from long options
local tar_compression_mode=none

if [[ -v _comp_cmd_tar__debug ]]; then
set -x
local PS4='$BASH_SOURCE:$LINENO: '
Expand Down Expand Up @@ -681,12 +706,13 @@ _comp_cmd_tar__posix()
# The mode argument, e.g. -cpf or -c
local tar_mode_arg=

# Compression mode - from long options
local tar_compression_mode=none

local cur prev words cword was_split comp_args

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

tar_mode=none

# relatively compatible modes are {c,t,x}
# relatively compatible options {b,f,m,v,w}
short_arg_req="fb"
Expand Down
15 changes: 15 additions & 0 deletions test/t/test_tar.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,19 @@ def test_22(self, bash, completion):
"""Test listing escaped chars in old option."""
assert completion == "c/"

# Test long options (gnu style)
@pytest.mark.complete("tar --create --file created.tar ", cwd="tar")
def test_23(self, completion):
assert completion == "archive.tar.xz dir/ dir2/ escape.tar".split()

# Test detection of file type by extension, J is for .xz
@pytest.mark.complete("tar xJf ", cwd="tar")
def test_24(self, completion):
assert completion == "archive.tar.xz dir/ dir2/".split()

# Test compression detection of gnu style options
@pytest.mark.complete("tar --extract --xz --file ", cwd="tar")
def test_25(self, completion):
assert completion == "archive.tar.xz dir/ dir2/".split()

# TODO: "tar tf escape.tar a/b"

0 comments on commit 529aff8

Please sign in to comment.