Когда вы нажимаете Ctrl+X, ваш эмулятор терминала записывает байт 0x18 на ведущую сторону пары псевдотерминалов.
Что будет дальше, зависит от того, как сконфигурирована дисциплина tty line (программный модуль в ядре, который находится между ведущей стороной (под управлением эмулятора) и ведомой стороной (с которой взаимодействуют приложения, работающие в терминале)).
Команда для настройки этой дисциплины линии tty является stty
командой.
При запуске такого тупого приложения cat
, которое не знает и не заботится о том, является ли его стандартный ввод терминалом, терминал находится в каноническом режиме по умолчанию, где дисциплина строки tty реализует редактор необработанных строк .
Некоторые интерактивные приложения, которым требуется больше, чем простой редактор строк, обычно изменяют эти параметры при запуске и восстанавливают их при выходе. Современные оболочки, по их подсказке, являются примерами таких приложений. Они реализуют свой собственный более продвинутый редактор строк.
Обычно, когда вы вводите командную строку, оболочка переводит дисциплину линии tty в этот режим, и когда вы нажимаете клавишу ввода, чтобы выполнить текущую команду, оболочка восстанавливает обычный режим tty (как это было до появления приглашения).
Если вы выполните stty -a
команду, вы увидите текущие настройки, используемые для глупых приложений . Вы, вероятно, увидите icanon
, что echo
и echoctl
настройки включены.
Это значит, что:
icanon
: этот грубый редактор строк включен.
echo
: Символы типа (что эмулятор терминала записывает в основной части) являются эхом назад (доступны для чтения с помощью эмулятора терминала).
echoctl
: Вместо того , чтобы быть эхом ASIS, символы управления эхом , как ^X
.
Итак, допустим, вы печатаете A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.
Ваш эмулятор терминала будет отправить: AB\bC\x18\b\r
. Дисциплина линии отзовется обратно: AB\b \bC^X\b \b\b \b\r\n
и приложение, которое читает входные данные от ведомой стороны ( /dev/pts/x
), будет читать AC\n
.
Все, что видит приложение AC\n
, и только тогда, когда ваша пресса, Enterтак что он не может иметь никакого контроля на выходе для ^X
там.
Вы заметите, что для echo первое ^H
( ^?
с некоторыми терминалами, см. erase
Настройку) привело \b \b
к отправке обратно на терминал. Это последовательность для перемещения курсора назад, перезаписи с пробелом, перемещения курсора назад снова, в то время как второе ^H
привело \b \b\b \b
к стиранию этих двух символов ^
и X
символов.
Сам ^X
(0x18) переводился в ^
и X
для вывода. Мол B
, он не попал в приложение, так как мы удалили его с помощью Backspace.
\r
(aka ^M
) был переведен в \r\n
( ^M^J
) для эха, и \n
( ^J
) для приложения.
Итак, каковы наши варианты для этих глупых приложений:
- отключить
echo
( stty -echo
). Это эффективно меняет способ отображения управляющих символов, ничего не отражая. Не совсем решение.
- отключить
echoctl
. Это изменяет способ отображения управляющих символов (кроме ^H
, ^M
... и всех других, используемых редактором строк). Затем они отражаются как есть. То есть, например, символ ESC отправляется как \e
( ^[
/ 0x1b
) байт (который распознается терминалом как начало escape-последовательности), ^G
вы отправляете \a
(BEL, издающий звуковой сигнал вашего терминала) ... Не вариант ,
- отключить редактор грубой строки (
stty -icanon
). Не совсем вариант, так как сырые приложения станут намного менее пригодными для использования.
- отредактируйте код ядра, чтобы изменить поведение дисциплины линии tty, чтобы эхо управляющего символа отправлялось
\e[7m^X\e[m
вместо просто ^X
(здесь \e[7m
обычно разрешается обратное видео в большинстве терминалов).
Можно было бы использовать такую обертку как rlwrap
грязный хак, чтобы добавить необычный редактор строк в тупые приложения. По сути, эта обертка пытается заменить простые read()
s из оконечного устройства вызовами редактора строк readline (которые изменяют режим дисциплины tty line).
Если пойти еще дальше, вы даже можете попробовать решения, подобные этому, которые перехватывают весь ввод с терминала, чтобы пройти через редактор строк zsh (который выделяется ^X
s в обратном видео), полагаясь на :exec
функцию экрана GNU .
Теперь для приложений, которые реализуют собственный редактор строк, они сами решают, как сделать эхо . bash
использует readline для того, что не поддерживает настройку отображения управляющих символов.
Для zsh
см .:
info --index-search='highlighting, special characters' zsh
zsh
по умолчанию выделяет непечатаемые символы. Вы можете настроить выделение, например:
zle_highlight=(special:fg=white,bg=red)
Для белого на красном подсветка для тех специальных символов.
Текстовое представление этих символов не настраивается, хотя.
В UTF-8 локали, 0x18 будет оказано , как ^X
, \u378
, \U7fffffff
(два нераспределенные точки Юникода кода) , как <0378>
, <7FFFFFFF>
, \u200b
(не-действительно для печати Юникода характера) , как <200B>
.
\x80
в iso8859-1 локаль будет отображаться как ^�
... и т. д.
bash
онreadline
обрабатывает эти вещи, а для большинства других это драйвер tty.