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

13

Когда вы вводите управляющие символы в оболочке, они отображаются с использованием так называемой «каретки». Escape, например, записывается как ^[в каретной нотации.

Мне нравится настраивать оболочку bash, чтобы она выглядела круто. Я, например, изменил мой PS1и PS2стал раскрашенным. Теперь я хочу, чтобы управляющие персонажи также приобрели уникальный внешний вид, чтобы они отличались от обычных персонажей.

$ # Here I type CTRL-C to abort the command.
$ blahblah^C
          ^^ I want these two characters to be displayed differently

Есть ли способ заставить мою оболочку выделять управляющие символы по-другому?

Можно ли заставить его отображать их жирным шрифтом или, возможно, заставить их отображаться разными цветами по сравнению с обычным текстом?

Я использую здесь оболочку bash, но я не пометил вопрос, bashпотому что, возможно, есть решение, которое применимо ко многим различным оболочкам.

Обратите внимание, что я не знаю, на каком уровне происходит выделение контрольных символов. Сначала я подумал, что это было в самой оболочке. Теперь я слышал, что это readline, который контролирует, как управляющие символы в оболочках, таких как bash . Итак, вопрос теперь помечен, readlineи я все еще ищу ответы.

wefwefa3
источник
почему вы думаете, что оболочка выделяет их? поскольку bashон readlineобрабатывает эти вещи, а для большинства других это драйвер tty.
mikeserv
Я не знал Вот почему я написал записку. Это было только мое предположение, потому что другие приложения любят viи lessчасто выделяют управляющие символы в отличие от обычного текста. Я буду редактировать вопрос с этой информацией. Спасибо!
wefwefa3
это имеет смысл. такие вещи сложнее для оболочки, потому что это своего рода второй приоритет. с редакторами вся их задача состоит в том, чтобы предоставить экранный интерфейс <>, но оболочка является интерпретатором команд для интерпретируемого языка сначала и для строкового редактора второго (или вовсе нет) .
mikeserv
Readline используется другими программами, но также является частью bash: это библиотека, связанная с ним. А сегодняшние оболочки, особенно bash, делают практически все, что только можно придумать.
Алексис
Просто используйте, zshкоторый делает это из коробки.
Стефан Шазелас

Ответы:

20

Когда вы нажимаете 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 (который выделяется ^Xs в обратном видео), полагаясь на :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 локаль будет отображаться как ^�... и т. д.

Стефан Шазелас
источник
3

У меня обычно есть этот код в моем файле .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", будут запрошены.

косолапый
источник
$? расширяется до статуса выхода в PS1, например, PS1 = '$? \ u @ \ h \ w'
teknopaul