4444import traceback
4545import unittest
4646from code import InteractiveConsole
47+ from enum import Enum
4748
4849import pyparsing
4950import pyperclip
@@ -128,25 +129,43 @@ def __subclasshook__(cls, C):
128129 except ImportError :
129130 pass
130131
131- # Load the GNU readline lib so we can make changes to it
132- readline_lib = None
133- if not sys .platform .startswith ('win' ):
134- import ctypes
135- from ctypes .util import find_library
136132
137- readline_lib_name = find_library ("readline" )
138- if readline_lib_name is not None and readline_lib_name :
139- readline_lib = ctypes .CDLL (readline_lib_name )
133+ # Tells what implementation of readline we are using
134+ class RlType (Enum ):
135+ GNU = 1
136+ PYREADLINE = 2
137+ NONE = 3
140138
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
144139
145- else :
140+ # Check what implementation of readline we are using
141+ rl_type = RlType .NONE
142+
143+ if 'pyreadline' in sys .modules :
144+ rl_type = RlType .PYREADLINE
145+
146146 # Save the original pyreadline display completion function since we need to override it and restore it
147147 # noinspection PyProtectedMember
148148 orig_pyreadline_display = readline .rl .mode ._display_completions
149149
150+ else :
151+ readline_lib_path = ''
152+
153+ if 'gnureadline' in sys .modules :
154+ readline_lib_path = sys .modules ['gnureadline' ].__dict__ ['__file__' ]
155+ elif 'readline' in sys .modules :
156+ readline_lib_path = sys .modules ['readline' ].__dict__ ['__file__' ]
157+
158+ # Load the readline lib so we can make changes to it
159+ if readline_lib_path :
160+ rl_type = RlType .GNU
161+
162+ import ctypes
163+ readline_lib = ctypes .CDLL (readline_lib_path )
164+
165+ # Save address that rl_basic_quote_characters is pointing to since we need to override and restore it
166+ rl_basic_quote_characters = ctypes .c_char_p .in_dll (readline_lib , "rl_basic_quote_characters" )
167+ orig_rl_basic_quote_characters_addr = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
168+
150169
151170# BrokenPipeError and FileNotFoundError exist only in Python 3. Use IOError for Python 2.
152171if six .PY3 :
@@ -1227,7 +1246,7 @@ def display_match_list_gnu_readline(substitution, matches, longest_match_length)
12271246 :param matches: list[str] - the tab completion matches to display
12281247 :param longest_match_length: int - longest printed length of the matches
12291248 """
1230- if readline_lib is not None :
1249+ if rl_type == RlType . GNU :
12311250 # We will use readline's display function (rl_display_match_list()), so we
12321251 # need to encode our string as bytes to place in a C array.
12331252 if six .PY3 :
@@ -1265,7 +1284,7 @@ def display_match_list_pyreadline(matches):
12651284 Prints a match list using pyreadline's _display_completions()
12661285 :param matches: list[str] - the tab completion matches to display
12671286 """
1268- if orig_pyreadline_display is not None :
1287+ if rl_type == RlType . PYREADLINE :
12691288 orig_pyreadline_display (matches )
12701289
12711290 def tokens_for_completion (self , line , begidx , endidx ):
@@ -1903,8 +1922,7 @@ def _set_readline_line(new_line):
19031922 Sets the readline line buffer
19041923 :param new_line: str - the new line contents
19051924 """
1906- # GNU readline specific way to update line buffer
1907- if readline_lib is not None :
1925+ if rl_type == RlType .GNU :
19081926 # Byte encode the new line
19091927 if six .PY3 :
19101928 encoded_line = bytes (new_line , encoding = 'utf-8' )
@@ -1914,8 +1932,7 @@ def _set_readline_line(new_line):
19141932 # Replace the line
19151933 readline_lib .rl_replace_line (encoded_line , 0 )
19161934
1917- # pyreadline specific way to update line buffer
1918- elif sys .platform .startswith ('win' ):
1935+ elif rl_type == RlType .PYREADLINE :
19191936 readline .rl .mode .l_buffer .set_line (new_line )
19201937
19211938 @staticmethod
@@ -1924,13 +1941,11 @@ def _set_readline_point(new_point):
19241941 Sets the cursor offset in the readline line buffer
19251942 :param new_point: int - the new cursor offset
19261943 """
1927- # GNU readline specific way to update line point
1928- if readline_lib is not None :
1944+ if rl_type == RlType .GNU :
19291945 rl_point = ctypes .c_int .in_dll (readline_lib , "rl_point" )
19301946 rl_point .value = new_point
19311947
1932- # pyreadline specific way to update line point
1933- elif sys .platform .startswith ('win' ):
1948+ elif rl_type == RlType .PYREADLINE :
19341949 readline .rl .mode .l_buffer .point = new_point
19351950
19361951 # ----- Methods which override stuff in cmd -----
@@ -2656,15 +2671,15 @@ def _cmdloop(self):
26562671 if self .use_rawinput and self .completekey :
26572672
26582673 # Set up readline for our tab completion needs
2659- if readline_lib is not None :
2674+ if rl_type == RlType . GNU :
26602675 readline .set_completion_display_matches_hook (self ._display_matches_gnu_readline )
26612676
26622677 # Set GNU readline's rl_basic_quote_characters to NULL so it won't automatically add a closing quote
26632678 # We don't need to worry about setting rl_completion_suppress_quote since we never declared
26642679 # rl_completer_quote_characters.
26652680 rl_basic_quote_characters .value = None
26662681
2667- elif sys . platform . startswith ( 'win' ) :
2682+ elif rl_type == RlType . PYREADLINE :
26682683 readline .rl .mode ._display_completions = self ._display_matches_pyreadline
26692684
26702685 try :
@@ -2717,11 +2732,11 @@ def _cmdloop(self):
27172732 except NameError :
27182733 pass
27192734
2720- if readline_lib is not None :
2735+ if rl_type == RlType . GNU :
27212736 readline .set_completion_display_matches_hook (None )
27222737 rl_basic_quote_characters .value = orig_rl_basic_quote_characters_addr
27232738
2724- elif sys . platform . startswith ( 'win' ) :
2739+ elif rl_type == RlType . PYREADLINE :
27252740 readline .rl .mode ._display_completions = orig_pyreadline_display
27262741
27272742 # Need to set empty list this way because Python 2 doesn't support the clear() method on lists
0 commit comments