7171 import ctypes
7272 from .rl_utils import readline_lib
7373
74- # Save address that rl_basic_quote_characters is pointing to since we need to override and restore it
75- rl_basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
76- orig_rl_basic_quote_characters_addr = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
77-
7874# Newer versions of pyperclip are released as a single file, but older versions had a more complicated structure
7975try :
8076 from pyperclip .exceptions import PyperclipException
@@ -595,11 +591,22 @@ def complete_submenu(_self, text, line, begidx, endidx):
595591 try :
596592 # copy over any shared attributes
597593 self ._copy_in_shared_attrs (_self )
594+
595+ # Reset the submenu's tab completion parameters
596+ submenu .allow_appended_space = True
597+ submenu .allow_closing_quote = True
598+ submenu .display_matches = []
599+
598600 return _complete_from_cmd (submenu , text , line , begidx , endidx )
599601 finally :
600602 # copy back original attributes
601603 self ._copy_out_shared_attrs (_self , original_attributes )
602604
605+ # Pass the submenu's tab completion parameters back up to the menu that called complete()
606+ _self .allow_appended_space = submenu .allow_appended_space
607+ _self .allow_closing_quote = submenu .allow_closing_quote
608+ _self .display_matches = copy .copy (submenu .display_matches )
609+
603610 original_do_help = cmd_obj .do_help
604611 original_complete_help = cmd_obj .complete_help
605612
@@ -987,6 +994,11 @@ def set_completion_defaults(self):
987994 self .allow_closing_quote = True
988995 self .display_matches = []
989996
997+ if rl_type == RlType .GNU :
998+ readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
999+ elif rl_type == RlType .PYREADLINE :
1000+ readline .rl .mode ._display_completions = self ._display_matches_pyreadline
1001+
9901002 def tokens_for_completion (self , line , begidx , endidx ):
9911003 """
9921004 Used by tab completion functions to get all tokens through the one being completed
@@ -2357,38 +2369,33 @@ def _cmdloop(self):
23572369 """
23582370 # An almost perfect copy from Cmd; however, the pseudo_raw_input portion
23592371 # has been split out so that it can be called separately
2360- if self .use_rawinput and self .completekey :
2372+ if self .use_rawinput and self .completekey and rl_type != RlType . NONE :
23612373
23622374 # Set up readline for our tab completion needs
23632375 if rl_type == RlType .GNU :
2364- readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
2365-
23662376 # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
23672377 # We don't need to worry about setting rl_completion_suppress_quote since we never declared
23682378 # rl_completer_quote_characters.
2369- rl_basic_quote_characters .value = None
2379+ basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
2380+ old_basic_quote_characters = ctypes .cast (basic_quote_characters , ctypes .c_void_p ).value
2381+ basic_quote_characters .value = None
23702382
2371- elif rl_type == RlType .PYREADLINE :
2372- readline .rl .mode ._display_completions = self ._display_matches_pyreadline
2383+ old_completer = readline .get_completer ()
2384+ old_delims = readline .get_completer_delims ()
2385+ readline .set_completer (self .complete )
23732386
2374- try :
2375- self .old_completer = readline .get_completer ()
2376- self .old_delims = readline .get_completer_delims ()
2377- readline .set_completer (self .complete )
2387+ # Break words on whitespace and quotes when tab completing
2388+ completer_delims = " \t \n " + '' .join (constants .QUOTES )
23782389
2379- # Break words on whitespace and quotes when tab completing
2380- completer_delims = " \t \n " + '' .join (constants .QUOTES )
2390+ if self .allow_redirection :
2391+ # If redirection is allowed, then break words on those characters too
2392+ completer_delims += '' .join (constants .REDIRECTION_CHARS )
23812393
2382- if self .allow_redirection :
2383- # If redirection is allowed, then break words on those characters too
2384- completer_delims += '' .join (constants .REDIRECTION_CHARS )
2394+ readline .set_completer_delims (completer_delims )
23852395
2386- readline .set_completer_delims (completer_delims )
2396+ # Enable tab completion
2397+ readline .parse_and_bind (self .completekey + ": complete" )
23872398
2388- # Enable tab completion
2389- readline .parse_and_bind (self .completekey + ": complete" )
2390- except NameError :
2391- pass
23922399 stop = None
23932400 try :
23942401 while not stop :
@@ -2412,19 +2419,15 @@ def _cmdloop(self):
24122419 # Run the command along with all associated pre and post hooks
24132420 stop = self .onecmd_plus_hooks (line )
24142421 finally :
2415- if self .use_rawinput and self .completekey :
2422+ if self .use_rawinput and self .completekey and rl_type != RlType . NONE :
24162423
24172424 # Restore what we changed in readline
2418- try :
2419- readline .set_completer (self .old_completer )
2420- readline .set_completer_delims (self .old_delims )
2421- except NameError :
2422- pass
2425+ readline .set_completer (old_completer )
2426+ readline .set_completer_delims (old_delims )
24232427
24242428 if rl_type == RlType .GNU :
24252429 readline .set_completion_display_matches_hook (None )
2426- rl_basic_quote_characters .value = orig_rl_basic_quote_characters_addr
2427-
2430+ basic_quote_characters .value = old_basic_quote_characters
24282431 elif rl_type == RlType .PYREADLINE :
24292432 readline .rl .mode ._display_completions = orig_pyreadline_display
24302433
@@ -2770,7 +2773,7 @@ def show(self, args, parameter):
27702773 set_parser = ACArgumentParser (formatter_class = argparse .RawTextHelpFormatter )
27712774 set_parser .add_argument ('-a' , '--all' , action = 'store_true' , help = 'display read-only settings as well' )
27722775 set_parser .add_argument ('-l' , '--long' , action = 'store_true' , help = 'describe function of parameter' )
2773- set_parser .add_argument ('settable' , nargs = (0 ,2 ), help = '[param_name] [value]' )
2776+ set_parser .add_argument ('settable' , nargs = (0 , 2 ), help = '[param_name] [value]' )
27742777
27752778 @with_argparser (set_parser )
27762779 def do_set (self , args ):
@@ -2851,7 +2854,6 @@ def complete_shell(self, text, line, begidx, endidx):
28512854 index_dict = {1 : self .shell_cmd_complete }
28522855 return self .index_based_complete (text , line , begidx , endidx , index_dict , self .path_complete )
28532856
2854-
28552857 # noinspection PyBroadException
28562858 def do_py (self , arg ):
28572859 """
0 commit comments