2525)
2626from .command_definition import CommandSet
2727from .table_creator import Column , SimpleTable
28- from .utils import CompletionError , basic_complete , get_defining_class
28+ from .utils import CompletionError , basic_complete
2929
3030# If no descriptive header is supplied, then this will be used instead
3131DEFAULT_DESCRIPTIVE_HEADER = 'Description'
@@ -405,7 +405,7 @@ def update_mutex_groups(arg_action: argparse.Action) -> None:
405405
406406 # Check if we are completing a flag's argument
407407 if flag_arg_state is not None :
408- completion_results = self ._complete_for_arg (flag_arg_state . action , text , line ,
408+ completion_results = self ._complete_for_arg (flag_arg_state , text , line ,
409409 begidx , endidx , consumed_arg_values ,
410410 cmd_set = cmd_set )
411411
@@ -426,7 +426,7 @@ def update_mutex_groups(arg_action: argparse.Action) -> None:
426426 action = remaining_positionals .popleft ()
427427 pos_arg_state = _ArgumentState (action )
428428
429- completion_results = self ._complete_for_arg (pos_arg_state . action , text , line ,
429+ completion_results = self ._complete_for_arg (pos_arg_state , text , line ,
430430 begidx , endidx , consumed_arg_values ,
431431 cmd_set = cmd_set )
432432
@@ -461,7 +461,7 @@ def _complete_flags(self, text: str, line: str, begidx: int, endidx: int, matche
461461
462462 return basic_complete (text , line , begidx , endidx , match_against )
463463
464- def _format_completions (self , action , completions : List [Union [str , CompletionItem ]]) -> List [str ]:
464+ def _format_completions (self , arg_state : _ArgumentState , completions : List [Union [str , CompletionItem ]]) -> List [str ]:
465465 # Check if the results are CompletionItems and that there aren't too many to display
466466 if 1 < len (completions ) <= self ._cmd2_app .max_completion_items and \
467467 isinstance (completions [0 ], CompletionItem ):
@@ -472,9 +472,18 @@ def _format_completions(self, action, completions: List[Union[str, CompletionIte
472472 self ._cmd2_app .matches_sorted = True
473473
474474 # If a metavar was defined, use that instead of the dest field
475- destination = action .metavar if action .metavar else action .dest
476-
477- desc_header = getattr (action , ATTR_DESCRIPTIVE_COMPLETION_HEADER , None )
475+ destination = arg_state .action .metavar if arg_state .action .metavar else arg_state .action .dest
476+
477+ # Handle case where metavar was a tuple
478+ if isinstance (destination , tuple ):
479+ # Figure out what string in the tuple to use based on how many of the arguments have been completed.
480+ # Use min() to avoid going passed the end of the tuple to support nargs being ZERO_OR_MORE and
481+ # ONE_OR_MORE. In those cases, argparse limits metavar tuple to 2 elements but we may be completing
482+ # the 3rd or more argument here.
483+ tuple_index = min (len (destination ) - 1 , arg_state .count )
484+ destination = destination [tuple_index ]
485+
486+ desc_header = getattr (arg_state .action , ATTR_DESCRIPTIVE_COMPLETION_HEADER , None )
478487 if desc_header is None :
479488 desc_header = DEFAULT_DESCRIPTIVE_HEADER
480489
@@ -546,7 +555,7 @@ def format_help(self, tokens: List[str]) -> str:
546555 break
547556 return self ._parser .format_help ()
548557
549- def _complete_for_arg (self , arg_action : argparse . Action ,
558+ def _complete_for_arg (self , arg_state : _ArgumentState ,
550559 text : str , line : str , begidx : int , endidx : int ,
551560 consumed_arg_values : Dict [str , List [str ]], * ,
552561 cmd_set : Optional [CommandSet ] = None ) -> List [str ]:
@@ -556,10 +565,10 @@ def _complete_for_arg(self, arg_action: argparse.Action,
556565 :raises: CompletionError if the completer or choices function this calls raises one
557566 """
558567 # Check if the arg provides choices to the user
559- if arg_action .choices is not None :
560- arg_choices = arg_action .choices
568+ if arg_state . action .choices is not None :
569+ arg_choices = arg_state . action .choices
561570 else :
562- arg_choices = getattr (arg_action , ATTR_CHOICES_CALLABLE , None )
571+ arg_choices = getattr (arg_state . action , ATTR_CHOICES_CALLABLE , None )
563572
564573 if arg_choices is None :
565574 return []
@@ -586,8 +595,8 @@ def _complete_for_arg(self, arg_action: argparse.Action,
586595 arg_tokens = {** self ._parent_tokens , ** consumed_arg_values }
587596
588597 # Include the token being completed
589- arg_tokens .setdefault (arg_action .dest , [])
590- arg_tokens [arg_action .dest ].append (text )
598+ arg_tokens .setdefault (arg_state . action .dest , [])
599+ arg_tokens [arg_state . action .dest ].append (text )
591600
592601 # Add the namespace to the keyword arguments for the function we are calling
593602 kwargs [ARG_TOKENS ] = arg_tokens
@@ -617,10 +626,10 @@ def _complete_for_arg(self, arg_action: argparse.Action,
617626 arg_choices [index ] = str (choice )
618627
619628 # Filter out arguments we already used
620- used_values = consumed_arg_values .get (arg_action .dest , [])
629+ used_values = consumed_arg_values .get (arg_state . action .dest , [])
621630 arg_choices = [choice for choice in arg_choices if choice not in used_values ]
622631
623632 # Do tab completion on the choices
624633 results = basic_complete (text , line , begidx , endidx , arg_choices )
625634
626- return self ._format_completions (arg_action , results )
635+ return self ._format_completions (arg_state , results )
0 commit comments