@@ -11,21 +11,20 @@ class Editor:
1111 b"\x1b [F" : 0x03 ,
1212 b"\x1b OF" : 0x03 ,
1313 b"\x1b [4~" : 0x03 ,
14- b"\x1b [5~" : 0x17 ,
15- b"\x1b [6~" : 0x19 ,
14+ b"\x1b [5~" : 0xfff1 ,
15+ b"\x1b [6~" : 0xfff3 ,
1616 b"\x03 " : 0x11 ,
1717 b"\r " : 0x0a ,
1818 b"\x7f " : 0x08 ,
1919 b"\x1b [3~" : 0x7f ,
2020 b"\x1b [Z" : 0x15 ,
21- b"\x0b " : 0xfffd ,
2221 }
2322 yank_buffer = []
2423 find_pattern = ""
2524 def __init__ (self , tab_size , undo_limit ):
2625 self .top_line = self .cur_line = self .row = self .col = self .margin = 0
2726 self .tab_size = tab_size
28- self .changed = " "
27+ self .changed = ""
2928 self .message = self .fname = ""
3029 self .content = ["" ]
3130 self .undo = []
@@ -58,17 +57,24 @@ def hilite(self, mode):
5857 self .wr (b"\x1b [43m" )
5958 else :
6059 self .wr (b"\x1b [0m" )
61- def set_screen_parms (self ):
62- self .cursor (False )
60+ def get_screen_size (self ):
6361 self .wr ('\x1b [999;999H\x1b [6n' )
6462 pos = b''
6563 char = self .rd ()
6664 while char != b'R' :
6765 pos += char
6866 char = self .rd ()
69- (self .height , self .width ) = [int (i , 10 ) for i in pos [2 :].split (b';' )]
70- self .height -= 1
71- self .scrbuf = [(False ,"\x00 " )] * self .height
67+ return [int (i , 10 ) for i in pos [2 :].split (b';' )]
68+ def redraw (self , flag ):
69+ self .cursor (False )
70+ Editor .height , Editor .width = self .get_screen_size ()
71+ Editor .height -= 1
72+ Editor .scrbuf = [(False ,"\x00 " )] * Editor .height
73+ self .row = min (Editor .height - 1 , self .row )
74+ if sys .implementation .name == "micropython" :
75+ gc .collect ()
76+ if flag :
77+ self .message = "{} Bytes Memory available" .format (gc .mem_free ())
7278 def get_input (self ):
7379 while True :
7480 in_buffer = self .rd ()
@@ -87,39 +93,39 @@ def get_input(self):
8793 def display_window (self ):
8894 self .cur_line = min (self .total_lines - 1 , max (self .cur_line , 0 ))
8995 self .col = max (0 , min (self .col , len (self .content [self .cur_line ])))
90- if self .col >= self .width + self .margin :
91- self .margin = self .col - self .width + (self .width >> 2 )
96+ if self .col >= Editor .width + self .margin :
97+ self .margin = self .col - Editor .width + (Editor .width >> 2 )
9298 elif self .col < self .margin :
93- self .margin = max (self .col - (self .width >> 2 ), 0 )
94- if not (self .top_line <= self .cur_line < self .top_line + self .height ):
99+ self .margin = max (self .col - (Editor .width >> 2 ), 0 )
100+ if not (self .top_line <= self .cur_line < self .top_line + Editor .height ):
95101 self .top_line = max (self .cur_line - self .row , 0 )
96102 self .row = self .cur_line - self .top_line
97103 self .cursor (False )
98104 i = self .top_line
99- for c in range (self .height ):
105+ for c in range (Editor .height ):
100106 if i == self .total_lines :
101- if self .scrbuf [c ] != (False ,'' ):
107+ if Editor .scrbuf [c ] != (False ,'' ):
102108 self .goto (c , 0 )
103109 self .clear_to_eol ()
104- self .scrbuf [c ] = (False ,'' )
110+ Editor .scrbuf [c ] = (False ,'' )
105111 else :
106112 l = (self .mark != None and (
107113 (self .mark <= i <= self .cur_line ) or (self .cur_line <= i <= self .mark )),
108- self .content [i ][self .margin :self .margin + self .width ])
109- if l != self .scrbuf [c ]:
114+ self .content [i ][self .margin :self .margin + Editor .width ])
115+ if l != Editor .scrbuf [c ]:
110116 self .goto (c , 0 )
111117 if l [0 ]: self .hilite (2 )
112118 self .wr (l [1 ])
113- if len (l [1 ]) < self .width :
119+ if len (l [1 ]) < Editor .width :
114120 self .clear_to_eol ()
115121 if l [0 ]: self .hilite (0 )
116- self .scrbuf [c ] = l
122+ Editor .scrbuf [c ] = l
117123 i += 1
118- self .goto (self .height , 0 )
124+ self .goto (Editor .height , 0 )
119125 self .hilite (1 )
120- self .wr ("[{}] {} Row: {} Col: {} {}" .format (
121- self .total_lines , self .changed , self .cur_line + 1 ,
122- self .col + 1 , self .message [:self .width - 25 ]))
126+ self .wr ("{} {} Row: {}/ {} Col: {} {}" .format (
127+ self .changed , self .fname , self .cur_line + 1 , self . total_lines ,
128+ self .col + 1 , self .message [:Editor .width - 25 - len ( self . fname ) ]))
123129 self .clear_to_eol ()
124130 self .hilite (0 )
125131 self .goto (self .row , self .col - self .margin )
@@ -131,7 +137,7 @@ def line_range(self):
131137 return ((self .mark , self .cur_line + 1 ) if self .mark < self .cur_line else
132138 (self .cur_line , self .mark + 1 ))
133139 def line_edit (self , prompt , default ):
134- self .goto (self .height , 0 )
140+ self .goto (Editor .height , 0 )
135141 self .hilite (1 )
136142 self .wr (prompt )
137143 self .wr (default )
@@ -153,11 +159,11 @@ def line_edit(self, prompt, default):
153159 self .wr ('\b \b ' * len (res ))
154160 res = ''
155161 elif 0x20 <= key < 0xfff0 :
156- if len (prompt ) + len (res ) < self .width - 2 :
162+ if len (prompt ) + len (res ) < Editor .width - 2 :
157163 res += chr (key )
158164 self .wr (chr (key ))
159165 def find_in_file (self , pattern , pos , end ):
160- self .find_pattern = pattern
166+ Editor .find_pattern = pattern
161167 if self .case != "y" :
162168 pattern = pattern .lower ()
163169 spos = pos
@@ -184,7 +190,7 @@ def undo_add(self, lnum, text, key, span = 1):
184190 def delete_lines (self , yank ):
185191 lrange = self .line_range ()
186192 if yank :
187- self .yank_buffer = self .content [lrange [0 ]:lrange [1 ]]
193+ Editor .yank_buffer = self .content [lrange [0 ]:lrange [1 ]]
188194 self .undo_add (lrange [0 ], self .content [lrange [0 ]:lrange [1 ]], 0 , 0 )
189195 del self .content [lrange [0 ]:lrange [1 ]]
190196 if self .content == []:
@@ -228,65 +234,26 @@ def handle_edit_keys(self, key):
228234 self .col = self .spaces (l ) if self .col == 0 else 0
229235 elif key == 0x03 :
230236 self .col = len (l )
231- elif key == 0x17 :
232- self .cur_line -= self .height
233- elif key == 0x19 :
234- self .cur_line += self .height
237+ elif key == 0xfff1 :
238+ self .cur_line -= Editor .height
239+ elif key == 0xfff3 :
240+ self .cur_line += Editor .height
235241 elif key == 0x06 :
236- pat = self .line_edit ("Find: " , self .find_pattern )
242+ pat = self .line_edit ("Find: " , Editor .find_pattern )
237243 if pat :
238244 self .find_in_file (pat , self .col , self .total_lines )
239- self .row = self .height >> 1
245+ self .row = Editor .height >> 1
240246 elif key == 0x0e :
241- if self .find_pattern :
242- self .find_in_file (self .find_pattern , self .col + 1 , self .total_lines )
243- self .row = self .height >> 1
247+ if Editor .find_pattern :
248+ self .find_in_file (Editor .find_pattern , self .col + 1 , self .total_lines )
249+ self .row = Editor .height >> 1
244250 elif key == 0x07 :
245251 line = self .line_edit ("Goto Line: " , "" )
246252 if line :
247253 self .cur_line = int (line ) - 1
248- self .row = self .height >> 1
254+ self .row = Editor .height >> 1
249255 elif key == 0x01 :
250256 self .autoindent = 'y' if self .autoindent != 'y' else 'n'
251- elif key == 0xfffd :
252- if self .col < len (l ):
253- opening = "([{<"
254- closing = ")]}>"
255- level = 0
256- pos = self .col
257- srch = l [pos ]
258- i = opening .find (srch )
259- if i >= 0 :
260- pos += 1
261- match = closing [i ]
262- for i in range (self .cur_line , self .total_lines ):
263- for c in range (pos , len (self .content [i ])):
264- if self .content [i ][c ] == match :
265- if level == 0 :
266- self .cur_line , self .col = i , c
267- return True
268- else :
269- level -= 1
270- elif self .content [i ][c ] == srch :
271- level += 1
272- pos = 0
273- else :
274- i = closing .find (srch )
275- if i >= 0 :
276- pos -= 1
277- match = opening [i ]
278- for i in range (self .cur_line , - 1 , - 1 ):
279- for c in range (pos , - 1 , - 1 ):
280- if self .content [i ][c ] == match :
281- if level == 0 :
282- self .cur_line , self .col = i , c
283- return True
284- else :
285- level -= 1
286- elif self .content [i ][c ] == srch :
287- level += 1
288- if i > 0 :
289- pos = len (self .content [i - 1 ]) - 1
290257 elif key == 0x0c :
291258 self .mark = self .cur_line if self .mark == None else None
292259 elif key == 0x0a :
@@ -308,8 +275,8 @@ def handle_edit_keys(self, key):
308275 if len (self .content [i ]) > 0 :
309276 self .content [i ] = ' ' * (self .tab_size - self .spaces (self .content [i ]) % self .tab_size ) + self .content [i ]
310277 else :
311- self .undo_add (self .cur_line , [l ], 0x09 )
312278 ni = self .tab_size - self .col % self .tab_size
279+ self .undo_add (self .cur_line , [l ], 0x09 )
313280 self .content [self .cur_line ] = l [:self .col ] + ' ' * ni + l [self .col :]
314281 self .col += ni
315282 elif key == 0x15 :
@@ -332,23 +299,22 @@ def handle_edit_keys(self, key):
332299 elif key == 0x04 :
333300 if self .mark != None :
334301 lrange = self .line_range ()
335- self .yank_buffer = self .content [lrange [0 ]:lrange [1 ]]
302+ Editor .yank_buffer = self .content [lrange [0 ]:lrange [1 ]]
336303 self .mark = None
337304 elif key == 0x16 :
338- if self .yank_buffer :
305+ if Editor .yank_buffer :
339306 if self .mark != None :
340307 self .delete_lines (False )
341- self .undo_add (self .cur_line , None , 0 , - len (self .yank_buffer ))
342- self .content [self .cur_line :self .cur_line ] = self .yank_buffer
343- self .total_lines += len (self .yank_buffer )
308+ self .undo_add (self .cur_line , None , 0 , - len (Editor .yank_buffer ))
309+ self .content [self .cur_line :self .cur_line ] = Editor .yank_buffer
310+ self .total_lines += len (Editor .yank_buffer )
344311 elif key == 0x13 :
345- if True :
346- fname = self .line_edit ("Save File: " , self .fname )
347- if fname :
348- self .put_file (fname , 0 , self .total_lines )
349- self .changed = ' '
350- self .undo_zero = len (self .undo )
351- self .fname = fname
312+ fname = self .line_edit ("Save File: " , self .fname )
313+ if fname :
314+ self .put_file (fname )
315+ self .changed = ''
316+ self .undo_zero = len (self .undo )
317+ if not self .fname : self .fname = fname
352318 elif key == 0x1a :
353319 if len (self .undo ) > 0 :
354320 action = self .undo .pop (- 1 )
@@ -363,50 +329,49 @@ def handle_edit_keys(self, key):
363329 else :
364330 del self .content [action [0 ]:action [0 ] - action [1 ]]
365331 self .total_lines = len (self .content )
366- self .changed = ' ' if len (self .undo ) == self .undo_zero else '*'
332+ if len (self .undo ) == self .undo_zero :
333+ self .changed = ''
367334 self .mark = None
335+ elif key == 0x05 :
336+ self .redraw (True )
368337 def edit_loop (self ):
369- if self .content == [] :
338+ if not self .content :
370339 self .content = ["" ]
371340 self .total_lines = len (self .content )
372- key = 0x05
341+ self . redraw ( self . message == "" )
373342 while True :
374343 try :
375- if key == 0x05 :
376- self .set_screen_parms ()
377- self .row = min (self .height - 1 , self .row )
378- if sys .implementation .name == "micropython" :
379- gc .collect ()
380- self .message = "{} Bytes Memory available" .format (gc .mem_free ())
381344 if not self .rd_any ():
382345 self .display_window ()
383346 key = self .get_input ()
384347 self .message = ''
385348 if key == 0x11 :
386- if self .changed != ' ' :
349+ if self .changed != '' :
387350 res = self .line_edit ("Content changed! Quit without saving (y/N)? " , "N" )
388351 if not res or res [0 ].upper () != 'Y' :
389352 continue
390- self .goto (self .height , 0 )
391- self .clear_to_eol ()
392- return None
353+ return (key , "" )
354+ elif key == 0x17 :
355+ return (key , "" )
356+ elif key == 0x0f :
357+ return (key , self .line_edit ("Open file: " , "" ))
393358 else : self .handle_edit_keys (key )
394359 except Exception as err :
395- self .message = "{}" .format (err )
360+ self .message = "{!r }" .format (err )
396361 def get_file (self , fname ):
362+ self .fname = fname
397363 try :
398364 with open (fname ) as f :
399- content = f .readlines ()
365+ self . content = f .readlines ()
400366 except Exception as err :
401- message = 'Could not load {}, {!r}' .format (fname , err )
402- return (None , message )
403- for i in range (len (content )):
404- content [i ] = expandtabs (content [i ].rstrip ('\r \n \t ' ))
405- return (content , "" )
406- def put_file (self , fname , start , stop ):
367+ self .content , self .message = ["" ], "{!r}" .format (err )
368+ else :
369+ for i in range (len (self .content )):
370+ self .content [i ] = expandtabs (self .content [i ].rstrip ('\r \n \t ' ))
371+ def put_file (self , fname ):
407372 import os
408373 with open ("tmpfile.pye" , "w" ) as f :
409- for l in self .content [ start : stop ] :
374+ for l in self .content :
410375 f .write (l + '\n ' )
411376 try : os .unlink (fname )
412377 except : pass
@@ -426,16 +391,36 @@ def expandtabs(s):
426391 return sb .getvalue ()
427392 else :
428393 return s
429- def pye (content = None , tab_size = 4 , undo = 50 , device = 0 , baud = 115200 ):
394+ def pye (* content , tab_size = 4 , undo = 50 , device = 0 , baud = 115200 ):
430395 gc .collect ()
431- e = Editor (tab_size , undo )
432- if type (content ) == str and content :
433- e .fname = content
434- (e .content , e .message ) = e .get_file (e .fname )
435- if e .content == None :
436- print (e .message )
437- return
438- elif type (content ) == list and len (content ) > 0 and type (content [0 ]) == str :
439- e .content = content
440- e .edit_loop ()
441- return e .content if (e .fname == "" ) else e .fname
396+ if content :
397+ slot = []
398+ index = 0
399+ for f in content :
400+ slot .append (Editor (tab_size , undo ))
401+ if type (f ) == str and f :
402+ slot [index ].get_file (f )
403+ elif type (f ) == list and len (f ) > 0 and type (f [0 ]) == str :
404+ slot [index ].content = f
405+ index += 1
406+ else :
407+ slot = [Editor (tab_size , undo )]
408+ index = 0
409+ while True :
410+ key ,f = slot [index ].edit_loop ()
411+ if key == 0x11 :
412+ if len (slot ) == 1 :
413+ break
414+ del slot [index ]
415+ index %= len (slot )
416+ elif key == 0x0f :
417+ slot .append (Editor (tab_size , undo ))
418+ index = len (slot ) - 1
419+ if f :
420+ slot [index ].get_file (f )
421+ elif key == 0x17 :
422+ index = (index + 1 ) % len (slot )
423+ slot [0 ].goto (slot [0 ].height , 0 )
424+ slot [0 ].clear_to_eol ()
425+ slot [0 ].undo , Editor .yank_buffer = [],[]
426+ return slot [0 ].content if (slot [0 ].fname == "" ) else slot [0 ].fname
0 commit comments