@@ -472,23 +472,43 @@ def _complete_for_arg(self, action: argparse.Action,
472472 if action .dest in self ._arg_choices :
473473 arg_choices = self ._arg_choices [action .dest ]
474474
475- if isinstance (arg_choices , tuple ) and len (arg_choices ) > 0 and callable (arg_choices [0 ]):
476- completer = arg_choices [0 ]
475+ # if arg_choices is a tuple
476+ # Let's see if it's a custom completion function. If it is, return what it provides
477+ # To do this, we make sure the first element is either a callable
478+ # or it's the name of a callable in the application
479+ if isinstance (arg_choices , tuple ) and len (arg_choices ) > 0 and \
480+ (callable (arg_choices [0 ]) or
481+ (isinstance (arg_choices [0 ], str ) and hasattr (self ._cmd2_app , arg_choices [0 ]) and
482+ callable (getattr (self ._cmd2_app , arg_choices [0 ]))
483+ )
484+ ):
485+
486+ if callable (arg_choices [0 ]):
487+ completer = arg_choices [0 ]
488+ elif isinstance (arg_choices [0 ], str ) and callable (getattr (self ._cmd2_app , arg_choices [0 ])):
489+ completer = getattr (self ._cmd2_app , arg_choices [0 ])
490+
491+ # extract the positional and keyword arguments from the tuple
477492 list_args = None
478493 kw_args = None
479494 for index in range (1 , len (arg_choices )):
480495 if isinstance (arg_choices [index ], list ) or isinstance (arg_choices [index ], tuple ):
481496 list_args = arg_choices [index ]
482497 elif isinstance (arg_choices [index ], dict ):
483498 kw_args = arg_choices [index ]
484- if list_args is not None and kw_args is not None :
485- return completer (text , line , begidx , endidx , * list_args , ** kw_args )
486- elif list_args is not None :
487- return completer (text , line , begidx , endidx , * list_args )
488- elif kw_args is not None :
489- return completer (text , line , begidx , endidx , ** kw_args )
490- else :
491- return completer (text , line , begidx , endidx )
499+ try :
500+ # call the provided function differently depending on the provided positional and keyword arguments
501+ if list_args is not None and kw_args is not None :
502+ return completer (text , line , begidx , endidx , * list_args , ** kw_args )
503+ elif list_args is not None :
504+ return completer (text , line , begidx , endidx , * list_args )
505+ elif kw_args is not None :
506+ return completer (text , line , begidx , endidx , ** kw_args )
507+ else :
508+ return completer (text , line , begidx , endidx )
509+ except TypeError :
510+ # assume this is due to an incorrect function signature, return nothing.
511+ return []
492512 else :
493513 return AutoCompleter .basic_complete (text , line , begidx , endidx ,
494514 self ._resolve_choices_for_arg (action , used_values ))
@@ -499,6 +519,16 @@ def _resolve_choices_for_arg(self, action: argparse.Action, used_values=()) -> L
499519 if action .dest in self ._arg_choices :
500520 args = self ._arg_choices [action .dest ]
501521
522+ # is the argument a string? If so, see if we can find an attribute in the
523+ # application matching the string.
524+ if isinstance (args , str ):
525+ try :
526+ args = getattr (self ._cmd2_app , args )
527+ except AttributeError :
528+ # Couldn't find anything matching the name
529+ return []
530+
531+ # is the provided argument a callable. If so, call it
502532 if callable (args ):
503533 try :
504534 if self ._cmd2_app is not None :
@@ -535,7 +565,10 @@ def _print_action_help(self, action: argparse.Action) -> None:
535565
536566 prefix = '{}{}' .format (flags , param )
537567 else :
538- prefix = '{}' .format (str (action .dest ).upper ())
568+ if action .dest != SUPPRESS :
569+ prefix = '{}' .format (str (action .dest ).upper ())
570+ else :
571+ prefix = ''
539572
540573 prefix = ' {0: <{width}} ' .format (prefix , width = 20 )
541574 pref_len = len (prefix )
0 commit comments