Eu mantenho uma extensão para o ambiente Bash chamada Basta . Basta fornece uma linha de status protegida por rolagem na parte inferior do seu terminal ANSI/VT100.
Quando o Basta se configura, o número efetivo de linhas, como conhecido pelo material termios no kernel e a LINES
variável shell diminui em 1. O redimensionamento do terminal é tratado bem. Quase. Há trap
um SIGWINCH
sinal para chamar a rotina de atualização, que também é chamada após cada comando, antes de retornar ao prompt.
No entanto, de vez em quando, vejo uma situação em que a região de rolagem é perdida. O prompt está sendo pintado sobre a linha inferior, onde o usuário está editando comandos e onde a saída do comando aparece, resultando em uma bagunça.
Tenho uma hipótese sobre como isso pode ocorrer, que tem etapas de reprodução confiáveis.
Executamos um programa que aguarda entrada, enquanto o Bash está em segundo plano, como
cat
.Enquanto o programa estiver em execução, redimensionamos a janela para reduzi-la em uma linha.
Encerrar o
cat
programa.
Se o terminal for redimensionado enquanto cat
estiver em execução, o Bash não obtém o SIGWINCH
(porque, eu acho, SIGWINCH
é enviado apenas para os processos no grupo de processos em primeiro plano das sessões do terminal, e o Bash está em segundo plano naquele momento). Nosso trap
não executa.
A função de atualização do Basta também depende da comparação do tamanho do terminal anterior com o atual para detectar uma alteração de tamanho.
Aqui está o problema: nesta situação em que um terminal com um status protegido contra rolagem como encolheu em uma linha, o número de linhas parece não ter mudado .
Por exemplo, tela de 40 linhas com região de rolagem de 39 linhas: LINES=39
. Redimensione o terminal para ter 39 linhas de comprimento. A região de rolagem desapareceu. LINES=39
de novo. Para o software, parece o mesmo tamanho, então ele conclui que não houve um redimensionamento. A linha de status agora está sendo pintada sobre a linha inferior, sobre a entrada do usuário, porque Basta quer colocá-la na linha 40, que não existe mais, então o cursor se fixa em 39.
Se Basta souber que uma mudança de tamanho de janela ocorreu, ele não fará a comparação de tamanho; nessa situação, ele pega o caminho lento, pelo qual ele consulta o próprio terminal para determinar o tamanho. (Seria indesejável fazer isso para cada atualização, porque enviar consultas para o terminal é duvidoso. Se o usuário estiver digitando rapidamente, a resposta do terminal pode se misturar com suas teclas, e pode haver um atraso perceptível em obter uma resposta do terminal em conexões remotas lentas.)
Existe alguma maneira inteligente de saber se o terminal mudou (ou pelo menos suspeitar disso com uma taxa de falsos positivos razoavelmente baixa), na ausência de ter recebido a WINCH
armadilha, devido a ter estado em segundo plano, sem falar com o terminal?