Как различить Escape и Up / Down / Left / Right с помощью termios? - PullRequest
2 голосов
/ 14 июля 2011

GitHub

Это лучшее, что я могу придумать для обработки нажатий клавиш в стиле ncurses (на самом деле я пишу альтернативу ncurses по разным причинам).

Пример приложения, созданного с использованием этого кода, советует пользователю «Выйти, нажав Escape».По правде говоря, это требует Escape + Escape или Escape + Arrow Key.Я бы хотел это исправить.

#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': return "up";
                        case 'B': return "down";
                        case 'C': return "right";
                        case 'D': return "left";
                    }
                case '\x1b': return "escape";
            }

        default: return "unknown";
    }

Ответы [ 3 ]

2 голосов
/ 14 июля 2011

Шаг 1. Исследование.

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

Если клавиша Esc и другие ключи, отправляющие escape-последовательности, оба должно быть значимым для приложения, возникает двусмысленность, если терминал или эмулятор терминала используется. В частности, когда приложение получает escape-символ ASCII, это не ясно является ли этот символ результатом нажатия клавиши Esc пользователем или является ли это начальным символом escape-последовательности (например, в результате нажатия клавиши со стрелкой). Традиционный метод Разрешение двусмысленности состоит в том, чтобы наблюдать, является ли другой персонаж быстро следует за спасательным персонажем. Если нет, то предполагается, что не будет часть escape-последовательности. Эта эвристика может потерпеть неудачу при некоторых обстоятельства, но на практике это работает достаточно хорошо, особенно с более высокими современными скоростями связи.

Шаг 2. Выясните, как увидеть, есть ли другой символ, ожидающий во входном буфере в вашей ОС. Если в буфере уже есть символ; это была последовательность побега. Если входной буфер пуст, это был escape.

Поскольку вы не упомянули свою ОС, неясно, как это можно сделать.

Windows: Что такое Windows, эквивалентный возможностям, определенным в sys / select.h и termios.h

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

0 голосов
/ 05 апреля 2012

Вместо того, чтобы полагаться на довольно хрупкий механизм синхронизации VMIN / VTIME, вы можете предпочесть перенести логику синхронизации в чистое пользовательское пространство. Я написал библиотеку для обработки этого и ряда других случаев:

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

Помимо разграничения клавиш со стрелками, он также может обрабатывать такие вещи, как модифицированные клавиши со стрелками и модифицированный Unicode, которые начинают использовать современные терминалы, поддерживает как блокирующие, так и неблокирующие применения, и многие другие. Фактически, ваша get_key() функция может быть легко выполнена с помощью termkey_waitkey() для получения нажатия клавиши, за которым следует termkey_strfkey() для форматирования ее в строковый буфер.

0 голосов
/ 19 июля 2011

Буфер и некоторые битовые опции прекрасно справляются со своей задачей.

GitHub

...