Почему Emacs, работающий в терминале, не может различить Ctrl +; от ";"?

8

Этот вопрос возник из моего предыдущего вопроса о бета-версии emacs . Короче говоря, я хочу привязать C-;функции Emacs в терминале, но кажется, что что-то захватывает эту клавишу до того, как она достигнет Emacs: Emacs считает, что я нажал ;.

Очевидным подозрением является эмулятор терминала, но я проверил многие из них (xterm, gnome-терминал, терминатор, терминология), и ни один из них не работает. Скорее всего, я могу исключить оконный менеджер, потому что в версии Emacs с графическим интерфейсом ключ C-;работает просто отлично. Я пробовал также две разные оболочки: bash и zsh, но снова безуспешно.

Что еще я могу попробовать?

WeSenseASoulInSearchOfAnswers
источник
В соответствии с вашим вопросом о Emacs , нажмите Ctrl +; отправляет ;в Emacs, так что ничто не захватывает его, что происходит, что Ctrl +; и голый; отправить ту же информацию. Что это: захват (т.е. Emacs ничего не получает) или потеря информации (т.е. Emacs получает ;)?
Жиль "ТАК - перестань быть злым"
C-;в терминале нет стандартного кода для . Что произойдет, если вы наберете C-v C-;обычный bash?
artm
@Gilles я вижу ;в emacs -nwхит независимо от того , я ;или C-;.
WeSenseASoulInSearchOfAnswers
@artm так bashже, как печатает Emacs просто голые ;.
WeSenseASoulInSearchOfAnswers

Ответы:

11

Возможно, ваша путаница возникает из-за того, что вы не использовали реальный терминал. Когда серьезные компьютеры были размером с несколько вертикальных холодильников, терминал связывался с центральным компьютером через последовательный кабель, используя только символы и символы. Символы были частью некоторого стандартизированного набора символов, например ASCII или EBCDIC, но обычно ASCII. ASCII имеет 33 управляющих символа, и оператор терминала отправил их, нажав специальную клавишу (например, DEL) или удерживая клавишу CTRL и нажимая другую клавишу. Центральный компьютер видел только управляющий символ; он не знал, какие клавиши были нажаты, чтобы создать персонажа.

Программа эмуляции терминала, такая как xterm, имитирует это поведение. Эмулятор терминала предоставляет способ отправки всех 33 управляющих символов ASCII, и Emacs получит эти символы, если они будут отправлены. Но Emacs похож на центральный компьютер в приведенном выше описании - он не может знать, какие клавиши были фактически нажаты, когда вы запускаете его под эмулятором терминала. Поэтому, если вы нажмете CTRL и точку с запятой, если программа эмуляции терминала не сопоставит эти нажатия клавиш с каким-либо символом ASCII, Emacs не будет знать, что что-то было напечатано.

Эмуляторы терминала обычно используют следующие сопоставления для генерации управляющих символов :

нажатие клавиши ASCII
--------------------
ESCAPE 27
УДАЛИТЬ 127
BACKSPACE 8
CTRL + ПРОБЕЛ 0
CTRL + @ 0
CTRL + A 1
CTRL + B 2
CTRL + C 3
так далее...
CTRL + X 24
CTRL + Y 25
CTRL + Z 26
CTRL + [27
CTRL + \ 28
CTRL +] 29
CTRL + ^ 30
CTRL + _ 31

Обратите внимание, что CTRL +; не появляется в этом списке. Терминалы, как правило , просто отправить печатаемый символ , назначенный клавишу , если CTRL + клавиша не отображаются на управляющий символ. Так что ваш эмулятор терминала говорит вам, посылая; единственное, что он не знает, что делать, когда вы нажимаете CTRL + ;.

Все это применимо, только если вы используете терминал или программу эмуляции терминала. Если вы запускаете Emacs как собственное приложение в некоторой оконной системе, то Emacs имеет полный доступ к событиям нажатия клавиш, а не только к символам. Таким образом, Emacs может видеть, что вы нажали CTRL и точку с запятой вместе, и вы можете назначить действие этой паре нажатий клавиш.

Терминалы часто имеют функциональные клавиши и клавиши со стрелками, которые также генерируют последовательности символов, которые включают управляющие символы. Эти последовательности обычно начинаются с кода ASCII 27 (ESCAPE).

Кайл Джонс
источник
3

Терминалы передают символы (точнее: байты), а не ключи. Когда вы нажимаете клавишу или последовательность клавиш, например Ctrl+ ;, эта информация должна быть закодирована в виде последовательности байтов. Keychords , которые представляют символ, как Aили Shift+ Aили À, посылается как этот символ: a, A, à(последний из которых один или два байта , в зависимости от кодировки символов терминала).

Связки ключей, включающие функциональные клавиши, не имеют соответствующего символа, поэтому они отправляются как escape-последовательности: последовательность байтов, начинающаяся с escape-символа ( \eв строке Emacs, которая отображается как голубая, ^[если она введена буквально в буфере). Несколько функциональных клавиш имеют соответствующие байты, которые являются управляющими символами .

Keychord Ctrl+ ;не имеет стандартной escape-последовательности, поэтому большинство эмуляторов терминала генерируют символ ;. Это теряет информацию о том, что Ctrlмодификатор был нажат.

Чтобы определить привязку для Ctrl+ ;, вам необходимо настроить эмулятор терминала для отправки другой escape-последовательности. Я не думаю, что вы можете сделать это с терминалом Gnome (Gnome редко настраивается). Вы можете сделать это с Xterm. См. Есть ли терминалы Linux, которые могут обрабатывать все комбинации клавиш? для инструкций.

Оболочка, которую вы можете запустить в терминале, не задействована. GUI Emacs не имеет проблем, потому что GUI (X11) передает входные события в форме, которая кодирует ключи и модификаторы, а не просто как последовательность символов.

См. Как работают ввод с клавиатуры и вывод текста? для получения более подробной информации о том, как ввод поступает с клавиатуры на ваше приложение.

Жиль "ТАК - перестань быть злым"
источник