Estou escrevendo um cliente para realizar várias tarefas no servidor zimbra via ssh e encontrei um pequeno obstáculo. Aqui está o código:
#!/bin/bash
set -e
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
export HISTCONTROL=ignoreboth
# History management
if [ -f $HOME/.zmcli_history ]; then
history -r $HOME/.zmcli_history
else
touch $HOME/.zmcli_history
history -r $HOME/.zmcli_history
fi
trap "history -a $HOME/.zmcli_history && echo -e '\nExiting now.\n'" exit
# Styling
yellow='[33m'
bold='[1m'
off='[0m'
echo
# Client
while :; do
read -ep "$bold${yellow}zimbra_cli[${off}server_domain$bold${yellow}]> $off" comm
history -s "$comm"
done
NOTA: se você executar este script, ele criará o arquivo de histórico (.zmcli_history) em seu diretório inicial.
Tudo funciona como planejado e o histórico está todo lá, mas muitas vezes a parte de algum comando anterior (geralmente longo) permanece enquanto continuo a percorrer o histórico. Essa parte do comando atua como parte do prompt para o resto da sessão, a menos que eu pressione CTRL+L, que limpa a tela e a redefine ao normal. Eu li muitas postagens que ajudaram pessoas que tiveram esse problema em seu terminal bash. O problema deles era que o PS1 estava formatado incorretamente e o bash ficou confuso sobre o comprimento da string do prompt. Provavelmente é algo semelhante aqui, mas essas soluções não funcionam, porque o comando read não pode usar caracteres de escape como echo pode (\ e).
Consegui encontrar uma maneira de escapar das sequências de cores usando escapes literais (CTRL+V ESCAPE no modo de inserção do vim). Então as cores funcionam, mas estou preso a esse problema de histórico.
Coisas que tentei:
- substituição de comando :: escreva e escape os códigos de cores de forma que echo -e possa imprimi-los e, em seguida, faça eco no comando de leitura $(echo -e '\e[33m'). Ainda vendo as cores, mas não ajudou no problema de histórico
- adicionando [e] escapado em torno dos códigos de cores
- colocando todo o prompt com códigos de cores em um comando echo separado que vem antes do comando read. A desvantagem é que não consigo desligar a formatação até depois do comando de leitura (em outro eco), o que significa que todo o prompt e comando estarão em negrito e coloridos. Além disso, se eu pressionar CTRL+L agora, até o prompt será limpo e só ficarei com o cursor
Por fim, como não consigo descartar o histórico, tentei descartar as cores. Mas então fica impossível diferenciar rapidamente entre comandos e saídas.
Você pode replicar o problema iniciando o script e inserindo de 10 a 15 comandos longos (sem sentido). Depois disso, tente rolar para cima e para baixo no histórico e você verá do que estou falando.
Alguém sabe uma maneira de fazer isso funcionar?
Responder1
Seu roteiro,como isso é, não me permitiu replicar o problema. Só depois de habilitar as cores e tal readline comecei a ficar confuso. Para que conste, eu habilitei essas coisas com
# Styling
yellow=$'\e[33m'
bold=$'\e[1m'
off=$'\e[0m'
E é verdade \[
e \]
não ajuda comoeles fazem em caso dePS1
.
Mas então eu encontreiesta resposta. Ele lê
Abri
info readline
e encontrei:[…]
Os aplicativos podem indicar que o prompt contém caracteres que não ocupam espaço físico na tela quando exibidos, colocando uma sequência de tais caracteres entre colchetes com os marcadores especiaisRL_PROMPT_START_IGNORE
eRL_PROMPT_END_IGNORE
(declarados emreadline.h
. Isso pode ser usado para incorporar sequências de escape específicas do terminal em prompts.Como diz o texto que procuro
RL_PROMPT_START_IGNORE
eRL_PROMPT_END_IGNORE
definiçãoreadline.h
e encontrei a seguir:/* Definitions available for use by readline clients. */ #define RL_PROMPT_START_IGNORE '\001' #define RL_PROMPT_END_IGNORE '\002'
Isso me levou ao seguinte:
# Styling
yellow=$'\1\e[33m\2'
bold=$'\1\e[1m\2'
off=$'\1\e[0m\2'
Funciona perfeitamente.