use this Read 1 char from terminal
- returns bytes
- get
str
by bytes.decode()
- doesn't echo (typing isn't visible)
- instead of
msvcrt.getch
use .getche
inside _GetchWindows.__call__
msvcrt
is not globally imported
do something like
while input != '\r': # or some other return char, depends
input += getch().decode()
and
# in front of erase
while msvcrt.kbhit(): # read while there is something to read
remember_input += getch().decode()
print(erase)
# and than you should return remember_input to stdin somehow (try msvcrt.putch)
I haven't done it myself because of complexity (writing with threading (I'm new to it), in/output controlling (because of which my vsc terminal hated me every time), and probably more reasons I'm too tired to think of),
but I'm sure you won't quit
EDIT: Oh, yes
I forgot to mention you will also probably want to write your own print
and input
,
in which case useful thing would be input(prompt, remember_string)
the prompt would be unerasable by a backspace, and remember_string would
BIG UPDATE
I used curses
module instead of msvcrt
(as originally suggested)
This actually dwells with problem similar to yours (much simplified simulation),
but resolves the core of the problem
- receiving input
- deleting line when something happens & writing message in that line
- reinputing with already-written stuff there
This takes input as long as it is <= 3 chars.
If >= 4 chars written, it will do (3.) what was, to you, finishing query,
and then ask for input again with old input.
when pressed ENTER, finishes input
import curses
import curses.ascii as ascii
def getch(stdscr: curses.window):
'return single char'
a = stdscr.get_wch()
stdscr.refresh()
return a
def prompt(stdscr: curses.window):
'write prompt for input'
addstr(stdscr, "Enter query: ")
def addstr(stdscr: curses.window, str):
'write string to window'
stdscr.addstr(str)
stdscr.refresh()
def del_line(stdscr: curses.window):
'deletes line in which cursor is'
row, col = stdscr.getyx()
stdscr.move(row, 0)
stdscr.clrtoeol()
@curses.wrapper
def main(stdscr: curses.window):
# next 3 lines were on some tutorial so I left them be
# Clear screen
stdscr.clear()
curses.echo()
# I will use marks like #x.y to indicate places
q = ''
while True: #EDIT from `for (5)` to `while`
prompt(stdscr)
addstr(stdscr, q) # at the beginning & after enter is pressed, q==''
# else it is old input (that was >= 4 chars
for i in range(4): # range 4 to take 4 or less chars
a = getch(stdscr) #read charby char
if ascii.isalnum(a): #letters & numbers
q += a
elif a == '\n' or a == '\r': # enter pressed == input finished
stdscr.addstr(f"\nfinished input {q}\n")
q = ''
break
else: # this block happens (in py) if no break occurred in loop
# that means, in this case, that ENTER was not pressed, i.e. input is stillongoing
# but since it is > 4 chars it is briefly interrupted to write message
del_line(stdscr)
addstr(stdscr, "Input interupted\n")
return
test
run this program (I recommend simply double-click the file to open std terminal, because other terminals may have something against this [program])
(E represents ENTER)
and type: abcE
, abcdefE
, abcdefghijE
to see what this does
P.S.
this may solve your problem, but the capabilities for this module are bigger,
and I didn't want to write to much to complex API.
solution for that would be to write API for easy managing more things like moving with arrows, but that is not in the scope of this question