xieve
xieve

Reputation: 61

(Python) Detecting arrow key press on Windows

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()

Upvotes: 1

Views: 4069

Answers (1)

xieve
xieve

Reputation: 61

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

Upvotes: 5

Related Questions