6464else :
6565 from .rl_utils import rl_force_redisplay , readline
6666
67+ # Used by rlcompleter in Python console loaded by py command
68+ orig_rl_delims = readline .get_completer_delims ()
69+
6770 if rl_type == RlType .PYREADLINE :
6871
6972 # Save the original pyreadline display completion function since we need to override it and restore it
7982 import ctypes
8083 from .rl_utils import readline_lib
8184
85+ rl_basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
86+ orig_rl_basic_quotes = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
87+
8288from .argparse_completer import AutoCompleter , ACArgumentParser
8389
8490# Newer versions of pyperclip are released as a single file, but older versions had a more complicated structure
@@ -2025,7 +2031,6 @@ def _cmdloop(self):
20252031 # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
20262032 # We don't need to worry about setting rl_completion_suppress_quote since we never declared
20272033 # rl_completer_quote_characters.
2028- rl_basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
20292034 old_basic_quotes = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
20302035 rl_basic_quote_characters .value = None
20312036
@@ -2586,8 +2591,36 @@ def quit():
25862591 readline .add_history (item )
25872592
25882593 if self .use_rawinput and self .completekey :
2589- # Disable tab completion while in interactive Python shell
2590- readline .parse_and_bind (self .completekey + ": " )
2594+ # Set up tab completion for the Python console
2595+ # rlcompleter relies on the default settings of the Python readline module
2596+ if rl_type == RlType .GNU :
2597+ old_basic_quotes = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
2598+ rl_basic_quote_characters .value = orig_rl_basic_quotes
2599+
2600+ if 'gnureadline' in sys .modules :
2601+ # rlcompleter imports readline by name, so it won't use gnureadline
2602+ # Force rlcompleter to use gnureadline instead so it has our settings and history
2603+ saved_readline = None
2604+ if 'readline' in sys .modules :
2605+ saved_readline = sys .modules ['readline' ]
2606+
2607+ sys .modules ['readline' ] = sys .modules ['gnureadline' ]
2608+
2609+ old_delims = readline .get_completer_delims ()
2610+ readline .set_completer_delims (orig_rl_delims )
2611+
2612+ # rlcompleter will not need cmd2's custom display function
2613+ # This will be restored by cmd2 the next time complete() is called
2614+ if rl_type == RlType .GNU :
2615+ readline .set_completion_display_matches_hook (None )
2616+ elif rl_type == RlType .PYREADLINE :
2617+ readline .rl .mode ._display_completions = self ._display_matches_pyreadline
2618+
2619+ # Load rlcompleter so it sets its completer function
2620+ old_completer = readline .get_completer ()
2621+ import rlcompleter
2622+ import importlib
2623+ importlib .reload (rlcompleter )
25912624
25922625 cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
25932626 keepstate = Statekeeper (sys , ('stdin' , 'stdout' ))
@@ -2609,14 +2642,26 @@ def quit():
26092642 for i in range (1 , readline .get_current_history_length () + 1 ):
26102643 self .py_history .append (readline .get_history_item (i ))
26112644
2612- # Restore cmd2 history
2645+ # Restore cmd2's history
26132646 readline .clear_history ()
26142647 for item in saved_cmd2_history :
26152648 readline .add_history (item )
26162649
26172650 if self .use_rawinput and self .completekey :
2618- # Enable tab completion since we are returning to cmd2
2619- readline .parse_and_bind (self .completekey + ": complete" )
2651+ # Restore cmd2's tab completion settings
2652+ readline .set_completer (old_completer )
2653+ readline .set_completer_delims (old_delims )
2654+
2655+ if rl_type == RlType .GNU :
2656+ rl_basic_quote_characters .value = old_basic_quotes
2657+
2658+ if 'gnureadline' in sys .modules :
2659+ # Restore what the readline module pointed to
2660+ if saved_readline is None :
2661+ del (sys .modules ['readline' ])
2662+ else :
2663+ sys .modules ['readline' ] = saved_readline
2664+
26202665 except Exception :
26212666 pass
26222667 finally :
0 commit comments