@@ -116,6 +116,16 @@ def clamp(x, lower, upper):
116116 return x
117117
118118
119+ def _count_leading_characters (text , char ):
120+ count = 0
121+ for c in text :
122+ if c == char :
123+ count += 1
124+ else :
125+ break
126+ return count
127+
128+
119129class Cursor :
120130 def __init__ (self , row = 0 , col = 0 , col_hint = None ):
121131 self .row = row
@@ -219,19 +229,40 @@ def end(window, buffer, cursor):
219229 window .horizontal_scroll (cursor )
220230
221231
222- def editor (stdscr , filename , visible_cursor ): # pylint: disable=too-many-branches,too-many-statements
232+ def editor (stdscr , filename , mouse = None , terminal_tilegrid = None ): # pylint: disable=too-many-branches,too-many-statements
233+
234+ def _only_spaces_before (cursor ):
235+ i = cursor .col - 1
236+ while i >= 0 :
237+ print (f"i: { i } chr: '{ buffer .lines [cursor .row ][i ]} '" )
238+ if buffer .lines [cursor .row ][i ] != " " :
239+ return False
240+ i -= 1
241+ return True
223242 if os_exists (filename ):
224243 with open (filename , "r" , encoding = "utf-8" ) as f :
225244 buffer = Buffer (f .read ().splitlines ())
226245 else :
227246 buffer = Buffer (["" ])
247+ print (f"cwd: { os .getcwd ()} | { os .getcwd () == "/apps/editor" } " )
248+ if os .getcwd () != "/apps/editor" and os .getcwd () != "/" :
249+ absolute_filepath = os .getcwd () + "/" + filename
250+ else :
251+ absolute_filepath = filename
228252
229253 user_message = None
254+ user_message_shown_time = - 1
255+
256+ clicked_tile_coords = [None , None ]
230257
231258 window = Window (curses .LINES - 1 , curses .COLS - 1 )
232259 cursor = Cursor ()
233- visible_cursor .text = buffer [0 ][0 ]
234- last_refresh_time = - 1
260+ terminal_tilegrid .pixel_shader [cursor .col ,cursor .row ] = [1 , 0 ]
261+ old_cursor_pos = (cursor .col , cursor .row )
262+ # try:
263+ # visible_cursor.text = buffer[0][0]
264+ # except IndexError:
265+ # visible_cursor.text = " "
235266
236267 stdscr .erase ()
237268
@@ -244,6 +275,7 @@ def setline(row, line):
244275 line += " " * (window .n_cols - len (line ))
245276 stdscr .addstr (row , 0 , line )
246277
278+ print (f"cwd: { os .getcwd ()} | abs path: { absolute_filepath } | filename: { filename } " )
247279 while True :
248280 lastrow = 0
249281 for row , line in enumerate (buffer [window .row : window .row + window .n_rows ]):
@@ -258,133 +290,183 @@ def setline(row, line):
258290 row = curses .LINES - 1
259291
260292 if user_message is None :
261- if util .readonly ():
262- line = f"{ filename :12} (mnt RO ^W) | ^R run | ^C: quit{ gc_mem_free_hint ()} "
293+ if (not absolute_filepath .startswith ("/saves/" ) and
294+ not absolute_filepath .startswith ("/sd/" ) and
295+ util .readonly ()):
296+
297+ line = f"{ absolute_filepath :12} (mnt RO ^W) | ^R run | ^O Open | ^C: quit{ gc_mem_free_hint ()} "
263298 else :
264- line = f"{ filename :12} (mnt RW ^W) | ^R run | ^S save | ^X: save & exit | ^C: exit no save{ gc_mem_free_hint ()} "
299+ line = f"{ absolute_filepath :12} (mnt RW ^W) | ^R run | ^O Open | ^S save | ^X: save & exit | ^C: exit no save{ gc_mem_free_hint ()} "
265300 else :
266301 line = user_message
267- user_message = None
302+ if user_message_shown_time + 3.0 < time .monotonic ():
303+ user_message = None
268304 setline (row , line )
269305
270306 stdscr .move (* window .translate (cursor ))
271- old_cursor_pos = ( cursor . col , cursor . row )
307+
272308 # display.refresh(minimum_frames_per_second=20)
273309 k = stdscr .getkey ()
274- # print(repr(k))
275- if len (k ) == 1 and " " <= k <= "~" :
276- buffer .insert (cursor , k )
277- for _ in k :
278- right (window , buffer , cursor )
279- elif k == "\x18 " : # ctrl-x
280- if not util .readonly ():
281- with open (filename , "w" , encoding = "utf-8" ) as f :
310+ if k is not None :
311+ # print(repr(k))
312+ if len (k ) == 1 and " " <= k <= "~" :
313+ buffer .insert (cursor , k )
314+ for _ in k :
315+ right (window , buffer , cursor )
316+ elif k == "\x18 " : # ctrl-x
317+ if not util .readonly ():
318+ with open (filename , "w" , encoding = "utf-8" ) as f :
319+ for row in buffer :
320+ f .write (f"{ row } \n " )
321+ return
322+ else :
323+ print ("Unable to Save due to readonly mode! File Contents:" )
324+ print ("---- begin file contents ----" )
282325 for row in buffer :
283- f .write (f"{ row } \n " )
284- return
285- else :
286- print ("Unable to Save due to readonly mode! File Contents:" )
287- print ("---- begin file contents ----" )
326+ print (row )
327+ print ("---- end file contents ----" )
328+ elif k == "\x13 " : # Ctrl-S
329+ print (absolute_filepath )
330+ print (f"starts with saves: { absolute_filepath .startswith ("/saves/" )} " )
331+ print (f"stars saves: { absolute_filepath .startswith ("/saves/" )} " )
332+ print (f"stars sd: { absolute_filepath .startswith ("/sd/" )} " )
333+ print (f"readonly: { util .readonly ()} " )
334+ if (absolute_filepath .startswith ("/saves/" ) or
335+ absolute_filepath .startswith ("/sd/" ) or
336+ not util .readonly ()):
337+
338+ with open (absolute_filepath , "w" , encoding = "utf-8" ) as f :
339+ for row in buffer :
340+ f .write (f"{ row } \n " )
341+ user_message = "Saved"
342+ user_message_shown_time = time .monotonic ()
343+ else :
344+ user_message = "Unable to Save due to readonly mode!"
345+ user_message_shown_time = time .monotonic ()
346+ elif k == "\x11 " : # Ctrl-Q
347+ print ("ctrl-Q" )
288348 for row in buffer :
289349 print (row )
290- print ("---- end file contents ----" )
291- elif k == "\x13 " : # Ctrl-S
292- if not util .readonly ():
293- with open (filename , "w" , encoding = "utf-8" ) as f :
294- for row in buffer :
295- f .write (f"{ row } \n " )
296- user_message = "Saved"
297- else :
298- print ("Unable to Save due to readonly mode!" )
299- elif k == "\x11 " : # Ctrl-Q
300- print ("ctrl-Q" )
301- for row in buffer :
302- print (row )
303- elif k == "\x17 " : # Ctrl-W
304- boot_args_file = argv_filename ("/boot.py" )
305- with open (boot_args_file , "w" ) as f :
306- f .write (json .dumps ([not util .readonly (), "/apps/editor/code.py" , Path (filename ).absolute ()]))
307- microcontroller .reset ()
308- elif k == "\x12 " : # Ctrl-R
309- print (f"Run: { filename } " )
310-
311- launcher_code_args_file = argv_filename ("/code.py" )
312- with open (launcher_code_args_file , "w" ) as f :
313- f .write (json .dumps (["/apps/editor/code.py" , Path (filename ).absolute ()]))
314-
315- supervisor .set_next_code_file (filename , sticky_on_reload = False , reload_on_error = True ,
316- working_directory = Path (filename ).parent .absolute ())
317- supervisor .reload ()
318- elif k == "KEY_HOME" :
319- home (window , buffer , cursor )
320- elif k == "KEY_END" :
321- end (window , buffer , cursor )
322- elif k == "KEY_LEFT" :
323- left (window , buffer , cursor )
324- elif k == "KEY_DOWN" :
325-
326- cursor .down (buffer )
327- window .down (buffer , cursor )
328- window .horizontal_scroll (cursor )
329- print (f"scroll pos: { window .row } " )
330- elif k == "KEY_PGDN" :
331- for _ in range (window .n_rows ):
350+ elif k == "\x17 " : # Ctrl-W
351+ boot_args_file = argv_filename ("/boot.py" )
352+ with open (boot_args_file , "w" ) as f :
353+ f .write (json .dumps ([not util .readonly (), "/apps/editor/code.py" , Path (filename ).absolute ()]))
354+ microcontroller .reset ()
355+ elif k == "\x12 " : # Ctrl-R
356+ print (f"Run: { filename } " )
357+
358+ launcher_code_args_file = argv_filename ("/code.py" )
359+ with open (launcher_code_args_file , "w" ) as f :
360+ f .write (json .dumps (["/apps/editor/code.py" , Path (filename ).absolute ()]))
361+
362+ supervisor .set_next_code_file (filename , sticky_on_reload = False , reload_on_error = True ,
363+ working_directory = Path (filename ).parent .absolute ())
364+ supervisor .reload ()
365+ elif k == "\x0f " : # Ctrl-O
366+
367+ supervisor .set_next_code_file ("/apps/editor/code.py" , sticky_on_reload = False , reload_on_error = True ,
368+ working_directory = "/apps/editor" )
369+ supervisor .reload ()
370+
371+
372+ elif k == "KEY_HOME" :
373+ home (window , buffer , cursor )
374+ elif k == "KEY_END" :
375+ end (window , buffer , cursor )
376+ elif k == "KEY_LEFT" :
377+ left (window , buffer , cursor )
378+ elif k == "KEY_DOWN" :
379+
332380 cursor .down (buffer )
333381 window .down (buffer , cursor )
334382 window .horizontal_scroll (cursor )
335- elif k == "KEY_UP" :
336- cursor .up (buffer )
337- window .up (cursor )
338- window .horizontal_scroll (cursor )
339- elif k == "KEY_PGUP" :
340- for _ in range (window .n_rows ):
383+ print (f"scroll pos: { window .row } " )
384+ elif k == "KEY_PGDN" :
385+ for _ in range (window .n_rows ):
386+ cursor .down (buffer )
387+ window .down (buffer , cursor )
388+ window .horizontal_scroll (cursor )
389+ elif k == "KEY_UP" :
341390 cursor .up (buffer )
342391 window .up (cursor )
343392 window .horizontal_scroll (cursor )
344- elif k == "KEY_RIGHT" :
345- right (window , buffer , cursor )
346- elif k == "\n " :
347- buffer .split (cursor )
348- right (window , buffer , cursor )
349- elif k in ("KEY_DELETE" , "\x04 " ):
350- print ("delete" )
351- if cursor .row < len (buffer .lines ) - 1 or \
352- cursor .col < len (buffer .lines [cursor .row ]):
353- buffer .delete (cursor )
354- try :
355- visible_cursor .text = buffer .lines [cursor .row ][cursor .col ]
356- except IndexError :
357- visible_cursor .text = " "
358-
359- elif k in ("KEY_BACKSPACE" , "\x7f " , "\x08 " ):
360- print (f"backspace { bytes (k , 'utf-8' )} " )
361- if (cursor .row , cursor .col ) > (0 , 0 ):
362- left (window , buffer , cursor )
363- buffer .delete (cursor )
393+ elif k == "KEY_PGUP" :
394+ for _ in range (window .n_rows ):
395+ cursor .up (buffer )
396+ window .up (cursor )
397+ window .horizontal_scroll (cursor )
398+ elif k == "KEY_RIGHT" :
399+ right (window , buffer , cursor )
400+ elif k == "\n " :
401+ leading_spaces = _count_leading_characters (buffer .lines [cursor .row ], " " )
402+ buffer .split (cursor )
403+ right (window , buffer , cursor )
404+ for i in range (leading_spaces ):
405+ buffer .insert (cursor , " " )
406+ right (window , buffer , cursor )
407+ elif k in ("KEY_DELETE" , "\x04 " ):
408+ print ("delete" )
409+ if cursor .row < len (buffer .lines ) - 1 or \
410+ cursor .col < len (buffer .lines [cursor .row ]):
411+ buffer .delete (cursor )
412+ # try:
413+ # visible_cursor.text = buffer.lines[cursor.row][cursor.col]
414+ # except IndexError:
415+ # visible_cursor.text = " "
416+
417+ elif k in ("KEY_BACKSPACE" , "\x7f " , "\x08 " ):
418+ print (f"backspace { bytes (k , 'utf-8' )} " )
419+ if (cursor .row , cursor .col ) > (0 , 0 ):
420+ if cursor .col > 0 and buffer .lines [cursor .row ][cursor .col - 1 ] == " " and _only_spaces_before (cursor ):
421+ for i in range (4 ):
422+ left (window , buffer , cursor )
423+ buffer .delete (cursor )
424+ else :
425+ left (window , buffer , cursor )
426+ buffer .delete (cursor )
427+
428+ else :
429+ print (f"unhandled k: { k } " )
430+ print (f"unhandled K: { ord (k )} " )
431+ print (f"unhandled k: { bytes (k , 'utf-8' )} " )
432+
433+
434+ if mouse is not None :
435+ pressed_btns = mouse .update ()
436+ if pressed_btns is not None and "left" in pressed_btns :
437+ clicked_tile_coords [0 ] = mouse .x // 6
438+ clicked_tile_coords [1 ] = mouse .y // 12
439+
440+ if clicked_tile_coords [0 ] > len (buffer .lines [clicked_tile_coords [1 ]]):
441+ clicked_tile_coords [0 ] = len (buffer .lines [clicked_tile_coords [1 ]])
442+ cursor .row = clicked_tile_coords [1 ]
443+ cursor .col = clicked_tile_coords [0 ]
444+
364445
365- else :
366- print (f"unhandled k: { k } " )
367- print (f"unhandled K: { ord (k )} " )
368- print (f"unhandled k: { bytes (k , 'utf-8' )} " )
369446 # print("updating visible cursor")
370447 # print(f"anchored pos: {((cursor.col * 6) - 1, (cursor.row * 12) + 20)}")
371- if old_cursor_pos != (cursor .col , cursor .row ):
372448
373- # terminal_tilegrid.pixel_shader[old_cursor_pos[0], old_cursor_pos[1]] = [0,1]
374- # terminal_tilegrid.pixel_shader[cursor.col, cursor.row] = [1,0]
449+ if old_cursor_pos != (cursor .col , cursor .row ):
450+ # print(f"old cursor: {old_cursor_pos}, new: {(cursor.col, cursor.row)}")
451+ terminal_tilegrid .pixel_shader [old_cursor_pos [0 ], old_cursor_pos [1 ]] = [0 ,1 ]
452+ terminal_tilegrid .pixel_shader [cursor .col , cursor .row ] = [1 ,0 ]
453+ # print(f"old: {terminal_tilegrid.pixel_shader[old_cursor_pos[0], old_cursor_pos[1]]} new: {terminal_tilegrid.pixel_shader[cursor.col, cursor.row]}")
375454
376455 # visible_cursor.anchored_position = ((cursor.col * 6) - 1, (cursor.row * 12) + 20)
377- visible_cursor .anchored_position = ((cursor .col * 6 ), ((cursor .row - window .row ) * 12 ))
378456
379- try :
380- visible_cursor .text = buffer .lines [cursor .row ][cursor .col ]
381- except IndexError :
382- visible_cursor .text = " "
457+ # visible_cursor.anchored_position = ((cursor.col * 6), ((cursor.row - window.row) * 12))
458+ #
459+ # try:
460+ # visible_cursor.text = buffer.lines[cursor.row][cursor.col]
461+ # except IndexError:
462+ # visible_cursor.text = " "
463+
383464
465+ old_cursor_pos = (cursor .col , cursor .row )
384466
385- def edit (filename , terminal = None , visible_cursor = None ):
467+ def edit (filename , terminal = None , mouse = None , terminal_tilegrid = None ):
386468 with MaybeDisableReload ():
387469 if terminal is None :
388470 return curses .wrapper (editor , filename )
389471 else :
390- return curses .custom_terminal_wrapper (terminal , editor , filename , visible_cursor )
472+ return curses .custom_terminal_wrapper (terminal , editor , filename , mouse , terminal_tilegrid )
0 commit comments