@@ -208,6 +208,7 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
208208 self .allow_redirection = allow_redirection # Security setting to prevent redirection of stdout
209209
210210 # Attributes which ARE dynamically settable via the set command at runtime
211+ self .always_show_hint = False
211212 self .debug = False
212213 self .echo = False
213214 self .editor = Cmd .DEFAULT_EDITOR
@@ -375,17 +376,21 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
375376 # will be added if there is an unmatched opening quote
376377 self .allow_closing_quote = True
377378
378- # An optional header that prints above the tab completion suggestions
379+ # An optional hint which prints above tab completion suggestions
380+ self .completion_hint = ''
381+
382+ # Header which prints above CompletionItem tables
379383 self .completion_header = ''
380384
381385 # Used by complete() for readline tab completion
382386 self .completion_matches = []
383387
384- # Use this list if you are completing strings that contain a common delimiter and you only want to
385- # display the final portion of the matches as the tab completion suggestions. The full matches
386- # still must be returned from your completer function. For an example, look at path_complete()
387- # which uses this to show only the basename of paths as the suggestions. delimiter_complete() also
388- # populates this list.
388+ # Use this list if you need to display tab completion suggestions that are different than the actual text
389+ # of the matches. For instance, if you are completing strings that contain a common delimiter and you only
390+ # want to display the final portion of the matches as the tab completion suggestions. The full matches
391+ # still must be returned from your completer function. For an example, look at path_complete() which
392+ # uses this to show only the basename of paths as the suggestions. delimiter_complete() also populates
393+ # this list.
389394 self .display_matches = []
390395
391396 # Used by functions like path_complete() and delimiter_complete() to properly
@@ -788,6 +793,8 @@ def build_settables(self):
788793 ansi .STYLE_NEVER ),
789794 choices = [ansi .STYLE_TERMINAL , ansi .STYLE_ALWAYS , ansi .STYLE_NEVER ]))
790795
796+ self .add_settable (Settable ('always_show_hint' , bool ,
797+ 'Display tab completion hint even when completion suggestions print' ))
791798 self .add_settable (Settable ('debug' , bool , "Show full traceback on exception" ))
792799 self .add_settable (Settable ('echo' , bool , "Echo command issued into output" ))
793800 self .add_settable (Settable ('editor' , str , "Program used by 'edit'" ))
@@ -984,6 +991,7 @@ def _reset_completion_defaults(self) -> None:
984991 """
985992 self .allow_appended_space = True
986993 self .allow_closing_quote = True
994+ self .completion_hint = ''
987995 self .completion_header = ''
988996 self .completion_matches = []
989997 self .display_matches = []
@@ -1479,6 +1487,22 @@ def _pad_matches_to_display(matches_to_display: List[str]) -> Tuple[List[str], i
14791487
14801488 return [cur_match + padding for cur_match in matches_to_display ], len (padding )
14811489
1490+ def _build_completion_metadata_string (self ) -> str : # pragma: no cover
1491+ """Build completion metadata string which can contain a hint and CompletionItem table header"""
1492+ metadata = ''
1493+
1494+ # Add hint if one exists and we are supposed to display it
1495+ if self .always_show_hint and self .completion_hint :
1496+ metadata += '\n ' + self .completion_hint
1497+
1498+ # Add table header if one exists
1499+ if self .completion_header :
1500+ if not metadata :
1501+ metadata += '\n '
1502+ metadata += '\n ' + self .completion_header
1503+
1504+ return metadata
1505+
14821506 def _display_matches_gnu_readline (self , substitution : str , matches : List [str ],
14831507 longest_match_length : int ) -> None : # pragma: no cover
14841508 """Prints a match list using GNU readline's rl_display_match_list()
@@ -1523,9 +1547,8 @@ def _display_matches_gnu_readline(self, substitution: str, matches: List[str],
15231547 strings_array [1 :- 1 ] = encoded_matches
15241548 strings_array [- 1 ] = None
15251549
1526- # Print the header if one exists
1527- if self .completion_header :
1528- sys .stdout .write ('\n \n ' + self .completion_header )
1550+ # Print any metadata like a hint or table header
1551+ sys .stdout .write (self ._build_completion_metadata_string ())
15291552
15301553 # Call readline's display function
15311554 # rl_display_match_list(strings_array, number of completion matches, longest match length)
@@ -1551,10 +1574,8 @@ def _display_matches_pyreadline(self, matches: List[str]) -> None: # pragma: no
15511574 # Add padding for visual appeal
15521575 matches_to_display , _ = self ._pad_matches_to_display (matches_to_display )
15531576
1554- # Print the header if one exists
1555- if self .completion_header :
1556- # noinspection PyUnresolvedReferences
1557- readline .rl .mode .console .write ('\n \n ' + self .completion_header )
1577+ # Print any metadata like a hint or table header
1578+ readline .rl .mode .console .write (sys .stdout .write (self ._build_completion_metadata_string ()))
15581579
15591580 # Display matches using actual display function. This also redraws the prompt and line.
15601581 orig_pyreadline_display (matches_to_display )
@@ -3317,7 +3338,7 @@ def complete_set_value(self, text: str, line: str, begidx: int, endidx: int,
33173338 # Create the parser for the set command
33183339 set_parser = DEFAULT_ARGUMENT_PARSER (parents = [set_parser_parent ])
33193340 set_parser .add_argument ('value' , nargs = argparse .OPTIONAL , help = 'new value for settable' ,
3320- completer_method = complete_set_value )
3341+ completer_method = complete_set_value , suppress_tab_hint = True )
33213342
33223343 # Preserve quotes so users can pass in quoted empty strings and flags (e.g. -h) as the value
33233344 @with_argparser (set_parser , preserve_quotes = True )
0 commit comments