RederickDeathwill

Cross-platform getch

Aug 23rd, 2015
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.21 KB | None | 0 0
  1. #!/usr/bin/env python
  2. '''
  3. A Python class implementing KBHIT, the standard keyboard-interrupt poller.
  4. Works transparently on Windows and Posix (Linux, Mac OS X).  Doesn't work
  5. with IDLE.
  6.  
  7. This program is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU Lesser General Public License as
  9. published by the Free Software Foundation, either version 3 of the
  10. License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. '''
  18.  
  19. import os
  20.  
  21. # Windows
  22. if os.name == 'nt':
  23.     import msvcrt
  24.  
  25. # Posix (Linux, OS X)
  26. else:
  27.     import sys
  28.     import termios
  29.     import atexit
  30.     from select import select
  31.  
  32. class KBHit:
  33.  
  34.     def __init__(self):
  35.         '''Creates a KBHit object that you can call to do various keyboard things.
  36.        '''
  37.  
  38.         if os.name == 'nt':
  39.             pass
  40.  
  41.         else:
  42.  
  43.             # Save the terminal settings
  44.             self.fd = sys.stdin.fileno()
  45.             self.new_term = termios.tcgetattr(self.fd)
  46.             self.old_term = termios.tcgetattr(self.fd)
  47.  
  48.             # New terminal setting unbuffered
  49.             self.new_term[3] = (self.new_term[3] & ~termios.ICANON & ~termios.ECHO)
  50.             termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term)
  51.  
  52.             # Support normal-terminal reset at exit
  53.             atexit.register(self.set_normal_term)
  54.  
  55.  
  56.     def set_normal_term(self):
  57.         ''' Resets to normal terminal.  On Windows this is a no-op.
  58.        '''
  59.  
  60.         if os.name == 'nt':
  61.             pass
  62.  
  63.         else:
  64.             termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old_term)
  65.  
  66.  
  67.     def getch(self):
  68.         ''' Returns a keyboard character after kbhit() has been called.
  69.            Should not be called in the same program as getarrow().
  70.        '''
  71.  
  72.         s = ''
  73.  
  74.         if os.name == 'nt':
  75.             return msvcrt.getch().decode('utf-8')
  76.  
  77.         else:
  78.             return sys.stdin.read(1)
  79.  
  80.  
  81.     def getarrow(self):
  82.         ''' Returns an arrow-key code after kbhit() has been called. Codes are
  83.        0 : up
  84.        1 : right
  85.        2 : down
  86.        3 : left
  87.        Should not be called in the same program as getch().
  88.        '''
  89.  
  90.         if os.name == 'nt':
  91.             msvcrt.getch() # skip 0xE0
  92.             c = msvcrt.getch()
  93.             vals = [72, 77, 80, 75]
  94.  
  95.         else:
  96.             c = sys.stdin.read(3)[2]
  97.             vals = [65, 67, 66, 68]
  98.  
  99.         return vals.index(ord(c.decode('utf-8')))
  100.  
  101.  
  102.     def kbhit(self):
  103.         ''' Returns True if keyboard character was hit, False otherwise.
  104.        '''
  105.         if os.name == 'nt':
  106.             return msvcrt.kbhit()
  107.  
  108.         else:
  109.             dr,dw,de = select([sys.stdin], [], [], 0)
  110.             return dr != []
  111.  
  112. if __name__ == "__main__":
  113.  
  114.     kb = KBHit()
  115.  
  116.     print('Hit any key, or ESC to exit')
  117.  
  118.     while True:
  119.  
  120.         if kb.kbhit():
  121.             c = kb.getch()
  122.             if ord(c) == 27: # ESC
  123.                 break
  124.             print(c)
  125.  
  126.     kb.set_normal_term()
Advertisement
Add Comment
Please, Sign In to add comment