Вообще, это надо в пост про curses, и я туда добавлю, но сейчас там никто не прочитает.
В винде мы привыкли, что можно определить любое сочетание клавиш. В графическом режиме линукса, по-видимому, тоже. Но если мы работаем в терминале, то всё не так. Я много поел говна, пока разбирался с сочетаниями с альтом, с хоум-эндом, с задержкой после нажатия эскейпа (а в винде всё тоже самое работает без проблем, тоже в терминале).
Но когда я решил провести углублённое тестирование, то обнаружил ещё две вещи.
1. Tab невозможно отличить от Ctrl+i. Потому что они оба возвращают один код. (это поведение присутствует и в винде, как выяснилось)
2. Ctrl+M невозможно получить. Потому что когда нажимаешь Ctrl+M, в программе получаешь Ctrl+J. То же самое происходит и при нажатии Enter (поэтому различить Ctrl+J и Enter невозможно тоже).
В некоторых терминалах поведение отличается. Там нажатие энтера генерирует Ctrl+M. Тогда не получится сгенерировать Ctrl+J, поскольку его нажатие будет генерировать Ctrl+M. Такое поведение связано с различием управляющих кодов CR/LF. И если в настройках терминала стоит одно, то во всех трёх случаях будет генерироваться Ctrl+J, а если другое -- Ctrl+M.
Есть очень окольные способы настроить такое под себя. Но если я пишу программу для терминала, которая должна более-менее работать в любом линуксе, то надо отказаться от Ctrl+J, Ctrl+M, Ctrl+i, Tab, а ещё, желательно, от Ctrl+H, который легко путается с Backspace. Но вот именно настройка управляющего кода бэкспейса в эмуляторах терминалов всегда расположена на видном месте.