@@ -209,6 +209,33 @@ 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 ):
213+ """Determine if a token looks like a flag. Based on argparse._parse_optional()."""
214+ # if it's an empty string, it was meant to be a positional
215+ if not token :
216+ return False
217+
218+ # if it doesn't start with a prefix, it was meant to be positional
219+ if not token [0 ] in parser .prefix_chars :
220+ return False
221+
222+ # if it's just a single character, it was meant to be positional
223+ if len (token ) == 1 :
224+ return False
225+
226+ # if it looks like a negative number, it was meant to be positional
227+ # unless there are negative-number-like options
228+ if parser ._negative_number_matcher .match (token ):
229+ if not parser ._has_negative_number_optionals :
230+ return False
231+
232+ # if it contains a space, it was meant to be a positional
233+ if ' ' in token :
234+ return False
235+
236+ # Looks like a flag
237+ return True
238+
212239class AutoCompleter (object ):
213240 """Automatically command line tab completion based on argparse parameters"""
214241
@@ -334,9 +361,8 @@ def complete_command(self, tokens: List[str], text: str, line: str, begidx: int,
334361 def consume_flag_argument () -> None :
335362 """Consuming token as a flag argument"""
336363 # we're consuming flag arguments
337- # if this is not empty and is not another potential flag, count towards flag arguments
338- # if the token is a single character, it doesn't matter whether it matches a flag prefix
339- if token and (len (token ) == 1 or token [0 ] not in self ._parser .prefix_chars ) and flag_action is not None :
364+ # if the token does not look like a new flag, then count towards flag arguments
365+ if not token_resembles_flag (token , self ._parser ) and flag_action is not None :
340366 flag_arg .count += 1
341367
342368 # does this complete a option item for the flag
@@ -431,12 +457,7 @@ def process_action_nargs(action: argparse.Action, arg_state: AutoCompleter._Argu
431457 skip_flag = True
432458
433459 # At this point we're no longer consuming flag arguments. Is the current argument a potential flag?
434- # If the argument is the start of a flag and this is the last token, we proceed forward to try
435- # and match against our known flags.
436- # If this argument is not the last token and the argument is exactly a flag prefix, then this
437- # token should be consumed as an argument to a prior flag or positional argument.
438- if len (token ) > 0 and token [0 ] in self ._parser .prefix_chars and not skip_flag and \
439- (is_last_token or token not in self ._parser .prefix_chars ):
460+ if token_resembles_flag (token , self ._parser ) and not skip_flag :
440461 # reset some tracking values
441462 flag_arg .reset ()
442463 # don't reset positional tracking because flags can be interspersed anywhere between positionals
0 commit comments