@@ -138,8 +138,12 @@ def __subclasshook__(cls, C):
138138 if readline_lib_name is not None and readline_lib_name :
139139 readline_lib = ctypes .CDLL (readline_lib_name )
140140
141- # On Windows, we save the original pyreadline display completion function since we have to override it
141+ # Save address that rl_basic_quote_characters is pointing to since we need to override and restore it
142+ rl_basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
143+ orig_rl_basic_quote_characters_addr = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
144+
142145else :
146+ # Save the original pyreadline display completion function since we need to override it and restore it
143147 # noinspection PyProtectedMember
144148 orig_pyreadline_display = readline .rl .mode ._display_completions
145149
@@ -1209,19 +1213,12 @@ def get_subcommands(self, command):
12091213 def set_completion_defaults (self ):
12101214 """
12111215 Resets tab completion settings
1212- Called each time complete() is called
1216+ Needs to be called each time readline runs tab completion
12131217 """
12141218 self .allow_appended_space = True
12151219 self .allow_closing_quote = True
12161220 self .display_matches = []
12171221
1218- if readline_lib is not None :
1219- # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
1220- # We don't need to worry about setting rl_completion_suppress_quote since we never declared
1221- # rl_completer_quote_characters.
1222- rl_basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
1223- rl_basic_quote_characters .value = None
1224-
12251222 @staticmethod
12261223 def display_match_list_gnu_readline (substitution , matches , longest_match_length ):
12271224 """
@@ -1956,14 +1953,6 @@ def complete(self, text, state):
19561953 unclosed_quote = ''
19571954 self .set_completion_defaults ()
19581955
1959- # GNU readline specific way to override the completions display function
1960- if readline_lib is not None :
1961- readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
1962-
1963- # pyreadline specific way to override the completions display function
1964- elif sys .platform .startswith ('win' ):
1965- readline .rl .mode ._display_completions = self ._display_matches_pyreadline
1966-
19671956 # lstrip the original line
19681957 orig_line = readline .get_line_buffer ()
19691958 line = orig_line .lstrip ()
@@ -2662,16 +2651,31 @@ def _cmdloop(self):
26622651 # An almost perfect copy from Cmd; however, the pseudo_raw_input portion
26632652 # has been split out so that it can be called separately
26642653 if self .use_rawinput and self .completekey :
2654+
2655+ # Set up readline for our tab completion needs
2656+ if readline_lib is not None :
2657+ readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
2658+
2659+ # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
2660+ # We don't need to worry about setting rl_completion_suppress_quote since we never declared
2661+ # rl_completer_quote_characters.
2662+ rl_basic_quote_characters .value = None
2663+
2664+ elif sys .platform .startswith ('win' ):
2665+ readline .rl .mode ._display_completions = self ._display_matches_pyreadline
2666+
26652667 try :
26662668 self .old_completer = readline .get_completer ()
26672669 self .old_delims = readline .get_completer_delims ()
26682670 readline .set_completer (self .complete )
26692671
26702672 # Break words on whitespace and quotes when tab completing
26712673 completer_delims = " \t \n \" '"
2674+
26722675 if self .allow_redirection :
26732676 # If redirection is allowed, then break words on those characters too
26742677 completer_delims += '' .join (REDIRECTION_CHARS )
2678+
26752679 readline .set_completer_delims (completer_delims )
26762680
26772681 # Enable tab completion
@@ -2702,12 +2706,21 @@ def _cmdloop(self):
27022706 stop = self .onecmd_plus_hooks (line )
27032707 finally :
27042708 if self .use_rawinput and self .completekey :
2709+
2710+ # Restore what we changed in readline
27052711 try :
27062712 readline .set_completer (self .old_completer )
27072713 readline .set_completer_delims (self .old_delims )
27082714 except NameError :
27092715 pass
27102716
2717+ if readline_lib is not None :
2718+ readline .set_completion_display_matches_hook (None )
2719+ rl_basic_quote_characters .value = orig_rl_basic_quote_characters_addr
2720+
2721+ elif sys .platform .startswith ('win' ):
2722+ readline .rl .mode ._display_completions = orig_pyreadline_display
2723+
27112724 # Need to set empty list this way because Python 2 doesn't support the clear() method on lists
27122725 self .cmdqueue = []
27132726 self ._script_dir = []
0 commit comments