@@ -71,7 +71,7 @@ _shtab_replace_nonword() {
7171# set default values (called for the initial parser & any subparsers)
7272_set_parser_defaults() {
7373 local subparsers_var="${prefix}_subparsers[@]"
74- sub_parsers=${!subparsers_var}
74+ sub_parsers=${!subparsers_var- }
7575
7676 local current_option_strings_var="${prefix}_option_strings[@]"
7777 current_option_strings=${!current_option_strings_var}
@@ -88,19 +88,19 @@ _set_new_action() {
8888 current_action="${prefix}_$(_shtab_replace_nonword $1)"
8989
9090 local current_action_compgen_var=${current_action}_COMPGEN
91- current_action_compgen="${!current_action_compgen_var}"
91+ current_action_compgen="${!current_action_compgen_var- }"
9292
9393 local current_action_choices_var="${current_action}_choices[@]"
94- current_action_choices="${!current_action_choices_var}"
94+ current_action_choices="${!current_action_choices_var- }"
9595
9696 local current_action_nargs_var="${current_action}_nargs"
97- if [ -n "${!current_action_nargs_var}" ]; then
97+ if [ -n "${!current_action_nargs_var- }" ]; then
9898 current_action_nargs="${!current_action_nargs_var}"
9999 else
100100 current_action_nargs=1
101101 fi
102102
103- current_action_args_start_index=$(( $word_index + 1 ))
103+ current_action_args_start_index=$(( $word_index + 1 - $pos_only ))
104104
105105 current_action_is_positional=$2
106106}
@@ -114,10 +114,20 @@ _set_new_action() {
114114# ${!x} -> ${hello} -> "world"
115115_shtab_scratch() {
116116 local completing_word="${COMP_WORDS[COMP_CWORD]}"
117+ local completed_positional_actions
118+ local current_action
119+ local current_action_args_start_index
120+ local current_action_choices
121+ local current_action_compgen
122+ local current_action_is_positional
123+ local current_action_nargs
124+ local current_option_strings
125+ local sub_parsers
117126 COMPREPLY=()
118127
119- prefix=_shtab_scratch
120- word_index=0
128+ local prefix=_shtab_scratch
129+ local word_index=0
130+ local pos_only=0 # "--" delimeter not encountered yet
121131 _set_parser_defaults
122132 word_index=1
123133
@@ -126,34 +136,38 @@ _shtab_scratch() {
126136 while [ $word_index -ne $COMP_CWORD ]; do
127137 local this_word="${COMP_WORDS[$word_index]}"
128138
129- if [[ -n $sub_parsers && " ${sub_parsers[@]} " =~ " ${this_word} " ]]; then
130- # valid subcommand: add it to the prefix & reset the current action
131- prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
132- _set_parser_defaults
133- fi
134-
135- if [[ " ${current_option_strings[@]} " =~ " ${this_word} " ]]; then
136- # a new action should be acquired (due to recognised option string or
137- # no more input expected from current action);
138- # the next positional action can fill in here
139- _set_new_action $this_word false
140- fi
141-
142- if [[ "$current_action_nargs" != "*" ]] && \
143- [[ "$current_action_nargs" != "+" ]] && \
144- [[ "$current_action_nargs" != *"..." ]] && \
145- (( $word_index + 1 - $current_action_args_start_index >= \
146- $current_action_nargs )); then
147- $current_action_is_positional && let "completed_positional_actions += 1"
148- _set_new_action "pos_${completed_positional_actions}" true
139+ if [[ $pos_only = 1 || " $this_word " != " -- " ]]; then
140+ if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then
141+ # valid subcommand: add it to the prefix & reset the current action
142+ prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
143+ _set_parser_defaults
144+ fi
145+
146+ if [[ " ${current_option_strings[@]} " == *" ${this_word} "* ]]; then
147+ # a new action should be acquired (due to recognised option string or
148+ # no more input expected from current action);
149+ # the next positional action can fill in here
150+ _set_new_action $this_word false
151+ fi
152+
153+ if [[ "$current_action_nargs" != "*" ]] && \
154+ [[ "$current_action_nargs" != "+" ]] && \
155+ [[ "$current_action_nargs" != *"..." ]] && \
156+ (( $word_index + 1 - $current_action_args_start_index - $pos_only >= \
157+ $current_action_nargs )); then
158+ $current_action_is_positional && let "completed_positional_actions += 1"
159+ _set_new_action "pos_${completed_positional_actions}" true
160+ fi
161+ else
162+ pos_only=1 # "--" delimeter encountered
149163 fi
150164
151165 let "word_index+=1"
152166 done
153167
154168 # Generate the completions
155169
156- if [[ "${completing_word}" == -* ]]; then
170+ if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then
157171 # optional argument started: use option strings
158172 COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
159173 else
0 commit comments