I have a pretty big problem, I'm making an _input function in python, and for that I need a getch function, so I started coding this, but I have a big problem: the escape sequences on linux, their size is variable! So I would like to know how to detect these sequences properly (and quickly).
import os
import sys
if os.name == "nt":
import msvcrt
else:
import tty
import termios
_special_key_tn = {
"H" : "A" , #top
"P" : "B" , #down
"M" : "C" , #right
"K" : "D" , #left
"S" : "?" , #suppr
"R" : "_" , #insert
"O" : "!" , #end
}
_special_key = {
"A" : "A" , #top
"B" : "B" , #down
"C" : "C" , #right
"D" : "D" , #left
"3" : "?" , #suppr
"2" : "_" , #insert
"F" : "!" , #end
}
def _getch() :
"""
Attend la frappe d'un caractère puis le retourne
@returns:
ch {str}
"""
sys.stdout.flush()
ch = ""
if os.name == "nt" :
ch = msvcrt.getwch()
else :
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try :
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally :
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
#if os.name == "nt" :
# if ord(ch) == 224 :
# ch = "^[" + _special_key_tn[_getch()]
#else :
# if ord(ch) == 27 :
# _getch()
# ch = "^[" + _special_key[_getch()]
# print(_getch())
if os.name == "nt" and msvcrt.kbhit() :
print("ok")
return ch
if __name__ == "__main__":
print("key pressed :", _getch())
print("key pressed :", _getch())
print("key pressed :", _getch())
print("key pressed :", _getch())
print("key pressed :", _getch())
print("key pressed :", _getch())
(the _input function but it has no problem at the moment)
class color :
def list() :
for i in range(100) :
print(f"\033[1;{i}m{i}")
white = lambda string: "\033[1;37m" + string + "\033[0;00m"
grey = lambda string: "\033[1;30m" + string + "\033[0;00m"
yellow = lambda string: "\033[1;33m" + string + "\033[0;00m"
green = lambda string: "\033[1;32m" + string + "\033[0;00m"
blue = lambda string: "\033[1;34m" + string + "\033[0;00m"
cyan = lambda string: "\033[1;36m" + string + "\033[0;00m"
red = lambda string: "\033[1;31m" + string + "\033[0;00m"
magenta = lambda string: "\033[1;35m" + string + "\033[0;00m"
black = lambda string: "\033[1;30m" + string + "\033[0;00m"
darkwhite = lambda string: "\033[0;37m" + string + "\033[0;00m"
darkyellow = lambda string: "\033[0;33m" + string + "\033[0;00m"
darkgreen = lambda string: "\033[0;32m" + string + "\033[0;00m"
darkblue = lambda string: "\033[0;34m" + string + "\033[0;00m"
darkcyan = lambda string: "\033[0;36m" + string + "\033[0;00m"
darkred = lambda string: "\033[0;31m" + string + "\033[0;00m"
darkmagenta = lambda string: "\033[0;35m" + string + "\033[0;00m"
darkblack = lambda string: "\033[0;30m" + string + "\033[0;00m"
placeholder = lambda string: "\033[1;30m" + string + "\033[0;00m" + f"\033[{len(string)}D"
def _input(string="", end="\n", pos=(0, 0), placeholder="", max=-1, width=-1, background="") :
enc = "utf-8"
line = ""
i = 0
start = 0
if width == -1 :
width = tuple(os.get_terminal_size())[0] - 2
width -= len(string) + pos[0]
stop = f"\033[{width+1}C"
placeholder = placeholder[:width]
y_pos = f"\033[{pos[1]}E" if pos[1] != 0 else ""
print(f"{y_pos}\033[{pos[0] + 1}G\0337\033[0G{background}\0338{string}◄{color.placeholder(placeholder)}\0338{stop}►\0338◄", end="")
while True :
sys.stdout.flush()
char = msvcrt.getwch()
if char in ["\n", "\r", "\n\r", "\r\n"] :
# entry
break
if char == "\x08" :
# backspace
if i != 0 :
temp = len(line)
line = line[:i-1] + line[i:]
i -= temp - len(line)
char = ""
if char == '\xe0' :
# arrows
mov = msvcrt.getwch()
if mov == "K" : # left
if i > 0 :
i -= 1
if mov == "M" : # right
if i < len(line) :
i += 1
if mov == "S" : # suppr
if len(line) - i != 0 :
temp = len(line)
line = line[:i] + line[i+1:]
char = ""
if max != -1 and len(line) >= max :
# limit lenght
char = ""
line = line[:i] + char + line[i:]
i += len(char)
if i > width :
width += 1
start += 1
elif i < start :
start -= 1
width -= 1
right = left = 0
if width < len(line) :
right = 1
if start > 0 :
left = 1
j = f"\033[{i-start+1}C" if i-start+1 != 0 else ""
l = color.green("◄") if left else "◄"
r = color.green("►") if right else "►"
ph = color.placeholder(placeholder) if len(line) == 0 else ""
print(f"\033[2K\033[0G{background}\0338{string}{l}{ph}{line[start:width]}\0338{stop}{r}\0338{j}", end="")
print(end, end="")
return line
PS: If you have ideas for optimizations for my functions, give them, because on my pc it runs almost well, but I doubt that it runs well on all PCs.
indeed, these are sequences ANSI, but I did not know them and they were not in the doc I had (gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797). Now I have another problem: When I type "only" esc, the program waits for another input. How can I check if there are still "pending entries"? (I tried
sys.stdinbut found it didn't work...My new code: