Skip to content

Instantly share code, notes, and snippets.

@tigerhawkvok
Last active February 26, 2019 21:58
Show Gist options
  • Save tigerhawkvok/9542594 to your computer and use it in GitHub Desktop.
Save tigerhawkvok/9542594 to your computer and use it in GitHub Desktop.
Cross-Platform Python getch, with a Y/N module for interpreter prompts.
"""
Python 2 and Python 3 input wrapper with helper Yes/No class for feedbackless boolean input
@author Philip Kahn
@date 2016
"""
class _qinput:
"""Take care of the changes in inputs between Python 2 and 3, as well as enabling a getch-like functionality"""
def __init__(self):
try:
from .yn import yn
except ImportError:
print("This package requires the module 'yn' to function. Please make sure it's in the load path or the same directory as this file.")
return None
def yn(self, string):
from .yn import yn
return yn(string)
def input(self, string):
try:
return raw_input(string)
except NameError:
return input(string)
#! python3
"""
Taken from http://code.activestate.com/recipes/134892/
Brought to Github for better versioning / editing / updating
Returns a string (as input() or raw_input() )
Use:
import getch
c = getch.getch()
@author Philip Kahn
@url https://gist.github.com/tigerhawkvok/9542594
"""
#pylint: disable= R, E0401, W0612
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
try:
self.impl = _GetchUnix()
except ImportError:
self.impl = _GetchMacCarbon()
def __call__(self):
# Return as a string
try:
try:
return self.impl()#.encode().decode('utf-8')
except AttributeError:
return self.impl()#.decode('utf-8')
except KeyboardInterrupt:
self.doExit()
@staticmethod
def doExit():
"""
Force a system exit
"""
import os, sys
print("\n")
os._exit(0) #pylint: disable= W0212
sys.exit(0)
# These helper child classes are not meant to be publically accessible
#pylint: disable= C0111
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
except KeyboardInterrupt:
_Getch.doExit()
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
class _GetchMacCarbon:
"""
A function which returns the current ASCII key that is down;
if no ASCII key is down, the null string is returned. The
page http://www.mactech.com/macintosh-c/chap02-1.html was
very helpful in figuring out how to do this.
"""
def __init__(self):
import Carbon
# pylint: disable= W0104
Carbon.Evt #see if it has this (in Unix, it doesn't)
def __call__(self):
import Carbon
if Carbon.Evt.EventAvail(0x0008)[0]==0: # 0x0008 is the keyDownMask
return ''
else:
#
# The event contains the following info:
# (what, msg, when, where, mod)=Carbon.Evt.GetNextEvent(0x0008)[1]
#
# The message (msg) contains the ASCII char which is
# extracted with the 0x000000FF charCodeMask; this
# number is converted to an ASCII character with chr() and
# returned
#
(what, msg, *other)=Carbon.Evt.GetNextEvent(0x0008)[1]
return chr(msg & 0x000000FF)
getch = _Getch()
#! python3
"""
A few helpful input wrappers.
Aggregated to deal well with Python 2 vs Python 3, and cross platform for getch.
Hasn't been tested on Python 2 in a few years, but it's about to be legacy anyway.
"""
from ._qinput import _qinput
def yn(string: str) -> bool:
"""
For a prompt, return boolean based on user input Y or N
"""
return _qinput().yn(string)
#pylint: disable= W0622
def input(string: str) -> str:
"""
Get the user response to an input. Cross-platform and version.
"""
return _qinput().input(string)
#! python3
"""
Taken from http://code.activestate.com/recipes/134892/
Brought to Github for better versioning / editing / updating
Returns a string (as input() or raw_input() )
Use:
import getch
c = getch.getch()
@author Philip Kahn
@url https://gist.github.com/tigerhawkvok/9542594
"""
#pylint: disable= R, E0401, W0612
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
try:
self.impl = _GetchUnix()
except ImportError:
self.impl = _GetchMacCarbon()
def __call__(self):
# Return as a string
try:
try:
return self.impl()#.encode().decode('utf-8')
except AttributeError:
return self.impl()#.decode('utf-8')
except KeyboardInterrupt:
self.doExit()
@staticmethod
def doExit():
"""
Force a system exit
"""
import os, sys
print("\n")
os._exit(0) #pylint: disable= W0212
sys.exit(0)
# These helper child classes are not meant to be publically accessible
#pylint: disable= C0111
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
except KeyboardInterrupt:
_Getch.doExit()
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
class _GetchMacCarbon:
"""
A function which returns the current ASCII key that is down;
if no ASCII key is down, the null string is returned. The
page http://www.mactech.com/macintosh-c/chap02-1.html was
very helpful in figuring out how to do this.
"""
def __init__(self):
import Carbon
# pylint: disable= W0104
Carbon.Evt #see if it has this (in Unix, it doesn't)
def __call__(self):
import Carbon
if Carbon.Evt.EventAvail(0x0008)[0]==0: # 0x0008 is the keyDownMask
return ''
else:
#
# The event contains the following info:
# (what, msg, when, where, mod)=Carbon.Evt.GetNextEvent(0x0008)[1]
#
# The message (msg) contains the ASCII char which is
# extracted with the 0x000000FF charCodeMask; this
# number is converted to an ASCII character with chr() and
# returned
#
(what, msg, *other)=Carbon.Evt.GetNextEvent(0x0008)[1]
return chr(msg & 0x000000FF)
getch = _Getch()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment