vipe se comportando mal na substituição do processo bash

3

Eu tenho o seguinte comando simples:

$ echo <(vipe)

Eu esperava que ele abrisse um buffer vim, que eu possa editar, então, quando terminar, faça o eco do nome do arquivo temporário designado para conter o conteúdo do buffer vim.

Em vez disso, o buffer vim se comporta de maneira muito estranha, não responde a alguns pressionamentos de tecla e, eventualmente, o vim falha completamente.

Quais das minhas suposições estão erradas?

    
por Dun Peal 28.03.2015 / 01:41

1 resposta

3

Primeiro, vamos ver o que vemos no terminal:

$ echo <(vim)
/dev/fd/63
$ Vim: Warning: Output is not to a terminal

Observe que você recebe um aviso imediatamente, sem aguardar o término do editor. A substituição do processo não espera que o comando termine, cria um canal entre o comando e o shell. Um nome para esse pipe é passado para o comando que a substituição do processo é um argumento de, aqui echo que imprime esse nome e retorna imediatamente, após o qual o bash fecha o pipe.

O Vim ainda está em execução e sua entrada padrão e erro padrão estão conectados ao terminal, mas não à saída padrão. Então, o Vim está recebendo entrada e emitindo algumas mensagens de erro, mas a maior parte de sua exibição vai para o stdout, que é um canal quebrado.

Tanto o bash quanto o vim estão lendo o terminal. Isso faz com que os pressionamentos de teclas sejam enviados aleatoriamente para um ou para o outro. Essa situação normalmente não acontece porque os processos em segundo plano são proibido de ler no terminal - se eles tentarem fazer isso, receberão um sinal SIGTTIN e se ignorarem o sinal então sua read call retorna um erro. Mas, neste caso, vim é executado como parte do grupo de processos em primeiro plano, porque a substituição de processos não cria um novo grupo de processos, portanto, ele pode ler a partir do terminal e pegar algumas das teclas digitadas.

Em algum ponto, o Vim decide que não aguenta mais e sai. Eu não sei o que faz isso decidir isso.

A substituição de processos não cria um arquivo temporário, cria um canal, portanto, sua abordagem não faz sentido. Zsh tem uma construção de substituição de processo que cria um arquivo temporário ( =(somecommand) ), mas isso também não funcionaria: você pode executar echo =(vipe </dev/null) e isso imprimirá o nome de um arquivo temporário que, no momento em que é impresso, acaba de ser excluído.

Para fazer o que você quer fazer, você precisa manipular a exclusão do arquivo temporário por conta própria. Eu não acho que haja alguma construção de shell que possa ajudá-lo. Chame mktemp para criar o arquivo temporário e, em seguida, edite-o da maneira normal.

tmpfile=$(mktemp)
"${VISUAL:-"${EDITOR:-vi}"}" "$tmpfile"
echo "$tmpfile"
…
rm "$tmpfile"
    
por 28.03.2015 / 02:10