Como obtenho longas linhas de comando para quebrar a próxima linha?

108

Algo que notei no Ubuntu por um longo tempo que foi frustrante para mim é que, quando estou digitando um comando na linha de comando que fica mais longo (mais largo) que a largura do terminal, em vez de agrupar em uma nova linha, ele volta para coluna 1 na mesma linha e começa a sobrescrever o início da minha linha de comando. (Na verdade, não substitui o comando real, mas visualmente, substitui o texto que foi exibido).

É difícil de explicar sem vê-lo, mas digamos que meu terminal tenha 20 caracteres de largura (o meu é mais parecido com 120 caracteres - mas por uma questão de exemplo), e quero repetir o alfabeto inglês. O que eu digito é este:

echo abcdefghijklmnopqrstuvwxyz

Mas a aparência do meu terminal antes de eu pressionar a tecla é:

pqrstuvwxyzghijklmno

Quando eu apertei enter, ele ecoa

abcdefghijklmnopqrstuvwxyz

então eu sei que o comando foi recebido corretamente. Apenas enrolou minha digitação após o "o" e recomeçou na mesma linha.

O que eu esperava que acontecesse, se eu digitasse este comando em um terminal com apenas 20 caracteres de largura, seria o seguinte:

echo abcdefghijklmno
pqrstuvwxyz

Background: Estou usando o bash como meu shell e tenho esta linha no meu ~ / .bashrc:

set -o vi

para poder navegar na linha de comandos com os comandos VI. Atualmente, estou usando o servidor Ubuntu 10.10 e me conectando ao servidor com o Putty.

Em qualquer outro ambiente em que trabalhei, se eu digitar uma linha de comando longa, ela adicionará uma nova linha abaixo da linha na qual estou trabalhando quando meu comando ultrapassa a largura do terminal e, quando eu continuar digitando, posso ver meu comando 2 linhas diferentes. Mas enquanto me lembro de usar o Ubuntu, meus comandos longos ocupam apenas 1 linha.

Isso também acontece quando estou retornando aos comandos anteriores da história (pressione Esc, depois 'K' para retornar aos comandos anteriores) - quando chego a um comando anterior que era maior que a largura do terminal, a linha de comando fica mutilado e não posso dizer onde estou no comando.

A única solução alternativa que encontrei para ver todo o comando longo é pressionar "Esc-V", que abre o comando atual em um editor de VI.

Acho que não tenho nada de estranho no meu arquivo .bashrc. Eu comentei a linha "set -o vi" e ainda tinha o problema.

Fiz o download de uma nova cópia do Putty e não fiz nenhuma alteração na configuração - apenas digitei o nome do host para me conectar e ainda tenho o problema, por isso não acho que haja nada com o Putty (a menos que precise faça algumas alterações na configuração)

Alguém já teve esse problema e alguém pode pensar em como corrigi-lo?

Editar

Era o meu arquivo .bashrc. Copiei o mesmo perfil de máquina para máquina e usei caracteres especiais no meu $ PS1 que, de alguma forma, estão jogando fora. Agora estou aderindo às variáveis ​​padrão do bash para o meu $ PS1.

Obrigado a @ ændrük pela dica sobre o .bashrc!

... Finalizar edição ...

BrianH
fonte
11
Apenas para garantir que o problema não seja causado pelo seu arquivo .bashrc, recomendo substituí-lo temporariamente por uma cópia do /etc/skel/.bashrc. Lembre-se de que você precisará se reconectar para que as alterações tenham efeito e mantenha um backup próprio .bashrc.
ændrük
11
Qual aplicativo de terminal você está usando? O comportamento que você está descrevendo não é usual, certamente não é um padrão.
João Pinto
Nos shells em que trabalhei (e no Cisco CLI), você também pode digitar Ctrl-L para exibir novamente a linha que está digitando, mesmo que esteja fora da tela. Na sua situação, isso ainda pode produzir a saída interrompida da qual você está falando, mas eu ficaria curioso.
23411 belacqua
3
Sinta-se à vontade para criar uma "resposta" explicando a solução e marque-a como aceita. Pode parecer um pouco tolo, mas ter uma resposta adequada ajuda a manter o site organizado e pode orientar com mais eficiência outras pessoas que têm problemas semelhantes no futuro.
ændrük
De acordo com esta resposta no serverfault , usetput smam
Samveen 23/10

Respostas:

136

Verifique se todos os bytes não imprimíveis no seu PS1 estão contidos \[ \]. Caso contrário, o bash os contará no comprimento do prompt. Ele usa o comprimento do prompt para determinar quando quebrar a linha.

Por exemplo, aqui o bash conta o prompt como 19 colunas de largura, enquanto o prompt exibido pelo terminal tem apenas 10 colunas de largura ( My promptescritas em ciano e >escritas na cor padrão):

PS1='\e[36mMy prompt\e[0m>'         # bash count: 19, actual: 10

enquanto aqui conta apenas o prompt com 10 colunas de largura porque ignora os bytes entre o especial \[e \]escapa:

PS1='\[\e[36m\]My prompt\[\e[0m\]>' # bash count: 10, actual: 10

Porém, para boas práticas, use tputpara gerar as fugas do terminal em vez de codificá-las:

cyan=$(tput setaf 6) # \e[36m
reset=$(tput sgr0)   # \e[0m
PS1='\[$cyan\]My prompt\[$reset\]>'

Consulte http://mywiki.wooledge.org/BashFAQ/053 e também http://wiki.bash-hackers.org/scripting/terminalcodes para obter mais informações tput.

Geirha
fonte
3
Essa é uma ótima explicação do problema que a resposta aceita não fornece
Jamie Cook
Na última linha do código PS1='...': por que as aspas simples não impedem $cyane $resetsubstituem?
andrybak
2
@andrybak, eles impedem $cyane $resetsão substituídos, mas PS1são avaliados sempre que o prompt é impresso. Você pode ver isso tentando PS1='$var> 'e, em seguida, forneça varvários valores e veja como o prompt muda. Em seguida, tente PS1="$var> " perceber que o prompt permanece estático; $varfoi expandido durante a tarefa, nem sempre PS1é avaliado.
Geirha
11
Isso é incrível. Muito obrigado por postar isto! Torna o escape dos colchetes muito mais fácil e mais legível.
Phyatt #
Como eu faço isso funcionar PS1=${PS1}"\e]2;$@\a". Eu tenteiPS1=${PS1}"\[\e]2;\]$@\[\a\]"
Ramana Reddy
59

Eu acho que você configurou o seu PS1com cores, certo?

Apenas certifique-se de ter \[dentro de sua PS1cotação anterior ao conjunto de cores

Por exemplo:

PS1='\[\e[0;32m\u@\w/:\[\e[m '
wjandrea
fonte
Meu PS1 foi export PS1='^[[96m'$(hostname)'<^[[92m${PWD}^[[96m>^[[97m '- Estive usando que um por um longo tempo - é KSH compatível ...
BrianH
2
Uau. Eu tenho usado avisos de terminal desde sempre e nunca tive esse problema antes. Nunca teria descoberto isso. Obrigado.
bchurchill
3
usar \ [enquanto estiver usando aspas simples gera uma barra não intencional. também, deve ser usado] no final dos caracteres mágicos, conforme observado na resposta mais votada
igorsantos07
2
-1 Não funciona. Você precisa envolver a seção de não impressão \[no início e \]no final.
Wjandrea
@ igorsantos07 A barra invertida dupla \\[foi um erro de digitação causado por uma edição. Eu consertei isso.
Wjandrea
11

Eu tive um problema semelhante e finalmente encontrei uma solução simples.

Adicione a seguinte linha no seu .bashrcarquivo:

COLUMNS=250

Em seguida, digite source ~/.bashrcpara obter o efeito desejado.

Deboshree
fonte
Em alguns casos, como subdivisões de terminadores estreitos, o problema não está nos caracteres de cor pronta, mas apenas em um valor COLUMNS errado. Esta resposta me tirou de um buraco muito chato!
Carles Sala
11
O logoff é desnecessário. Faça source .bashrc. Seu prompt será atualizado imediatamente
Sergiy Kolodyazhnyy 17/08/2015
11
Achei que desde que eu não tinha shopt setwinsizeconjunto para o meu bash, por isso não estava atualizando colunas da direita, consulte unix.stackexchange.com/a/167911/8337
rogerdpack
11
Eu export COLUMNS=250segui export TERM=xterme foi feliz.
Philip Kearns
5

Eu tive o mesmo problema com um prompt colorido personalizado, apesar de conter códigos de cores \[e \]delimitadores. Acontece que o bash tem problemas em reproduzir cores de dentro de uma função . Acabei usando apenas variáveis ​​para meu prompt e, embora meu .bashrc seja um pouco menos elegante, tudo funciona bem agora.

reentim
fonte
Se alguém ainda estiver lendo isso, é realmente possível escapar das cores em uma função. Veja esta resposta na pergunta vinculada.
Wjandrea 29/10
3

Uma coisa simples a fazer seria adicionar a seguinte linha antes de configurar o PS1:

stty columns 1000

Por exemplo,

stty columns 1000
PS1='\[\e[0;32m\u@\w/:[\e[m '

no entanto, isso afeta outros comandos unix como ls e man.

Gennady
fonte
11
Isso funciona no OSX.
raskhadafi
4
Isso também afeta muito o vim. Por favor, não use isso.
Just dec
0

Eu tive esse problema quando conectado no tmux. O problema era que eu tive uma ipythonsessão em segundo plano ( ctrl + z) e que de alguma forma quebrou a quebra de linha. Assim que eu terminei ( fg, ctrl+d+d) meu terminal começou a funcionar corretamente

Portanto, verifique se há avisos interativos interrompidos.

Ciprian Tomoiagă
fonte
0

Então, eu tive o mesmo problema com uma ligeira torção e pensei em compartilhar minha solução também, apenas para adicionar minha pequena nuance: D

Meu PS1 inicial era

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$"

O problema que tive foi que estava tentando alterar o título do meu terminal e o prompt de comando. A maneira como fiz isso foi adicionando \[\033]0;\]Title\aà variável PS1 .

Então agora meu PS1 era:

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[\033]0;\]Title\a"

Isso estragou tudo para mim. Finalmente descobri que o bash não parece gostar de ter \ano final. Para contornar isso, coloquei o título em uma variável, que parecia corrigi-lo.

TITLE="\033]0;Title\a"
PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[$TITLE\]"
Ciarán J. Hagen
fonte
0

\[e \]não funcionou para mim. Eu acho que havia algo diferente sobre como eu estava gerando o prompt (de um programa externo) ou porque meu prompt era "dinâmico".

Depois de ler este eu achei que você pode realmente escapar os códigos de cor com o 0x01e 0x02bytes.

por exemplo, estou usando uma versão especial do Chalk e envolvo as cores usando isso:

const Chalk = require('@nasc/chalk');

const chalk = new Chalk.constructor({
  wrapper: {
    pre: '\1',
    post: '\2',
  }
});
mpen
fonte