@@ -208,6 +208,7 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
208
208
self .allow_redirection = allow_redirection # Security setting to prevent redirection of stdout
209
209
210
210
# Attributes which ARE dynamically settable via the set command at runtime
211
+ self .always_show_hint = False
211
212
self .debug = False
212
213
self .echo = False
213
214
self .editor = Cmd .DEFAULT_EDITOR
@@ -375,17 +376,21 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
375
376
# will be added if there is an unmatched opening quote
376
377
self .allow_closing_quote = True
377
378
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
379
383
self .completion_header = ''
380
384
381
385
# Used by complete() for readline tab completion
382
386
self .completion_matches = []
383
387
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.
389
394
self .display_matches = []
390
395
391
396
# Used by functions like path_complete() and delimiter_complete() to properly
@@ -788,6 +793,8 @@ def build_settables(self):
788
793
ansi .STYLE_NEVER ),
789
794
choices = [ansi .STYLE_TERMINAL , ansi .STYLE_ALWAYS , ansi .STYLE_NEVER ]))
790
795
796
+ self .add_settable (Settable ('always_show_hint' , bool ,
797
+ 'Display tab completion hint even when completion suggestions print' ))
791
798
self .add_settable (Settable ('debug' , bool , "Show full traceback on exception" ))
792
799
self .add_settable (Settable ('echo' , bool , "Echo command issued into output" ))
793
800
self .add_settable (Settable ('editor' , str , "Program used by 'edit'" ))
@@ -984,6 +991,7 @@ def _reset_completion_defaults(self) -> None:
984
991
"""
985
992
self .allow_appended_space = True
986
993
self .allow_closing_quote = True
994
+ self .completion_hint = ''
987
995
self .completion_header = ''
988
996
self .completion_matches = []
989
997
self .display_matches = []
@@ -1479,6 +1487,22 @@ def _pad_matches_to_display(matches_to_display: List[str]) -> Tuple[List[str], i
1479
1487
1480
1488
return [cur_match + padding for cur_match in matches_to_display ], len (padding )
1481
1489
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
+
1482
1506
def _display_matches_gnu_readline (self , substitution : str , matches : List [str ],
1483
1507
longest_match_length : int ) -> None : # pragma: no cover
1484
1508
"""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],
1523
1547
strings_array [1 :- 1 ] = encoded_matches
1524
1548
strings_array [- 1 ] = None
1525
1549
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 ())
1529
1552
1530
1553
# Call readline's display function
1531
1554
# 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
1551
1574
# Add padding for visual appeal
1552
1575
matches_to_display , _ = self ._pad_matches_to_display (matches_to_display )
1553
1576
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 ()))
1558
1579
1559
1580
# Display matches using actual display function. This also redraws the prompt and line.
1560
1581
orig_pyreadline_display (matches_to_display )
@@ -3317,7 +3338,7 @@ def complete_set_value(self, text: str, line: str, begidx: int, endidx: int,
3317
3338
# Create the parser for the set command
3318
3339
set_parser = DEFAULT_ARGUMENT_PARSER (parents = [set_parser_parent ])
3319
3340
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 )
3321
3342
3322
3343
# Preserve quotes so users can pass in quoted empty strings and flags (e.g. -h) as the value
3323
3344
@with_argparser (set_parser , preserve_quotes = True )
0 commit comments