1818# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1919# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2020
21+ import re
2122from pyrepl import commands , reader
2223from pyrepl .reader import Reader
2324
2425
25- def prefix (wordlist , j = 0 ):
26+ def prefix (wordlist , j = 0 ):
2627 d = {}
2728 i = j
2829 try :
@@ -36,14 +37,18 @@ def prefix(wordlist, j = 0):
3637 except IndexError :
3738 return wordlist [0 ][j :i ]
3839
39- import re
40+
41+ STRIPCOLOR_REGEX = re .compile (r"\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[m|K]" )
42+
43+
4044def stripcolor (s ):
41- return stripcolor .regexp .sub ('' , s )
42- stripcolor . regexp = re . compile ( r"\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[m|K]" )
45+ return STRIPCOLOR_REGEX .regexp .sub ('' , s )
46+
4347
4448def real_len (s ):
4549 return len (stripcolor (s ))
4650
51+
4752def left_align (s , maxlen ):
4853 stripped = stripcolor (s )
4954 if len (stripped ) > maxlen :
@@ -52,6 +57,7 @@ def left_align(s, maxlen):
5257 padding = maxlen - len (stripped )
5358 return s + ' ' * padding
5459
60+
5561def build_menu (cons , wordlist , start , use_brackets , sort_in_column ):
5662 if use_brackets :
5763 item = "[ %s ]"
@@ -66,14 +72,14 @@ def build_menu(cons, wordlist, start, use_brackets, sort_in_column):
6672 if sort_in_column :
6773 # sort_in_column=False (default) sort_in_column=True
6874 # A B C A D G
69- # D E F B E
75+ # D E F B E
7076 # G C F
7177 #
7278 # "fill" the table with empty words, so we always have the same amout
7379 # of rows for each column
7480 missing = cols * rows - len (wordlist )
7581 wordlist = wordlist + ['' ]* missing
76- indexes = [(i % cols )* rows + i // cols for i in range (len (wordlist ))]
82+ indexes = [(i % cols ) * rows + i // cols for i in range (len (wordlist ))]
7783 wordlist = [wordlist [i ] for i in indexes ]
7884 menu = []
7985 i = start
@@ -84,14 +90,14 @@ def build_menu(cons, wordlist, start, use_brackets, sort_in_column):
8490 i += 1
8591 if i >= len (wordlist ):
8692 break
87- menu .append ( '' .join (row ) )
93+ menu .append ('' .join (row ))
8894 if i >= len (wordlist ):
8995 i = 0
9096 break
9197 if r + 5 > cons .height :
92- menu .append (" %d more... " % (len (wordlist ) - i ))
98+ menu .append (" %d more... " % (len (wordlist ) - i ))
9399 break
94- return menu , i
100+ return menu , i
95101
96102# this gets somewhat user interface-y, and as a result the logic gets
97103# very convoluted.
@@ -118,7 +124,7 @@ def build_menu(cons, wordlist, start, use_brackets, sort_in_column):
118124# only if the ``assume_immutable_completions`` is True.
119125#
120126# now it gets complicated.
121- #
127+ #
122128# for the first press of a completion key:
123129# if there's a common prefix, stick it in.
124130
@@ -140,30 +146,30 @@ def build_menu(cons, wordlist, start, use_brackets, sort_in_column):
140146# for subsequent bangs, rotate the menu around (if there are sufficient
141147# choices).
142148
149+
143150class complete (commands .Command ):
144151 def do (self ):
145152 r = self .reader
153+ last_is_completer = r .last_command_is (self .__class__ )
154+ immutable_completions = r .assume_immutable_completions
155+ completions_unchangable = last_is_completer and immutable_completions
146156 stem = r .get_stem ()
147- if r .assume_immutable_completions and \
148- r .last_command_is (self .__class__ ):
149- completions = r .cmpltn_menu_choices
150- else :
151- r .cmpltn_menu_choices = completions = \
152- r .get_completions (stem )
153- if len (completions ) == 0 :
157+ if not completions_unchangable :
158+ r .cmpltn_menu_choices = r .get_completions (stem )
159+
160+ completions = r .cmpltn_menu_choices
161+ if not completions :
154162 r .error ("no matches" )
155163 elif len (completions ) == 1 :
156- if r .assume_immutable_completions and \
157- len (completions [0 ]) == len (stem ) and \
158- r .last_command_is (self .__class__ ):
164+ if completions_unchangable and len (completions [0 ]) == len (stem ):
159165 r .msg = "[ sole completion ]"
160166 r .dirty = 1
161167 r .insert (completions [0 ][len (stem ):])
162168 else :
163169 p = prefix (completions , len (stem ))
164170 if p :
165171 r .insert (p )
166- if r . last_command_is ( self . __class__ ) :
172+ if last_is_completer :
167173 if not r .cmpltn_menu_vis :
168174 r .cmpltn_menu_vis = 1
169175 r .cmpltn_menu , r .cmpltn_menu_end = build_menu (
@@ -177,6 +183,7 @@ def do(self):
177183 r .msg = "[ not unique ]"
178184 r .dirty = 1
179185
186+
180187class self_insert (commands .self_insert ):
181188 def do (self ):
182189 commands .self_insert .do (self )
@@ -195,6 +202,7 @@ def do(self):
195202 else :
196203 r .cmpltn_reset ()
197204
205+
198206class CompletingReader (Reader ):
199207 """Adds completion support
200208
@@ -204,26 +212,25 @@ class CompletingReader(Reader):
204212 """
205213 # see the comment for the complete command
206214 assume_immutable_completions = True
207- use_brackets = True # display completions inside []
215+ use_brackets = True # display completions inside []
208216 sort_in_column = False
209-
217+
210218 def collect_keymap (self ):
211219 return super (CompletingReader , self ).collect_keymap () + (
212220 (r'\t' , 'complete' ),)
213-
221+
214222 def __init__ (self , console ):
215223 super (CompletingReader , self ).__init__ (console )
216224 self .cmpltn_menu = ["[ menu 1 ]" , "[ menu 2 ]" ]
217225 self .cmpltn_menu_vis = 0
218226 self .cmpltn_menu_end = 0
219- for c in [ complete , self_insert ] :
227+ for c in ( complete , self_insert ) :
220228 self .commands [c .__name__ ] = c
221- self .commands [c .__name__ .replace ('_' , '-' )] = c
229+ self .commands [c .__name__ .replace ('_' , '-' )] = c
222230
223231 def after_command (self , cmd ):
224232 super (CompletingReader , self ).after_command (cmd )
225- if not isinstance (cmd , self .commands ['complete' ]) \
226- and not isinstance (cmd , self .commands ['self_insert' ]):
233+ if not isinstance (cmd , (complete , self_insert )):
227234 self .cmpltn_reset ()
228235
229236 def calc_screen (self ):
@@ -243,7 +250,7 @@ def cmpltn_reset(self):
243250 self .cmpltn_menu = []
244251 self .cmpltn_menu_vis = 0
245252 self .cmpltn_menu_end = 0
246- self .cmpltn_menu_choices = []
253+ self .cmpltn_menu_choices = []
247254
248255 def get_stem (self ):
249256 st = self .syntax_table
@@ -257,11 +264,14 @@ def get_stem(self):
257264 def get_completions (self , stem ):
258265 return []
259266
267+
260268def test ():
261269 class TestReader (CompletingReader ):
262270 def get_completions (self , stem ):
263- return [s for l in map (lambda x :x .split (),self .history )
264- for s in l if s and s .startswith (stem )]
271+ return [s for l in self .history
272+ for s in l .split ()
273+ if s and s .startswith (stem )]
274+
265275 reader = TestReader ()
266276 reader .ps1 = "c**> "
267277 reader .ps2 = "c/*> "
@@ -270,5 +280,6 @@ def get_completions(self, stem):
270280 while reader .readline ():
271281 pass
272282
273- if __name__ == '__main__' :
283+
284+ if __name__ == '__main__' :
274285 test ()
0 commit comments