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
@@ -580,11 +576,22 @@ def complete_submenu(_self, text, line, begidx, endidx):
580576 try :
581577 # copy over any shared attributes
582578 self ._copy_in_shared_attrs (_self )
579+
580+ # Reset the submenu's tab completion parameters
581+ submenu .allow_appended_space = True
582+ submenu .allow_closing_quote = True
583+ submenu .display_matches = []
584+
583585 return _complete_from_cmd (submenu , text , line , begidx , endidx )
584586 finally :
585587 # copy back original attributes
586588 self ._copy_out_shared_attrs (_self , original_attributes )
587589
590+ # Pass the submenu's tab completion parameters back up to the menu that called complete()
591+ _self .allow_appended_space = submenu .allow_appended_space
592+ _self .allow_closing_quote = submenu .allow_closing_quote
593+ _self .display_matches = copy .copy (submenu .display_matches )
594+
588595 original_do_help = cmd_obj .do_help
589596 original_complete_help = cmd_obj .complete_help
590597
@@ -972,6 +979,11 @@ def set_completion_defaults(self):
972979 self .allow_closing_quote = True
973980 self .display_matches = []
974981
982+ if rl_type == RlType .GNU :
983+ readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
984+ elif rl_type == RlType .PYREADLINE :
985+ readline .rl .mode ._display_completions = self ._display_matches_pyreadline
986+
975987 def tokens_for_completion (self , line , begidx , endidx ):
976988 """
977989 Used by tab completion functions to get all tokens through the one being completed
@@ -2342,38 +2354,33 @@ def _cmdloop(self):
23422354 """
23432355 # An almost perfect copy from Cmd; however, the pseudo_raw_input portion
23442356 # has been split out so that it can be called separately
2345- if self .use_rawinput and self .completekey :
2357+ if self .use_rawinput and self .completekey and rl_type != RlType . NONE :
23462358
23472359 # Set up readline for our tab completion needs
23482360 if rl_type == RlType .GNU :
2349- readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
2350-
23512361 # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
23522362 # We don't need to worry about setting rl_completion_suppress_quote since we never declared
23532363 # rl_completer_quote_characters.
2354- rl_basic_quote_characters .value = None
2364+ basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
2365+ old_basic_quote_characters = ctypes .cast (basic_quote_characters , ctypes .c_void_p ).value
2366+ basic_quote_characters .value = None
23552367
2356- elif rl_type == RlType .PYREADLINE :
2357- readline .rl .mode ._display_completions = self ._display_matches_pyreadline
2368+ old_completer = readline .get_completer ()
2369+ old_delims = readline .get_completer_delims ()
2370+ readline .set_completer (self .complete )
23582371
2359- try :
2360- self .old_completer = readline .get_completer ()
2361- self .old_delims = readline .get_completer_delims ()
2362- readline .set_completer (self .complete )
2372+ # Break words on whitespace and quotes when tab completing
2373+ completer_delims = " \t \n " + '' .join (constants .QUOTES )
23632374
2364- # Break words on whitespace and quotes when tab completing
2365- completer_delims = " \t \n " + '' .join (constants .QUOTES )
2375+ if self .allow_redirection :
2376+ # If redirection is allowed, then break words on those characters too
2377+ completer_delims += '' .join (constants .REDIRECTION_CHARS )
23662378
2367- if self .allow_redirection :
2368- # If redirection is allowed, then break words on those characters too
2369- completer_delims += '' .join (constants .REDIRECTION_CHARS )
2379+ readline .set_completer_delims (completer_delims )
23702380
2371- readline .set_completer_delims (completer_delims )
2381+ # Enable tab completion
2382+ readline .parse_and_bind (self .completekey + ": complete" )
23722383
2373- # Enable tab completion
2374- readline .parse_and_bind (self .completekey + ": complete" )
2375- except NameError :
2376- pass
23772384 stop = None
23782385 try :
23792386 while not stop :
@@ -2397,19 +2404,15 @@ def _cmdloop(self):
23972404 # Run the command along with all associated pre and post hooks
23982405 stop = self .onecmd_plus_hooks (line )
23992406 finally :
2400- if self .use_rawinput and self .completekey :
2407+ if self .use_rawinput and self .completekey and rl_type != RlType . NONE :
24012408
24022409 # Restore what we changed in readline
2403- try :
2404- readline .set_completer (self .old_completer )
2405- readline .set_completer_delims (self .old_delims )
2406- except NameError :
2407- pass
2410+ readline .set_completer (old_completer )
2411+ readline .set_completer_delims (old_delims )
24082412
24092413 if rl_type == RlType .GNU :
24102414 readline .set_completion_display_matches_hook (None )
2411- rl_basic_quote_characters .value = orig_rl_basic_quote_characters_addr
2412-
2415+ basic_quote_characters .value = old_basic_quote_characters
24132416 elif rl_type == RlType .PYREADLINE :
24142417 readline .rl .mode ._display_completions = orig_pyreadline_display
24152418
@@ -2755,7 +2758,7 @@ def show(self, args, parameter):
27552758 set_parser = ACArgumentParser (formatter_class = argparse .RawTextHelpFormatter )
27562759 set_parser .add_argument ('-a' , '--all' , action = 'store_true' , help = 'display read-only settings as well' )
27572760 set_parser .add_argument ('-l' , '--long' , action = 'store_true' , help = 'describe function of parameter' )
2758- set_parser .add_argument ('settable' , nargs = (0 ,2 ), help = '[param_name] [value]' )
2761+ set_parser .add_argument ('settable' , nargs = (0 , 2 ), help = '[param_name] [value]' )
27592762
27602763 @with_argparser (set_parser )
27612764 def do_set (self , args ):
@@ -2836,7 +2839,6 @@ def complete_shell(self, text, line, begidx, endidx):
28362839 index_dict = {1 : self .shell_cmd_complete }
28372840 return self .index_based_complete (text , line , begidx , endidx , index_dict , self .path_complete )
28382841
2839-
28402842 # noinspection PyBroadException
28412843 def do_py (self , arg ):
28422844 """
0 commit comments