Por que não preciso redefinir os atributos de texto com menos?

2

Este script gera 5 linhas com o terceiro sublinhado:

#!/usr/bin/env bash
set -eu
bold=$(tput bold)
reset=$(tput sgr0)
underline=$(tput smul)
echo 'line 1
line 2
line 3
line 4
line 5' | awk -v bold="$bold" -v reset="$reset" -v underline="$underline" '
    NR == 3 {print underline $0 reset}
    NR != 3 {print $0}
'

Se eu não redefinir (no script) no final da terceira linha, todas as linhas a seguir serão sublinhadas, incluindo os comandos que eu digito em seguida (no shell). Até eu executar reset . Com less ( ./my-script.sh | less -R ) não apenas reset (no script) não é necessário (a terceira linha fica sublinhada), mas também produz um símbolo extra em tmux ( ^O , TERM=screen-256color ):

line 1
line 2
line 3^O
line 4
line 5

Mas nenhum símbolo no console simples ( TERM=xterm-256color ).

O que exatamente e por que isso acontece? Existe uma maneira de fazer o script funcionar em todos esses casos?

$ ./my-script.sh
$ ./my-script.sh | grep line --color=never
$ ./my-script.sh | less -R

Por exemplo, para tornar o seguinte script funcione melhor.

    
por x-yuri 28.05.2018 / 20:33

1 resposta

2

less envia seu próprio "reset" no final da linha, que é derivado do terminfo sgr0 por (ncurses) eliminando o ^O (redefinir conjunto de caracteres alternativos) porque less é usando a interface termcap. O recurso termcap me que corresponde ao terminfo sgr0 convencionalmente não modifica o estado do conjunto de caracteres alternativos, como observado na página de manual curs_termcap(3x) :

Note that termcap has nothing analogous to terminfo's sgr string. One consequence of this is that termcap applications assume me (terminfo sgr0) does not reset the alternate character set. This implementation checks for, and modifies the data shown to the termcap interface to ac- commodate termcap's limitation in this respect.

Talvez less esteja fazendo essa redefinição para recuperar seqüências de escape inesperadas: a opção -R é projetada apenas para manipular cores ANSI (e saídas formatadas de forma semelhante, como negrito, sublinhado, piscada, destaque). O código-fonte não menciona isso, mas a atribuição A_NORMAL informa less para posteriormente emitir a redefinição:

    /* 
     * Add a newline if necessary, 
     * and append a '
reset=$(tput rmul)
' to the end of the line. * We output a newline if we're not at the right edge of the screen, * or if the terminal doesn't auto wrap, * or if this is really the end of the line AND the terminal ignores * a newline at the right edge. * (In the last case we don't want to output a newline if the terminal * doesn't ignore it since that would produce an extra blank line. * But we do want to output a newline if the terminal ignores it in case * the next line is blank. In that case the single newline output for * that blank line would be ignored!) */ if (column < sc_width || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) { linebuf[curr] = '\n'; attr[curr] = AT_NORMAL; curr++; }

Como alternativa aos atributos de vídeo sgr0 (que redefine todos e é apenas parcialmente entendido por menos), você pode fazer

    /* 
     * Add a newline if necessary, 
     * and append a '
reset=$(tput rmul)
' to the end of the line. * We output a newline if we're not at the right edge of the screen, * or if the terminal doesn't auto wrap, * or if this is really the end of the line AND the terminal ignores * a newline at the right edge. * (In the last case we don't want to output a newline if the terminal * doesn't ignore it since that would produce an extra blank line. * But we do want to output a newline if the terminal ignores it in case * the next line is blank. In that case the single newline output for * that blank line would be ignored!) */ if (column < sc_width || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) { linebuf[curr] = '\n'; attr[curr] = AT_NORMAL; curr++; }

e (para muitos terminais / muitos sistemas, incluindo TERM=screen-256color ) redefinem apenas o sublinhado. No entanto, isso não afeta negrito , nem existe um recurso terminfo / termcap convencional para redefinir negrito. Mas a tela implementa a sequência ECMA-48 correspondente que faz isso (SGR 22 versus 24 usado em rmul ), então você poderia codificar esse caso.

    
por 28.05.2018 / 21:27