diff --git a/completions/bsdtar b/completions/bsdtar new file mode 120000 index 00000000..e1d18b02 --- /dev/null +++ b/completions/bsdtar @@ -0,0 +1 @@ +tar \ No newline at end of file diff --git a/completions/star b/completions/star new file mode 120000 index 00000000..e1d18b02 --- /dev/null +++ b/completions/star @@ -0,0 +1 @@ +tar \ No newline at end of file diff --git a/completions/tar b/completions/tar index 8d867d00..dc053a12 100644 --- a/completions/tar +++ b/completions/tar @@ -1,37 +1,455 @@ # bash completion for GNU tar -*- shell-script -*- +# +# General info +# ============ +# +# The "old" style arguments +# ------------------------- +# +# We don't "advice" the old tar option format by default for GNU tar, example: +# +# 'tar czfT /tmp/archive.tar patterns.txt' +# +# We rather advice the 'tar -czf /tmp/archive.tar -T patterns.txt' format of +# arguments. Though, if user starts the 'first' tar argument without leading +# dash, we treat the command line apropriately. +# +# +# long/short options origin +# ------------------------- +# +# For GNU tar, everything is parsed from `tar --help` output so not so much +# per-distribution work should be needed. The _parse_help does not seem to be +# good enough so parsed here directly. +# +# +# FIXME: --starting-file (-K) (should be matched for extraction only) +# FIXME: handle already used (at least short) options +# FIXME: Test-cases for make check. +# - check for no global variable pollution +# FIXME: why PS4='$BASH_SOURCE:$LINENO: ' shows sometimes negative lines? +# FIXME: timeout on tarball listing +# FIXME: cache 'tar --help' parsing results into global variables +# FIXME: at least 'tar -' should show some helping text (apart from just +# pure option advices) +# FIXME: short option completion should be more intuitive +# - verbose mode option should be adviced multiple times +# - mode option should be adviced only once +# - format option should be adviced only once +# ... -_tar() +__gtar_parse_help_opt() { - local cur prev words cword split - _init_completion -s || return + local opttype arg opt separator optvar + opttype=long + arg="$2" + opt="$1" + separator=" " - local ext regex tar untar + case "$opt" in + --*) + ;; + -\?) + return ;; + -*) + opttype=short + opt=${opt##-} + separator= + ;; + *) + echo >&2 "not an option $opt" + return 1 + ;; + esac - if [[ $cword -eq 1 ]]; then - COMPREPLY=( $( compgen -W 'c t x u r d A' -- "$cur" ) ) + # Remove arguments. + opt=${opt//\[*/} + opt=${opt//=*/=} + + # Basic sanity. + opt=${opt//\"*/} + opt=${opt//\'*/} + opt=${opt//\;*/} + + optvar=$opttype'_arg_'$arg + + eval "$optvar=\"\$$optvar$separator\"\"$opt\"" +} + + +__gtar_parse_help_line() +{ + local i + + for i in $1; do + case "$i" in + # regular options + --*|-*) + __gtar_parse_help_opt "$i" "$2" + ;; + + # end once there is single non-option word + *) + break; + esac + done +} + + +__gnu_tar_parse_help() +{ + local str line arg + while IFS= read line; do + # Ok, this requires some comment probably. The GNU help output prints + # options on lines beginning with spaces. After that, there is one + # or more options separated by ', ' separator string. We are matching + # like this then: ^(?