Как по-разному отображать управляющие символы (^C, ^D, ^[, ...) в оболочке

Как по-разному отображать управляющие символы (^C, ^D, ^[, ...) в оболочке

Когда вы вводите управляющие символы в оболочке, они отображаются с использованием так называемой "обозначения каретки". Например, 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 (который, как оказалось, подсвечивает ^Xs в обратном порядке), полагаясь на функцию 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».

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