1

I found various ways to detect any keypress, from curses over click to creating a function to do that (also msvcrt but this has gotta work on Linux sometime), but I always encountered the same problem: No matter which arrow key I pressed, all those functions returned b'\xe0'. I tried it in cmd and in powershell, same result. I'm running Win7 Pro 64bit.

Edit: Sorry, I used this code and tried msvcrt.getch() and click.getchar()

xieve
  • 61
  • 1
  • 7

1 Answers1

5

I figured out that an arrow key's represented by two chars, so I modified this solution so that if the first char is put in, it reads the second (and third, wtf Linux?) too and then converts them into platform-independent strings.

# Find the right getch() and getKey() implementations
try:
    # POSIX system: Create and return a getch that manipulates the tty
    import termios
    import sys, tty
    def getch():
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(fd)
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
            return ch

    # Read arrow keys correctly
    def getKey():
        firstChar = getch()
        if firstChar == '\x1b':
            return {"[A": "up", "[B": "down", "[C": "right", "[D": "left"}[getch() + getch()]
        else:
            return firstChar

except ImportError:
    # Non-POSIX: Return msvcrt's (Windows') getch
    from msvcrt import getch

    # Read arrow keys correctly
    def getKey():
        firstChar = getch()
        if firstChar == b'\xe0':
            return {"H": "up", "P": "down", "M": "right", "K": "left"}[getch()]
        else:
            return firstChar
xieve
  • 61
  • 1
  • 7
  • It should only call [`getch`](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getch-getwch) a second time when the first character read is `b'\x00'` or `b'\xe0'`. – Eryk Sun Nov 19 '17 at 17:32
  • Here's an [alternate implementation](https://pastebin.com/0CMbB7EK) that handles Unicode strings in Python 3; always gets key pairs (i.e. leading "\x00" or "\xe0") to avoid leaving the input buffer in a bad state; and handles unmapped keys (e.g. HOME) more gracefully by returning the joined first and second character instead of raising `KeyError`. – Eryk Sun Nov 24 '17 at 12:07