Às vezes eu acidentalmente cat
alguns dados binários; às vezes, alguns programas ncurses travam - por vários motivos, o terminal pode acabar em mau estado, exigindo manual reset
. Isso está acontecendo com muita frequência.
Esse mau estado pode ser a falta de eco, ou a conversão de tudo em lixo chinês, ou muitas outras coisas.
Existe alguma maneira fácil de garantir que as configurações do terminal (sem reinicialização forçada, tela limpa, etc.) sejam restauradas quando o shell recuperar o controle?
É bash
e, Terminal.app
mas acho que esse problema é praticamente universal.
Responder1
Os problemas que você menciona surgem em diferentes camadas e apenas alguns deles podem ser resolvidos com “códigos de escape”.
Conjuntos de caracteres alternativos na emulação de terminal
Há um problema comum de terminal que pode ser descrito como “(algumas) letras minúsculas são exibidas como símbolos ou caracteres de desenho de linha” (consulteesta outra pergunta SO). Isso pode não estar relacionado ao seu problema do “lixo chinês”, mas é a coisa mais próxima que já vi. Você também pode encontrar “lixo chinês” ao interpretar quase qualquer fluxo de dados de 8 bits como texto codificado em UTF-16. Normalmente, esse não é um problema “pegajoso” que precisa ser redefinido; portanto, provavelmente não é o problema que você está vendo.
O problema de “preso com caracteres de desenho de linha” geralmente vem do envio ao emulador de terminal de uma sequência de controle não intencional (ou da interrupção de um programa antes de redefinir o terminal após mudar para o conjunto de caracteres alternativo). Isso pode acontecer quando alguns dados binários são exibidos e o fluxo de bytes contém uma sequência de controle de terminal que seleciona um conjunto de caracteres alternativo.
Isso é fácil de acionar na maioria dos terminais estilo VT-100, pois basta um único byte (0x0e; consulteminha resposta à pergunta SO vinculada anteriormente). A sequência de controle para redefinir esta condição também é um único byte (0x0f; geralmente produzido via echo ^V^O
(digitado como echo
Control++ ou digitado diretamente como ). V ControlOprintf '\017'
Você pode resolver esse tipo de problema ** solicitando a inclusão de um byte 0x0f.
** Se o seu “lixo chinês” for devido a algum outro problema então pode haver uma solução diferente.
PS1="\[\017\]… "
Os \[
e \]
estão aí para contarfestaque o caractere delimitado não é imprimível. Isso permitefestamantenha uma ideia precisa da posição “física” do cursor (isso é importante para uma nova exibição adequada ao usar a funcionalidade de edição de linha de comando).
Como aponta Ignacio Vázquez-Abrams ema resposta dele, outra maneira de obter a sequência de controle desejada é através dotputcomando:
tput rmacs
Usando este método você pode evitar a modificação do PS1 e apenas colocar o comando acima em PROMPT_COMMAND:
PROMPT_COMMAND='tput rmacs'
Opções de TTY (termios)
O problema “sem eco” *** vem de configurações inesperadas das opções do dispositivo tty baseado em sistema operacional que conecta seu emulador de terminal a todos os programas executados dentro da janela do terminal. Isso geralmente é causado por programas de interface de usuário de texto interativo que apresentam bugs, travam ou são eliminados, de modo que não conseguem restaurar o tty ao seu estado original.
Você pode controlar essas configurações com osttycomando. Este tipo de problema não pode ser resolvido com “códigos de escape”, pois as opções tty são configuradas através de APIs de software (vejatcsetattr(3)etermos(4)). Geralmente stty sane
é um bom mecanismo de reinicialização.
*** Também “no ^C/^Z/^/”, “saída escalonada” (sem CR automático quando um LF é recebido) e vários outros problemas.
reiniciar
OreiniciarO comando geralmente pode ajudar com os dois tipos de problemas. Ele enviará sequências de controle de inicialização do terminal que normalmente corrigirão o problema do conjunto de caracteres alternativo e redefinirá as opções tty para valores razoáveis.
O problema comreiniciaré que também imprime mensagens extras em alguns sistemas (ex. “Apagar é…”, “Interromper é…”); você provavelmente não deseja que eles sejam exibidos antes de cada prompt. Se a sua implementação dereiniciarenvia as mensagens e as sequências de controle para locais diferentes (por exemplo, um vai para stdout enquanto o outro vai para stderr), então você poderá filtrar as mensagens (por exemplo, PROMPT_COMMAND='reset 2>/dev/null'
(veja abaixo) e pular a colocação de ^O no prompt).
^O estty sane
Emfesta, você pode definir o parâmetro PROMPT_COMMAND
como comando efestaserá executado antes de exibir o prompt principal. Você poderia colocar todas as chamadas stty sane
lá e colocar ^O no seu prompt:
PROMPT_COMMAND='stty sane'
PS1="\[\017\]… "
Novamente, você pode evitar a modificação do PS1 (e lidar com terminais que não sejam do estilo VT-100) usandotput(conforme sugerido por Ignacio Vazquez-Abrams):
PROMPT_COMMAND='stty sane; tput rmacs'
Responder2
Colocar
echo -n "$(tput rmacs)"
em $PROMPT_COMMAND
.
Responder3
Então serei menos linha de comando, você sempre tem no xterm ou em qualquer terminal um "botão" de reset ou hard reset, para terminal.app está no menu Shell. Enviar reinicialização forçada alt-command-r.