Признавая клавиши со стрелками с stdin
возможно ли иметь кросс-платформенный способ обработки backspace и клавиш со стрелками в программе C или OCaml?
на самом деле решение OCaml было бы оценено, но многие стандартные функции unix обернуты непосредственно к соответствующим вызовам API, поэтому не должно быть никаких проблем в переносе решения C.
то, что я собираюсь достичь, это поймать клавиши со стрелками, чтобы переопределить его поведение внутри оболочки (путем перепробования последней строки или таких операций). Я думаю что эта вещь падает перед фактической программой, и она не обрабатывается самим кодом, поэтому я не знаю, возможно ли это.
программа компилируется либо на Linux, OS X и Windows (на cygwin), поэтому я хотел бы сделать это для всех платформ..
4 ответов
недавно я сделал что-то похожее (хотя мой код-только Linux). Вы должны установить stdin в неканонический режим, чтобы прочитать нажатия клавиш со стрелками. Это должно работать на 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 tsdin TCSAFLUSH terminfo); (* reset stdin when you quit*)
tcsetattr stdin TCSAFLUSH newterminfo;
когда канонический режим выключен, вам не нужно ждать новой строки для чтения из stdin. c_vmin представляет минимальное количество символов для чтения перед возвратом (вероятно, вы хотите иметь возможность для чтения одного символа за раз) и c_vtime-максимальное время ожидания чтения (в единицах 0,1 с).
вы также можете установить c_echo
false, чтобы клавиши со стрелками печатаются в терминале (но тогда вам придется вручную печатать все остальное.
большинство терминалов представляют клавиши со стрелками с помощью ANSI escape-последовательности. Если вы бежите cat
без аргументов и начать нажимать клавиши со стрелками вы можете увидеть escape-последовательности, используемые. Они обычно
up - "7[A"
down - "7[B"
left - "7[D"
right - "7[C"
где '\027 ' - значение ascii для esc
используйте ncurses для извлечения последовательностей для возможностей клавиши со стрелкой, а затем ищите их при чтении stdin. Это, наверное, проще использовать что-то вроде libedit или вместо readline и пусть это дело с keyhandling.
стандартный способ поддержки ввода с клавиатуры за пределами строк печатаемых символов - через ncurses библиотека, которая имеет данные, используемые переплетные. Еще одна распространенная возможность -readline библиотека (наиболее широко используется Bash).
Если все, что вы делаете, это чтение ввода строка за строкой, но хотите, чтобы ваши пользователи имели достойный редактор строк, нет необходимости включать какую-либо поддержку в вашу программу. Вместо этого просто скажите своим пользователям использовать программа-оболочка, такая как rlwrap (который основан на readline) или прикольно. Эти обертки предоставляют line edition и историю, две функции, которые вы перечисляете в качестве своих требований. Я бы рекомендовал вам построить обработку ввода в вашу программу, только если вы хотите что-то более причудливое, например, завершение программы, когда пользователь нажимает Tab.
Backspace является символом ASCII и будет помещен в stdin, как и любой другой символ. Символ escape-последовательности '\b'
является символом backspace.
для клавиш курсора они не связаны с каким-либо управляющим символом, поэтому не генерируйте данные в потоке stdin. Низкий уровень доступа обязательно зависит от платформы, хотя существуют кросс-платформенные библиотеки, которые абстрагируются от различий платформы. Я считаю, что ncurses доступен для всех платформ, которые вы упомянутый.