Por que eu posso mudar o histórico do bash?

6

Por que o bash altera o histórico mesmo que eu não esteja executando um comando que estou modificando? Por exemplo, se eu digitar:

$ echo foo1
foo1
$ echo foo2
foo2
$ echo foo3
foo3

Depois disso, pressiono para cima duas vezes e recebo echo foo2 no prompt. Eu pressiono 2 e obtenho echo foo22 . Agora de volta ao fim (linha vazia) com para baixo para baixo . Se eu agora pesquisar o histórico, verei echo foo22 , embora eu nunca tenha executado esse comando!

No entanto, quando saio do shell e abro outro, vejo os comandos originais executados. Acho tudo isso muito confuso, contra-intuitivo e irritante.

Eu gostaria que a história funcionasse assim:

  1. Apenas os comandos realmente executados são salvos no histórico.

  2. A história é imutável. (A menos que seja explicitamente limpo.)

Existe uma maneira de realizar isso?

Editar - esta questão parece relacionada: Existe alguma maneira de desfazer uma modificação do histórico bash?

    
por tuomassalo 13.05.2015 / 10:07

2 respostas

2

I find all this very confusing, counter-intuitive and irritating.

Essa é a sua opinião; Implementei um REPL interativo para uma linguagem de programação na qual cada linha da história não só pode ser editada, mas tem seu próprio histórico de desfazer independente. Assim, embora possa existir um comando que nunca tenha sido executado, você pode voltar para lá com a seta para cima e desfazê-lo de volta ao original.

No entanto, assim como no Bash essa edição do histórico só é salva no histórico quando você sai da linha modificada. Não, se você editar a linha e, em seguida, reenviá-la como um novo comando sem nunca ter navegado para longe dela! Nesse caso especial, as edições não são salvas no histórico, porque estão sendo salvas como uma nova entrada de histórico.

Há uma rima e uma razão para isso!

  1. Seria claramente contra-intuitivo e irritante não poder editar uma linha histórica antes de enviá-la como um novo comando.

  2. Seria contra-intuitivo e irritante simplesmente perder suas edições para uma linha de histórico se você sair dela para ver outra linha.

Uma possível solução pode ser a seguinte: quando o usuário edita uma linha do histórico, salve-a em uma área temporária que represente a nova linha a ser enviada (e não atualize o histórico). No entanto:

  1. Isso ainda seria contra-intuitivo e irritante. O usuário não poderá editar uma linha, pressionar a seta para cima duas vezes para ver uma linha anterior e, em seguida, a seta para baixo duas vezes para retornar à edição. O usuário então veria a linha original não editada e teria que navegar até a frente do histórico para encontrar a nova versão da linha no buffer de edição atual ("zero histórico").

  2. E se o usuário fizer duas edições em duas linhas de histórico diferentes? Seria irritante ter a edição mais recente menos criticada pelos mais recentes.

A única maneira de ter um histórico imutável no qual você pode fazer várias edições temporárias ao mesmo tempo e enviá-las como novos comandos em qualquer ordem provavelmente seria difícil de apresentar no paradigma da IU atual sem ser confuso. Esse "paradigma atual da interface do usuário" é que toda a área de trabalho (histórico mais nova entrada) é mapeada para uma única janela de edição na tela, com qualquer sinal visual sobre onde o usuário está e qualquer indicação de estado.

Provavelmente precisaríamos de um indicador de posição (algum pequeno número indicando ao usuário onde eles estão no espaço do histórico), um indicador de se essa linha do histórico contém modificações temporárias; uma maneira de alternar entre ver as modificações ou a linha subjacente inalterada; uma maneira de tornar as modificações permanentes (fazer histórico de mutação); uma maneira de descartar as modificações para uma linha ou intervalo de linhas ou todas as linhas, etc.

    
por 04.08.2017 / 11:22
2

Eu concordo, é um comportamento padrão chato (e parece ser exclusivo para bash / readline ). Em minha própria experiência, pelo menos, se eu me afastar de uma linha que eu modifiquei, é geralmente porque eu desisti dessas modificações e preferia tê-las descartadas do que perder a linha original!

Deixar essas modificações pode ser útil se o motivo de você ter desistido de modificar essa linha é porque você teve que fazer outra coisa primeiro, e essa pode ser a justificativa original para fazer isso dessa maneira. Ainda assim, ignorar a entrada do histórico original é uma má IMO, já que você está perdendo evidências do que você fez antes.

Os casos mais irritantes são onde você acaba limpando toda a linha para iniciar um novo comando, em seguida, vai para uma linha diferente que você aceita e percebe mais tarde que uma entrada no histórico parece ter ido embora.

Além disso, mesmo que pretenda manter essas modificações, se pretender voltar a essa linha modificada, tem de a pesquisar novamente.

O comportamento de zsh é mais útil para IMO. Você pode modificar todo o histórico, desde que não aceite uma linha e entre as linhas modificadas, mas, depois de aceitar uma nova linha, ela é adicionada ao histórico, mas as antigas linhas do histórico são preservadas (enquanto pressiona Ctrl + C cancela todas as modificações sem adicionar uma nova linha ao histórico).

E se você quisesse salvar as modificações feitas em linhas diferentes, você armazenaria a linha em uma fila com Alt + Q (a parte superior é automaticamente puxada no próximo prompt ), ou armazene-o no killring com Ctrl + U .

Felizmente, em bash / readline , você pode alterar o comportamento com

bind 'set revert-all-at-newline on'

(ou set revert-all-at-newline on in ~/.inputrc , portanto, aplica-se a todos os aplicativos que usam readline).

Em seguida, você terá um comportamento semelhante ao de yash , que é igual a zsh , mas sem a fila hold (mas você ainda pode usar o killring > (puxado com Ctrl + Y , Alt + Y )).

    
por 04.08.2017 / 14:16