Informações do sistema:
macOS Sierra 10.12.6
zsh 5.4.2 (x86_64-apple-darwin16.7.0)
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)
Role até o EXEMPLOS na parte inferior, se quiser apenas analisar os exemplos simplificados que eu fiz.
OBSERVAÇÃO: não sou um grande usuário zsh .
Eu estava vendo os fzf keybindings para bash e zsh .
Observe como ambos executam um comando variável $(__fzfcmd) . __fzfcmd por padrão envia fzf para stdout e a substituição de parâmetro apenas executa o comando ( fzf ) resultante da saída.
Uma diferença entre o script bash e zsh é que o bash canaliza ainda mais a saída de $(__fzfcmd) , mas zsh apenas captura-o dentro de uma matriz. Meu palpite é por causa de um problema em zsh quando você canaliza ainda mais a saída de fzf , onde você não pode inserir fzf e o processo enviado por fzf não recebe nenhum stdin. Sua única opção é ^Z ou ^C . ^C parece basear o processo por algum motivo. Ou talvez eles apenas o quisessem em uma matriz para que pudessem executar zle vi-fetch-history em isso . A versão bash faz alguma mágica na associação de chaves com "\e^": history-expand-line
Agora fzf não é importante. Parece que você só precisa de um programa que produza o tty para ser chamado por substituição de parâmetro para causar esse problema. Então, mostrarei alguns exemplos mais simples.
Aqui estão alguns outros comandos que saem para o tty que pode causar esse problema em zsh :
-
vipe (execute o editor no meio de um pipe)
-
'vim -' (faz o vim ler o stdin. similar ao vipe, mas não sai para o stdout)
Nos exemplos abaixo, substitua todas as ocorrências de vipe por vim - se você não quiser fazer uma instalação separada. Lembre-se de que vim - não exibe o conteúdo do editor como stdout vipe .
EXEMPLOS:
1) echo 1 | vipe | cat # works in both bash and zsh
2) echo 1 | $(echo vipe) | cat # works in bash only. zsh problem with no output until I hit '^C':
^C
zsh: done echo 1 |
zsh: suspended (tty output) $(echo vipe) |
zsh: interrupt cat
# seems like the process is backgrounded. I can still see it in jobs command
3) cat <(echo 1 | $(echo vipe)) # zsh and bash has the problem. I'm guessing because
# the file isn't finished writing and cat is
# blocking vipe's tty output
# both their '^C' output is just:
^C # nothing special, as expected
4) cat < <(echo 1 | $(echo vipe)) # works in both bash and zsh
5) echo 1 | $(echo vipe) > >(cat) # works in both bash and zsh
# The following don't have and input pipe to vipe.
# Type something then send EOF with ^D
6) vipe | cat # works for both
7) $(echo vipe) | cat # works for both
Agora, estou principalmente imaginando por que 2) tem um problema para zsh , mas não para bash e por que 4) e 5) corrigem o problema de zsh .
Os requisitos para zsh para ter esse problema parecem ser exatamente o que eu coloquei no título:
- tubo de entrada
- comando executado por substituição de variável / parâmetro que possui
tty output
- tubo de saída
ATUALIZAÇÃO
Eu adicionei outra solução alternativa que não causa zsh para ter esse problema, 5) . É semelhante a 4) , mas em vez de redirecionar stdout diretamente para stin , eu o redireciono para um arquivo que redireciona para stdin usando a substituição do processo.