%20%D0%B2%20%D0%BE%D0%B1%D0%BE%D0%BB%D0%BE%D1%87%D0%BA%D0%B5.png)
Когда вы вводите управляющие символы в оболочке, они отображаются с использованием так называемой "обозначения каретки". Например, Escape записывается как ^[
обозначение каретки.
Мне нравится настраивать свою оболочку bash, чтобы она выглядела круто. Например, я изменил свои PS1
и PS2
, чтобы они стали цветными. Теперь я хочу, чтобы символы управления также получили уникальный внешний вид, чтобы сделать их более отличимыми от обычных символов.
$ # Here I type CTRL-C to abort the command.
$ blahblah^C
^^ I want these two characters to be displayed differently
Есть ли способ заставить мою оболочку по-другому подсвечивать управляющие символы?
Можно ли сделать так, чтобы они отображались жирным шрифтом или отличались по цвету от обычного текста?
Я используюБашshell здесь, но я не пометил вопрос тегом , bash
потому что, возможно, есть решение, применимое ко многим различным оболочкам.
Примечаниечто я не знаю на каком уровне происходит подсветка управляющих символов. Я сначала думал, что это в самой оболочке. Теперь я слышал, что эторидлайнкоторый контролирует, как управляют символы в оболочках, напримерБаш. Итак, вопрос теперь помечен тегом readline
, и я все еще ищу ответы.
решение1
При нажатии кнопки Ctrl+Xэмулятор терминала записывает байт 0x18 на главную сторону пары псевдотерминалов.
Дальнейшие действия зависят от того, как настроена дисциплина линии tty (программный модуль в ядре, который находится между главной стороной (под управлением эмулятора) и подчиненной стороной (с которой взаимодействуют приложения, работающие в терминале)).
Команда для настройки этогодисциплина линии телетайпаэто stty
команда.
При запуске такого глупого приложения, cat
которое не знает и не заботится о том, является ли его stdin терминалом или нет, терминал находится в состоянии по умолчаниюканоническийрежим, в котором дисциплина линии tty реализует грубыйредактор строки.
Некоторые интерактивные приложения, которым нужно больше, чем просто грубая обработкаредактор строкиобычно изменяют эти настройки при запуске и восстанавливают их при выходе. Современные оболочки,по их настояниюявляются примерами таких приложений. Они реализуют свой собственный более продвинутый редактор строк.
Обычно при вводе командной строки оболочка переводит дисциплину линии tty в этот режим, а когда вы нажимаете Enter для выполнения текущей команды, оболочка восстанавливает обычный режим tty (который действовал до выдачи приглашения).
Если вы выполните stty -a
команду, вы увидите текущие настройки, используемые длятупые приложения. Вероятно, вы увидите icanon
, что настройки echo
и echoctl
включены.
Это означает, что:
icanon
: этот редактор грубой строки включен.echo
: вводимые вами символы (которые эмулятор терминала записывает на главную сторону)эхом отозвалсяобратно (доступно для чтения эмулятором терминала).echoctl
: вместо того, чтобыэхом отозвалсякак и прежде, управляющие символыэхом отозвалсякак^X
.
Итак, предположим, вы вводите A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.
Ваш эмулятор терминала отправит: AB\bC\x18\b\r
. Дисциплина линии будетэхоback: AB\b \bC^X\b \b\b \b\r\n
, а приложение, которое считывает ввод со стороны подчиненного устройства ( /dev/pts/x
), будет считывать AC\n
.
Все, что видит приложение, это AC\n
, и только тогда, когда вы нажимаете , Enterпоэтому оно не может никак управлять выводом ^X
.
Вы заметите, что дляэхо, первый ^H
( ^?
с некоторыми терминалами, см. erase
настройку) привел к \b \b
отправке обратно на терминал. Это последовательность перемещения курсора назад, перезаписи пробелом, перемещения курсора снова назад, тогда как второй ^H
привел \b \b\b \b
к стиранию этих двух ^
и X
символов.
Сам ^X
(0x18) был переведен в ^
и X
для вывода. Как и B
, он не попал в приложение, так как мы удалили его с помощью Backspace.
\r
(он же ^M
) был переведен в \r\n
( ^M^J
) для эха и \n
( ^J
) для приложения.
Итак, какие у нас есть варианты для тех,тупойПриложения:
- отключить
echo
(stty -echo
). Это фактически меняет способ отображения управляющих символов, не отображая ничего. Не совсем решение. - отключить
echoctl
. Это изменяет способ отображения управляющих символов (кроме^H
,^M
... и всех остальных, используемых редактором строк). Затем ониэхом отозвалсякак есть. То есть, например, символ ESC отправляется как байт\e
(^[
/0x1b
) (который распознается терминалом как начало управляющей последовательности),^G
вы отправляете\a
(BEL, заставляя ваш терминал издать звуковой сигнал)... Не вариант. - отключить редактор грубой строки (
stty -icanon
). Не совсем вариант, так как грубые приложения станут гораздо менее пригодными для использования. - отредактируйте код ядра, чтобы изменить поведение дисциплины линии tty, чтобыэхоуправляющего символа отправляет
\e[7m^X\e[m
вместо просто^X
(здесь\e[7m
обычно включает обратное видео в большинстве терминалов).
Вариантом может быть использование такой оболочки, как rlwrap
эта, грязный хак для добавления причудливого редактора строк в тупые приложения. Эта оболочка в действительности пытается заменить простые read()
s из терминального устройства на вызовы редактора строк readline (которые действительно изменяют режим дисциплины линии tty).
Если пойти еще дальше, вы можете попробовать такие решения, какВот этоткоторый перехватывает весь ввод с терминала и пропускает его через редактор строк zsh (который, как оказалось, подсвечивает ^X
s в обратном порядке), полагаясь на функцию GNU screen :exec
.
Теперь для приложений, которые реализуют свой собственный редактор строк, им самим решать, какэхосделано. bash
использует readline для этого, который не поддерживает настройку того, как отображаются управляющие символы.
Для zsh
, см.:
info --index-search='highlighting, special characters' zsh
zsh
по умолчанию выделяет непечатаемые символы. Вы можете настроить выделение, например:
zle_highlight=(special:fg=white,bg=red)
Для выделения белым шрифтом на красном фоне специальных символов.
Однако текстовое представление этих символов не подлежит настройке.
В локали UTF-8 0x18 будет отображаться как ^X
, \u378
, \U7fffffff
(две неназначенные кодовые точки Unicode) как <0378>
, <7FFFFFFF>
, \u200b
(непечатаемый символ Unicode) как <200B>
.
\x80
в локали iso8859-1 будет отображаться как ^�
... и т.д.
решение2
Обычно в моем файле .bashrc есть следующий код:
function get_exit_status()
{
local code=$?
if [ $code -ne 0 ]
then
printf $'\001\033[31m\002'"($code)"$'\001\033[0m\002'" "
fi
}
и затем я вызываю эту функцию в моем PS1
PS1='\u@\h \w $(get_exit_status)'
При этом, если вы нажмете ^C, вы увидите это в командной строке.
I@mycomputer ~ ^C
I@mycomputer ~ (130)
Будут запрошены все коды статуса выхода, отличные от «0».