开发者

How to differentiate between Escape and Up/Down/Left/Right with termios?

开发者 https://www.devze.com 2023-03-20 18:11 出处:网络
GitHub This is the best I can come up with to handle ncurses-style key presses (I\'m actually writing an alternative to ncurses for various reasons).

GitHub

This is the best I can come up with to handle ncurses-style key presses (I'm actually writing an alternative to ncurses for various reasons).

An example app built with this code advises the user to "Quit by pressing Escape". In truth, it requires Escape + Escape or Escape + An Arrow Key. I'd like to fix this.

#include <sys/ioctl.h>
#include <termios.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *get_key() {
    char c = getchar();

    switch(c) {
        case 'a': return "a";
        case 'b': return "b";
        case 'c': return "c";

        ...

        case '\x1b':
            c = getchar();
            switch(c) {
                case '[':
                    c = getchar();
                    switch(c) {
                        case 'A': retu开发者_Go百科rn "up";
                        case 'B': return "down";
                        case 'C': return "right";
                        case 'D': return "left";
                    }
                case '\x1b': return "escape";
            }

        default: return "unknown";
    }


Step 1. Research.

http://en.wikipedia.org/wiki/Escape_sequence

If the Esc key and other keys that send escape sequences are both supposed to be meaningful to an application, an ambiguity arises, if a terminal or terminal emulator is in use. In particular, when the application receives the ASCII escape character, it is not clear whether that character is the result of the user pressing the Esc key or whether it is the initial character of an escape sequence (e.g., resulting from an arrow key press). The traditional method of resolving the ambiguity is to observe whether or not another character quickly follows the escape character. If not, it is assumed not to be part of an escape sequence. This heuristic can fail under some circumstances, but in practice it works reasonably well, especially with faster modern communication speeds.

Step 2. Figure out how to see if there's another character waiting in the input buffer on your OS. If there's a character already in the buffer; it was an escape sequence. If the input buffer is empty, it was escape.

Since you didn't mention your OS, it's not clear how this can be done.

Windows: What is the Windows equivalent to the capabilities defined in sys/select.h and termios.h

Linux: http://linux.die.net/man/3/termios


Rather than relying on the rather fragile timing mechanism of VMIN/VTIME, you may prefer to move the timing logic up into pure userland. I wrote a library to handle this and a number of other cases:

http://www.leonerd.org.uk/code/libtermkey/

As well as distinguishing Escape from arrow keys, it can also handle things like modified arrow keys and modified Unicode that modern terminals are starting to use, supports both blocking and non-blocking uses, and many other things. In fact your get_key() function could be easily performed by termkey_waitkey() to obtain a keypress followed by termkey_strfkey() to format it into a string buffer.


A buffer and some bit options do the job nicely.

GitHub

0

精彩评论

暂无评论...
验证码 换一张
取 消