66import argparse
77import dataclasses
88import inspect
9- from collections import deque
9+ from collections import (
10+ defaultdict ,
11+ deque ,
12+ )
1013from collections .abc import Sequence
1114from typing import (
1215 IO ,
@@ -247,15 +250,14 @@ def complete(
247250 used_flags : set [str ] = set ()
248251
249252 # Keeps track of arguments we've seen and any tokens they consumed
250- consumed_arg_values : dict [str , list [str ]] = {} # dict(arg_name -> list[tokens] )
253+ consumed_arg_values : dict [str , list [str ]] = defaultdict ( list )
251254
252255 # Completed mutually exclusive groups
253256 completed_mutex_groups : dict [argparse ._MutuallyExclusiveGroup , argparse .Action ] = {}
254257
255258 def consume_argument (arg_state : _ArgumentState , arg_token : str ) -> None :
256259 """Consume token as an argument."""
257260 arg_state .count += 1
258- consumed_arg_values .setdefault (arg_state .action .dest , [])
259261 consumed_arg_values [arg_state .action .dest ].append (arg_token )
260262
261263 #############################################################################################
@@ -315,7 +317,11 @@ def consume_argument(arg_state: _ArgumentState, arg_token: str) -> None:
315317
316318 if action is not None :
317319 self ._update_mutex_groups (action , completed_mutex_groups , used_flags , remaining_positionals )
318- if isinstance (
320+
321+ # Check if the action type allows the same flag to be provided multiple times.
322+ # Reusable actions (append, count, extend) preserve their history so the
323+ # completion logic knows which values have already been 'consumed'.
324+ if not isinstance (
319325 action ,
320326 (
321327 argparse ._AppendAction ,
@@ -324,16 +330,12 @@ def consume_argument(arg_state: _ArgumentState, arg_token: str) -> None:
324330 argparse ._ExtendAction ,
325331 ),
326332 ):
327- # Flags with actions set to append, append_const, count, and extend can be reused.
328- # Therefore don't erase any tokens already consumed for this flag.
329- consumed_arg_values .setdefault (action .dest , [])
330- else :
331- # This flag is not reusable, so mark that we've seen it
333+ # For standard 'overwrite' actions (e.g., --store), providing the flag
334+ # again resets its state. We mark the flags as 'used' to potentially
335+ # filter them from future completion results and clear any previously
336+ # recorded values for this destination.
332337 used_flags .update (action .option_strings )
333-
334- # It's possible we already have consumed values for this flag if it was used
335- # earlier in the command line. Reset them now for this use of it.
336- consumed_arg_values [action .dest ] = []
338+ consumed_arg_values [action .dest ].clear ()
337339
338340 new_arg_state = _ArgumentState (action )
339341
@@ -554,15 +556,15 @@ def _complete_flags(self, text: str, line: str, begidx: int, endidx: int, used_f
554556 match_against .append (flag )
555557
556558 # Build a dictionary linking actions with their matched flag names
557- matched_actions : dict [argparse .Action , list [str ]] = {}
559+ matched_actions : dict [argparse .Action , list [str ]] = defaultdict ( list )
558560
559561 # Keep flags sorted in the order provided by argparse so our completion
560562 # suggestions display the same as argparse help text.
561563 matched_flags = self ._cmd2_app .basic_complete (text , line , begidx , endidx , match_against , sort = False )
562564
563- for item in matched_flags .items :
564- action = self ._flag_to_action [item . text ]
565- matched_actions . setdefault ( action , []) .append (item . text )
565+ for flag in matched_flags .to_strings () :
566+ action = self ._flag_to_action [flag ]
567+ matched_actions [ action ] .append (flag )
566568
567569 # For completion suggestions, group matched flags by action
568570 items : list [CompletionItem ] = []
0 commit comments