From 3b40ff371774089d1fe1307b26bf93c372cfaa2c Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Thu, 22 Feb 2024 23:13:36 +0000 Subject: [PATCH] bash: support -- delimeter - fixes #163 --- shtab/__init__.py | 49 ++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/shtab/__init__.py b/shtab/__init__.py index b751284..457bd2f 100644 --- a/shtab/__init__.py +++ b/shtab/__init__.py @@ -368,7 +368,7 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): current_action_nargs=1 fi - current_action_args_start_index=$(( $word_index + 1 )) + current_action_args_start_index=$(( $word_index + 1 - $pos_only )) current_action_is_positional=$2 } @@ -395,6 +395,7 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): local prefix=${root_prefix} local word_index=0 + local pos_only=0 # "--" delimeter not encountered yet _set_parser_defaults word_index=1 @@ -403,26 +404,30 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): while [ $word_index -ne $COMP_CWORD ]; do local this_word="${COMP_WORDS[$word_index]}" - if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then - # valid subcommand: add it to the prefix & reset the current action - prefix="${prefix}_$(_shtab_replace_nonword $this_word)" - _set_parser_defaults - fi - - if [[ " ${current_option_strings[@]} " == *" ${this_word} "* ]]; then - # a new action should be acquired (due to recognised option string or - # no more input expected from current action); - # the next positional action can fill in here - _set_new_action $this_word false - fi - - if [[ "$current_action_nargs" != "*" ]] && \\ - [[ "$current_action_nargs" != "+" ]] && \\ - [[ "$current_action_nargs" != *"..." ]] && \\ - (( $word_index + 1 - $current_action_args_start_index >= \\ - $current_action_nargs )); then - $current_action_is_positional && let "completed_positional_actions += 1" - _set_new_action "pos_${completed_positional_actions}" true + if [[ $pos_only = 1 || " $this_word " != " -- " ]]; then + if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then + # valid subcommand: add it to the prefix & reset the current action + prefix="${prefix}_$(_shtab_replace_nonword $this_word)" + _set_parser_defaults + fi + + if [[ " ${current_option_strings[@]} " == *" ${this_word} "* ]]; then + # a new action should be acquired (due to recognised option string or + # no more input expected from current action); + # the next positional action can fill in here + _set_new_action $this_word false + fi + + if [[ "$current_action_nargs" != "*" ]] && \\ + [[ "$current_action_nargs" != "+" ]] && \\ + [[ "$current_action_nargs" != *"..." ]] && \\ + (( $word_index + 1 - $current_action_args_start_index - $pos_only >= \\ + $current_action_nargs )); then + $current_action_is_positional && let "completed_positional_actions += 1" + _set_new_action "pos_${completed_positional_actions}" true + fi + else + pos_only=1 # "--" delimeter encountered fi let "word_index+=1" @@ -430,7 +435,7 @@ def complete_bash(parser, root_prefix=None, preamble="", choice_functions=None): # Generate the completions - if [[ "${completing_word}" == -* ]]; then + if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then # optional argument started: use option strings COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") ) else