diff --git a/completions/tar b/completions/tar index 26df2efcbd4..e4423b154bb 100644 --- a/completions/tar +++ b/completions/tar @@ -59,7 +59,7 @@ _comp_deprecate_var 2.12 \ COMP_TAR_INTERNAL_PATHS BASH_COMPLETION_CMD_TAR_INTERNAL_PATHS -_comp_cmd_gtar__parse_help_opt() +_comp_cmd_gtar__init_parse_help_opt() { local opttype arg opt separator optvar opttype=long @@ -98,7 +98,7 @@ _comp_cmd_gtar__parse_help_opt() eval "$optvar=\"\$$optvar$separator\"\"$opt\"" } -_comp_cmd_gtar__parse_help_line() +_comp_cmd_gtar__init_parse_help_line() { local i local -a tmp @@ -107,7 +107,7 @@ _comp_cmd_gtar__parse_help_line() case "$i" in # regular options --* | -*) - _comp_cmd_gtar__parse_help_opt "$i" "$2" + _comp_cmd_gtar__init_parse_help_opt "$i" "$2" ;; # end once there is single non-option word @@ -119,8 +119,21 @@ _comp_cmd_gtar__parse_help_line() done <<<"$1" } -_comp_cmd_gtar__parse_help() +# Parse the output of "tar --help" with GNU tar and store the parse results +# in a global variable. +# +# @var[out] _comp_cmd_gtar__saved_opts +# The parse results are stored in this global variable in a form that can +# be evaluated by the builtin "eval". +_comp_cmd_gtar__init_parse_help() { + local long_arg_none="" + local long_arg_opt="" + local long_arg_req="" + local short_arg_none="" + local short_arg_opt="" + local short_arg_req="" + local str line arg while IFS= read -r line; do # Ok, this requires some comment probably. The GNU help output prints @@ -141,14 +154,49 @@ _comp_cmd_gtar__parse_help() [[ ${BASH_REMATCH[1]} ]] && arg=opt || arg=req fi - _comp_cmd_gtar__parse_help_line "$str" "$arg" + _comp_cmd_gtar__init_parse_help_line "$str" "$arg" fi done <<<"$(tar --help)" - long_opts="\ - $long_arg_none $long_arg_opt $long_arg_req" + local long_opts="$long_arg_none $long_arg_opt $long_arg_req" + + local short_opts="$short_arg_none$short_arg_opt$short_arg_req" + + printf -v _comp_cmd_gtar__saved_opts '%s=%q ' \ + long_opts "$long_opts" \ + short_opts "$short_opts" \ + long_arg_none "$long_arg_none" \ + long_arg_opt "$long_arg_opt" \ + long_arg_req "$long_arg_req" \ + short_arg_none "$short_arg_none" \ + short_arg_opt "$short_arg_opt" \ + short_arg_req "$short_arg_req" - short_opts="$short_arg_none$short_arg_opt$short_arg_req" + # Clean up functions only used in initialization + unset -f _comp_cmd_gtar__init_parse_help + unset -f _comp_cmd_gtar__init_parse_help_line + unset -f _comp_cmd_gtar__init_parse_help_opt +} +_comp_cmd_gtar__init_parse_help + +# Load the parse results of "tar --help" for GNU tar into variables. +# +# @var[out] long_opts +# @var[out] short_opts +# @var[out] long_arg_none +# @var[out] long_arg_opt +# @var[out] long_arg_req +# @var[out] short_arg_none +# @var[out] short_arg_opt +# @var[out] short_arg_req +# The parse results are returned in these variables. +# +# @var[in] _comp_cmd_gtar__saved_opts +# The parse results are obtained by evaluating this variable with the +# "eval" builtin. +_comp_cmd_gtar__load_opts() +{ + eval -- "$_comp_cmd_gtar__saved_opts" } # Hack: parse --warning keywords from tar's error output @@ -165,8 +213,15 @@ _comp_cmd_gtar__parse_warnings() _comp_compgen -- -W '"${warnings[@]}"' } +# @var[out] old_opt_progress +# @var[out] old_opt_used +# @var[out,array] old_opt_parsed _comp_cmd_tar__parse_old_opt() { + old_opt_progress="" + old_opt_used="" + old_opt_parsed=() + local first_word char # current word is the first word @@ -193,6 +248,10 @@ _comp_cmd_tar__parse_old_opt() } # Make the analysis of whole command line. +# +# @var[out] old_opt_progress +# @var[out] old_opt_used +# @var[out,array] old_opt_parsed _comp_cmd_tar__preparse_cmdline() { local first_arg=set i modes="ctxurdA" @@ -507,11 +566,7 @@ _comp_cmd_tar__detect_ext() _comp_cmd_tar__gnu() { - local long_opts short_opts basic_tar="" \ - long_arg_none="" long_arg_opt="" long_arg_req="" \ - short_arg_none="" short_arg_opt="" short_arg_req="" \ - tar_mode tar_mode_arg old_opt_progress="" \ - old_opt_used="" old_opt_parsed=() + local basic_tar="" # Main mode, e.g. "x" or "c" or the long forms "extract" or "create" local tar_mode=none @@ -528,12 +583,15 @@ _comp_cmd_tar__gnu() fi local cur prev words cword was_split comp_args - _comp_initialize -s -- "$@" || return # Fill the {long,short}_{opts,arg*} - _comp_cmd_gtar__parse_help + local long_opts short_opts \ + long_arg_none long_arg_opt long_arg_req \ + short_arg_none short_arg_opt short_arg_req + _comp_cmd_gtar__load_opts + local old_opt_progress old_opt_used old_opt_parsed _comp_cmd_tar__preparse_cmdline "${words[@]}" local ext @@ -694,11 +752,7 @@ _comp_cmd_tar__posix_prev_handle() _comp_cmd_tar__posix() { - local long_opts short_opts basic_tar=set \ - long_arg_none="" long_arg_opt long_arg_req="" \ - short_arg_none short_arg_opt short_arg_req \ - tar_mode tar_mode_arg old_opt_progress="" \ - old_opt_used=set old_opt_parsed=() + local basic_tar=set # Main mode, e.g. -x or -c (extract/creation) local tar_mode=none @@ -710,15 +764,25 @@ _comp_cmd_tar__posix() local tar_compression_mode=none local cur prev words cword was_split comp_args - _comp_initialize -s -- "$@" || return + # Initialize option variables: # relatively compatible modes are {c,t,x} # relatively compatible options {b,f,m,v,w} + # Note: long_{opts,arg_{none,opt}} and short_arg_opt are currently unused + local long_opts short_opts \ + long_arg_none long_arg_opt long_arg_req \ + short_arg_none short_arg_opt short_arg_req + long_arg_none="" + long_arg_opt="" + long_arg_req="" + long_opts="" short_arg_req="fb" + short_arg_opt="" short_arg_none="wmv" short_opts="$short_arg_req$short_arg_none" + local old_opt_progress old_opt_used old_opt_parsed _comp_cmd_tar__preparse_cmdline "${words[@]}" local ext