diff --git a/readchar/readchar_linux.py b/readchar/readchar_linux.py index 9a56911..8ef79f2 100644 --- a/readchar/readchar_linux.py +++ b/readchar/readchar_linux.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- -# Initially taken from: -# http://code.activestate.com/recipes/134892/ -# Thanks to Danny Yoo +# Copyright (c) 2014, 2015 Miguel Ángel García (@magmax9). +# Based on previous work on gist getch()-like unbuffered character +# reading from stdin on both Windows and Unix (Python recipe), +# started by Danny Yoo. Licensed under the MIT license. + import sys import os import select @@ -13,22 +15,40 @@ def readchar(wait_for_char=True): old_settings = termios.tcgetattr(sys.stdin) tty.setcbreak(sys.stdin.fileno()) - char_buffer = '' + charbuffer = '' + + while True: + if charbuffer in key.ESCAPE_SEQUENCES: + char1 = getkey(False, old_settings) + else: + char1 = getkey(wait_for_char, old_settings) + if (charbuffer + char1) not in key.ESCAPE_SEQUENCES: + # escape sequence complete or not an escape character.. + return convertchar(charbuffer + char1) + + # handle cases where the escape is finished, but looks incomplete - + # such as a plain old 'ESC' (\x1b) that is not followed by other + # codes: + if (charbuffer + char1) == charbuffer: + return convertchar(charbuffer) + + charbuffer += char1 + + +def getkey(wait_for_char, old_settings): + charbuffer = '' try: if wait_for_char or select.select([sys.stdin, ], [], [], 0.0)[0]: char = os.read(sys.stdin.fileno(), 1) - char_buffer = char if type(char) is str else char.decode() + charbuffer = char if type(char) is str else char.decode() except Exception: - char_buffer = '' + pass finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) + return charbuffer - while True: - if char_buffer not in key.ESCAPE_SEQUENCES: - return char_buffer - else: - c = readchar(False) - if c is None: - return char_buffer - else: - char_buffer += c + +def convertchar(charbuffer): + if charbuffer in key.linux_keys: + return key.linux_keys[charbuffer] + return charbuffer