@@ -11,21 +11,20 @@ class Editor:
11
11
b"\x1b [F" : 0x03 ,
12
12
b"\x1b OF" : 0x03 ,
13
13
b"\x1b [4~" : 0x03 ,
14
- b"\x1b [5~" : 0x17 ,
15
- b"\x1b [6~" : 0x19 ,
14
+ b"\x1b [5~" : 0xfff1 ,
15
+ b"\x1b [6~" : 0xfff3 ,
16
16
b"\x03 " : 0x11 ,
17
17
b"\r " : 0x0a ,
18
18
b"\x7f " : 0x08 ,
19
19
b"\x1b [3~" : 0x7f ,
20
20
b"\x1b [Z" : 0x15 ,
21
- b"\x0b " : 0xfffd ,
22
21
}
23
22
yank_buffer = []
24
23
find_pattern = ""
25
24
def __init__ (self , tab_size , undo_limit ):
26
25
self .top_line = self .cur_line = self .row = self .col = self .margin = 0
27
26
self .tab_size = tab_size
28
- self .changed = " "
27
+ self .changed = ""
29
28
self .message = self .fname = ""
30
29
self .content = ["" ]
31
30
self .undo = []
@@ -58,17 +57,24 @@ def hilite(self, mode):
58
57
self .wr (b"\x1b [43m" )
59
58
else :
60
59
self .wr (b"\x1b [0m" )
61
- def set_screen_parms (self ):
62
- self .cursor (False )
60
+ def get_screen_size (self ):
63
61
self .wr ('\x1b [999;999H\x1b [6n' )
64
62
pos = b''
65
63
char = self .rd ()
66
64
while char != b'R' :
67
65
pos += char
68
66
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 ())
72
78
def get_input (self ):
73
79
while True :
74
80
in_buffer = self .rd ()
@@ -87,39 +93,39 @@ def get_input(self):
87
93
def display_window (self ):
88
94
self .cur_line = min (self .total_lines - 1 , max (self .cur_line , 0 ))
89
95
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 )
92
98
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 ):
95
101
self .top_line = max (self .cur_line - self .row , 0 )
96
102
self .row = self .cur_line - self .top_line
97
103
self .cursor (False )
98
104
i = self .top_line
99
- for c in range (self .height ):
105
+ for c in range (Editor .height ):
100
106
if i == self .total_lines :
101
- if self .scrbuf [c ] != (False ,'' ):
107
+ if Editor .scrbuf [c ] != (False ,'' ):
102
108
self .goto (c , 0 )
103
109
self .clear_to_eol ()
104
- self .scrbuf [c ] = (False ,'' )
110
+ Editor .scrbuf [c ] = (False ,'' )
105
111
else :
106
112
l = (self .mark != None and (
107
113
(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 ]:
110
116
self .goto (c , 0 )
111
117
if l [0 ]: self .hilite (2 )
112
118
self .wr (l [1 ])
113
- if len (l [1 ]) < self .width :
119
+ if len (l [1 ]) < Editor .width :
114
120
self .clear_to_eol ()
115
121
if l [0 ]: self .hilite (0 )
116
- self .scrbuf [c ] = l
122
+ Editor .scrbuf [c ] = l
117
123
i += 1
118
- self .goto (self .height , 0 )
124
+ self .goto (Editor .height , 0 )
119
125
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 ) ]))
123
129
self .clear_to_eol ()
124
130
self .hilite (0 )
125
131
self .goto (self .row , self .col - self .margin )
@@ -131,7 +137,7 @@ def line_range(self):
131
137
return ((self .mark , self .cur_line + 1 ) if self .mark < self .cur_line else
132
138
(self .cur_line , self .mark + 1 ))
133
139
def line_edit (self , prompt , default ):
134
- self .goto (self .height , 0 )
140
+ self .goto (Editor .height , 0 )
135
141
self .hilite (1 )
136
142
self .wr (prompt )
137
143
self .wr (default )
@@ -153,11 +159,11 @@ def line_edit(self, prompt, default):
153
159
self .wr ('\b \b ' * len (res ))
154
160
res = ''
155
161
elif 0x20 <= key < 0xfff0 :
156
- if len (prompt ) + len (res ) < self .width - 2 :
162
+ if len (prompt ) + len (res ) < Editor .width - 2 :
157
163
res += chr (key )
158
164
self .wr (chr (key ))
159
165
def find_in_file (self , pattern , pos , end ):
160
- self .find_pattern = pattern
166
+ Editor .find_pattern = pattern
161
167
if self .case != "y" :
162
168
pattern = pattern .lower ()
163
169
spos = pos
@@ -184,7 +190,7 @@ def undo_add(self, lnum, text, key, span = 1):
184
190
def delete_lines (self , yank ):
185
191
lrange = self .line_range ()
186
192
if yank :
187
- self .yank_buffer = self .content [lrange [0 ]:lrange [1 ]]
193
+ Editor .yank_buffer = self .content [lrange [0 ]:lrange [1 ]]
188
194
self .undo_add (lrange [0 ], self .content [lrange [0 ]:lrange [1 ]], 0 , 0 )
189
195
del self .content [lrange [0 ]:lrange [1 ]]
190
196
if self .content == []:
@@ -228,65 +234,26 @@ def handle_edit_keys(self, key):
228
234
self .col = self .spaces (l ) if self .col == 0 else 0
229
235
elif key == 0x03 :
230
236
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
235
241
elif key == 0x06 :
236
- pat = self .line_edit ("Find: " , self .find_pattern )
242
+ pat = self .line_edit ("Find: " , Editor .find_pattern )
237
243
if pat :
238
244
self .find_in_file (pat , self .col , self .total_lines )
239
- self .row = self .height >> 1
245
+ self .row = Editor .height >> 1
240
246
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
244
250
elif key == 0x07 :
245
251
line = self .line_edit ("Goto Line: " , "" )
246
252
if line :
247
253
self .cur_line = int (line ) - 1
248
- self .row = self .height >> 1
254
+ self .row = Editor .height >> 1
249
255
elif key == 0x01 :
250
256
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
290
257
elif key == 0x0c :
291
258
self .mark = self .cur_line if self .mark == None else None
292
259
elif key == 0x0a :
@@ -308,8 +275,8 @@ def handle_edit_keys(self, key):
308
275
if len (self .content [i ]) > 0 :
309
276
self .content [i ] = ' ' * (self .tab_size - self .spaces (self .content [i ]) % self .tab_size ) + self .content [i ]
310
277
else :
311
- self .undo_add (self .cur_line , [l ], 0x09 )
312
278
ni = self .tab_size - self .col % self .tab_size
279
+ self .undo_add (self .cur_line , [l ], 0x09 )
313
280
self .content [self .cur_line ] = l [:self .col ] + ' ' * ni + l [self .col :]
314
281
self .col += ni
315
282
elif key == 0x15 :
@@ -332,23 +299,22 @@ def handle_edit_keys(self, key):
332
299
elif key == 0x04 :
333
300
if self .mark != None :
334
301
lrange = self .line_range ()
335
- self .yank_buffer = self .content [lrange [0 ]:lrange [1 ]]
302
+ Editor .yank_buffer = self .content [lrange [0 ]:lrange [1 ]]
336
303
self .mark = None
337
304
elif key == 0x16 :
338
- if self .yank_buffer :
305
+ if Editor .yank_buffer :
339
306
if self .mark != None :
340
307
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 )
344
311
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
352
318
elif key == 0x1a :
353
319
if len (self .undo ) > 0 :
354
320
action = self .undo .pop (- 1 )
@@ -363,50 +329,49 @@ def handle_edit_keys(self, key):
363
329
else :
364
330
del self .content [action [0 ]:action [0 ] - action [1 ]]
365
331
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 = ''
367
334
self .mark = None
335
+ elif key == 0x05 :
336
+ self .redraw (True )
368
337
def edit_loop (self ):
369
- if self .content == [] :
338
+ if not self .content :
370
339
self .content = ["" ]
371
340
self .total_lines = len (self .content )
372
- key = 0x05
341
+ self . redraw ( self . message == "" )
373
342
while True :
374
343
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 ())
381
344
if not self .rd_any ():
382
345
self .display_window ()
383
346
key = self .get_input ()
384
347
self .message = ''
385
348
if key == 0x11 :
386
- if self .changed != ' ' :
349
+ if self .changed != '' :
387
350
res = self .line_edit ("Content changed! Quit without saving (y/N)? " , "N" )
388
351
if not res or res [0 ].upper () != 'Y' :
389
352
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: " , "" ))
393
358
else : self .handle_edit_keys (key )
394
359
except Exception as err :
395
- self .message = "{}" .format (err )
360
+ self .message = "{!r }" .format (err )
396
361
def get_file (self , fname ):
362
+ self .fname = fname
397
363
try :
398
364
with open (fname ) as f :
399
- content = f .readlines ()
365
+ self . content = f .readlines ()
400
366
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 ):
407
372
import os
408
373
with open ("tmpfile.pye" , "w" ) as f :
409
- for l in self .content [ start : stop ] :
374
+ for l in self .content :
410
375
f .write (l + '\n ' )
411
376
try : os .unlink (fname )
412
377
except : pass
@@ -426,16 +391,36 @@ def expandtabs(s):
426
391
return sb .getvalue ()
427
392
else :
428
393
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 ):
430
395
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