дальнейшее чтение

дальнейшее чтение

Когда вы запускаете 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!). Они сделали maninvoke groffс параметрами, которые изменили его поведение по умолчанию, и добавили недокументированные файлы, которые заставляли выводить дополнительный ditroff.

Каждый раз, когда вы читаете страницу руководства на своем терминале, запускается система руководства groff, которая добросовестно преобразует исходный текст руководства в выходной поток символов с помощью этих старых управляющих последовательностей телетайпа модели 37, которые lessпреобразуются moreв управляющие последовательности вашего терминала.

дальнейшее чтение

решение2

Ctrl-Hэто backspace, он перемещает курсор на один шаг влево. Отправка подчеркивания, backspace и какого-либо другого символа была способом подчеркнуть что-либо на печатном («бумажном») терминале в старые добрые времена. Это использовалось для выделения текущего дня в выводе cal.

Моя calпрограмма, когда запускается, konsoleне выводит эту последовательность. Если я запущу script -c calи изучу полученный typescriptфайл, я увижу, что программа cal использует escape-последовательность <esc>[7mдля переключения на инверсный режим видео.

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