Распознавание клавиш со стрелками с помощью stdin

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

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

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

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

Недавно я сделал что-то довольно похожее (хотя мой код только для 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, чтобы c_echo клавиши со стрелкой на терминал (но тогда вам придется вручную печатать все остальное.

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

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

Где ‘\ 027’ – значение ascii для esc

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

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

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

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

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