# 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 appropriately. # # # 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 _comp_compgen_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 advice) # FIXME: short option completion should be more intuitive # - verbose mode option should be advised multiple times # - mode option should be advised only once # - format option should be advised only once # ... # # Tar files vs internal paths # =========================== # # bash's programmable completion is limited in how it handles the list of # possible completions it returns. # # Because the paths returned from within the tar file are likely not existing # paths on the file system, `-o dirnames` must be passed to the `complete` # built-in to make it treat them as such. However, then bash will append a # space when completing on directories during pathname completion to the tar # files themselves. # # It's more important to have proper completion of paths to tar files than it # is to have completion for their contents, so this sacrifice was made and # `-o filenames` is used with complete instead by default. Setting the # `$BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS` environment variable to a non-null # value *before sourcing* this completion toggles that the other way around. _comp_deprecate_var 2.12 \ COMP_TAR_INTERNAL_PATHS BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS _comp_cmd_gtar__parse_help_opt() { local opttype arg opt separator optvar opttype=long arg="$2" opt="$1" separator=" " case "$opt" in --*) ;; -\?) return ;; -*) opttype=short opt=${opt##-} separator= ;; *) echo "bash_completion: $FUNCNAME: unknown option $opt" >&2 return 1 ;; esac # Remove arguments. opt=${opt//\[*/} opt=${opt//=*/=} # Basic sanity. opt=${opt//\"*/} opt=${opt//\'*/} opt=${opt//\;*/} optvar=$opttype'_arg_'$arg eval "$optvar=\"\$$optvar$separator\"\"$opt\"" } _comp_cmd_gtar__parse_help_line() { local i local -a tmp while read -ra tmp; do for i in "${tmp[@]}"; do case "$i" in # regular options --* | -*) _comp_cmd_gtar__parse_help_opt "$i" "$2" ;; # end once there is single non-option word *) break ;; esac done done <<<"$1" } _comp_cmd_gtar__parse_help() { local str line arg while IFS= read -r 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: ^(?