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

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

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

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

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

решение1

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

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

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

нажатие клавиши ASCII
--------------------
ПОБЕГ 27
УДАЛИТЬ 127
ВОЗВРАТ 8
CTRL+ПРОБЕЛ 0
CTRL+@ 0
CTRL+A 1
CTRL+B 2
CTRL+C3
и т. д...
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).

решение2

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

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

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

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

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

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

Связанный контент