@@ -59,6 +59,7 @@ def my_completer(text: str, line: str, begidx: int, endidx:int, extra_param: str
5959
6060import argparse
6161from colorama import Fore
62+ import os
6263import sys
6364from typing import List , Dict , Tuple , Callable , Union
6465
@@ -78,6 +79,15 @@ def my_completer(text: str, line: str, begidx: int, endidx:int, extra_param: str
7879ACTION_SUPPRESS_HINT = 'suppress_hint'
7980
8081
82+ class CompletionItem (str ):
83+ def __new__ (cls , o , desc = '' , * args , ** kwargs ):
84+ return str .__new__ (cls , o , * args , ** kwargs )
85+
86+ # noinspection PyMissingConstructor,PyUnusedLocal
87+ def __init__ (self , o , desc = '' , * args , ** kwargs ):
88+ self .description = desc
89+
90+
8191class _RangeAction (object ):
8292 def __init__ (self , nargs : Union [int , str , Tuple [int , int ], None ]):
8393 self .nargs_min = None
@@ -413,6 +423,8 @@ def consume_positional_argument() -> None:
413423 completion_results = self ._complete_for_arg (flag_action , text , line , begidx , endidx , consumed )
414424 if not completion_results :
415425 self ._print_action_help (flag_action )
426+ elif len (completion_results ) > 1 :
427+ completion_results = self ._format_completions (flag_action , completion_results )
416428
417429 # ok, we're not a flag, see if there's a positional argument to complete
418430 else :
@@ -422,9 +434,37 @@ def consume_positional_argument() -> None:
422434 completion_results = self ._complete_for_arg (pos_action , text , line , begidx , endidx , consumed )
423435 if not completion_results :
424436 self ._print_action_help (pos_action )
437+ elif len (completion_results ) > 1 :
438+ completion_results = self ._format_completions (pos_action , completion_results )
425439
426440 return completion_results
427441
442+ def _format_completions (self , action , completions : List [Union [str , CompletionItem ]]):
443+ if completions and len (completions ) > 1 and \
444+ isinstance (completions [0 ], CompletionItem ):
445+
446+ token_width = len (action .dest )
447+ completions_with_desc = []
448+
449+ for item in completions :
450+ if len (item ) > token_width :
451+ token_width = len (item )
452+
453+ term_size = os .get_terminal_size ()
454+ fill_width = int (term_size .columns * .6 ) - (token_width + 2 )
455+ for item in completions :
456+ entry = '{: <{token_width}}{: <{fill_width}}' .format (item , item .description ,
457+ token_width = token_width + 2 ,
458+ fill_width = fill_width )
459+ completions_with_desc .append (entry )
460+
461+ header = '\n {: <{token_width}}{}' .format (action .dest , action .desc_header , token_width = token_width + 2 )
462+ print (header )
463+
464+ self ._cmd2_app .display_matches = completions_with_desc
465+
466+ return completions
467+
428468 def complete_command_help (self , tokens : List [str ], text : str , line : str , begidx : int , endidx : int ) -> List [str ]:
429469 """Supports the completion of sub-commands for commands through the cmd2 help command."""
430470 for idx , token in enumerate (tokens ):
0 commit comments