@@ -209,8 +209,8 @@ def register_custom_actions(parser: argparse.ArgumentParser) -> None:
209209 parser .register ('action' , 'append' , _AppendRangeAction )
210210
211211
212- def token_resembles_flag (token : str , parser : argparse .ArgumentParser ) -> bool :
213- """Determine if a token looks like a flag. Based on argparse._parse_optional()."""
212+ def is_potential_flag (token : str , parser : argparse .ArgumentParser ) -> bool :
213+ """Determine if a token looks like a potential flag. Based on argparse._parse_optional()."""
214214 # if it's an empty string, it was meant to be a positional
215215 if not token :
216216 return False
@@ -340,6 +340,10 @@ def complete_command(self, tokens: List[str], text: str, line: str, begidx: int,
340340 # Skip any flags or flag parameter tokens
341341 next_pos_arg_index = 0
342342
343+ # This gets set to True when flags will no longer be processed as argparse flags
344+ # That can happen when -- is used or an argument with nargs=argparse.REMAINDER is used
345+ skip_remaining_flags = False
346+
343347 pos_arg = AutoCompleter ._ArgumentState ()
344348 pos_action = None
345349
@@ -363,7 +367,7 @@ def consume_flag_argument() -> None:
363367 """Consuming token as a flag argument"""
364368 # we're consuming flag arguments
365369 # if the token does not look like a new flag, then count towards flag arguments
366- if not token_resembles_flag (token , self ._parser ) and flag_action is not None :
370+ if not is_potential_flag (token , self ._parser ) and flag_action is not None :
367371 flag_arg .count += 1
368372
369373 # does this complete a option item for the flag
@@ -432,8 +436,10 @@ def process_action_nargs(action: argparse.Action, arg_state: AutoCompleter._Argu
432436
433437 for idx , token in enumerate (tokens ):
434438 is_last_token = idx >= len (tokens ) - 1
439+
435440 # Only start at the start token index
436441 if idx >= self ._token_start_index :
442+
437443 # If a remainder action is found, force all future tokens to go to that
438444 if remainder ['arg' ] is not None :
439445 if remainder ['action' ] == pos_action :
@@ -442,28 +448,38 @@ def process_action_nargs(action: argparse.Action, arg_state: AutoCompleter._Argu
442448 elif remainder ['action' ] == flag_action :
443449 consume_flag_argument ()
444450 continue
451+
445452 current_is_positional = False
446453 # Are we consuming flag arguments?
447454 if not flag_arg .needed :
448- # Special case when each of the following is true:
449- # - We're not in the middle of consuming flag arguments
450- # - The current positional argument count has hit the max count
451- # - The next positional argument is a REMAINDER argument
452- # Argparse will now treat all future tokens as arguments to the positional including tokens that
453- # look like flags so the completer should skip any flag related processing once this happens
454- skip_flag = False
455- if (pos_action is not None ) and pos_arg .count >= pos_arg .max and \
456- next_pos_arg_index < len (self ._positional_actions ) and \
457- self ._positional_actions [next_pos_arg_index ].nargs == argparse .REMAINDER :
458- skip_flag = True
455+
456+ if not skip_remaining_flags :
457+ # Special case when each of the following is true:
458+ # - We're not in the middle of consuming flag arguments
459+ # - The current positional argument count has hit the max count
460+ # - The next positional argument is a REMAINDER argument
461+ # Argparse will now treat all future tokens as arguments to the positional including tokens that
462+ # look like flags so the completer should skip any flag related processing once this happens
463+ if (pos_action is not None ) and pos_arg .count >= pos_arg .max and \
464+ next_pos_arg_index < len (self ._positional_actions ) and \
465+ self ._positional_actions [next_pos_arg_index ].nargs == argparse .REMAINDER :
466+ skip_remaining_flags = True
459467
460468 # At this point we're no longer consuming flag arguments. Is the current argument a potential flag?
461- if token_resembles_flag (token , self ._parser ) and not skip_flag :
469+ if is_potential_flag (token , self ._parser ) and not skip_remaining_flags :
462470 # reset some tracking values
463471 flag_arg .reset ()
464472 # don't reset positional tracking because flags can be interspersed anywhere between positionals
465473 flag_action = None
466474
475+ if token == '--' :
476+ if is_last_token :
477+ # Exit loop and see if -- can be completed into a flag
478+ break
479+ else :
480+ # In argparse, all args after -- are non-flags
481+ skip_remaining_flags = True
482+
467483 # does the token fully match a known flag?
468484 if token in self ._flag_to_action :
469485 flag_action = self ._flag_to_action [token ]
@@ -524,22 +540,25 @@ def process_action_nargs(action: argparse.Action, arg_state: AutoCompleter._Argu
524540 else :
525541 consume_flag_argument ()
526542
543+ if remainder ['arg' ] is not None :
544+ skip_remaining_flags = True
545+
527546 # don't reset this if we're on the last token - this allows completion to occur on the current token
528- if not is_last_token and flag_arg .min is not None :
547+ elif not is_last_token and flag_arg .min is not None :
529548 flag_arg .needed = flag_arg .count < flag_arg .min
530549
531550 # Here we're done parsing all of the prior arguments. We know what the next argument is.
532551
552+ completion_results = []
553+
533554 # if we don't have a flag to populate with arguments and the last token starts with
534555 # a flag prefix then we'll complete the list of flag options
535- completion_results = []
536556 if not flag_arg .needed and len (tokens [- 1 ]) > 0 and tokens [- 1 ][0 ] in self ._parser .prefix_chars and \
537- remainder [ 'arg' ] is None :
557+ not skip_remaining_flags :
538558 return AutoCompleter .basic_complete (text , line , begidx , endidx ,
539559 [flag for flag in self ._flags if flag not in matched_flags ])
540560 # we're not at a positional argument, see if we're in a flag argument
541561 elif not current_is_positional :
542- # current_items = []
543562 if flag_action is not None :
544563 consumed = consumed_arg_values [flag_action .dest ]\
545564 if flag_action .dest in consumed_arg_values else []
0 commit comments