33
33
import cmd
34
34
import collections
35
35
from colorama import Fore
36
+ import copy
36
37
import glob
37
38
import os
38
39
import platform
@@ -494,13 +495,19 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, persistent_histor
494
495
# will be added if there is an unmatched opening quote
495
496
self .allow_closing_quote = True
496
497
497
- # Use this list if you are completing strings that contain a common delimiter and you only want to
498
- # display the final portion of the matches as the tab-completion suggestions. The full matches
499
- # still must be returned from your completer function. For an example, look at path_complete()
500
- # which uses this to show only the basename of paths as the suggestions. delimiter_complete() also
501
- # populates this list.
498
+ # An optional header that prints above the tab-completion suggestions
499
+ self .completion_header = ''
500
+
501
+ # If the tab-completion suggestions should be displayed in a way that is different than the actual match values,
502
+ # then place those results in this list. The full matches still must be returned from your completer function.
503
+ # For an example, look at path_complete() which uses this to show only the basename of paths as the
504
+ # suggestions. delimiter_complete() also populates this list.
502
505
self .display_matches = []
503
506
507
+ # Used by functions like path_complete() and delimiter_complete() to properly
508
+ # quote matches that are completed in a delimited fashion
509
+ self .matches_delimited = False
510
+
504
511
# ----- Methods related to presenting output to the user -----
505
512
506
513
@property
@@ -657,7 +664,9 @@ def reset_completion_defaults(self):
657
664
"""
658
665
self .allow_appended_space = True
659
666
self .allow_closing_quote = True
667
+ self .completion_header = ''
660
668
self .display_matches = []
669
+ self .matches_delimited = False
661
670
662
671
if rl_type == RlType .GNU :
663
672
readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
@@ -683,7 +692,6 @@ def tokens_for_completion(self, line, begidx, endidx):
683
692
On Failure
684
693
Both items are None
685
694
"""
686
- import copy
687
695
unclosed_quote = ''
688
696
quotes_to_try = copy .copy (constants .QUOTES )
689
697
@@ -836,6 +844,8 @@ def delimiter_complete(self, text, line, begidx, endidx, match_against, delimite
836
844
837
845
# Display only the portion of the match that's being completed based on delimiter
838
846
if matches :
847
+ # Set this to True for proper quoting of matches with spaces
848
+ self .matches_delimited = True
839
849
840
850
# Get the common beginning for the matches
841
851
common_prefix = os .path .commonprefix (matches )
@@ -1037,6 +1047,9 @@ def complete_users():
1037
1047
search_str = os .path .join (os .getcwd (), search_str )
1038
1048
cwd_added = True
1039
1049
1050
+ # Set this to True for proper quoting of paths with spaces
1051
+ self .matches_delimited = True
1052
+
1040
1053
# Find all matching path completions
1041
1054
matches = glob .glob (search_str )
1042
1055
@@ -1245,6 +1258,10 @@ def _display_matches_gnu_readline(self, substitution, matches, longest_match_len
1245
1258
strings_array [1 :- 1 ] = encoded_matches
1246
1259
strings_array [- 1 ] = None
1247
1260
1261
+ # Print the header if one exists
1262
+ if self .completion_header :
1263
+ sys .stdout .write ('\n ' + self .completion_header )
1264
+
1248
1265
# Call readline's display function
1249
1266
# rl_display_match_list(strings_array, number of completion matches, longest match length)
1250
1267
readline_lib .rl_display_match_list (strings_array , len (encoded_matches ), longest_match_length )
@@ -1270,6 +1287,10 @@ def _display_matches_pyreadline(self, matches): # pragma: no cover
1270
1287
# Add padding for visual appeal
1271
1288
matches_to_display , _ = self ._pad_matches_to_display (matches_to_display )
1272
1289
1290
+ # Print the header if one exists
1291
+ if self .completion_header :
1292
+ readline .rl .mode .console .write ('\n ' + self .completion_header )
1293
+
1273
1294
# Display matches using actual display function. This also redraws the prompt and line.
1274
1295
orig_pyreadline_display (matches_to_display )
1275
1296
@@ -1414,17 +1435,10 @@ def complete(self, text, state):
1414
1435
display_matches_set = set (self .display_matches )
1415
1436
self .display_matches = list (display_matches_set )
1416
1437
1417
- # Check if display_matches has been used. If so, then matches
1418
- # on delimited strings like paths was done.
1419
- if self .display_matches :
1420
- matches_delimited = True
1421
- else :
1422
- matches_delimited = False
1423
-
1438
+ if not self .display_matches :
1424
1439
# Since self.display_matches is empty, set it to self.completion_matches
1425
1440
# before we alter them. That way the suggestions will reflect how we parsed
1426
1441
# the token being completed and not how readline did.
1427
- import copy
1428
1442
self .display_matches = copy .copy (self .completion_matches )
1429
1443
1430
1444
# Check if we need to add an opening quote
@@ -1435,7 +1449,7 @@ def complete(self, text, state):
1435
1449
# This is the tab completion text that will appear on the command line.
1436
1450
common_prefix = os .path .commonprefix (self .completion_matches )
1437
1451
1438
- if matches_delimited :
1452
+ if self . matches_delimited :
1439
1453
# Check if any portion of the display matches appears in the tab completion
1440
1454
display_prefix = os .path .commonprefix (self .display_matches )
1441
1455
0 commit comments