
Когда вы запускаете cal на Linux, вывод для текущего месяца будет инвертировать видеоподсветку текущего дня. Когда я отправляю этот вывод в hexdump -c, я получаю некоторые интересные результаты:
0000000 N o v e m b e r 2 0 1 6
0000010 \n S u M o T u
0000020 W e T h F r S a \n
0000030 1 2 _ \b _ \b 3
0000040 4 5 \n 6 7
0000050 8 9 1 0 1 1 1 2 \n
0000060 1 3 1 4 1 5 1 6 1 7 1
0000070 8 1 9 \n 2 0 2 1 2 2
0000080 2 3 2 4 2 5 2 6 \n 2 7
0000090 2 8 2 9 3 0
00000a0 \n
00000b0 \n
00000bc
Как вы можете видеть, перед выделенной сегодня «3» печатается невидимая последовательность _\b _\b. _ — это подчеркивание (5F в шестнадцатеричном коде ascii), а \b — это Ctrl-H или 08 в шестнадцатеричном коде ASCII. Что это? Я знаю, что есть много непонятных кодов терминала, но я бы ожидал, что он будет использовать что-то более стандартное, например \e[7m. Еще более странно то, что я не могу воспроизвести то же поведение cal, распечатав те же символы с помощью стандартных функций printf, например, одной из этих команд:
/usr/bin/printf "1 2 _\b _\b3 4 5\n"
/usr/bin/printf "1 2 _^H _^H3 4 5\n"
Где ^H создается нажатием Ctrl-V Ctrl-H. Но ни один из них не дает тот же инвертированный видеовыход, что и cal. Я даже пытался написать небольшую программу на C, чтобы сделать это. Я также пробовал с echo -e. Интересно то, что хотя это не инвертирует видео в терминале, если я передаю вывод из less -R, оно меняет свой цвет на желтый и подчеркивает его. На других терминалах, которые я пробовал, это просто подчеркивает его. Это почти похоже на перечеркивание, но если я использую символ, отличный от _, это не работает, что заставляет меня думать, что _\b - это одна кодовая последовательность. И как тогда инвертируется видео для этого символа?
Есть ли у вас какие-либо сведения по этому поводу?
На странице руководства написано, что вывод cal должен быть бит в бит совместимой версией оригинальной команды Unix cal. Так что я могу только предположить, что это какой-то древний код.
решение1
Кажется, это почти перебор.
Это именно то, что есть. Как обсуждалось наПочему на 80-колоночной консоли имеется 11 позиций табуляции?, полезно вспомнить действие механических пишущих машинок, когда речь идет о терминалах Unix. В этом случае последовательность _
BS (символ возврата на одну позицию) перед символом — это условность, которая используется для указания подчеркивания этого символа, потому что на некоторых терминалах именно так подчеркивался текст. Альтернативная управляющая последовательность — BS _
после символа. На оригинальных терминалах, конечно, не имело значения, что перечеркивалось. На современных видеотерминалах последний записанный символ «выигрывает», стирая предыдущие данные. Поэтому _
BS <персонаж>порядок предпочтительнее.
FreeBSD ncal
, а именно ею и является эта программа, имеет два режима работы, когда дело касается подсветки.
- Если его вывод представляет собой терминал, он ищет последовательности
so
иse
для текущего типа терминала в базе данных termcap и выводит их по обе стороны от выделенного текста. (На самом деле в коде есть ошибка, которая делает это, связанная с выходом буфера в стеке из области видимости и использованием его содержимого позже, которую, похоже, никто не заметил.) - Если его выход не является терминалом, он выводит текст, в котором каждому выделяемому символу предшествует
_
последовательность BS.
Вы не можете повторить это, выдавая _
последовательность BS на свой терминал, если (конечно) ваш терминал не является одним из терминалов, где так подчеркивают вещи. Это не относится к эмуляторам терминала, и почти наверняка не относится к любому терминалу(ам) или эмулятору(ам) терминала(ов), которые вы здесь используете.
Однако вы можетефильтртекст, который использует это соглашение, через ul
программу, которая распознает это и несколько других соглашений, подобных соглашениям пишущей машинки, и транслирует их в те последовательности управления для вашего терминала, которые на самом деле есть, просматривая их в базе данных termcap. Вы также можете фильтровать выходные данные ваших printf
команд через ul
.
На других терминалах, которые я пробовал, он просто подчеркивается.
По иронии судьбы, фильтрация нетерминального режима вывода ncal
через ul
программу на самом деле немного лучше, чем позволить ncal
писать последовательности управления терминалом. В то время как ncal
использует терминалвыделятьсярежим, ul
будет пытаться использовать фактический терминалподчеркиваниеmode (если он есть) при переводе _
последовательности BS. Как объясняется в руководстве termcap, standout mode может быть любым, подходящим для терминала (включая жирный шрифт, обратное видео или цвета) и не обязательно подчеркиванием. На одном из ваших терминалов это явно комбинация подчеркивания и изменения цвета.
Более того, ul
также справляется с терминалами, которые не имеют подчеркивания начальных/конечных последовательностей, но имеют подчеркивание последних последовательностей символов. По иронии судьбы, ul
справится, если ваш терминална самом делетот, который подчеркивает наличием BS _
после каждого символа, тогда как ncal
не справится.
И, конечно же, ul
не имеет ncal
ошибки обработки буфера. ☺
Если я передам вывод в
less -R
, он изменит цвет на желтый и будет подчеркнут.
Как вы заметили, less
программа понимает _
последовательности BS и обрабатывает их примерно так же, как ul
и программа. Это не совсем то же самое. ul
может обрабатывать последовательности, включающие несколько _
символов и BS, а также может обрабатывать похожие последовательности для полужирного шрифта. less
не может. Сравните то, что вы видите, с этими двумя:
/usr/bin/printf "1 2 ______\b\b\b\b\b\b 3 _\b4. \b\b\b45 6\n" | ул
/usr/bin/printf "1 2 ______\b\b\b\b\b\b\b 3 _\b4. \b\b\b45 6\n" | меньше
назад в старые добрые времена
К сожалению, это все еще "добрые старые времена". Не позволяйте людям обманывать себя, думая, что это редко используется в наши дни.
Этого нет в руководстве, но исходный код ul
указывает, что он пытается реализовать обработку управляющей последовательности телетайпа модели 37, потому что «это то, что nroff
выводится». GNU-заменитель оригинальной nroff
программы Unix, написанный задолго до того, как терминалы приобрели такие модные функции, как цвета, жирный шрифт и курсив, способен генерироватьЕСМА-48последовательности управления для цветов, полужирного шрифта и курсива. Это действительно такв обычном случае.
nroff
и его замена GNU используются для форматирования страниц руководства для отображения на вашем терминале. К сожалению, и по иронии судьбы, примерно через 10 лет после его написания люди начали калечить инструмент GNU, так что он генерировал старые последовательности Teletype Model 37 от 1968 года вместо "новых" управляющих последовательностей ECMA-48 от 1976 года (sic!). Они сделали man
invoke groff
с параметрами, которые изменили его поведение по умолчанию, и добавили недокументированные файлы, которые заставляли выводить дополнительный ditroff.
Каждый раз, когда вы читаете страницу руководства на своем терминале, запускается система руководства groff
, которая добросовестно преобразует исходный текст руководства в выходной поток символов с помощью этих старых управляющих последовательностей телетайпа модели 37, которые less
преобразуются more
в управляющие последовательности вашего терминала.
дальнейшее чтение
- Джонатан де Бойн Поллард (2016). Курсив и цвет на страницах руководства на виртуальном терминале пользовательского пространства Nosh (архивная версия,текущая версия). Пакет «Перекус».
- Джонатан де Бойн Поллард (2017).
Улучшенная страница руководства для
ul
(архивная версия,текущая версия). Предложения.
решение2
Ctrl-H
это backspace, он перемещает курсор на один шаг влево. Отправка подчеркивания, backspace и какого-либо другого символа была способом подчеркнуть что-либо на печатном («бумажном») терминале в старые добрые времена. Это использовалось для выделения текущего дня в выводе cal
.
Моя cal
программа, когда запускается, konsole
не выводит эту последовательность. Если я запущу script -c cal
и изучу полученный typescript
файл, я увижу, что программа cal использует escape-последовательность <esc>[7m
для переключения на инверсный режим видео.