Вопрос или проблема
В bash я нажимаю ctrl+v, чтобы начать ввод в прямом режиме. В прямом режиме я нажимаю клавишу Esc, и bash показывает ^[
. Я перенаправляю это в файл esc
.
Также в прямом режиме я нажимаю клавишу ctrl вместе с клавишей [, и bash показывает ^[
. Я перенаправляю это в файл ctrl
.
Затем я сравниваю два файла, и они одинаковые!
$ echo '^[' > esc
$ echo '^[' > ctrl
$ diff esc ctrl
$
Почему Ctrl+[ и Esc производят одинаковое содержимое?
Является ли ^[
здесь кодами управления C0 и C1? Если да, то википедийная статья говорит, что ^[
это Escape, так почему ctrl+[ тоже Escape?
Основная проблема в том, что я хочу проверить и создать привязку клавиш.
(zsh)$ bindkey -L
...
bindkey "^['" quote-line
...
Так нужно ли мне вводить ESC+'
или ctrl+[+'
?
Это выглядит так, будто следует той же логике, что и Ctrl-A, или ^A
, являющегося кодом символа 1, и ^@
, используемым для представления байта NUL. Здесь ^
является распространённым способом представления Ctrl с другой клавишей.
А именно, ввод Ctrl-foo дает код символа foo с очищенным битом 6, уменьшая код символа на 64. Таким образом, A
— это код символа 65, а ^A
— код символа 1; @
— 64, а ^@
— 0, NUL; также [
— 91, а ^[
— 27, ESC. Просто для ESC у вас также есть отдельная клавиша, но у вас также есть клавиши enter и tab, которые также производят управляющие символы, так что это не так уж странно.
Конечно, как работает Ctrl-что-то на современных системах, вероятно, также зависит от других факторов, таких как настройки ваших раскладок клавиш и привязок клавиш. Также не спрашивайте меня, как это работает для кодов символов < 64, например, ^1
. На терминале, который я пробовал, Ctrl-space выдавала байт NUL.
При использовании текстового терминала с текстовыми терминальными приложениями (такими как bash) вы не можете различить специальные клавиши, такие как Esc, Tab, Enter и Backspace, и их соответствующие управляющие символы. Аналогично, вы не можете различить цифры на числе и на числовой клавиатуре. Некоторые другие клавиши (стрелки, функциональные клавиши, пролистывание вверх/вниз и т. д.) производят несколько последовательностей символов.
Тем не менее, в графической среде (X11, Wayland) клавиши производят события, связанные с клавишей, которые отделены от (но связаны с) отображением символов, независимо от того, является ли это односимвольным или многосимвольным отображением. Графическое приложение может различать большинство из этих клавиш, если оно решит это сделать. (В некоторых случаях клавиши могут все еще иметь неразличимые отображения, но это редко и зависит от того, как ключи распределены.)
В основном графическое терминальное приложение выбирает не различать эти клавиши и последовательности клавиш, и через текстовый pty нет способа сообщить о различии в любом случае в основное текстовое приложение.
Например, клавиша Backspace традиционно может быть сопоставлена либо с Ctrl-H, либо с Ctrl-?. В графическом терминале существует настройка выбора, к чему она сопоставлена. Таким образом, графическое терминальное приложение может обнаружить разницу и изменить отображение, но текстовое приложение, работающее в терминале, не может.
Кратко: история.
“Почему” возвращает нас к проектным решениям, принятым, когда разрабатывался ASCII за десятилетие до его стандартизации как ISO 646 в 1967 году. Каждый код представлял либо одну клавишу (с shift или ctrl или без), либо функцию, которую можно было выполнить с помощью телетайпа.
Первый широко используемый телетайп, поддерживающий ASCII, был модель 33. У него была клавиша ALT MODE, которая излучала код 27, таким образом функционируя так же, как клавиша ESC, которую мы стали знать позже.
Важно подчеркнуть, что изначально ESC
был полностью синонимичен коду ASCII 27, который позже терминалы понимали как “сменить режим, где следующий байт будет восприниматься как команда, а не как что-то для отображения“.
Перейти вперед на пятнадцать лет, к различным видам оконных систем, и появилась совершенно новая функция для клавиши ESC: запрашивать “отмену текущей операции“.
Однако это не применимо, когда вы используете терминал, даже в оконной среде. Скорее, вы все еще получаете такое же поведение, как это предписано ASCII в 1967 году.
Что касается того, почему клавиша ctrl делает то, что она делает, другой ответ от @user10489 объясняет это.
Ответ или решение
Почему комбинации клавиш Ctrl+[
и ESC
обе производят ^[
?
Комбинации клавиш Ctrl+[
и Esc
в терминале Bash ведут себя довольно интересно и могут вызвать путаницу. Оба этих нажатия выдают символ ^[
, который соответствует ASCII-коду 27, или символу Escape. Ниже мы рассмотрим, как это работает, и причины, по которым обе комбинации выдают один и тот же результат.
Дерево соответствий клавиш
-
ASCII и контрольные символы:
- Стандарт ASCII был разработан в начале 1960-х годов и определяет набор кодов для представления символов. Код
27
соответствует символу Escape. Комбинации клавиш с использованиемCtrl
используют так называемое преобразование контрольных символов: нажатиеCtrl
с любой клавишей уменьшает код символа на 64. Таким образом, код[
(91) в комбинации сCtrl
становится 27 (кодEsc
).
- Стандарт ASCII был разработан в начале 1960-х годов и определяет набор кодов для представления символов. Код
-
Функции клавиш:
- Клавиша
Esc
была изначально создана как управляющий символ в системе ASCII.Ctrl+[
в некоторых аспектах функционирует аналогичноEsc
благодаря тому, что обе комбинации приводят к одному и тому же результату: коду 27.
- Клавиша
-
Среда терминала:
- Когда вы работаете в текстовой среде, такой как терминал, не существует различия в том, какую клавишу вы нажимаете (или комбинацию клавиш). Это связано с тем, что текстовые интерфейсы не различают специальные клавиши и их соответствующие управляющие символы. Например, клавиша
Enter
,Tab
и такие клавиши, какEsc
, работают по одному и тому же принципу: они возвращают управляющие коды, которые трактуются непосредственно терминалом.
- Когда вы работаете в текстовой среде, такой как терминал, не существует различия в том, какую клавишу вы нажимаете (или комбинацию клавиш). Это связано с тем, что текстовые интерфейсы не различают специальные клавиши и их соответствующие управляющие символы. Например, клавиша
Исторический контекст
История формирования поведения этих клавиш уходит корнями в проектирование ASCII и в использование электрических машин для печати, таких как телетайпы. Клавиша Esc
была включена в первую версию ASCII как средство для изменения режима, в котором следующий входящий символ интерпретируется не как текст, а как команда. С увеличением популярности терминалов и текстовых редакторов, это поведение оставалось неизменным.
Клавиша Ctrl
добавляет дополнительный уровень функциональности: с помощью этого модификатора можно использовать привычные буквы и знаки для достижения функционала управления, который раньше был доступен только через специальные клавиши.
Применение в настройках оболочки
Теперь, когда возникает вопрос создания привязок клавиш, таких как bindkey
в Zsh, вы можете использовать любую из этих комбинаций. Это зависит от личных предпочтений и привычек пользователя. Хорошей практикой может быть использование более очевидного варианта в зависимости от контекста: для базового управления редакцией команд лучше использовать Esc
, тогда как в случае, когда основное внимание уделяется управлению командой, вполне подойдет Ctrl+[
.
Заключение
Таким образом, комбинации Ctrl+[
и Esc
выводят один и тот же управляющий символ из-за их соответствия в стандарте ASCII, а также из-за особенностей работы текстовых терминалов. Это использование кодов было консистентным с историей и проектированием клавиатурного ввода. Понимание этой взаимосвязи основано на знании того, как терминалы обрабатывают управляющие коды, и на практических применениях в конфигурации оболочки.