1
0
mirror of https://github.com/mnaberez/py65.git synced 2024-06-26 20:29:27 +00:00
py65/py65/utils/console.py
2018-10-06 12:50:59 -07:00

104 lines
3.2 KiB
Python

import sys
if sys.platform[:3] == "win":
import msvcrt
def getch(stdin):
""" Read one character from the Windows console, blocking until one
is available. Does not echo the character. The stdin argument is
for function signature compatibility and is ignored.
"""
c = msvcrt.getch()
if isinstance(c, bytes): # Python 3
c = c.decode('latin-1')
return c
def getch_noblock(stdin):
""" Read one character from the Windows console without blocking.
Does not echo the character. The stdin argument is for function
signature compatibility and is ignored. If no character is
available, an empty string is returned.
"""
if msvcrt.kbhit():
return getch(stdin)
return ''
else:
import select
import os
import termios
import fcntl
def getch(stdin):
""" Read one character from stdin, blocking until one is available.
Does not echo the character.
"""
fd = stdin.fileno()
oldattr = termios.tcgetattr(fd)
newattr = oldattr[:]
newattr[3] &= ~termios.ICANON & ~termios.ECHO
try:
termios.tcsetattr(fd, termios.TCSANOW, newattr)
char = stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldattr)
return char
def getch_noblock(stdin):
""" Read one character from stdin without blocking. Does not echo the
character. If no character is available, an empty string is returned.
"""
char = ''
fd = stdin.fileno()
try:
oldterm = termios.tcgetattr(fd)
except termios.error: # https://github.com/mnaberez/py65/issues/46
return char
newattr = oldterm[:]
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
try:
r, w, e = select.select([fd], [], [], 0.1)
if r:
char = stdin.read(1)
if char == "\n":
char = "\r"
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
return char
def line_input(prompt='', stdin=sys.stdin, stdout=sys.stdout):
""" Read a line from stdin, printing each character as it is typed.
Does not echo a newline at the end. This allows the calling program
to overwrite the line by first sending a carriage return ('\r'), which
is useful in modes like the interactive assembler.
"""
stdout.write(prompt)
line = ''
while True:
char = getch(stdin)
code = ord(char)
if char in ("\n", "\r"):
break
elif code in (0x7f, 0x08): # backspace
if len(line) > 0:
line = line[:-1]
stdout.write("\r%s\r%s%s" %
(' ' * (len(prompt + line) + 5), prompt, line))
elif code == 0x1b: # escape
pass
else:
line += char
stdout.write(char)
stdout.flush()
return line