@@ -164,10 +164,6 @@ class RlType(Enum):
164164 import ctypes
165165 readline_lib = ctypes .CDLL (readline .__file__ )
166166
167- # Save address that rl_basic_quote_characters is pointing to since we need to override and restore it
168- rl_basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
169- orig_rl_basic_quote_characters_addr = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
170-
171167
172168# BrokenPipeError and FileNotFoundError exist only in Python 3. Use IOError for Python 2.
173169if six .PY3 :
@@ -889,11 +885,22 @@ def complete_submenu(_self, text, line, begidx, endidx):
889885 try :
890886 # copy over any shared attributes
891887 self ._copy_in_shared_attrs (_self )
888+
889+ # Reset the submenu's tab completion parameters
890+ submenu .allow_appended_space = True
891+ submenu .allow_closing_quote = True
892+ submenu .display_matches = []
893+
892894 return _complete_from_cmd (submenu , text , line , begidx , endidx )
893895 finally :
894896 # copy back original attributes
895897 self ._copy_out_shared_attrs (_self , original_attributes )
896898
899+ # Pass the submenu's tab completion parameters back up to the menu that called complete()
900+ _self .allow_appended_space = submenu .allow_appended_space
901+ _self .allow_closing_quote = submenu .allow_closing_quote
902+ _self .display_matches = copy .copy (submenu .display_matches )
903+
897904 original_do_help = cmd_obj .do_help
898905 original_complete_help = cmd_obj .complete_help
899906
@@ -1324,6 +1331,11 @@ def set_completion_defaults(self):
13241331 self .allow_closing_quote = True
13251332 self .display_matches = []
13261333
1334+ if rl_type == RlType .GNU :
1335+ readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
1336+ elif rl_type == RlType .PYREADLINE :
1337+ readline .rl .mode ._display_completions = self ._display_matches_pyreadline
1338+
13271339 def tokens_for_completion (self , line , begidx , endidx ):
13281340 """
13291341 Used by tab completion functions to get all tokens through the one being completed
@@ -2699,38 +2711,33 @@ def _cmdloop(self):
26992711 """
27002712 # An almost perfect copy from Cmd; however, the pseudo_raw_input portion
27012713 # has been split out so that it can be called separately
2702- if self .use_rawinput and self .completekey :
2714+ if self .use_rawinput and self .completekey and rl_type != RlType . NONE :
27032715
27042716 # Set up readline for our tab completion needs
27052717 if rl_type == RlType .GNU :
2706- readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
2707-
27082718 # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
27092719 # We don't need to worry about setting rl_completion_suppress_quote since we never declared
27102720 # rl_completer_quote_characters.
2711- rl_basic_quote_characters .value = None
2721+ basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
2722+ old_basic_quote_characters = ctypes .cast (basic_quote_characters , ctypes .c_void_p ).value
2723+ basic_quote_characters .value = None
27122724
2713- elif rl_type == RlType .PYREADLINE :
2714- readline .rl .mode ._display_completions = self ._display_matches_pyreadline
2725+ old_completer = readline .get_completer ()
2726+ old_delims = readline .get_completer_delims ()
2727+ readline .set_completer (self .complete )
27152728
2716- try :
2717- self .old_completer = readline .get_completer ()
2718- self .old_delims = readline .get_completer_delims ()
2719- readline .set_completer (self .complete )
2729+ # Break words on whitespace and quotes when tab completing
2730+ completer_delims = " \t \n " + '' .join (QUOTES )
27202731
2721- # Break words on whitespace and quotes when tab completing
2722- completer_delims = " \t \n " + '' .join (QUOTES )
2732+ if self .allow_redirection :
2733+ # If redirection is allowed, then break words on those characters too
2734+ completer_delims += '' .join (REDIRECTION_CHARS )
27232735
2724- if self .allow_redirection :
2725- # If redirection is allowed, then break words on those characters too
2726- completer_delims += '' .join (REDIRECTION_CHARS )
2736+ readline .set_completer_delims (completer_delims )
27272737
2728- readline .set_completer_delims (completer_delims )
2738+ # Enable tab completion
2739+ readline .parse_and_bind (self .completekey + ": complete" )
27292740
2730- # Enable tab completion
2731- readline .parse_and_bind (self .completekey + ": complete" )
2732- except NameError :
2733- pass
27342741 stop = None
27352742 try :
27362743 while not stop :
@@ -2754,19 +2761,15 @@ def _cmdloop(self):
27542761 # Run the command along with all associated pre and post hooks
27552762 stop = self .onecmd_plus_hooks (line )
27562763 finally :
2757- if self .use_rawinput and self .completekey :
2764+ if self .use_rawinput and self .completekey and rl_type != RlType . NONE :
27582765
27592766 # Restore what we changed in readline
2760- try :
2761- readline .set_completer (self .old_completer )
2762- readline .set_completer_delims (self .old_delims )
2763- except NameError :
2764- pass
2767+ readline .set_completer (old_completer )
2768+ readline .set_completer_delims (old_delims )
27652769
27662770 if rl_type == RlType .GNU :
27672771 readline .set_completion_display_matches_hook (None )
2768- rl_basic_quote_characters .value = orig_rl_basic_quote_characters_addr
2769-
2772+ basic_quote_characters .value = old_basic_quote_characters
27702773 elif rl_type == RlType .PYREADLINE :
27712774 readline .rl .mode ._display_completions = orig_pyreadline_display
27722775
0 commit comments