Распознавание клавиш со стрелками с помощью стандартного ввода - PullRequest
11 голосов
/ 09 ноября 2010

возможно ли иметь кроссплатформенный способ обработки клавиш возврата и возврата в программе C или OCaml?

На самом деле решение OCaml приветствуется, но многие стандартные функции Unix обернуты непосредственно в соответствующие вызовы API, поэтому при переносе решения C не должно возникнуть никаких проблем.

Чего я хочу добиться, так это перехватить клавиши со стрелками, чтобы переопределить их поведение внутри оболочки (путем повторной установки последней строки или подобных операций). Я думаю, что эта вещь выпадает перед самой программой, и она не обрабатывается самим кодом, поэтому я не знаю, возможно ли это.

Программа скомпилирована либо на Linux, OS X и Windows (на cygwin), поэтому я хотел бы сделать это для всех платформ ..

Ответы [ 4 ]

9 голосов
/ 09 ноября 2010

Недавно я сделал нечто похожее (хотя мой код только для Linux). Вы должны установить стандартный ввод в неканонический режим, чтобы читать нажатия клавиш со стрелками. Это должно работать на OS X и Linux и, вероятно, будет работать на Cygwin, хотя я не могу сказать наверняка.

open Unix
let terminfo = tcgetattr stdin in
  let newterminfo = {terminfo with c_icanon = false; c_vmin = 0; c_vtime = 0} in
    at_exit (fun _ -> tcsetattr stdin TCSAFLUSH terminfo); (* reset stdin when you quit*)
    tcsetattr stdin TCSAFLUSH newterminfo;

когда канонический режим выключен, вам не нужно ждать новой строки для чтения из stdin. c_vmin представляет минимальное количество символов для чтения перед возвратом (вы, вероятно, хотите иметь возможность читать один символ за раз), а c_vtime - максимальное время ожидания чтения (в единицах 0,1 с).

Вы также можете установить для c_echo значение false, чтобы нажатия клавиш со стрелками печатались на терминале (но тогда вам придется печатать все остальное вручную.

Большинство терминалов представляют нажатия клавиш со стрелками, используя escape-последовательности ANSI . Если вы запустите cat без аргументов и начнете нажимать клавиши со стрелками, вы увидите используемые escape-последовательности. Они, как правило,

up - "\033[A"
down - "\033[B"
left - "\033[D"
right - "\033[C"

Где '\ 033' - это значение ascii для esc

5 голосов
/ 09 ноября 2010

Используйте ncurses для извлечения последовательностей для возможностей клавиш со стрелками, а затем ищите их при чтении стандартного ввода.Вероятно, вместо этого проще использовать что-то вроде libedit или readline, и позволить этому разобраться с обработкой ключей.

2 голосов
/ 09 ноября 2010

Стандартный способ поддержки ввода с клавиатуры вне строк печатаемых символов - это библиотека ncurses , которая имеет привязку Ocaml . Другой распространенной возможностью является библиотека readline (наиболее широко используемая Bash).

Если все, что вы делаете, это читаете ввод за строкой, но хотите, чтобы у ваших пользователей был приличный редактор строк, нет необходимости включать какую-либо поддержку в вашу программу. Вместо этого, просто попросите своих пользователей использовать программу-оболочку, такую ​​как rlwrap (которая основана на readline) или ledit . Эти оболочки предоставляют строчную версию и историю, две функции, которые вы указываете в качестве своих требований. Я бы порекомендовал вам встроить обработку ввода в вашу программу, только если вы хотите что-то более изощренное, например, завершение программы, когда пользователь нажимает Tab .

1 голос
/ 10 ноября 2010

Backspace является символом ASCII и будет помещен в стандартный ввод, как и любой другой символ.Экранирующая последовательность символов '\b' является символом возврата.

Для клавиш курсора они не связаны ни с одним управляющим символом, поэтому не генерируют данные в потоке stdin.Низкоуровневый доступ обязательно зависит от платформы, хотя существуют кроссплатформенные библиотеки, которые абстрагируют различия платформы.Я считаю, что ncurses доступен для всех платформ, которые вы упомянули.

...