Files
t-deckard/repl/tdeck_repl.py
T
2025-12-22 17:54:40 +02:00

270 lines
9.0 KiB
Python

from sys import stdin
import board
from supervisor import runtime
from adafruit_bus_device.i2c_device import I2CDevice
import keypad
import time
class PyDOS_UI:
def __init__(self):
self.trackevent = None
self.scrollable = False
self.arrow = ""
self._cmdhistlock = False
self._seqCnt = 0
self._key = bytearray(1)
self._touched = False
_ADDRESS_KBD = 0x55
self.commandHistory = [""]
self._i2c = I2CDevice(board.I2C(), _ADDRESS_KBD)
self.trackball = keypad.Keys(
[
board.TRACKBALL_CLICK,
board.TRACKBALL_UP,
board.TRACKBALL_DOWN,
board.TRACKBALL_LEFT,
board.TRACKBALL_RIGHT
],
value_when_pressed=False
)
def serial_bytes_available(self):
if not self._touched:
retval = 0
# Find the last direction the trackball was moved
# and wait for trackball to stop moving
self.arrow = ''
self.trackevent = Pydos_ui.trackball.events.get()
if self.trackevent and (self.trackevent.key_number not in [1,2] or not self._cmdhistlock):
self.arrow = ' ABDC'[self.trackevent.key_number]
if self.arrow == " ":
self.arrow = ""
else:
retval = 1
self._touched = True
if not self._touched:
with self._i2c as i2c:
try:
i2c.readinto(self._key)
except Exception as err:
self._key=bytearray(1)
if self._key[0] != 0:
retval = 1
self._touched = True
else:
retval = self.uart_bytes_available()
else:
retval = 1
return retval
def uart_bytes_available(self):
# Does the same function as supervisor.runtime.serial_bytes_available
retval = runtime.serial_bytes_available
return retval
def read_keyboard(self,num):
retval = ""
while num > 0:
self.serial_bytes_available()
if self._touched:
if self.arrow != "":
if self._seqCnt == 0:
retval += chr(27)
self._seqCnt = 1
num -= 1
elif self._seqCnt == 1:
retval += chr(91)
self._seqCnt = 2
num -= 1
elif self._seqCnt == 2:
retval += self.arrow
self._seqCnt = 0
self._touched = False
self.arrow = ""
num -= 1
else:
retval += chr(self._key[0])
self._touched = False
num -= 1
else:
if self.uart_bytes_available():
retval = stdin.read(num)
num -= len(retval)
return retval
Pydos_ui = PyDOS_UI()
def input(disp_text=None):
if disp_text != None:
print(disp_text,end="")
bld_chr1 = '_(+(-__-_'
bld_chr2 = '-+)-)/#/!'
bld_chr = '=[]<>\^%&'
bld_started = False
histPntr = len(Pydos_ui.commandHistory)
Pydos_ui._cmdhistlock = False
keys = ''
editCol = 0
loop = True
ctrlkeys = ''
arrow = ''
onLast = True
onFirst = True
blink = True
timer = time.time()
while loop:
#print(editCol,keys)
if ctrlkeys == '':
arrow = ""
else:
ctrlkeys = ''
if arrow == 'A' or arrow == 'B':
if len(Pydos_ui.commandHistory) > 0:
print(('\x08'*(editCol))+(" "*(len(keys)+1))+('\x08'*(len(keys)+1)),end="")
if arrow == 'A':
histPntr -= 1
else:
histPntr += 1
histPntr = histPntr % len(Pydos_ui.commandHistory)
print(Pydos_ui.commandHistory[histPntr],end="")
keys = Pydos_ui.commandHistory[histPntr]
editCol = len(keys)
if editCol == 0:
onFirst = True
else:
onFirst = False
elif arrow == 'D':
Pydos_ui._cmdhistlock = True
if len(keys) > editCol:
print(keys[editCol:editCol+1]+"\x08",end="")
elif editCol == len(keys):
print(" \x08",end="")
editCol = max(0,editCol-1)
if editCol > 0:
print('\x08',end="")
onLast = False
elif editCol == 0:
if not onFirst:
print('\x08',end="")
onFirst = True
elif arrow == 'C':
if len(keys) > editCol:
print(keys[editCol:editCol+1]+"\x08",end="")
editCol += 1
editCol = min(len(keys),editCol)
if editCol < len(keys):
print(keys[editCol-1:editCol],end="")
onFirst = False
elif editCol == len(keys):
if not onLast:
print(keys[editCol-1:],end="")
onLast = True
Pydos_ui._cmdhistlock = False
if Pydos_ui.serial_bytes_available():
if Pydos_ui.uart_bytes_available():
keys = keys[:editCol]+stdin.read(1)+keys[editCol:]
else:
keys = keys[:editCol]+Pydos_ui.read_keyboard(1)+keys[editCol:]
editCol += 1
if keys[editCol-1] == '\x1b':
keys = keys[:editCol-1]+keys[editCol:]
if Pydos_ui.uart_bytes_available():
ctrlkeys = stdin.read(2)
else:
ctrlkeys = Pydos_ui.read_keyboard(2)
# ctrlkeys = up:[A down:[B right:[C left:[D
arrow = ctrlkeys[1]
# Convert two character sequences into missing keyboard keys
# '_-' -> '=' '(+' -> '[' '+)' -> ']'
bld_done = False
if bld_started:
bcindx = bld_chr2.find(keys[editCol-1:editCol])
nextbc = 0
while nextbc != -1 and bld_started:
if keys[editCol-2:editCol] == bld_chr1[bcindx]+bld_chr2[bcindx]:
bld_started = False
bld_done = True
keys = keys[:editCol-2]+bld_chr[bcindx]+keys[editCol:]
print('\x08'+keys[editCol-2:]+' '+('\x08'*(len(keys[editCol:])+(1 if onLast else 2))),end="")
editCol -= 1
else:
nextbc = bld_chr2[bcindx+1:].find(keys[editCol-1:editCol])
bcindx = bcindx + nextbc + 1
if bld_chr1.find(keys[editCol-1:editCol]) != -1 and arrow == "" and not bld_done:
bld_started = True
else:
bld_started = False
if arrow != "" and ctrlkeys != "":
editCol -= 1
elif arrow !='':
pass
elif keys[editCol-1:editCol] in ['\x08','\x7f']:
keys = keys[:max(0,editCol-2)]+keys[editCol:]
if editCol > 1:
print(('\x08'*(editCol-1))+keys+' \x08\x08',end="")
editCol = max(0,editCol-2)
if editCol < len(keys):
print("\x08"*(len(keys)-editCol),end="")
else:
editCol -= 1
onFirst = True
elif len(keys[editCol-1:editCol]) > 0 and keys[editCol-1:editCol] in '\n\r':
if len(keys) > editCol:
print(keys[editCol:editCol+1]+"\x08",end="")
elif editCol == len(keys):
print(" \x08",end="")
keys = keys[:editCol-1]+keys[editCol:]
if keys.strip() != "":
Pydos_ui.commandHistory.append(keys)
if len(Pydos_ui.commandHistory) > 10:
Pydos_ui.commandHistory.pop(1)
histPntr = len(Pydos_ui.commandHistory)
print()
loop = False
elif not bld_done:
onFirst = False
print(keys[editCol-1:],end="")
if len(keys[editCol-1:]) > 1:
print(" \x08",end="")
if editCol < len(keys):
print("\x08"*(len(keys)-editCol),end="")
if loop:
if time.time() != timer:
blink = not blink
timer = time.time()
if blink:
print("_\x08",end="")
else:
if len(keys) > editCol:
print(keys[editCol:editCol+1]+"\x08",end="")
else:
print(" \x08",end="")
return keys